diff options
Diffstat (limited to 'forms')
290 files changed, 74639 insertions, 0 deletions
diff --git a/forms/inc/makefile.mk b/forms/inc/makefile.mk new file mode 100644 index 000000000000..cc581afa8899 --- /dev/null +++ b/forms/inc/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=.. + +PRJNAME=forms +TARGET=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/forms/inc/pch/precompiled_forms.cxx b/forms/inc/pch/precompiled_forms.cxx new file mode 100644 index 000000000000..098a10ebaaa3 --- /dev/null +++ b/forms/inc/pch/precompiled_forms.cxx @@ -0,0 +1,29 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_forms.hxx" + diff --git a/forms/inc/pch/precompiled_forms.hxx b/forms/inc/pch/precompiled_forms.hxx new file mode 100644 index 000000000000..f75e8ca4316a --- /dev/null +++ b/forms/inc/pch/precompiled_forms.hxx @@ -0,0 +1,400 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:42.358362 + +#ifdef PRECOMPILED_HEADERS +//---MARKER--- +#include "sal/config.h" +#include "sal/types.h" + +#include "com/sun/star/awt/ActionEvent.hpp" +#include "com/sun/star/awt/FontDescriptor.hpp" +#include "com/sun/star/awt/FontEmphasisMark.hpp" +#include "com/sun/star/awt/FontRelief.hpp" +#include "com/sun/star/awt/ImageStatus.hpp" +#include "com/sun/star/awt/LineEndFormat.hpp" +#include "com/sun/star/awt/MouseButton.hpp" +#include "com/sun/star/awt/MouseEvent.hpp" +#include "com/sun/star/awt/PopupMenuDirection.hpp" +#include "com/sun/star/awt/PosSize.hpp" +#include "com/sun/star/awt/SystemPointer.hpp" +#include "com/sun/star/awt/VclWindowPeerAttribute.hpp" +#include "com/sun/star/awt/XActionListener.hpp" +#include "com/sun/star/awt/XButton.hpp" +#include "com/sun/star/awt/XCheckBox.hpp" +#include "com/sun/star/awt/XComboBox.hpp" +#include "com/sun/star/awt/XControlModel.hpp" +#include "com/sun/star/awt/XDialog.hpp" +#include "com/sun/star/awt/XFocusListener.hpp" +#include "com/sun/star/awt/XImageConsumer.hpp" +#include "com/sun/star/awt/XImageProducer.hpp" +#include "com/sun/star/awt/XItemListener.hpp" +#include "com/sun/star/awt/XListBox.hpp" +#include "com/sun/star/awt/XMouseListener.hpp" +#include "com/sun/star/awt/XRadioButton.hpp" +#include "com/sun/star/awt/XTabControllerModel.hpp" +#include "com/sun/star/awt/XTextComponent.hpp" +#include "com/sun/star/awt/XWindowListener2.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/beans/Property.hpp" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/beans/PropertyChangeEvent.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/XFastPropertySet.hpp" +#include "com/sun/star/beans/XMultiPropertySet.hpp" +#include "com/sun/star/beans/XPropertyChangeListener.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/beans/XPropertySetInfo.hpp" +#include "com/sun/star/beans/XPropertyState.hpp" +#include "com/sun/star/container/ElementExistException.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XChild.hpp" +#include "com/sun/star/container/XContainer.hpp" +#include "com/sun/star/container/XContainerListener.hpp" +#include "com/sun/star/container/XEnumeration.hpp" +#include "com/sun/star/container/XEnumerationAccess.hpp" +#include "com/sun/star/container/XIndexAccess.hpp" +#include "com/sun/star/container/XIndexContainer.hpp" +#include "com/sun/star/container/XIndexReplace.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/container/XNameReplace.hpp" +#include "com/sun/star/container/XNamed.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/form/DataSelectionType.hpp" +#include "com/sun/star/form/DatabaseParameterEvent.hpp" +#include "com/sun/star/form/FormButtonType.hpp" +#include "com/sun/star/form/FormComponentType.hpp" +#include "com/sun/star/form/FormSubmitEncoding.hpp" +#include "com/sun/star/form/FormSubmitMethod.hpp" +#include "com/sun/star/form/ListSourceType.hpp" +#include "com/sun/star/form/NavigationBarMode.hpp" +#include "com/sun/star/form/TabulatorCycle.hpp" +#include "com/sun/star/form/XApproveActionBroadcaster.hpp" +#include "com/sun/star/form/XApproveActionListener.hpp" +#include "com/sun/star/form/XBoundComponent.hpp" +#include "com/sun/star/form/XBoundControl.hpp" +#include "com/sun/star/form/XChangeBroadcaster.hpp" +#include "com/sun/star/form/XDatabaseParameterBroadcaster2.hpp" +#include "com/sun/star/form/XDatabaseParameterListener.hpp" +#include "com/sun/star/form/XForm.hpp" +#include "com/sun/star/form/XFormComponent.hpp" +#include "com/sun/star/form/XGridColumnFactory.hpp" +#include "com/sun/star/form/XImageProducerSupplier.hpp" +#include "com/sun/star/form/XLoadListener.hpp" +#include "com/sun/star/form/XLoadable.hpp" +#include "com/sun/star/form/XReset.hpp" +#include "com/sun/star/form/XResetListener.hpp" +#include "com/sun/star/form/binding/XBindableValue.hpp" +#include "com/sun/star/form/binding/XListEntryListener.hpp" +#include "com/sun/star/form/binding/XListEntrySink.hpp" +#include "com/sun/star/form/binding/XListEntrySource.hpp" +#include "com/sun/star/form/binding/XValueBinding.hpp" +#include "com/sun/star/form/submission/XSubmission.hpp" +#include "com/sun/star/form/submission/XSubmissionSupplier.hpp" +#include "com/sun/star/form/validation/XValidatableFormComponent.hpp" +#include "com/sun/star/form/validation/XValidator.hpp" +#include "com/sun/star/form/validation/XValidityConstraintListener.hpp" +#include "com/sun/star/frame/FrameSearchFlag.hpp" +#include "com/sun/star/frame/XComponentLoader.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/frame/XDispatchProviderInterception.hpp" +#include "com/sun/star/frame/XDispatchProviderInterceptor.hpp" +#include "com/sun/star/frame/XStatusListener.hpp" +#include "com/sun/star/graphic/XGraphic.hpp" +#include "com/sun/star/io/NotConnectedException.hpp" +#include "com/sun/star/io/WrongFormatException.hpp" +#include "com/sun/star/io/XActiveDataSink.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/io/XMarkableStream.hpp" +#include "com/sun/star/io/XObjectInputStream.hpp" +#include "com/sun/star/io/XObjectOutputStream.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XPersistObject.hpp" +#include "com/sun/star/io/XTextInputStream.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/EventObject.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/IndexOutOfBoundsException.hpp" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/lang/XTypeProvider.hpp" +#include "com/sun/star/lang/XUnoTunnel.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/script/ScriptEvent.hpp" +#include "com/sun/star/script/ScriptEventDescriptor.hpp" +#include "com/sun/star/script/XEventAttacherManager.hpp" +#include "com/sun/star/sdb/CommandType.hpp" +#include "com/sun/star/sdb/ParametersRequest.hpp" +#include "com/sun/star/sdb/RowSetVetoException.hpp" +#include "com/sun/star/sdb/SQLContext.hpp" +#include "com/sun/star/sdb/SQLErrorEvent.hpp" +#include "com/sun/star/sdb/XColumn.hpp" +#include "com/sun/star/sdb/XColumnUpdate.hpp" +#include "com/sun/star/sdb/XCompletedExecution.hpp" +#include "com/sun/star/sdb/XInteractionSupplyParameters.hpp" +#include "com/sun/star/sdb/XParametersSupplier.hpp" +#include "com/sun/star/sdb/XQueriesSupplier.hpp" +#include "com/sun/star/sdb/XResultSetAccess.hpp" +#include "com/sun/star/sdb/XRowSetApproveBroadcaster.hpp" +#include "com/sun/star/sdb/XRowSetApproveListener.hpp" +#include "com/sun/star/sdb/XSQLErrorBroadcaster.hpp" +#include "com/sun/star/sdb/XSQLErrorListener.hpp" +#include "com/sun/star/sdb/XSQLQueryComposer.hpp" +#include "com/sun/star/sdb/XSQLQueryComposerFactory.hpp" +#include "com/sun/star/sdb/XSingleSelectQueryComposer.hpp" +#include "com/sun/star/sdbc/ColumnValue.hpp" +#include "com/sun/star/sdbc/DataType.hpp" +#include "com/sun/star/sdbc/ResultSetConcurrency.hpp" +#include "com/sun/star/sdbc/ResultSetType.hpp" +#include "com/sun/star/sdbc/SQLException.hpp" +#include "com/sun/star/sdbc/XCloseable.hpp" +#include "com/sun/star/sdbc/XConnection.hpp" +#include "com/sun/star/sdbc/XDataSource.hpp" +#include "com/sun/star/sdbc/XParameters.hpp" +#include "com/sun/star/sdbc/XResultSetUpdate.hpp" +#include "com/sun/star/sdbc/XRowSet.hpp" +#include "com/sun/star/sdbc/XRowSetListener.hpp" +#include "com/sun/star/sdbcx/Privilege.hpp" +#include "com/sun/star/sdbcx/XColumnsSupplier.hpp" +#include "com/sun/star/sdbcx/XDeleteRows.hpp" +#include "com/sun/star/sdbcx/XTablesSupplier.hpp" +#include "com/sun/star/task/XInteractionContinuation.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/task/XInteractionRequest.hpp" +#include "com/sun/star/ucb/PostCommandArgument2.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/ucb/XProgressHandler.hpp" +#include "com/sun/star/ucb/XSimpleFileAccess.hpp" +#include "com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp" +#include "com/sun/star/ui/dialogs/TemplateDescription.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/ui/dialogs/XFilePicker.hpp" +#include "com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.h" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/Type.hxx" +#include "com/sun/star/uno/XAggregation.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/Date.hpp" +#include "com/sun/star/util/DateTime.hpp" +#include "com/sun/star/util/NumberFormat.hpp" +#include "com/sun/star/util/SearchAlgorithms.hpp" +#include "com/sun/star/util/Time.hpp" +#include "com/sun/star/util/URL.hpp" +#include "com/sun/star/util/XCancellable.hpp" +#include "com/sun/star/util/XCloneable.hpp" +#include "com/sun/star/util/XModifyBroadcaster.hpp" +#include "com/sun/star/util/XModifyListener.hpp" +#include "com/sun/star/util/XNumberFormatTypes.hpp" +#include "com/sun/star/util/XNumberFormatsSupplier.hpp" +#include "com/sun/star/util/XNumberFormatter.hpp" +#include "com/sun/star/util/XRefreshable.hpp" +#include "com/sun/star/util/XURLTransformer.hpp" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/view/XSelectionSupplier.hpp" +#include "com/sun/star/xforms/InvalidDataOnSubmitException.hpp" +#include "com/sun/star/xforms/XDataTypeRepository.hpp" +#include "com/sun/star/xforms/XFormsEvent.hpp" +#include "com/sun/star/xforms/XFormsSupplier.hpp" +#include "com/sun/star/xforms/XModel.hpp" +#include "com/sun/star/xforms/XSubmission.hpp" +#include "com/sun/star/xml/dom/NodeType.hpp" +#include "com/sun/star/xml/dom/XCharacterData.hpp" +#include "com/sun/star/xml/dom/XDocument.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/dom/XDocumentFragment.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNamedNodeMap.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "com/sun/star/xml/dom/XText.hpp" +#include "com/sun/star/xml/dom/events/XDocumentEvent.hpp" +#include "com/sun/star/xml/dom/events/XEventListener.hpp" +#include "com/sun/star/xml/dom/events/XEventTarget.hpp" +#include "com/sun/star/xml/xpath/Libxml2ExtensionHandle.hpp" +#include "com/sun/star/xml/xpath/XPathObjectType.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/xml/xpath/XXPathExtension.hpp" +#include "com/sun/star/xml/xpath/XXPathObject.hpp" +#include "com/sun/star/xsd/DataTypeClass.hpp" +#include "com/sun/star/xsd/WhiteSpaceTreatment.hpp" +#include "com/sun/star/xsd/XDataType.hpp" + +#include "comphelper/basicio.hxx" +#include "comphelper/broadcasthelper.hxx" +#include "comphelper/container.hxx" +#include "comphelper/enumhelper.hxx" +#include "comphelper/eventattachermgr.hxx" +#include "comphelper/guarding.hxx" +#include "comphelper/implementationreference.hxx" +#include "comphelper/interaction.hxx" +#include "comphelper/listenernotification.hxx" +#include "comphelper/numbers.hxx" +#include "comphelper/processfactory.hxx" +#include "comphelper/propertycontainer.hxx" +#include "comphelper/propertycontainerhelper.hxx" +#include "comphelper/propertysetinfo.hxx" +#include "comphelper/seqstream.hxx" +#include "comphelper/sequence.hxx" +#include "comphelper/stl_types.hxx" +#include "comphelper/streamsection.hxx" +#include "comphelper/types.hxx" +#include "comphelper/uno3.hxx" + +#include "connectivity/dbconversion.hxx" +#include "connectivity/predicateinput.hxx" +#include "connectivity/sqlparse.hxx" + +#include "cppuhelper/compbase3.hxx" +#include "cppuhelper/component.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase11.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/implbase4.hxx" +#include "cppuhelper/implbase5.hxx" +#include "cppuhelper/implbase6.hxx" +#include "cppuhelper/implbase7.hxx" +#include "cppuhelper/implbase8.hxx" +#include "cppuhelper/interfacecontainer.h" +#include "cppuhelper/interfacecontainer.hxx" +#include "cppuhelper/propshlp.hxx" +#include "cppuhelper/queryinterface.hxx" +#include "cppuhelper/typeprovider.hxx" +#include "cppuhelper/weak.hxx" +#include "cppuhelper/weakref.hxx" + +#include "i18npool/mslangid.hxx" + +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" + +#include "osl/conditn.hxx" +#include "osl/diagnose.h" +#include "osl/file.hxx" +#include "osl/mutex.hxx" + +#include "rtl/alloc.h" +#include "rtl/logfile.hxx" +#include "rtl/math.hxx" +#include "rtl/memory.h" +#include "rtl/strbuf.hxx" +#include "rtl/string.hxx" +#include "rtl/tencinfo.h" +#include "rtl/textenc.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "rtl/uuid.h" + +#include "sfx2/imgmgr.hxx" +#include "sfx2/msgpool.hxx" +#include "sfx2/sfxuno.hxx" + + +#include "svtools/cliplistener.hxx" +#include "svtools/imageresourceaccess.hxx" +#include "svl/inetstrm.hxx" +#include "svl/inettype.hxx" +#include "svl/itempool.hxx" +#include "svl/itemset.hxx" +#include "svl/languageoptions.hxx" +#include "unotools/lingucfg.hxx" +#include "svl/numuno.hxx" +#include "svl/poolitem.hxx" +#include "svl/solar.hrc" +#include "svtools/transfer.hxx" + +#include "editeng/editdata.hxx" +#include "editeng/editeng.hxx" +#include "editeng/editobj.hxx" +#include "editeng/editstat.hxx" +#include "editeng/editview.hxx" +#include "editeng/eeitem.hxx" +#include "editeng/frmdir.hxx" +#include "editeng/scripttypeitem.hxx" +#include "editeng/svxenum.hxx" +#include "svx/svxids.hrc" +#include "editeng/unoedsrc.hxx" +#include "editeng/unofored.hxx" + +#include "toolkit/helper/emptyfontdescriptor.hxx" + +#include "tools/color.hxx" +#include "tools/date.hxx" +#include "tools/debug.hxx" +#include "tools/diagnose_ex.h" +#include "tools/inetmsg.hxx" +#include "tools/link.hxx" +#include "tools/list.hxx" +#include "tools/resid.hxx" +#include "tools/simplerm.hxx" +#include "tools/solar.h" +#include "tools/stream.hxx" +#include "tools/string.hxx" +#include "tools/urlobj.hxx" + +#include "ucbhelper/activedatasink.hxx" +#include "ucbhelper/content.hxx" + + +#include "uno/lbnames.h" +#include "uno/mapping.hxx" + +#include "unotools/desktopterminationobserver.hxx" +#include "unotools/idhelper.hxx" +#include "unotools/processfactory.hxx" +#include "unotools/streamhelper.hxx" +#include "unotools/textsearch.hxx" +#include "unotools/ucbstreamhelper.hxx" + +#include "vcl/bmpacc.hxx" +#include "vcl/cvtgrf.hxx" +#include "vcl/mapmod.hxx" +#include "vcl/mapunit.hxx" +#include "vcl/stdtext.hxx" +#include "vcl/timer.hxx" +#include "vcl/wintypes.hxx" + +#include "vos/mutex.hxx" +#include "vos/thread.hxx" +//---MARKER--- +#endif diff --git a/forms/makefile.pmk b/forms/makefile.pmk new file mode 100644 index 000000000000..ccb15e70959e --- /dev/null +++ b/forms/makefile.pmk @@ -0,0 +1,28 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +VISIBILITY_HIDDEN = TRUE diff --git a/forms/prj/build.lst b/forms/prj/build.lst new file mode 100644 index 000000000000..ec07ab8e243c --- /dev/null +++ b/forms/prj/build.lst @@ -0,0 +1,17 @@ +fm forms : l10n oovbaapi svx sfx2 QADEVOOO:qadevOOo NULL +fm forms usr1 - all fm_mkofrm NULL +fm forms\inc nmake - all fm_inc NULL +fm forms\source\inc get - all fm_sinc NULL +fm forms\source\component nmake - all fm_component fm_inc NULL +fm forms\source\solar\component nmake - all fm_solar_component fm_inc NULL +fm forms\source\solar\control nmake - all fm_solar_control fm_inc NULL +fm forms\source\helper nmake - all fm_helper fm_inc NULL +fm forms\source\misc nmake - all fm_misc fm_inc NULL +fm forms\source\xforms\submission nmake - all fm_xforms_submit fm_inc NULL +fm forms\source\xforms\xpathlib nmake - all fm_xforms_xpathlib fm_inc NULL +fm forms\source\xforms nmake - all fm_xforms fm_xforms_submit fm_xforms_xpathlib fm_inc NULL +fm forms\source\resource nmake - all fm_resource fm_inc NULL +fm forms\source\richtext nmake - all fm_richtext fm_inc NULL +fm forms\source\runtime nmake - all frm_runtime NULL +fm forms\util nmake - all fm_util fm_component fm_solar_component fm_solar_control fm_helper fm_misc fm_resource fm_richtext frm_runtime fm_xforms NULL +fm forms\qa nmake - all fm_qa NULL diff --git a/forms/prj/d.lst b/forms/prj/d.lst new file mode 100644 index 000000000000..de1655d7d7f8 --- /dev/null +++ b/forms/prj/d.lst @@ -0,0 +1,7 @@ +..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll +..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT% +..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib +..\%__SRC%\lib\*.sl %_DEST%\lib%_EXT%\*.sl +..\%__SRC%\bin\*.bin %_DEST%\bin%_EXT%\*.bin +..\%__SRC%\bin\*.res %_DEST%\bin%_EXT%\*.res +..\util\*.xml %_DEST%\xml%_EXT%\*.xml diff --git a/forms/qa/complex/forms/CheckOGroupBoxModel.java b/forms/qa/complex/forms/CheckOGroupBoxModel.java new file mode 100755 index 000000000000..8a2ae5c7f0e4 --- /dev/null +++ b/forms/qa/complex/forms/CheckOGroupBoxModel.java @@ -0,0 +1,147 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package complex.forms; + +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyChangeEvent; +import com.sun.star.beans.XMultiPropertySet; +import com.sun.star.beans.XPropertiesChangeListener; +import com.sun.star.lang.EventObject; +import com.sun.star.drawing.XControlShape; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import complexlib.ComplexTestCase; +import java.io.PrintWriter; +import java.util.Vector; +import util.FormTools; +import util.SOfficeFactory; +import util.ValueChanger; + +/** + */ +public class CheckOGroupBoxModel extends ComplexTestCase { + + private XMultiPropertySet xPropSet = null; + + public String[] getTestMethodNames() { + return new String[] {"setPropertyValues"}; + } + + public void before() { + XComponent xDrawDoc = null; + SOfficeFactory SOF = SOfficeFactory.getFactory(((XMultiServiceFactory) param.getMSF())); + + try { + log.println("creating a draw document"); + xDrawDoc = SOF.createDrawDoc(null); + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace((PrintWriter)log); + failed("Couldn't create document."); + } + + String objName = "GroupBox"; + XControlShape shape = FormTools.insertControlShape(xDrawDoc, 5000, 7000, 2000, 2000, objName); + xPropSet = (XMultiPropertySet)UnoRuntime.queryInterface(XMultiPropertySet.class, shape.getControl()); + } + + + public void setPropertyValues() { + String[] boundPropsToTest = getBoundPropsToTest(); + + MyChangeListener ml = new MyChangeListener(); + xPropSet.addPropertiesChangeListener(boundPropsToTest, ml); + + Object[] gValues = xPropSet.getPropertyValues(boundPropsToTest); + Object[] newValue = new Object[gValues.length]; + log.println("Trying to change all properties."); + for (int i=0; i<boundPropsToTest.length; i++) { + newValue[i] = ValueChanger.changePValue(gValues[i]); + } + try { + xPropSet.setPropertyValues(boundPropsToTest, newValue); + } catch (com.sun.star.beans.PropertyVetoException e) { + e.printStackTrace((PrintWriter)log); + failed("Exception occured while trying to change the properties."); + } catch (com.sun.star.lang.IllegalArgumentException e) { + e.printStackTrace((PrintWriter)log); + failed("Exception occured while trying to change the properties."); + } catch (com.sun.star.lang.WrappedTargetException e) { + e.printStackTrace((PrintWriter)log); + failed("Exception occured while trying to change the properties."); + } // end of try-catch + + assure("Listener was not called.", ml.wasListenerCalled()); + xPropSet.removePropertiesChangeListener(ml); + } + + private String[] getBoundPropsToTest() { + Property[] properties = xPropSet.getPropertySetInfo().getProperties(); + String[] testPropsNames = null; + + Vector tNames = new Vector(); + + for (int i = 0; i < properties.length; i++) { + + Property property = properties[i]; + String name = property.Name; + boolean isWritable = ((property.Attributes & + PropertyAttribute.READONLY) == 0); + boolean isNotNull = ((property.Attributes & + PropertyAttribute.MAYBEVOID) == 0); + boolean isBound = ((property.Attributes & + PropertyAttribute.BOUND) != 0); + + if ( isWritable && isNotNull && isBound) { + tNames.add(name); + } + + } // endfor + + //get a array of bound properties + testPropsNames = new String[tNames.size()]; + testPropsNames = (String[])tNames.toArray(testPropsNames); + return testPropsNames; + } + + /** + * Listener implementation which sets a flag when + * listener was called. + */ + public class MyChangeListener implements XPropertiesChangeListener { + boolean propertiesChanged = false; + public void propertiesChange(PropertyChangeEvent[] e) { + propertiesChanged = true; + } + public void disposing (EventObject obj) {} + public boolean wasListenerCalled() { return propertiesChanged; } + public void reset() { propertiesChanged = false; } + }; + +} diff --git a/forms/qa/complex/forms/makefile.mk b/forms/qa/complex/forms/makefile.mk new file mode 100755 index 000000000000..6caf244cddc1 --- /dev/null +++ b/forms/qa/complex/forms/makefile.mk @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +TARGET = CheckOGroupBoxModel +PRJNAME = $(TARGET) +PACKAGE = complex$/forms + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar mysql.jar +JAVAFILES = CheckOGroupBoxModel.java +JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +JARCLASSDIRS = $(PACKAGE) + +# --- Parameters for the test -------------------------------------- + +# start an office if the parameter is set for the makefile +.IF "$(OFFICE)" == "" +CT_APPEXECCOMMAND = +.ELSE +CT_APPEXECCOMMAND = -AppExecutionCommand "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;" +.ENDIF + +# test base is java complex +CT_TESTBASE = -TestBase java_complex + +# build up package name with "." instead of $/ +CT_PACKAGE = -o $(PACKAGE:s\$/\.\) + +# start the runner application +CT_APP = org.openoffice.Runner + +# --- Targets ------------------------------------------------------ + +.IF "$(depend)" == "" +run : ALLTAR +.ELSE +run : ALLDEP +.ENDIF + +.INCLUDE : target.mk + +run: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_APPEXECCOMMAND) $(CT_TESTBASE) $(CT_PACKAGE).$(JAVAFILES:b) diff --git a/forms/qa/forms_all.sce b/forms/qa/forms_all.sce new file mode 100644 index 000000000000..3aef2c95ecc1 --- /dev/null +++ b/forms/qa/forms_all.sce @@ -0,0 +1,8 @@ +-o integration.forms.RadioButtons +-o integration.forms.FormControlTest +-o integration.forms.FormPropertyBags +-o integration.forms.CellBinding +-o integration.forms.ListSelection +-o integration.forms.MasterDetailForms +-o integration.forms.XMLFormSettings +-o integration.forms.ListBox diff --git a/forms/qa/integration/forms/BooleanValidator.java b/forms/qa/integration/forms/BooleanValidator.java new file mode 100644 index 000000000000..3cba1273d63f --- /dev/null +++ b/forms/qa/integration/forms/BooleanValidator.java @@ -0,0 +1,59 @@ +/* + * BooleanValidator.java + * + * Created on 10. Maerz 2004, 16:27 + */ + +package integration.forms; + +/** + * + * @author fs93730 + */ +public class BooleanValidator extends integration.forms.ControlValidator +{ + private boolean m_preventChecked; + private com.sun.star.uno.AnyConverter m_converter; + + /** Creates a new instance of BooleanValidator */ + public BooleanValidator( boolean preventChecked ) + { + m_preventChecked = preventChecked; + m_converter = new com.sun.star.uno.AnyConverter(); + } + + public String explainInvalid( Object Value ) + { + try + { + if ( m_converter.isVoid( Value ) ) + return "'indetermined' is not an allowed state"; + boolean value = ((Boolean)Value).booleanValue(); + if ( m_preventChecked && ( value == true ) ) + return "no no no. Don't check it."; + } + catch( java.lang.Exception e ) + { + return "ooops. Unknown error"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + if ( m_converter.isVoid( Value ) ) + return false; + + boolean value = ((Boolean)Value).booleanValue(); + if ( m_preventChecked && ( value == true ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } +} diff --git a/forms/qa/integration/forms/CellBinding.java b/forms/qa/integration/forms/CellBinding.java new file mode 100644 index 000000000000..3bf171d82465 --- /dev/null +++ b/forms/qa/integration/forms/CellBinding.java @@ -0,0 +1,560 @@ +/* + * CellBinding.java + * + * Created on 12. Mai 2004, 15:15 + */ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.beans.*; +import com.sun.star.form.binding.*; +import com.sun.star.accessibility.*; +import com.sun.star.awt.XListBox; +import com.sun.star.table.CellAddress; +import com.sun.star.table.XCell; +import com.sun.star.sheet.XCellRangeData; +import com.sun.star.sheet.XCellRangeFormula; +import com.sun.star.table.CellRangeAddress; +import com.sun.star.text.XTextRange; + +/** + * + * @author fs93730 + */ +public class CellBinding extends complexlib.ComplexTestCase +{ + /** the test document our form layer lives in */ + private SpreadsheetDocument m_document; + /** our form layer */ + private FormLayer m_formLayer; + /** our service factory */ + private XMultiServiceFactory m_orb; + + /** Creates a new instance of CellBinding */ + public CellBinding() + { + } + + public String[] getTestMethodNames() + { + return new String[] { + "checkTextFieldBinding", + "checkBooleanRadioBinding", + "checkStringRadioBinding", + "checkBooleanCheckBoxBinding", + "checkStringCheckBoxBinding", + "checkListBoxBinding", + "checkListBoxIndexBinding" + }; + } + + public String getTestObjectName() + { + return "Form Control Spreadsheet Cell Binding Test"; + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + private void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + } + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + m_document = new SpreadsheetDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + public void checkTextFieldBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + final short col = 0; + final short row = 2; + final String text = new String( "content" ); + final String otherText = new String( "something else" ); + final String yetAnotherText = new String( "yet another text" ); + + // cretae a normal text control + XPropertySet controlModel = m_formLayer.createControlAndShape( "DatabaseTextField", 30, 9, 30, 6 ); + + // bind it to cell A1 + bindToCell( controlModel, col, row ); + + // switch to alive mode + m_document.getCurrentView().toggleFormDesignMode(); + + // test the data transfer control -> cell + simulateUserTextInput( controlModel, text ); + verifyStringCellContent( col, row, text, "A text field does not forward its user input to the cell." ); + + // the same, but this time changing the control value programmatically + controlModel.setPropertyValue( "Text", otherText ); + verifyStringCellContent( col, row, otherText, "A text field does not forward programmatic changes to the cell." ); + + // the other way round: cell->control + setCellText( col, row, yetAnotherText ); + String controlText = (String)controlModel.getPropertyValue( "Text" ); + if ( !controlText.equals( yetAnotherText ) ) + failed( "Changes in the cell are not forwarded to the text field." ); + } + /* ------------------------------------------------------------------ */ + public void checkBooleanRadioBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // two radio buttons + XPropertySet primaryRadio = createRadio( 28, "radio button no. 1", "radio group", "primary" ); + XPropertySet secondaryRadio = createRadio( 33, "radio button no. 2", "radio group", "secodary" ); + + // bind them + short col = (short)0; + short row1 = (short)6; + short row2 = (short)7; + bindToCell( primaryRadio, col, row1 ); + bindToCell( secondaryRadio, col, row2 ); + + // check the first button + simulateUserRadioCheck( primaryRadio ); + // check the cell content + verifyNumericCellContent( col, row1, 1, "Radio buttons do not forward their (boolean) values to cells (1)." ); + verifyNumericCellContent( col, row2, 0, "Radio buttons do not forward their (boolean) values to cells (2)." ); + // check the second button + simulateUserRadioCheck( secondaryRadio ); + // check the cell content + verifyNumericCellContent( col, row1, 0, "Radio buttons do not forward their (boolean) values to cells (3)." ); + verifyNumericCellContent( col, row2, 1, "Radio buttons do not forward their (boolean) values to cells (4)." ); + + // the other way round: writing values into the cell + setCellValue( col, row1, 1.0 ); + // setting this should have checked the primary radio, which should have unchecked the secondary radio, + // which should have been propagated to the second cell + verifyNumericCellContent( col, row2, 0, "Changing primary cell is not propagated to the secondary cell (via the radio buttons)." ); + + // setting an empty cell should result in the radio being unchecked + setCellEmpty( col, row1 ); + if ( ((Short)primaryRadio.getPropertyValue( "State" )).shortValue() != 0 ) + failed( "Setting a cell to 'empty' does not reset the bound radio button." ); + } + + /* ------------------------------------------------------------------ */ + public void checkStringRadioBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // two radio buttons + XPropertySet primaryRadio = createRadio( 46, "radio button A", "radio ref group", "primary" ); + XPropertySet secondaryRadio = createRadio( 51, "radio button B", "radio ref group", "secodary" ); + + // give the ref values + String refValueA = new String( "ref value A" ); + String refValueB = new String( "ref value B" ); + primaryRadio.setPropertyValue( "RefValue", refValueA ); + secondaryRadio.setPropertyValue( "RefValue", refValueB ); + + // bind them to the same cell + short col = (short)0; + short row = (short)10; + bindToCell( primaryRadio, col, row ); + bindToCell( secondaryRadio, col, row ); + + // checking a radio should set the respective ref value at the cell + simulateUserRadioCheck( primaryRadio ); + verifyStringCellContent( col, row, refValueA, "A bound radio button with a reference value does not pass this value to the cell upon checking (1)." ); + simulateUserRadioCheck( secondaryRadio ); + verifyStringCellContent( col, row, refValueB, "A bound radio button with a reference value does not pass this value to the cell upon checking (2)." ); + + // changing the cell should check the buttons if the cell text equals the ref value + setCellText( col, row, "no ref value" ); + verifyRadioStates( primaryRadio, secondaryRadio, (short)0, (short)0, "Radio button not unchecked, though the bound cell value does not equal ref value." ); + + setCellText( col, row, refValueA ); + verifyRadioStates( primaryRadio, secondaryRadio, (short)1, (short)0, "Radio button not properly un/checked according to the cell and ref value (1)." ); + + setCellText( col, row, refValueB ); + verifyRadioStates( primaryRadio, secondaryRadio, (short)0, (short)1, "Radio button not properly un/checked according to the cell and ref value (2)." ); + } + + /* ------------------------------------------------------------------ */ + public void checkBooleanCheckBoxBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet checkBox = m_formLayer.createControlAndShape( "DatabaseCheckBox", 30, 59, 40, 4 ); + checkBox.setPropertyValue( "Label", "check box" ); + checkBox.setPropertyValue( "TriState", new Boolean( true ) ); + + short col = (short)0; + short row = (short)13; + bindToCell( checkBox, col, row ); + + // initialize with "not checked" + checkBox.setPropertyValue( "State", new Short( (short)0 ) ); + verifyNumericCellContent( col, row, 0, "programmatically unchecking the check box is not propagated to the cell." ); + + // first click: "not checked" -> "checked" + simulateUserCheckBoxCheck( checkBox, (short)1 ); + verifyNumericCellContent( col, row, 1, "moving the check box state to 'checked' is not propagated to the cell." ); + + // second click: "checked" -> "indetermined" + simulateUserCheckBoxCheck( checkBox, (short)2 ); + verifyVoidCell( col, row, "propagating the 'indetermined' state to the cell does not work." ); + + // third click: "indetermined" -> "not checked" + simulateUserCheckBoxCheck( checkBox, (short)0 ); + verifyNumericCellContent( col, row, 0, "unchecking a check box via UI is not propagated to the cell." ); + } + + /* ------------------------------------------------------------------ */ + public void checkStringCheckBoxBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + String refValue = new String( "checked " ); + + XPropertySet checkBox = m_formLayer.createControlAndShape( "DatabaseCheckBox", 30, 68, 40, 4 ); + checkBox.setPropertyValue( "Label", "check box with ref value" ); + checkBox.setPropertyValue( "TriState", new Boolean( true ) ); + checkBox.setPropertyValue( "RefValue", refValue ); + + short col = (short)0; + short row = (short)15; + bindToCell( checkBox, col, row ); + + // initialize with "not checked" + checkBox.setPropertyValue( "State", new Short( (short)0 ) ); + verifyNumericCellContent( col, row, 0, "programmatically unchecking the check box is not propagated to the cell." ); + + // first click: "not checked" -> "checked" + simulateUserCheckBoxCheck( checkBox, (short)1 ); + verifyStringCellContent( col, row, refValue, "moving the check box state to 'checked' does not propagated the ref value to the cell." ); + + // second click: "checked" -> "indetermined" + simulateUserCheckBoxCheck( checkBox, (short)2 ); + verifyVoidCell( col, row, "propagating the 'indetermined' state to the cell does not work, when exchanging ref values." ); + + // third click: "indetermined" -> "not checked" + simulateUserCheckBoxCheck( checkBox, (short)0 ); + verifyStringCellContent( col, row, "", "unchecking a check box via UI does not propagated the ref value to the cell." ); + } + + /* ------------------------------------------------------------------ */ + /** verifies that a list box, which is bound via an ordinary value binding, + * works as expected + */ + public void checkListBoxBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet listBox = m_formLayer.createControlAndShape( "DatabaseListBox", 30, 80, 40, 6 ); + listBox.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBox.setPropertyValue( "StringItemList", new String[] { "Apples", "Oranges", "Peaches" } ); + + short col = (short)0; + short row = (short)18; + + // ............................................................... + // add a list entry source which fills the list boxes list from cells in the + // spreadsheet + short sourceCol = (short)4; + setCellText( sourceCol, (short)( row - 1 ), "Apples" ); + setCellText( sourceCol, (short)( row + 0 ), "Oranges" ); + setCellText( sourceCol, (short)( row + 1 ), "Peaches" ); + + //setListSource( listBox, sourceCol, row, (short)( row + 2 ) ); + // TODO: this is currently prone to deadlocks + + // ............................................................... + // bind to a cell + bindToCell( listBox, col, row ); + + // ............................................................... + // do the tests + listBox.setPropertyValue( "SelectedItems", new short[] { (short)0 } ); + verifyStringCellContent( col, row, "Apples", "programmatically selecting a list entry is not propagated to the cell." ); + + simulateUserListBoxSelection( listBox, "Oranges" ); + verifyStringCellContent( col, row, "Oranges", "UI-selecting a list entry is not propagated to the cell." ); + + setCellText( col, row, "Peaches" ); + short[] selectedItems = (short[])listBox.getPropertyValue( "SelectedItems" ); + assureEquals( "changes in the cell bound to a list box are not propagated to the list box selection", + 2, selectedItems[0] ); + } + + /* ------------------------------------------------------------------ */ + /** verifies that a list box, which is bound via a value binding exchanging the <b>index</b> + * of the selected entry, works as expected + */ + public void checkListBoxIndexBinding() throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet listBox = m_formLayer.createControlAndShape( "DatabaseListBox", 30, 94, 40, 6 ); + listBox.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBox.setPropertyValue( "StringItemList", new String[] { "Pears", "Bananas", "Strawberries" } ); + + short col = (short)0; + short row = (short)21; + + // ............................................................... + // add a list entry source which fills the list boxes list from cells in the + // spreadsheet + short sourceCol = (short)4; + setCellText( sourceCol, (short)( row - 1 ), "Pears" ); + setCellText( sourceCol, (short)( row + 0 ), "Bananas" ); + setCellText( sourceCol, (short)( row + 1 ), "Strawberries" ); + + //setListSource( listBox, sourceCol, row, (short)( row + 2 ) ); + // TODO: this is currently prone to deadlocks + + // ............................................................... + // bind to a cell + bindToCell( listBox, col, row, "com.sun.star.table.ListPositionCellBinding" ); + + // ............................................................... + // do the tests + listBox.setPropertyValue( "SelectedItems", new short[] { (short)0 } ); + verifyNumericCellContent( col, row, 1, "programmatically selecting a list entry is not propagated (as index) to the cell." ); + + simulateUserListBoxSelection( listBox, "Bananas" ); + verifyNumericCellContent( col, row, 2, "UI-selecting a list entry is not propagated (as index) to the cell." ); + + setCellValue( col, row, 3 ); + short[] selectedItems = (short[])listBox.getPropertyValue( "SelectedItems" ); + assureEquals( "changes in the cell bound to a list box via list index are not propagated to the list box selection", + 2, selectedItems[0] ); + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private XPropertySet createRadio( int yPos, String label, String name, String tag ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet radio = m_formLayer.createControlAndShape( "DatabaseRadioButton", 30, yPos, 40, 4 ); + radio.setPropertyValue( "Label", label ); + radio.setPropertyValue( "Name", name ); + radio.setPropertyValue( "Tag", tag ); + return radio; + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of two radio button + */ + private boolean verifyRadioStates( XPropertySet radio1, XPropertySet radio2, short value1, short value2, + String errorMessage ) throws com.sun.star.uno.Exception, java.lang.Exception + { + if ( ( ((Short)radio1.getPropertyValue( "State" )).shortValue() != value1 ) + || ( ((Short)radio2.getPropertyValue( "State" )).shortValue() != value2 ) + ) + { + failed( errorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private boolean verifyVoidCell( short col, short row, String failErrorMessage ) throws com.sun.star.uno.Exception + { + XCellRangeData cell = (XCellRangeData)UnoRuntime.queryInterface( XCellRangeData.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + Object cellContent = cell.getDataArray()[0][0]; + if ( ((com.sun.star.uno.Any)cellContent).getType().getTypeClass() != com.sun.star.uno.TypeClass.VOID ) + { + failed( failErrorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private boolean verifyNumericCellContent( short col, short row, double value, String failErrorMessage ) throws com.sun.star.uno.Exception + { + XCell cell = (XCell)UnoRuntime.queryInterface( XCell.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + if ( cell.getValue() != value ) + { + failed( failErrorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private boolean verifyStringCellContent( short col, short row, String text, String failErrorMessage ) throws com.sun.star.uno.Exception + { + XTextRange cell = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + if ( !cell.getString().equals( text ) ) + { + failed( failErrorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** sets the text of a given cell to a given string + */ + private void setCellText( short col, short row, String text ) throws com.sun.star.uno.Exception + { + XTextRange cell = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + cell.setString( text ); + } + + /* ------------------------------------------------------------------ */ + /** sets a numeric value in a given cell + */ + private void setCellValue( short col, short row, double value ) throws com.sun.star.uno.Exception + { + XCell cell = (XCell)UnoRuntime.queryInterface( XCell.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + cell.setValue( value ); + } + + /* ------------------------------------------------------------------ */ + /** sets a numeric value in a given cell + */ + private void setCellEmpty( short col, short row ) throws com.sun.star.uno.Exception + { + // as long as #i29130# is not fixed, we do not set the cell to "empty", but to + // an invalid formular, which serves well for our purpose + XCellRangeFormula cell = (XCellRangeFormula)UnoRuntime.queryInterface( XCellRangeFormula.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + String[][] args = new String[][] { new String[] { "=INVALID_FUNCTION()" } }; + cell.setFormulaArray( args ); + } + + /* ------------------------------------------------------------------ */ + /** binds the given control model to the given cell in the first sheet, + * using the given service name for the binding + */ + private void bindToCell( XPropertySet controlModel, short column, short row, String _bindingServiceName ) throws com.sun.star.uno.Exception + { + XBindableValue bindableModel = (XBindableValue)UnoRuntime.queryInterface( XBindableValue.class, + controlModel + ); + + CellAddress address = new CellAddress(); + address.Column = column; + address.Row = row; + address.Sheet = 0; + + NamedValue[] parameters = new NamedValue[] { new NamedValue() }; + parameters[0].Name = "BoundCell"; + parameters[0].Value = address; + + XValueBinding cellBinding = (XValueBinding)UnoRuntime.queryInterface( XValueBinding.class, + m_document.createInstanceWithArguments( _bindingServiceName, parameters ) + ); + + bindableModel.setValueBinding( cellBinding ); + } + + /* ------------------------------------------------------------------ */ + /** binds the given control model to the given cell in the first sheet + */ + private void bindToCell( XPropertySet _controlModel, short _column, short _row ) throws com.sun.star.uno.Exception + { + bindToCell( _controlModel, _column, _row, "com.sun.star.table.CellValueBinding" ); + } + + /* ------------------------------------------------------------------ */ + /** sets the given cell range as list entry source for the given control + */ + private void setListSource( XPropertySet _listSink, short _sourceCol, short _rowStart, short _rowEnd ) throws com.sun.star.uno.Exception + { + CellRangeAddress listSourceAddress = new CellRangeAddress( (short)0, (int)_sourceCol, (int)_rowStart, (int)_sourceCol, (int)_rowEnd ); + NamedValue addressParameter = new NamedValue( "CellRange", listSourceAddress ); + + XListEntrySource listSource = (XListEntrySource)UnoRuntime.queryInterface( XListEntrySource.class, + m_document.createInstanceWithArguments( "com.sun.star.table.CellRangeListSource", new NamedValue[]{ addressParameter } ) + ); + XListEntrySink listSink = (XListEntrySink)UnoRuntime.queryInterface( XListEntrySink.class, + _listSink ); + listSink.setListEntrySource( listSource ); + } + + /* ------------------------------------------------------------------ */ + /** simulates a user action to check a radio button + */ + private void simulateUserRadioCheck( XPropertySet radioModel ) throws com.sun.star.uno.Exception + { + XAccessible accessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, m_document.getCurrentView().getControl( radioModel ) ); + + XAccessibleValue xValue = (XAccessibleValue)UnoRuntime.queryInterface( + XAccessibleValue.class, accessible.getAccessibleContext() ); + + Integer newValue = new Integer( 1 ); + xValue.setCurrentValue( newValue ); + } + + /* ------------------------------------------------------------------ */ + /** simulates a user action to check a radio button + */ + private void simulateUserCheckBoxCheck( XPropertySet checkBox, short state ) throws com.sun.star.uno.Exception + { + XAccessible accessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, m_document.getCurrentView().getControl( checkBox ) ); + + XAccessibleValue xValue = (XAccessibleValue)UnoRuntime.queryInterface( + XAccessibleValue.class, accessible.getAccessibleContext() ); + + xValue.setCurrentValue( new Short( state ) ); + } + + /* ------------------------------------------------------------------ */ + /** simulates a user selecting an entry in a list box + */ + private void simulateUserListBoxSelection( XPropertySet _listBox, String _selectEntry ) throws com.sun.star.uno.Exception + { + XListBox listBoxControl = (XListBox)UnoRuntime.queryInterface( + XListBox.class, m_document.getCurrentView().getControl( _listBox ) ); + listBoxControl.selectItem( _selectEntry, true ); + } + + /* ------------------------------------------------------------------ */ + /** simulates text input into the control belonging to the given model + */ + private void simulateUserTextInput( XPropertySet controlModel, String text ) throws com.sun.star.uno.Exception + { + XAccessible accessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, m_document.getCurrentView().getControl( controlModel ) ); + + XAccessibleContext context = accessible.getAccessibleContext(); + XServiceInfo si = (XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, + accessible.getAccessibleContext() ); + + XAccessibleEditableText textAccess = (XAccessibleEditableText)UnoRuntime.queryInterface( + XAccessibleEditableText.class, accessible.getAccessibleContext() ); + + textAccess.setText( text ); + } +} diff --git a/forms/qa/integration/forms/ControlValidation.java b/forms/qa/integration/forms/ControlValidation.java new file mode 100644 index 000000000000..c480ded16a4b --- /dev/null +++ b/forms/qa/integration/forms/ControlValidation.java @@ -0,0 +1,202 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.accessibility.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.form.binding.*; + +import integration.forms.DocumentHelper; +import integration.forms.NumericValidator; +import integration.forms.TextValidator; +import integration.forms.BooleanValidator; +import integration.forms.ListSelectionValidator; +import integration.forms.SingleControlValidation; + +/** + * + * @author fs@openoffice.org + */ +public class ControlValidation extends complexlib.ComplexTestCase implements com.sun.star.lang.XEventListener +{ + private DocumentHelper m_document; /// our current test document + private XMultiServiceFactory m_orb; /// our service factory + + /** Creates a new instance of ControlValidation */ + public ControlValidation() + { + } + + public String[] getTestMethodNames() + { + return new String[] { + "interactiveValidation" + }; + } + + public String getTestObjectName() + { + return "Form Control Validation Test"; + } + + public static boolean isInteractiveTest() + { + return true; + } + + /* ------------------------------------------------------------------ */ + /* test framework */ + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + private void prepareTestStep( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + m_document = DocumentHelper.blankTextDocument( m_orb ); + m_document.getDocument( ).addEventListener( this ); + } + + /* ------------------------------------------------------------------ */ + public void after() + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + private void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /* public test methods */ + /* ------------------------------------------------------------------ */ + public void interactiveValidation() throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep(); + + SingleControlValidation validation; + XPropertySet focusField; + + validation = new SingleControlValidation( m_document, 5, 5, "DatabaseFormattedField", new NumericValidator() ); + focusField = validation.getInputField(); + validation.setExplanatoryText( "Please enter a number between 0 and 100, with at most 1 decimal digit" ); + + validation = new SingleControlValidation( m_document, 90, 5, "DatabaseTextField", new TextValidator() ); + validation.setExplanatoryText( "Please enter a text whose length is a multiple of 3, and which does not contain the letter 'Z'" ); + + validation = new SingleControlValidation( m_document, 5, 55, "DatabaseDateField", new DateValidator() ); + validation.setExplanatoryText( "Please enter a date in the current month" ); + validation.getInputField().setPropertyValue( "Dropdown", new Boolean( true ) ); + + validation = new SingleControlValidation( m_document, 90, 55, "DatabaseTimeField", new TimeValidator() ); + validation.setExplanatoryText( "Please enter a time. Valid values are all full hours." ); + + validation = new SingleControlValidation( m_document, 5, 110, "DatabaseCheckBox", new BooleanValidator( false ) ); + validation.setExplanatoryText( "Please check (well, or uncheck) the box. Don't leave it in indetermined state." ); + validation.getInputField().setPropertyValue( "TriState", new Boolean( true ) ); + + validation = new SingleControlValidation( m_document, 90, 110, "DatabaseRadioButton", new BooleanValidator( true ), 3, 0 ); + validation.setExplanatoryText( "Please check any but the first button" ); + + validation = new SingleControlValidation( m_document, 5, 165, "DatabaseListBox", new ListSelectionValidator( ), 1, 24 ); + validation.setExplanatoryText( "Please select not more than two entries." ); + validation.getInputField().setPropertyValue( "MultiSelection", new Boolean( true ) ); + validation.getInputField().setPropertyValue( "StringItemList", new String[] { "first", "second", "third", "forth", "fivth" } ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + m_document.getCurrentView( ).grabControlFocus( focusField ); + + // wait for the user telling us to exit + waitForUserInput(); + } + + /* ------------------------------------------------------------------ */ + /* internal methods */ + /* ------------------------------------------------------------------ */ + /** waits for the user to press a key (on the console where she started the java program) + or the document to be closed by the user. + @return + <TRUE/> if the user pressed a key on the console, <FALSE/> if she closed the document + */ + protected boolean waitForUserInput() throws java.lang.Exception + { + synchronized (this) + { + integration.forms.WaitForInput aWait = new integration.forms.WaitForInput( this ); + aWait.start(); + wait(); + + // if the waiter thread is done, the user pressed enter + boolean bKeyPressed = aWait.isDone(); + if ( !bKeyPressed ) + aWait.interrupt(); + + return bKeyPressed; + } + } + + /* ------------------------------------------------------------------ */ + /* XEventListener overridables */ + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject eventObject ) + { + if ( m_document.getDocument().equals( eventObject.Source ) ) + { + // notify ourself that we can stop waiting for user input + synchronized (this) + { + notify(); + } + } + } + +} diff --git a/forms/qa/integration/forms/ControlValidator.java b/forms/qa/integration/forms/ControlValidator.java new file mode 100644 index 000000000000..969a9d2f46aa --- /dev/null +++ b/forms/qa/integration/forms/ControlValidator.java @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +/** base class for components validating the content of form controls + * + * @author fs@openoffice.org + */ +public abstract class ControlValidator implements com.sun.star.form.validation.XValidator +{ + + /** Creates a new instance of ControlValidator */ + public ControlValidator() + { + } + + public void addValidityConstraintListener(com.sun.star.form.validation.XValidityConstraintListener xValidityConstraintListener) + { + } + + public void removeValidityConstraintListener(com.sun.star.form.validation.XValidityConstraintListener xValidityConstraintListener) + { + } + + protected boolean isVoid( Object Value ) + { + try + { + return ( com.sun.star.uno.AnyConverter.getType(Value).getTypeClass() + == com.sun.star.uno.TypeClass.VOID ); + } + catch( java.lang.ClassCastException e ) + { + } + return false; + } +} diff --git a/forms/qa/integration/forms/DateValidator.java b/forms/qa/integration/forms/DateValidator.java new file mode 100644 index 000000000000..1ae2bbe48058 --- /dev/null +++ b/forms/qa/integration/forms/DateValidator.java @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class DateValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public DateValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return "empty input"; + + com.sun.star.util.Date dateValue = (com.sun.star.util.Date)Value; + if ( isDedicatedInvalidDate( dateValue ) ) + return "this is no valid date"; + + if ( !isNextMonthsDate( dateValue ) ) + return "date must denote a day in the current month"; + } + catch( java.lang.Exception e ) + { + return "oops. What did you enter for this to happen?"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return false; + + com.sun.star.util.Date dateValue = (com.sun.star.util.Date) + com.sun.star.uno.AnyConverter.toObject( + com.sun.star.util.Date.class, Value); + if ( isDedicatedInvalidDate( dateValue ) ) + return false; + + if ( !isNextMonthsDate( dateValue ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + e.printStackTrace( System.err ); + } + return false; + } + + private boolean isDedicatedInvalidDate( com.sun.star.util.Date dateValue ) + { + return ( dateValue.Day == 0 ) && ( dateValue.Month == 0 ) && ( dateValue.Year == 0 ); + } + + private boolean isNextMonthsDate( com.sun.star.util.Date dateValue ) + { + int overallMonth = dateValue.Year * 12 + dateValue.Month - 1; + + int todaysMonth = new java.util.Date().getMonth(); + int todaysYear = new java.util.Date().getYear() + 1900; + int todaysOverallMonth = todaysYear * 12 + todaysMonth; + + return overallMonth == todaysOverallMonth; + } +} diff --git a/forms/qa/integration/forms/DocumentHelper.java b/forms/qa/integration/forms/DocumentHelper.java new file mode 100644 index 000000000000..f24e090537af --- /dev/null +++ b/forms/qa/integration/forms/DocumentHelper.java @@ -0,0 +1,387 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XChild; +import com.sun.star.container.XIndexContainer; +import com.sun.star.container.XNameContainer; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XDrawPageSupplier; +import com.sun.star.drawing.XDrawPages; +import com.sun.star.drawing.XDrawPagesSupplier; +import com.sun.star.form.XFormsSupplier; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XController; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.util.XModifiable; + +/**************************************************************************/ + +/**************************************************************************/ +/** provides a small wrapper around a document +*/ +public class DocumentHelper +{ + private XMultiServiceFactory m_orb; + private XComponent m_documentComponent; + + /* ================================================================== */ + /* ------------------------------------------------------------------ */ + public DocumentHelper( XMultiServiceFactory orb, XComponent document ) + { + m_orb = orb; + m_documentComponent = document; + } + + /* ------------------------------------------------------------------ */ + protected static XComponent implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception + { + XComponentLoader aLoader = (XComponentLoader)UnoRuntime.queryInterface( + XComponentLoader.class, + orb.createInstance( "com.sun.star.frame.Desktop" ) + ); + + XComponent document = dbfTools.queryComponent( + aLoader.loadComponentFromURL( documentOrFactoryURL, "_blank", 0, new PropertyValue[ 0 ] ) + ); + return document; + } + + /* ------------------------------------------------------------------ */ + private static DocumentHelper implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception + { + XComponent document = implLoadAsComponent( orb, documentOrFactoryURL ); + + XServiceInfo xSI = (XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, + document ); + if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) ) + return new SpreadsheetDocument( orb, document ); + return new DocumentHelper( orb, document ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper loadDocument( XMultiServiceFactory orb, String documentURL ) throws com.sun.star.uno.Exception + { + return implLoadDocument( orb, documentURL ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper blankTextDocument( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception + { + return blankDocument( orb, DocumentType.WRITER ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper blankXMLForm( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception + { + return blankDocument( orb, DocumentType.XMLFORM ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper blankDocument( XMultiServiceFactory orb, DocumentType eType ) throws com.sun.star.uno.Exception + { + return implLoadDocument( orb, getDocumentFactoryURL( eType ) ); + } + + /* ================================================================== */ + /* ------------------------------------------------------------------ */ + public XComponent getDocument( ) + { + return m_documentComponent; + } + + /* ------------------------------------------------------------------ */ + public boolean isModified() + { + XModifiable modify = (XModifiable)query( XModifiable.class ); + return modify.isModified(); + } + + /* ------------------------------------------------------------------ */ + public Object query( Class aInterfaceClass ) + { + return UnoRuntime.queryInterface( aInterfaceClass, m_documentComponent ); + } + + /* ------------------------------------------------------------------ */ + public XMultiServiceFactory getOrb( ) + { + return m_orb; + } + + /* ------------------------------------------------------------------ */ + /** retrieves the current view of the document + @return + the view component, queried for the interface described by aInterfaceClass + */ + public DocumentViewHelper getCurrentView( ) + { + // get the model interface for the document + XModel xDocModel = (XModel)UnoRuntime.queryInterface(XModel.class, m_documentComponent ); + // get the current controller for the document - as a controller is tied to a view, + // this gives us the currently active view for the document. + XController xController = xDocModel.getCurrentController(); + + if ( classify() == DocumentType.CALC ) + return new SpreadsheetView( m_orb, this, xController ); + + return new DocumentViewHelper( m_orb, this, xController ); + } + + /* ------------------------------------------------------------------ */ + /** reloads the document + * + * The reload is done by dispatching the respective URL at a frame of the document. + * As a consequence, if you have references to a view of the document, or any interface + * of the document, they will become invalid. + * The Model instance itself, at which you called reload, will still be valid, it will + * automatically update its internal state after the reload. + * + * Another consequence is that if the document does not have a view at all, it cannot + * be reloaded. + */ + public void reload() throws Exception + { + DocumentViewHelper view = getCurrentView(); + XFrame frame = view.getController().getFrame(); + XModel oldModel = frame.getController().getModel(); + + getCurrentView().dispatch( ".uno:Reload" ); + + m_documentComponent = (XComponent)UnoRuntime.queryInterface( XComponent.class, + frame.getController().getModel() ); + + XModel newModel = getCurrentView().getController().getModel(); + if ( UnoRuntime.areSame( oldModel, newModel ) ) + throw new java.lang.IllegalStateException( "reload failed" ); + } + + /* ------------------------------------------------------------------ */ + /** creates a new form which is a child of the given form components container + + @param xParentContainer + The parent container for the new form + @param sInitialName + The initial name of the form. May be null, in this case the default (which + is an implementation detail) applies. + */ + protected XIndexContainer createSubForm( XIndexContainer xParentContainer, String sInitialName ) + throws com.sun.star.uno.Exception + { + // create a new form + Object xNewForm = m_orb.createInstance( "com.sun.star.form.component.DataForm" ); + + // insert + xParentContainer.insertByIndex( xParentContainer.getCount(), xNewForm ); + + // set the name if necessary + if ( null != sInitialName ) + { + XPropertySet xFormProps = dbfTools.queryPropertySet( xNewForm ); + xFormProps.setPropertyValue( "Name", sInitialName ); + } + + // outta here + return (XIndexContainer)UnoRuntime.queryInterface( XIndexContainer.class, xNewForm ); + } + + /* ------------------------------------------------------------------ */ + /** creates a new form which is a child of the given form components container + + @param aParentContainer + The parent container for the new form + @param sInitialName + The initial name of the form. May be null, in this case the default (which + is an implementation detail) applies. + */ + public XIndexContainer createSubForm( Object aParentContainer, String sInitialName ) + throws com.sun.star.uno.Exception + { + XIndexContainer xParentContainer = (XIndexContainer)UnoRuntime.queryInterface( + XIndexContainer.class, aParentContainer ); + return createSubForm( xParentContainer, sInitialName ); + } + + /* ------------------------------------------------------------------ */ + /** creates a form which is a sibling of the given form + @param aForm + A sinbling of the to be created form. + + @param sInitialName + The initial name of the form. May be null, in this case the default (which + is an implementation detail) applies. + */ + public XIndexContainer createSiblingForm( Object aForm, String sInitialName ) throws com.sun.star.uno.Exception + { + // get the parent + XIndexContainer xContainer = (XIndexContainer)dbfTools.getParent( + aForm, XIndexContainer.class ); + // append a new form to this parent container + return createSubForm( xContainer, sInitialName ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the document model which a given form component belongs to + */ + static public DocumentHelper getDocumentForComponent( Object aFormComponent, XMultiServiceFactory orb ) + { + XChild xChild = (XChild)UnoRuntime.queryInterface( XChild.class, aFormComponent ); + XModel xModel = null; + while ( ( null != xChild ) && ( null == xModel ) ) + { + XInterface xParent = (XInterface)xChild.getParent(); + xModel = (XModel)UnoRuntime.queryInterface( XModel.class, xParent ); + xChild = (XChild)UnoRuntime.queryInterface( XChild.class, xParent ); + } + + return new DocumentHelper( orb, xModel ); + } + + /* ------------------------------------------------------------------ */ + /** returns a URL which can be used to create a document of a certain type + */ + public static String getDocumentFactoryURL( DocumentType eType ) + { + if ( eType == DocumentType.WRITER ) + return "private:factory/swriter"; + if ( eType == DocumentType.CALC ) + return "private:factory/scalc"; + if ( eType == DocumentType.DRAWING ) + return "private:factory/sdraw"; + if ( eType == DocumentType.XMLFORM ) + return "private:factory/swriter?slot=21053"; + return "private:factory/swriter"; + } + + /* ------------------------------------------------------------------ */ + /** classifies a document + */ + public DocumentType classify( ) + { + XServiceInfo xSI = (XServiceInfo)UnoRuntime.queryInterface( + XServiceInfo.class, m_documentComponent ); + + if ( xSI.supportsService( "com.sun.star.text.TextDocument" ) ) + return DocumentType.WRITER; + else if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) ) + return DocumentType.CALC; + else if ( xSI.supportsService( "com.sun.star.drawing.DrawingDocument" ) ) + return DocumentType.DRAWING; + + return DocumentType.UNKNOWN; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a com.sun.star.drawing.DrawPage of the document, denoted by index + * @param index + * the index of the draw page + * @throws + * com.sun.star.lang.IndexOutOfBoundsException + * com.sun.star.lang.WrappedTargetException + */ + protected XDrawPage getDrawPage( int index ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + XDrawPagesSupplier xSuppPages = (XDrawPagesSupplier)UnoRuntime.queryInterface( + XDrawPagesSupplier.class, getDocument() ); + XDrawPages xPages = xSuppPages.getDrawPages(); + + return (XDrawPage)UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( index ) ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the <type scope="com.sun.star.drawing">DrawPage</type> of the document + */ + protected XDrawPage getMainDrawPage( ) throws com.sun.star.uno.Exception + { + XDrawPage xReturn; + + // in case of a Writer document, this is rather easy: simply ask the XDrawPageSupplier + XDrawPageSupplier xSuppPage = (XDrawPageSupplier)UnoRuntime.queryInterface( + XDrawPageSupplier.class, getDocument() ); + if ( null != xSuppPage ) + xReturn = xSuppPage.getDrawPage(); + else + { // the model itself is no draw page supplier - okay, it may be a Writer or Calc document + // (or any other multi-page document) + XDrawPagesSupplier xSuppPages = (XDrawPagesSupplier)UnoRuntime.queryInterface( + XDrawPagesSupplier.class, getDocument() ); + XDrawPages xPages = xSuppPages.getDrawPages(); + + xReturn = (XDrawPage)UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( 0 ) ); + + // Note that this is no really error-proof code: If the document model does not support the + // XDrawPagesSupplier interface, or if the pages collection returned is empty, this will break. + } + + return xReturn; + } + + /* ------------------------------------------------------------------ */ + /** retrieves the root of the hierarchy of form components + */ + protected XNameContainer getFormComponentTreeRoot( ) throws com.sun.star.uno.Exception + { + XFormsSupplier xSuppForms = (XFormsSupplier)UnoRuntime.queryInterface( + XFormsSupplier.class, getMainDrawPage( ) ); + + XNameContainer xFormsCollection = null; + if ( null != xSuppForms ) + { + xFormsCollection = xSuppForms.getForms(); + } + return xFormsCollection; + } + + /* ------------------------------------------------------------------ */ + /** creates a component at the service factory provided by the document + */ + public XInterface createInstance( String serviceSpecifier ) throws com.sun.star.uno.Exception + { + XMultiServiceFactory xORB = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class, + m_documentComponent ); + return (XInterface)xORB.createInstance( serviceSpecifier ); + } + + /* ------------------------------------------------------------------ */ + /** creates a component at the service factory provided by the document + */ + public XInterface createInstanceWithArguments( String serviceSpecifier, Object[] arguments ) throws com.sun.star.uno.Exception + { + XMultiServiceFactory xORB = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class, + m_documentComponent ); + return (XInterface) xORB.createInstanceWithArguments( serviceSpecifier, arguments ); + } +}; + diff --git a/forms/qa/integration/forms/DocumentType.java b/forms/qa/integration/forms/DocumentType.java new file mode 100644 index 000000000000..cc52e6a1aabc --- /dev/null +++ b/forms/qa/integration/forms/DocumentType.java @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +/** a helper "enumeration class" for classifying a document type +*/ +public class DocumentType extends com.sun.star.uno.Enum +{ + private DocumentType( int value ) + { + super( value ); + } + + public static DocumentType getDefault() + { + return WRITER; + } + + public static final DocumentType WRITER = new DocumentType(0); + public static final DocumentType CALC = new DocumentType(1); + public static final DocumentType DRAWING = new DocumentType(2); + public static final DocumentType XMLFORM = new DocumentType(3); + public static final DocumentType UNKNOWN = new DocumentType(-1); + + public static DocumentType fromInt(int value) + { + switch(value) + { + case 0: return WRITER; + case 1: return CALC; + case 2: return DRAWING; + case 3: return XMLFORM; + default: return UNKNOWN; + } + } +}; + diff --git a/forms/qa/integration/forms/DocumentViewHelper.java b/forms/qa/integration/forms/DocumentViewHelper.java new file mode 100644 index 000000000000..afd89841a8d2 --- /dev/null +++ b/forms/qa/integration/forms/DocumentViewHelper.java @@ -0,0 +1,257 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +/**************************************************************************/ + +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XWindow; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XIndexContainer; +import com.sun.star.form.FormComponentType; +import com.sun.star.form.XForm; +import com.sun.star.form.runtime.XFormController; +import com.sun.star.frame.XController; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.URL; +import com.sun.star.util.XURLTransformer; +import com.sun.star.view.XControlAccess; +import com.sun.star.view.XFormLayerAccess; +import org.openoffice.xforms.XMLDocument; + +/**************************************************************************/ +/** provides a small wrapper around a document view +*/ +public class DocumentViewHelper +{ + private XMultiServiceFactory m_orb; + private XController m_controller; + private DocumentHelper m_document; + + /* ------------------------------------------------------------------ */ + final protected XController getController() + { + return m_controller; + } + + /* ------------------------------------------------------------------ */ + final protected DocumentHelper getDocument() + { + return m_document; + } + + /* ------------------------------------------------------------------ */ + public DocumentViewHelper( XMultiServiceFactory orb, DocumentHelper document, XController controller ) + { + m_orb = orb; + m_document = document; + m_controller = controller; + } + + /* ------------------------------------------------------------------ */ + /** Quick access to a given interface of the view + @param aInterfaceClass + the class of the interface which shall be returned + */ + public Object query( Class aInterfaceClass ) + { + return UnoRuntime.queryInterface( aInterfaceClass, m_controller ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves a dispatcher for the given URL, obtained at the current view of the document + @param aURL + a one-element array. The first element must contain a valid + <member scope="com.sun.star.util">URL::Complete</member> value. Upon return, the URL is correctly + parsed. + @return + the dispatcher for the URL in question + */ + public XDispatch getDispatcher( URL[] aURL ) throws java.lang.Exception + { + XDispatch xReturn = null; + + // go get the current view + XController xController = (XController)query( XController.class ); + // go get the dispatch provider of it's frame + XDispatchProvider xProvider = (XDispatchProvider)UnoRuntime.queryInterface( + XDispatchProvider.class, xController.getFrame() ); + if ( null != xProvider ) + { + // need an URLTransformer + XURLTransformer xTransformer = (XURLTransformer)UnoRuntime.queryInterface( + XURLTransformer.class, m_orb.createInstance( "com.sun.star.util.URLTransformer" ) ); + xTransformer.parseStrict( aURL ); + + xReturn = xProvider.queryDispatch( aURL[0], new String( ), 0 ); + } + return xReturn; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a dispatcher for the given URL, obtained at the current view of the document + */ + public XDispatch getDispatcher( String url ) throws java.lang.Exception + { + URL[] aURL = new URL[] { new URL() }; + aURL[0].Complete = url; + return getDispatcher( aURL ); + } + + /* ------------------------------------------------------------------ */ + /** dispatches the given URL into the view, if there's a dispatcher for it + + @return + <TRUE/> if the URL was successfully dispatched + */ + public boolean dispatch( String url ) throws java.lang.Exception + { + URL[] completeURL = new URL[] { new URL() }; + completeURL[0].Complete = url; + XDispatch dispatcher = getDispatcher( completeURL ); + if ( dispatcher == null ) + return false; + + PropertyValue[] aDummyArgs = new PropertyValue[] { }; + dispatcher.dispatch( completeURL[0], aDummyArgs ); + return true; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a control within the current view of a document + @param xModel + specifies the control model whose control should be located + @return + the control tied to the model + */ + public XControl getControl( XControlModel xModel ) throws com.sun.star.uno.Exception + { + // the current view of the document + XControlAccess xCtrlAcc = (XControlAccess)query( XControlAccess.class ); + // delegate the task of looking for the control + return xCtrlAcc.getControl( xModel ); + } + + /* ------------------------------------------------------------------ */ + public XControl getControl( Object aModel ) throws com.sun.star.uno.Exception + { + XControlModel xModel = (XControlModel)UnoRuntime.queryInterface( XControlModel.class, aModel ); + return getControl( xModel ); + } + + /* ------------------------------------------------------------------ */ + public Object getControl( Object aModel, Class aInterfaceClass ) throws com.sun.star.uno.Exception + { + XControlModel xModel = (XControlModel)UnoRuntime.queryInterface( XControlModel.class, aModel ); + return UnoRuntime.queryInterface( aInterfaceClass, getControl( xModel ) ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the form controller for a given logical form + */ + public XFormController getFormController( XForm _form ) + { + XFormLayerAccess formLayerAccess = (XFormLayerAccess)query( XFormLayerAccess.class ); + return formLayerAccess.getFormController( _form ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the form controller for a given logical form + */ + public XFormController getFormController( Object _form ) + { + return getFormController( UnoRuntime.queryInterface( XForm.class, _form )); + } + + /* ------------------------------------------------------------------ */ + /** toggles the design mode of the form layer of active view of our sample document + */ + protected void toggleFormDesignMode( ) throws java.lang.Exception + { + if ( m_document instanceof XMLDocument ) + dispatch( ".uno:SwitchXFormsDesignMode" ); + else + dispatch( ".uno:SwitchControlDesignMode" ); + } + + /* ------------------------------------------------------------------ */ + /** sets the focus to a specific control + @param xModel + a control model. The focus is set to that control which is part of our view + and associated with the given model. + */ + public void grabControlFocus( Object xModel ) throws com.sun.star.uno.Exception + { + // look for the control from the current view which belongs to the model + XControl xControl = getControl( xModel ); + + // the focus can be set to an XWindow only + XWindow xControlWindow = (XWindow)UnoRuntime.queryInterface( XWindow.class, + xControl ); + + // grab the focus + xControlWindow.setFocus(); + } + + /* ------------------------------------------------------------------ */ + /** sets the focus to the first control + */ + protected void grabControlFocus( ) throws java.lang.Exception + { + // the forms container of our document + XIndexContainer xForms = dbfTools.queryIndexContainer( m_document.getFormComponentTreeRoot( ) ); + // the first form + XIndexContainer xForm = dbfTools.queryIndexContainer( xForms.getByIndex( 0 ) ); + + // the first control model which is no FixedText (FixedText's can't have the focus) + for ( int i = 0; i<xForm.getCount(); ++i ) + { + XPropertySet xControlProps = dbfTools.queryPropertySet( xForm.getByIndex( i ) ); + if ( FormComponentType.FIXEDTEXT != ((Short)xControlProps.getPropertyValue( "ClassId" )).shortValue() ) + { + XControlModel xControlModel = (XControlModel)UnoRuntime.queryInterface( + XControlModel.class, xControlProps ); + // set the focus to this control + grabControlFocus( xControlModel ); + // outta here + break; + } + } + + // Note that we simply took the first control model from the hierarchy. This does state nothing + // about the location of the respective control in the view. A control model is tied to a control + // shape, and the shapes are where the geometry information such as position and size is hung up. + // So you could easily have a document where the first control model is bound to a shape which + // has a greater ordinate than any other control model. + } +}; + diff --git a/forms/qa/integration/forms/FormComponent.java b/forms/qa/integration/forms/FormComponent.java new file mode 100644 index 000000000000..6e6676fff94f --- /dev/null +++ b/forms/qa/integration/forms/FormComponent.java @@ -0,0 +1,197 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.form.XFormsSupplier; +import com.sun.star.container.XNameAccess; +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XChild; +import com.sun.star.container.XNamed; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.lang.XServiceInfo; + +public class FormComponent +{ + private Object m_component; + private XNameAccess m_nameAccess; + private XIndexAccess m_indexAccess; + private XChild m_child; + private XNamed m_named; + + /* ------------------------------------------------------------------ */ + private FormComponent() + { + m_component = null; + m_nameAccess = null; + m_indexAccess = null; + m_child = null; + m_named = null; + } + + /* ------------------------------------------------------------------ */ + public FormComponent( XDrawPage drawPage ) + { + XFormsSupplier supp = (XFormsSupplier)UnoRuntime.queryInterface( + XFormsSupplier.class, drawPage ); + m_component = supp.getForms(); + + m_nameAccess = (XNameAccess)m_component; + m_indexAccess = (XIndexAccess)UnoRuntime.queryInterface( + XIndexAccess.class, m_component ); + m_child = (XChild)UnoRuntime.queryInterface( + XChild.class, m_component ); + m_named = (XNamed)UnoRuntime.queryInterface( + XNamed.class, m_component ); + } + + /* ------------------------------------------------------------------ */ + public FormComponent( Object element ) + { + m_component = element; + m_nameAccess = (XNameAccess)UnoRuntime.queryInterface( + XNameAccess.class, m_component ); + m_indexAccess = (XIndexAccess)UnoRuntime.queryInterface( + XIndexAccess.class, m_component ); + m_child = (XChild)UnoRuntime.queryInterface( + XChild.class, m_component ); + m_named = (XNamed)UnoRuntime.queryInterface( + XNamed.class, m_component ); + } + + /* ------------------------------------------------------------------ */ + /** Quick access to a given interface of the view + @param aInterfaceClass + the class of the interface which shall be returned + */ + public Object query( Class aInterfaceClass ) + { + return UnoRuntime.queryInterface( aInterfaceClass, m_component ); + } + + /* ------------------------------------------------------------------ */ + public FormComponent getByName( String name ) + { + try + { + if ( m_nameAccess != null ) + return new FormComponent( m_nameAccess.getByName( name ) ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return new FormComponent(); + } + + /* ------------------------------------------------------------------ */ + public String[] getElementNames() + { + if ( m_nameAccess != null ) + return m_nameAccess.getElementNames(); + return new String[]{}; + } + + /* ------------------------------------------------------------------ */ + public boolean hasByName( String name ) + { + if ( m_nameAccess != null ) + return m_nameAccess.hasByName( name ); + return false; + } + + /* ------------------------------------------------------------------ */ + public int getCount() + { + if ( m_indexAccess != null ) + return m_indexAccess.getCount(); + return 0; + } + + /* ------------------------------------------------------------------ */ + public FormComponent getByIndex( int index ) + { + try + { + if ( m_indexAccess != null ) + return new FormComponent( m_indexAccess.getByIndex( index ) ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return new FormComponent(); + } + + /* ------------------------------------------------------------------ */ + public com.sun.star.uno.Type getElementType( ) + { + if ( m_indexAccess != null ) + return m_indexAccess.getElementType(); + else if ( m_nameAccess != null ) + return m_nameAccess.getElementType(); + return new com.sun.star.uno.Type( String.class ); + } + + /* ------------------------------------------------------------------ */ + public boolean hasElements() + { + if ( m_indexAccess != null ) + return m_indexAccess.hasElements(); + else if ( m_nameAccess != null ) + return m_nameAccess.hasElements(); + return false; + } + + /* ------------------------------------------------------------------ */ + public FormComponent getParent() + { + if ( m_child != null ) + return new FormComponent( m_child.getParent() ); + return new FormComponent(); + } + + /* ------------------------------------------------------------------ */ + public String getName() + { + if ( m_named != null ) + return m_named.getName(); + return ""; + } + + /* ------------------------------------------------------------------ */ + public String getImplementationName() + { + XServiceInfo si = (XServiceInfo)UnoRuntime.queryInterface( + XServiceInfo.class, m_component ); + if ( si != null ) + return si.getImplementationName(); + return ""; + } +} diff --git a/forms/qa/integration/forms/FormControlTest.java b/forms/qa/integration/forms/FormControlTest.java new file mode 100644 index 000000000000..7fdf68dea796 --- /dev/null +++ b/forms/qa/integration/forms/FormControlTest.java @@ -0,0 +1,952 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.awt.XImageProducer; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNameAccess; +import com.sun.star.form.runtime.XFormController; +import com.sun.star.form.XImageProducerSupplier; +import com.sun.star.frame.XDispatch; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.sdb.CommandType; +import com.sun.star.sdb.SQLErrorEvent; +import com.sun.star.sdb.XSQLErrorBroadcaster; +import com.sun.star.sdb.XSQLErrorListener; +import com.sun.star.sdbc.XConnection; +import com.sun.star.sdbc.XDataSource; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.sdbc.XResultSetUpdate; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XNamingService; +import com.sun.star.util.URL; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XURLTransformer; +import connectivity.tools.HsqlDatabase; +import connectivity.tools.sdb.Connection; +import java.io.FileOutputStream; + + +public class FormControlTest extends complexlib.ComplexTestCase implements XSQLErrorListener +{ + private static String s_tableName = "CTC_form_controls"; + + private HsqlDatabase m_databaseDocument; + private XDataSource m_dataSource; + private XPropertySet m_dataSourceProps; + private XMultiServiceFactory m_orb; + private DocumentHelper m_document; + private FormLayer m_formLayer; + private XPropertySet m_masterForm; + private XFormController m_masterFormController; + private String m_sImageURL; + private SQLErrorEvent m_mostRecentErrorEvent; + + private final String m_dataSourceName = "integration.forms.FormControlTest"; + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkFirstRow", + "checkInsertRow", + "checkImageControl", + "checkCrossUpdates_checkBox", + "checkCrossUpdates_radioButton", + "checkRowUpdates", + "checkEmptyIsNull" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Database Form Controls Test"; + } + + /* ------------------------------------------------------------------ */ + /// pre-test initialization + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + // ensure that we have a data source to work with, and the required tables + if ( !ensureDataSource() || !ensureTables() ) + { + failed( "could not access the required data source or table therein." ); + return; + } + + // create the document which we work on + createSampleDocument(); + + createImageFile(); + } + + /* ------------------------------------------------------------------ */ + public void checkFirstRow() throws com.sun.star.uno.Exception, java.lang.Exception + { + moveToFirst(); + + // and check the content of the various controls + if ( !checkRadios( (short)1, (short)0, (short)0 ) + || !checkDoubleValue( 1, "ID", "Value" ) + || !checkDoubleValue( 42, "f_integer", "EffectiveValue" ) + || !checkStringValue( "the answer", "f_text", "Text" ) + || !checkDoubleValue( 0.12, "f_decimal", "Value" ) + || !checkIntValue ( 20030922, "f_date", "Date" ) + || !checkIntValue ( 15000000, "f_time", "Time" ) + || !checkIntValue ( 20030923, "f_timestamp_date", "Date" ) + || !checkIntValue ( 17152300, "f_timestamp_time", "Time" ) + || !checkShortValue ( (short)1, "f_tinyint", "State" ) + ) + { + failed( "checking the content of one or more controls on the first row failed (see the log for details)" ); + return; + } + } + + /* ------------------------------------------------------------------ */ + public void checkInsertRow() throws com.sun.star.uno.Exception, java.lang.Exception + { + // move the cursor to the insert row + moveToInsertRow(); + + // and check the content of the various controls + if ( !verifyCleanInsertRow() ) + { + failed( "checking the content of one or more controls on the insert row failed (see the log for details)" ); + return; + } + } + + /* ------------------------------------------------------------------ */ + /// some tests with the image control + public void checkImageControl() throws com.sun.star.uno.Exception, java.lang.Exception + { + // since we did not yet insert any image, the control should not display one ... + moveToFirst(); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image control failed to display empty image" ); + return; + } + + // check if the image control is able to insert our sample image into the database + // insert an + XPropertySet xImageModel = getControlModel( "f_blob" ); + xImageModel.setPropertyValue( "ImageURL", m_sImageURL ); + + if ( !verifyReferenceImage( getSamplePictureBytes() ) ) + { + failed( "image control does not display the sample image as required" ); + return; + } + + // save the record + saveRecordByUI(); + + // still needs to be the sample image + if ( !verifyReferenceImage( getSamplePictureBytes() ) ) + { + failed( "image control does not, after saving the record, display the sample image as required" ); + return; + } + + // on the next record, the image should be empty + moveToNext(); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image control failed to display empty image, after coming from a non-empty image" ); + return; + } + + // back to the record where we just inserted the image, it should be our sample image + moveToFirst(); + if ( !verifyReferenceImage( getSamplePictureBytes() ) ) + { + failed( "image control does not, after coming back to the record, display the sample image as required" ); + return; + } + + // okay, now remove the image + xImageModel.setPropertyValue( "ImageURL", new String() ); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image control failed to remove the image" ); + return; + } + nextRecordByUI(); + previousRecordByUI(); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image still there after coming back, though we just removed it" ); + return; + } + } + + /* ------------------------------------------------------------------ */ + /** This is both a test for controls which are bound to the same column (they must reflect + * each others updates), and for the immediate updates which need to happen for both check + * boxes and radio buttons: They must commit their content to the underlying column as soon + * as the change is made, *not* only upon explicit commit + */ + public void checkCrossUpdates_checkBox() throws com.sun.star.uno.Exception, java.lang.Exception + { + // move to the first record + moveToFirst(); + if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) + || !checkDoubleValue( 1, "f_tinyint_format", "EffectiveValue" ) + ) + { + failed( "huh? inconsistence in the test!" ); + // we created the sample data in a way that the f_tinyint field should contain a "1" at the first + // record. We already asserted the proper function of the check box in checkFirstRow, so if this + // fails here, the script became inconsistent + return; + } + + XPropertySet checkModel = getControlModel( "f_tinyint" ); + checkModel.setPropertyValue( "State", new Short( (short)0 ) ); + + // setting the state of the check box needs to be reflected in the formatted field immediately + if ( !checkDoubleValue( 0, "f_tinyint_format", "EffectiveValue" ) ) + { + failed( "cross-update failed: updating the check box should result in updating the same-bound formatted field (1)!" ); + return; + } + + // same for the "indetermined" state of the check box + checkModel.setPropertyValue( "State", new Short( (short)2 ) ); + if ( !checkNullValue( "f_tinyint_format", "EffectiveValue" ) ) + { + failed( "cross-update failed: updating the check box should result in updating the same-bound formatted field (2)!" ); + return; + } + + // undo the changes done so far + undoRecordByUI(); + // and see if this is properly reflected in the controls + if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) + || !checkDoubleValue( 1, "f_tinyint_format", "EffectiveValue" ) + ) + { + failed( "either the check box or the formatted field failed to recognize the UNDO!" ); + return; + } + + // the other way round - when changing the formatted field - the change should *not* + // be reflected to the check box, since the formatted field needs an explicit commit + XPropertySet tinyFormattedModel = getControlModel( "f_tinyint_format" ); + m_document.getCurrentView().grabControlFocus( tinyFormattedModel ); + m_formLayer.userTextInput( tinyFormattedModel, "0" ); + if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) + ) + { + failed( "the check box should not be updated here! (did the formatted model commit immediately?)" ); + return; + } + + // set the focus to *any* other control (since we just have it at hand, we use the check box control) + // this should result in the formatted control being committed, and thus in the check box updating + m_document.getCurrentView().grabControlFocus( checkModel ); + if ( !checkShortValue ( (short)0, "f_tinyint", "State" ) + ) + { + failed( "formatted field did not commit (or check box did not update)" ); + return; + } + + // undo the changes done so far, so we leave the document in a clean state for the next test + undoRecordByUI(); + } + + /* ------------------------------------------------------------------ */ + /** very similar to checkCrossUpdates_checkBox - does nearly the same for the radio buttons. See there for more + * explanations. + */ + public void checkCrossUpdates_radioButton() throws com.sun.star.uno.Exception, java.lang.Exception + { + // move to the first record + moveToFirst(); + if ( !checkRadios( (short)1, (short)0, (short)0 ) + || !checkStringValue( "none", "f_text_enum_text", "Text" ) + ) + { + failed( "huh? inconsistence in the test!" ); + return; + } + + XPropertySet radioModel = getRadioModel( "radio_group", "normal" ); + radioModel.setPropertyValue( "State", new Short( (short)1 ) ); + + // setting the state of the radio button needs to be reflected in the formatted field immediately + if ( !checkStringValue( "normal", "f_text_enum_text", "Text" ) ) + { + failed( "cross-update failed: updating the radio button should result in updating the same-bound text field (1)!" ); + return; + } + + // same for the "indetermined" state of the check box + getRadioModel( "radio_group", "important" ).setPropertyValue( "State", new Short( (short)1 ) ); + if ( !checkStringValue( "important", "f_text_enum_text", "Text" ) ) + { + failed( "cross-update failed: updating the radio button should result in updating the same-bound text field (2)!" ); + return; + } + + // undo the changes done so far + undoRecordByUI(); + // and see if this is properly reflected in the controls + if ( !checkRadios( (short)1, (short)0, (short)0 ) + || !checkStringValue( "none", "f_text_enum_text", "Text" ) + ) + { + failed( "either the radio button or the text field failed to recognize the UNDO!" ); + return; + } + + // the other way round - when changing the formatted field - the change should *not* + // be reflected to the check box, since the formatted field needs an explicit commit + XPropertySet textModel = getControlModel( "f_text_enum_text" ); + m_document.getCurrentView().grabControlFocus( textModel ); + m_formLayer.userTextInput( textModel, "normal" ); + if ( !checkRadios( (short)1, (short)0, (short)0 ) + ) + { + failed( "the radio buttons should not be updated here! (did the formatted model commit immediately?)" ); + return; + } + + // set the focus to *any* other control (since we just have it at hand, we use the check box control) + // this should result in the formatted control being committed, and thus in the check box updating + m_document.getCurrentView().grabControlFocus( radioModel ); + if ( !checkRadios( (short)0, (short)1, (short)0 ) + ) + { + failed( "text field did not commit (or radio button did not update)" ); + return; + } + + // undo the changes done so far, so we leave the document in a clean state for the next test + undoRecordByUI(); + } + + /* ------------------------------------------------------------------ */ + /** some tests with updating the table via our controls + */ + public void checkRowUpdates() throws com.sun.star.uno.Exception, java.lang.Exception + { + // start with inserting a new record + moveToInsertRow(); + assure( "insert row not in expected clean state", verifyCleanInsertRow() ); + + userTextInput( "ID", "3", true ); + userTextInput( "f_integer", "729", true ); + userTextInput( "f_text", "test", true ); + userTextInput( "f_decimal", "152343", true ); + userTextInput( "f_date", "31.12.1999", true ); + userTextInput( "f_time", "23:59:59", true ); + + // move to the next row, this should automatically commit the changes we made + nextRecordByUI(); + // and back to the row we just inserted + previousRecordByUI(); + + if ( !checkDoubleValue( 3, "ID", "Value" ) + || !checkDoubleValue( 729, "f_integer", "EffectiveValue" ) + || !checkStringValue( "test", "f_text", "Text" ) + || !checkDoubleValue( 152343, "f_decimal", "Value" ) + || !checkIntValue ( 19991231, "f_date", "Date" ) + || !checkIntValue ( 23595900, "f_time", "Time" ) + ) + { + failed( "the changes we made on the insert row have not been committed" ); + return; + } + + // now change the data, to see if regular updates work, too + userTextInput( "ID", "4", true ); + userTextInput( "f_integer", "618", true ); + userTextInput( "f_text", "yet another stupid, meaningless text", true ); + userTextInput( "f_required_text", "this must not be NULL", true ); + userTextInput( "f_decimal", "4562", true ); + userTextInput( "f_date", "26.03.2004", true ); + userTextInput( "f_time", "17:05:00", true ); + + // move to the next row, this should automatically commit the changes we made + nextRecordByUI(); + // and back to the row we just inserted + previousRecordByUI(); + + if ( !checkDoubleValue( 4, "ID", "Value" ) + || !checkDoubleValue( 618, "f_integer", "EffectiveValue" ) + || !checkStringValue( "yet another stupid, meaningless text", "f_text", "Text" ) + || !checkDoubleValue( 4562, "f_decimal", "Value" ) + || !checkIntValue ( 20040326, "f_date", "Date" ) + || !checkIntValue ( 17050000, "f_time", "Time" ) + ) + { + failed( "the changes we made on the insert row have not been committed" ); + return; + } + + m_document.getCurrentView().grabControlFocus( getControlModel( "ID" ) ); + } + + /* ------------------------------------------------------------------ */ + /** checks the "ConvertEmptyToNull" property behavior of an edit control + * + */ + public void checkEmptyIsNull() throws com.sun.star.uno.Exception, java.lang.Exception + { + // start with inserting a new record + moveToInsertRow(); + assure( "insert row not in expected clean state", verifyCleanInsertRow() ); + + // make an input in any field, but leave the edit control which is bound to a required field + // empty + userTextInput( "ID", "5", true ); + userTextInput( "f_text", "more text", true ); + + // this should *not* fail. Even if we did not input anything into the control bound to the + // f_required_text column, this control's reset (done when moving to the insertion row) is + // expected to write an empty string into its bound column, since its EmptyIsNULL property + // is set to FALSE + // (#i92471#) + m_mostRecentErrorEvent = null; + nextRecordByUI(); + assure( "updating an incomplete record did not work as expected", m_mostRecentErrorEvent == null ); + } + + /* ------------------------------------------------------------------ */ + private boolean verifyCleanInsertRow( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // and check the content of the various controls + return ( checkRadios( (short)0, (short)0, (short)0 ) + && checkShortValue( (short)2, "f_tinyint", "State" ) + && checkStringValue( "", "f_text", "Text" ) + && checkNullValue( "ID", "Value" ) + && checkNullValue( "f_integer", "EffectiveValue" ) + && checkNullValue( "f_decimal", "Value" ) + ); + } + + /* ------------------------------------------------------------------ */ + /// post-test cleanup + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + + //========================================================================= + /* ------------------------------------------------------------------ */ + private boolean ensureDataSource() throws Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + + XNameAccess databaseContext = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, + m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) ); + XNamingService namingService = (XNamingService)UnoRuntime.queryInterface( XNamingService.class, + databaseContext ); + + // revoke the data source, if it previously existed + if ( databaseContext.hasByName( m_dataSourceName ) ) + namingService.revokeObject( m_dataSourceName ); + + // // create a new ODB file, and register it with its URL + m_databaseDocument = new HsqlDatabase( m_orb ); + String documentURL = m_databaseDocument.getDocumentURL(); + namingService.registerObject( m_dataSourceName, databaseContext.getByName( documentURL ) ); + + m_dataSource = (XDataSource)UnoRuntime.queryInterface( XDataSource.class, + databaseContext.getByName( m_dataSourceName ) ); + m_dataSourceProps = dbfTools.queryPropertySet( m_dataSource ); + + XPropertySet dataSourceSettings = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + m_dataSourceProps.getPropertyValue( "Settings" ) ); + dataSourceSettings.setPropertyValue( "FormsCheckRequiredFields", new Boolean( false ) ); + + return m_dataSource != null; + } + + /* ------------------------------------------------------------------ */ + /** retrives the control model with the given name + */ + private XPropertySet getControlModel( String name ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XNameAccess nameAccess = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, + m_masterForm ); + return (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + nameAccess.getByName( name ) ); + } + + /* ------------------------------------------------------------------ */ + private void createSampleDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + + m_document = DocumentHelper.blankTextDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + + // insert some controls + XPropertySet xIDField = m_formLayer.insertControlLine( "DatabaseNumericField", "ID", "", 3 ); + m_formLayer.insertControlLine( "DatabaseFormattedField","f_integer", "", 11 ); + m_formLayer.insertControlLine( "DatabaseTextField", "f_text", "", 19 ); + XPropertySet xReqField = m_formLayer.insertControlLine( "DatabaseTextField", "f_required_text", "", 27 ); + m_formLayer.insertControlLine( "DatabaseNumericField", "f_decimal", "", 35 ); + m_formLayer.insertControlLine( "DatabaseDateField", "f_date", "", 43 ); + XPropertySet xTimeField = m_formLayer.insertControlLine( "DatabaseTimeField", "f_time", "", 51 ); + m_formLayer.insertControlLine( "DatabaseDateField", "f_timestamp", "_date", 59 ); + m_formLayer.insertControlLine( "DatabaseTimeField", "f_timestamp", "_time", 67 ); + XPropertySet xImageField = m_formLayer.insertControlLine( "DatabaseImageControl", "f_blob", "", 2, 75, 40 ); + m_formLayer.insertControlLine( "DatabaseTextField", "f_text_enum", "_text", 80, 25, 6 ); + XPropertySet xCheckBox = m_formLayer.insertControlLine( "DatabaseCheckBox", "f_tinyint", "", 80, 33, 6 ); + m_formLayer.insertControlLine( "DatabaseFormattedField","f_tinyint", "_format",80, 41, 6 ); + m_formLayer.insertControlLine( "DatabaseTextField", "dummy", "", 150 ); + + xIDField.setPropertyValue( "DecimalAccuracy", new Short( (short)0 ) ); + xImageField.setPropertyValue( "ScaleImage", new Boolean( true) ); + xImageField.setPropertyValue( "Tabstop", new Boolean( true ) ); + xCheckBox.setPropertyValue( "TriState", new Boolean( true ) ); + xCheckBox.setPropertyValue( "DefaultState", new Short( (short)2 ) ); + xTimeField.setPropertyValue( "TimeFormat", new Short( (short)1 ) ); + xTimeField.setPropertyValue( "TimeMax", new Integer( 23595999 ) ); + xReqField.setPropertyValue( "ConvertEmptyToNull", new Boolean( false ) ); + + // the logical form + m_masterForm = (XPropertySet)dbfTools.getParent( xIDField, XPropertySet.class ); + m_masterForm.setPropertyValue( "DataSourceName", m_dataSourceProps.getPropertyValue( "Name" ) ); + m_masterForm.setPropertyValue( "CommandType", new Integer( CommandType.TABLE ) ); + m_masterForm.setPropertyValue( "Command", s_tableName ); + + insertRadio( 3, "none", "none" ); + insertRadio( 10, "normal", "normal" ); + insertRadio( 17, "important", "important" ); + + // switch the forms into data entry mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + m_masterFormController = m_document.getCurrentView().getFormController( m_masterForm ); + XSQLErrorBroadcaster errorBroadcaster = (XSQLErrorBroadcaster)UnoRuntime.queryInterface( XSQLErrorBroadcaster.class, + m_masterFormController ); + errorBroadcaster.addSQLErrorListener( this ); + + // set the focus to the ID control + m_document.getCurrentView().grabControlFocus( xIDField ); + } + + /* ------------------------------------------------------------------ */ + private void insertRadio( int nYPos, String label, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet xRadio = m_formLayer.createControlAndShape( "DatabaseRadioButton", 106, nYPos, 25, 6 ); + xRadio.setPropertyValue( "Label", label ); + xRadio.setPropertyValue( "RefValue", refValue ); + xRadio.setPropertyValue( "Name", new String( "radio_group" ) ); + xRadio.setPropertyValue( "DataField", new String( "f_text_enum" ) ); + } + + /* ------------------------------------------------------------------ */ + private String getCreateTableStatement( ) + { + String sCreateTableStatement = "CREATE TABLE \"" + s_tableName + "\" ("; + sCreateTableStatement += "\"ID\" INTEGER NOT NULL PRIMARY KEY,"; + sCreateTableStatement += "\"f_integer\" INTEGER default NULL,"; + sCreateTableStatement += "\"f_text\" VARCHAR(50) default NULL,"; + sCreateTableStatement += "\"f_required_text\" VARCHAR(50) NOT NULL,"; + sCreateTableStatement += "\"f_decimal\" DECIMAL(10,2) default NULL,"; + sCreateTableStatement += "\"f_date\" DATE default NULL,"; + sCreateTableStatement += "\"f_time\" TIME default NULL,"; + sCreateTableStatement += "\"f_timestamp\" DATETIME default NULL,"; + sCreateTableStatement += "\"f_blob\" VARBINARY,"; + sCreateTableStatement += "\"f_text_enum\" VARCHAR(50) default NULL,"; + sCreateTableStatement += "\"f_tinyint\" TINYINT default NULL"; + sCreateTableStatement += ");"; + return sCreateTableStatement; + } + + /* ------------------------------------------------------------------ */ + private String[] getSampleDataValueString( ) throws java.lang.Exception + { + String[] aValues = new String[] { + "1,42,'the answer','foo',0.12,'2003-09-22','15:00:00','2003-09-23 17:15:23',NULL,'none',1", + "2,13,'the question','bar',12.43,'2003-09-24','16:18:00','2003-09-24 08:45:12',NULL,'none',0" + }; + return aValues; + } + + /* ------------------------------------------------------------------ */ + private boolean ensureTables() throws com.sun.star.uno.Exception, java.lang.Exception + { + Connection connection = new Connection( m_dataSource.getConnection( "", "" ) ); + assure( "could not connect to the data source", connection != null ); + + // drop the table, if it already exists + if ( !implExecuteStatement( "DROP TABLE \"" + s_tableName + "\" IF EXISTS" ) + || !implExecuteStatement( getCreateTableStatement() ) + ) + { + failed( "could not create the required sample table!" ); + return false; + } + + String sInsertionPrefix = "INSERT INTO \"" + s_tableName + "\" VALUES ("; + String[] aValues = getSampleDataValueString(); + for ( int i=0; i<aValues.length; ++i ) + if ( !implExecuteStatement( sInsertionPrefix + aValues[ i ] + ")" ) ) + { + failed( "could not create the required sample data" ); + return false; + } + + connection.refreshTables(); + + // do not need the connection anymore + connection.close(); + + return true; + } + + /* ------------------------------------------------------------------ */ + /// checks the 3 radio buttons for the given states + private boolean checkRadios( short stateNone, short stateNormal, short stateImportant ) throws com.sun.star.uno.Exception, java.lang.Exception + { + if ( ((Short)getRadioModel( "radio_group", "none" ).getPropertyValue( "State" )).shortValue() != stateNone ) + { + failed( "wrong value of the 'none' radio button!" ); + } + else if ( ((Short)getRadioModel( "radio_group", "normal" ).getPropertyValue( "State" )).shortValue() != stateNormal ) + { + failed( "wrong value of the 'normal' radio button!" ); + } + else if ( ((Short)getRadioModel( "radio_group", "important" ).getPropertyValue( "State" )).shortValue() != stateImportant ) + { + failed( "wrong value of the 'important' radio button!" ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkNullValue( String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + Object value = getControlModel( fieldName ).getPropertyValue( propertyName ); + if ( !util.utils.isVoid( value ) ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: <null/>" ); + log.println( " found : " + value.toString() ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkIntValue( int requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + try + { + if ( fieldName.equals( "f_time" ) ) + // http://bugs.mysql.com/bug.php?id=5681 + return true; + + int currentValue = ((Integer)getControlModel( fieldName ).getPropertyValue( propertyName )).intValue(); + if ( currentValue != requiredValue ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + String.valueOf( requiredValue ) ); + log.println( " found : " + String.valueOf( currentValue ) ); + } + else + return true; + } + catch( com.sun.star.uno.Exception e ) + { + log.println( "caught an exception while retrieving property value '" + propertyName + "' of control model '" + fieldName + "'" ); + throw e; + } + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkShortValue( short requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + try + { + short currentValue = ((Short)getControlModel( fieldName ).getPropertyValue( propertyName )).shortValue(); + if ( currentValue != requiredValue ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + String.valueOf( requiredValue ) ); + log.println( " found : " + String.valueOf( currentValue ) ); + } + else + return true; + } + catch( com.sun.star.uno.Exception e ) + { + log.println( "caught an exception while retrieving property value '" + propertyName + "' of control model '" + fieldName + "'" ); + throw e; + } + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkDoubleValue( double requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + double currentValue = ((Double)getControlModel( fieldName ).getPropertyValue( propertyName )).doubleValue(); + if ( currentValue != requiredValue ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + String.valueOf( requiredValue ) ); + log.println( " found : " + String.valueOf( currentValue ) ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkStringValue( String requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + String currentValue = (String)getControlModel( fieldName ).getPropertyValue( propertyName ); + if ( !currentValue.equals( requiredValue ) ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + requiredValue ); + log.println( " found : " + currentValue ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private XPropertySet getRadioModel( String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return m_formLayer.getRadioModelByRefValue( m_masterForm, name, refValue ); + } + + /* ------------------------------------------------------------------ */ + /** executes the given statement on the given connection + */ + protected boolean implExecuteStatement( String sStatement ) throws java.lang.Exception + { + try + { + m_databaseDocument.executeSQL( sStatement ); + } + catch(com.sun.star.sdbc.SQLException e) + { + System.err.println( e ); + return false; + } + + return true; + } + + /* ------------------------------------------------------------------ */ + /** simulates a user's text input into a control given by model name + */ + private void userTextInput( String modelName, String text, boolean withCommit ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet controlModel = getControlModel( modelName ); + // the form runtime environment (namely the form controller) rely on focus events for recognizing + // control content changes ... + if ( withCommit ) + m_document.getCurrentView().grabControlFocus( controlModel ); + + m_formLayer.userTextInput( controlModel, text ); + + // focus back to a dummy control model so the content of the model we just changed will + // be committed to the underlying database column + if ( withCommit ) + m_document.getCurrentView().grabControlFocus( getControlModel( "dummy" ) ); + } + + /* ------------------------------------------------------------------ */ + private void moveToInsertRow() throws com.sun.star.uno.Exception, java.lang.Exception + { + XResultSetUpdate xResultSet = (XResultSetUpdate)UnoRuntime.queryInterface( XResultSetUpdate.class, m_masterForm ); + xResultSet.moveToInsertRow( ); + } + + /* ------------------------------------------------------------------ */ + private void moveToFirst() throws com.sun.star.uno.Exception, java.lang.Exception + { + XResultSet xResultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); + xResultSet.first( ); + } + + /* ------------------------------------------------------------------ */ + private void moveToNext() throws com.sun.star.uno.Exception, java.lang.Exception + { + XResultSet xResultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); + xResultSet.next( ); + } + + /* ------------------------------------------------------------------ */ + /** simulates pressing a toolbox button with the given URL + */ + private void executeSlot( String slotURL ) throws java.lang.Exception + { + XDispatch xDispatch = m_document.getCurrentView().getDispatcher( slotURL ); + + URL[] url = new URL[] { new URL() }; + url[0].Complete = slotURL; + XURLTransformer xTransformer = (XURLTransformer)UnoRuntime.queryInterface( + XURLTransformer.class, m_orb.createInstance( "com.sun.star.util.URLTransformer" ) ); + xTransformer.parseStrict( url ); + + PropertyValue[] aArgs = new PropertyValue[0]; + xDispatch.dispatch( url[0], aArgs ); + } + + /* ------------------------------------------------------------------ */ + /** undos the changes on the current record, by simulating pressing of the respective toolbox button + */ + private void undoRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:RecUndo" ); + } + + /* ------------------------------------------------------------------ */ + /** saves the current record, by simulating pressing of the respective toolbox button + */ + private void saveRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:RecSave" ); + } + + /* ------------------------------------------------------------------ */ + /** moves to the next record, by simulating pressing of the respective toolbox button + */ + private void nextRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:NextRecord" ); + } + /* ------------------------------------------------------------------ */ + /** moves to the previous record, by simulating pressing of the respective toolbox button + */ + private void previousRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:PrevRecord" ); + } + + /* ------------------------------------------------------------------ */ + private void createImageFile() throws java.io.IOException + { + m_sImageURL = util.utils.getOfficeTempDir( m_orb ) + "image.gif"; + + FileOutputStream aFile = new FileOutputStream( m_sImageURL ); + aFile.write( getSamplePicture() ); + aFile.close(); + log.println( "created temporary image file: " + m_sImageURL ); + + // for later setting the url at the imaghe control, we need a real URL, no system path + m_sImageURL = util.utils.getOfficeTemp( m_orb ) + "image.gif"; + } + + /* ------------------------------------------------------------------ */ + private byte[] getSamplePicture() + { + byte[] aBytes = new byte[] { + (byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38, (byte)0x39, (byte)0x61, (byte)0x0A, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0xB3, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0x00, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x2C, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x20, (byte)0x10, (byte)0xC8, (byte)0x49, (byte)0x41, (byte)0xB9, (byte)0xF8, (byte)0xCA, + (byte)0x12, (byte)0xBA, (byte)0x2F, (byte)0x5B, (byte)0x30, (byte)0x8C, (byte)0x43, (byte)0x00, (byte)0x5A, (byte)0x22, (byte)0x41, (byte)0x94, (byte)0x27, (byte)0x37, (byte)0xA8, (byte)0x6C, + (byte)0x48, (byte)0xC6, (byte)0xA8, (byte)0xD7, (byte)0xB5, (byte)0x19, (byte)0x56, (byte)0xED, (byte)0x11, (byte)0x00, (byte)0x3B + }; + + return aBytes; + } + + /* ------------------------------------------------------------------ */ + private byte[] getSamplePictureBytes() + { + byte[] aBytes = new byte[] { + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, + (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, + (byte)0x01, (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, (byte)0x04, (byte)0x04, (byte)0x03, (byte)0x01, + (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, (byte)0x04, (byte)0x04, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, + (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, + (byte)0x00, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 + }; + return aBytes; + } + + /* ------------------------------------------------------------------ */ + private boolean verifyReferenceImage( byte[] referenceBytes ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet xImageModel = getControlModel( "f_blob" ); + + // check if the image control properly says that there currently is no image on the first record + XImageProducerSupplier xSuppProducer = (XImageProducerSupplier)UnoRuntime.queryInterface( XImageProducerSupplier.class, + xImageModel ); + XImageProducer xProducer = xSuppProducer.getImageProducer(); + + ImageComparison compareImages = new ImageComparison( referenceBytes, this ); + synchronized( this ) + { + xProducer.addConsumer( compareImages ); + xProducer.startProduction(); +// wait(); + } + xProducer.removeConsumer( compareImages ); + + return compareImages.imagesEqual( ); + } + + /* ------------------------------------------------------------------ */ + public void errorOccured( SQLErrorEvent _event ) + { + // just remember for the moment + m_mostRecentErrorEvent = _event; + } + + /* ------------------------------------------------------------------ */ + public void disposing( EventObject _event ) + { + // not interested in + } +} diff --git a/forms/qa/integration/forms/FormLayer.java b/forms/qa/integration/forms/FormLayer.java new file mode 100644 index 000000000000..d1b50f0d246c --- /dev/null +++ b/forms/qa/integration/forms/FormLayer.java @@ -0,0 +1,376 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleEditableText; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XIndexContainer; +import com.sun.star.container.XIndexAccess; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.drawing.XControlShape; +import com.sun.star.drawing.XShapes; +import com.sun.star.awt.Size; +import com.sun.star.awt.Point; +import com.sun.star.awt.VisualEffect; +import com.sun.star.awt.XControlModel; +import com.sun.star.container.XNameAccess; +import com.sun.star.text.TextContentAnchorType; +import com.sun.star.drawing.XDrawPage; + +/** + * + * @author fs@openoffice.org + */ +public class FormLayer +{ + private DocumentHelper m_document; + private XDrawPage m_page; + + /* ------------------------------------------------------------------ */ + /** Creates a new instance of FormLayer */ + public FormLayer( DocumentHelper _document ) + { + m_document = _document; + } + + /* ------------------------------------------------------------------ */ + /** sets the page which is to be used for subsequent insertions of controls/shapes + */ + void setInsertPage( int page ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + m_page = m_document.getDrawPage( page ); + } + + /* ------------------------------------------------------------------ */ + /** creates a control in the document + + <p>Note that <em>control<em> here is an incorrect terminology. What the method really does is + it creates a control shape, together with a control model, and inserts them into the document model. + This will result in every view to this document creating a control described by the model-shape pair. + </p> + + @param sFormComponentService + the service name of the form component to create, e.g. "TextField" + @param nXPos + the abscissa of the position of the newly inserted shape + @param nXPos + the ordinate of the position of the newly inserted shape + @param nWidth + the width of the newly inserted shape + @param nHeight + the height of the newly inserted shape + @param xParentForm + the form to use as parent for the newly create form component. May be null, in this case + a default parent is chosen by the implementation + @return + the property access to the control's model + */ + public XPropertySet createControlAndShape( String sFormComponentService, int nXPos, + int nYPos, int nWidth, int nHeight, Object _parentForm ) throws java.lang.Exception + { + // let the document create a shape + XMultiServiceFactory xDocAsFactory = UnoRuntime.queryInterface( + XMultiServiceFactory.class, m_document.getDocument() ); + XControlShape xShape = UnoRuntime.queryInterface( XControlShape.class, + xDocAsFactory.createInstance( "com.sun.star.drawing.ControlShape" ) ); + + // position and size of the shape + xShape.setSize( new Size( nWidth * 100, nHeight * 100 ) ); + xShape.setPosition( new Point( nXPos * 100, nYPos * 100 ) ); + + // adjust the anchor so that the control is tied to the page + XPropertySet xShapeProps = dbfTools.queryPropertySet( xShape ); + TextContentAnchorType eAnchorType = TextContentAnchorType.AT_PARAGRAPH; + xShapeProps.setPropertyValue( "AnchorType", eAnchorType ); + + // create the form component (the model of a form control) + String sQualifiedComponentName = "com.sun.star.form.component." + sFormComponentService; + XControlModel xModel = UnoRuntime.queryInterface( XControlModel.class, + m_document.getOrb().createInstance( sQualifiedComponentName ) ); + + // insert the model into the form component hierarchy, if the caller gave us a location + if ( null != _parentForm ) + { + XIndexContainer parentForm = null; + if ( _parentForm instanceof XIndexContainer ) + parentForm = (XIndexContainer)_parentForm; + else + parentForm = UnoRuntime.queryInterface( XIndexContainer.class, _parentForm ); + parentForm.insertByIndex( parentForm.getCount(), xModel ); + } + + // knitt them + xShape.setControl( xModel ); + + // add the shape to the shapes collection of the document + XDrawPage pageWhereToInsert = ( m_page != null ) ? m_page : m_document.getMainDrawPage(); + + XShapes xDocShapes = UnoRuntime.queryInterface( XShapes.class, pageWhereToInsert ); + xDocShapes.add( xShape ); + + // and outta here with the XPropertySet interface of the model + XPropertySet xModelProps = dbfTools.queryPropertySet( xModel ); + return xModelProps; + } + + /* ------------------------------------------------------------------ */ + /** creates a control in the document + + <p>Note that <em>control<em> here is an incorrect terminology. What the method really does is + it creates a control shape, together with a control model, and inserts them into the document model. + This will result in every view to this document creating a control described by the model-shape pair. + </p> + + @param sFormComponentService + the service name of the form component to create, e.g. "TextField" + @param nXPos + the abscissa of the position of the newly inserted shape + @param nXPos + the ordinate of the position of the newly inserted shape + @param nWidth + the width of the newly inserted shape + @param nHeight + the height of the newly inserted shape + @return + the property access to the control's model + */ + public XPropertySet createControlAndShape( String sFormComponentService, int nXPos, + int nYPos, int nWidth, int nHeight ) throws java.lang.Exception + { + return createControlAndShape( sFormComponentService, nXPos, nYPos, nWidth, nHeight, null ); + } + + /** creates a pair of controls, namely a label control, and another control labeled by it + * + * @param _formComponentServiceName + * the service name for the control which is not the label control + * @param _label + * the label to be shown in the label control + * @param _xPos + * the horizontal position of the control pair + * @param _yPos + * the vertical position of the control pair + * @param _height + * the height of the control which is not the label control + * @return + * the model of the control which is not the label control + * @throws java.lang.Exception + */ + public XPropertySet createLabeledControl( String _formComponentServiceName, String _label, int _xPos, + int _yPos, int _height ) + throws java.lang.Exception + { + // insert the label control + XPropertySet label = createControlAndShape( "FixedText", _xPos, _yPos, 25, 6 ); + label.setPropertyValue( "Label", _label ); + + // insert the text field control + XPropertySet field = createControlAndShape( _formComponentServiceName, + _xPos + 25, _yPos, 40, _height ); + // knit it to it's label component + field.setPropertyValue( "LabelControl", label ); + + // names + label.setPropertyValue( "Name", _label + "_Label" ); + field.setPropertyValue( "Name", _label ); + + return field; + } + + /* ------------------------------------------------------------------ */ + /** creates a line of controls, consisting of a label and a field for data input. + + <p>In opposite to the second form of this method, here the height of the field, + as well as the abscissa of the label, are under the control of the caller.</p> + + @param sControlType + specifies the type of the data input control + @param sFieldName + specifies the field name the text field should be bound to + @param sControlNamePostfix + specifies a postfix to append to the logical control names + @param nYPos + specifies the Y position of the line to start at + @param nHeight + the height of the field + @return + the control model of the created data input field + */ + public XPropertySet insertControlLine( String sControlType, String sFieldName, String _controlNamePostfix, + int nXPos, int nYPos, int nHeight ) + throws java.lang.Exception + { + // insert the label control + XPropertySet xLabelModel = createControlAndShape( "FixedText", nXPos, nYPos, 25, 6 ); + xLabelModel.setPropertyValue( "Label", sFieldName ); + + // insert the text field control + XPropertySet xFieldModel = createControlAndShape( sControlType, nXPos + 26, nYPos, 40, nHeight ); + xFieldModel.setPropertyValue( "DataField", sFieldName ); + if ( xFieldModel.getPropertySetInfo().hasPropertyByName( "Border" ) ) + { + xFieldModel.setPropertyValue( "Border", new Short( VisualEffect.FLAT ) ); + if ( xFieldModel.getPropertySetInfo().hasPropertyByName( "BorderColor" ) ) + xFieldModel.setPropertyValue( "BorderColor", new Integer( 0x00C0C0C0 ) ); + } + // knit it to it's label component + xFieldModel.setPropertyValue( "LabelControl", xLabelModel ); + + // some names, so later on we can find them + if ( _controlNamePostfix == null ) + _controlNamePostfix = ""; + xLabelModel.setPropertyValue( "Name", sFieldName + _controlNamePostfix + "_Label" ); + xFieldModel.setPropertyValue( "Name", sFieldName + _controlNamePostfix ); + + return xFieldModel; + } + + /* ------------------------------------------------------------------ */ + /** creates a line of controls, consisting of a label and a field for data input. + + @param sControlType + specifies the type of the data input control + @param sFieldName + specifies the field name the text field should be bound to + @param nYPos + specifies the Y position of the line to start at + @return + the control model of the created data input field + */ + public XPropertySet insertControlLine( String sControlType, String sFieldName, String sControlNamePostfix, int nYPos ) + throws java.lang.Exception + { + return insertControlLine( sControlType, sFieldName, sControlNamePostfix, 10, nYPos, 6 ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the radio button model with the given name and the given ref value + * @param form + * the parent form of the radio button model to find + * @param name + * the name of the radio button + * @param refValue + * the reference value of the radio button + */ + public XPropertySet getRadioModelByRefValue( XPropertySet form, String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XIndexAccess indexAccess = UnoRuntime.queryInterface( XIndexAccess.class, form ); + + for ( int i=0; i<indexAccess.getCount(); ++i ) + { + XPropertySet control = dbfTools.queryPropertySet( indexAccess.getByIndex( i ) ); + + if ( ((String)control.getPropertyValue( "Name" )).equals( name ) ) + if ( ((String)control.getPropertyValue( "RefValue" )).equals( refValue ) ) + return control; + } + return null; + } + + /* ------------------------------------------------------------------ */ + /** retrieves the radio button model with the given name and the given tag + * @param form + * the parent form of the radio button model to find + * @param name + * the name of the radio button + * @param refValue + * the tag of the radio button + */ + public XPropertySet getRadioModelByTag( XPropertySet form, String name, String tag ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XIndexAccess indexAccess = UnoRuntime.queryInterface( XIndexAccess.class, form ); + + for ( int i=0; i<indexAccess.getCount(); ++i ) + { + XPropertySet control = dbfTools.queryPropertySet( indexAccess.getByIndex( i ) ); + + if ( ((String)control.getPropertyValue( "Name" )).equals( name ) ) + if ( ((String)control.getPropertyValue( "Tag" )).equals( tag ) ) + return control; + } + return null; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a control model with a given (integer) access path + */ + public XPropertySet getControlModel( int[] _accessPath ) throws com.sun.star.uno.Exception + { + XIndexAccess indexAcc = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + m_document.getFormComponentTreeRoot() ); + XPropertySet controlModel = null; + int i=0; + while ( ( indexAcc != null ) && ( i < _accessPath.length ) ) + { + controlModel = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + indexAcc.getByIndex( _accessPath[i] ) ); + indexAcc = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + controlModel ); + ++i; + } + return controlModel; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a control model with a given (string) access path + */ + public XPropertySet getControlModel( String[] _accessPath ) throws com.sun.star.uno.Exception + { + XNameAccess nameAcc = m_document.getFormComponentTreeRoot(); + XPropertySet controlModel = null; + int i=0; + while ( ( nameAcc != null ) && ( i < _accessPath.length ) ) + { + controlModel = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + nameAcc.getByName( _accessPath[i] ) ); + nameAcc = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, + controlModel ); + ++i; + } + return controlModel; + } + + /* ------------------------------------------------------------------ */ + /** simulates a user's text input into a control given by control model + */ + public void userTextInput( XPropertySet controlModel, String text ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // we will *not* simply set the value property at the model. This is not the same as + // doing a user input, as the latter will trigger a lot of notifications, which the forms runtime environment + // (namely the FormController) relies on to notice that the control changed. + // Instead, we use the Accessibility interfaces of the control to simulate text input + XAccessible formattedAccessible = UnoRuntime.queryInterface( XAccessible.class, + m_document.getCurrentView().getControl( controlModel ) + ); + XAccessibleEditableText textAccess = UnoRuntime.queryInterface( XAccessibleEditableText.class, + formattedAccessible.getAccessibleContext() ); + textAccess.setText( text ); + } +} diff --git a/forms/qa/integration/forms/FormPropertyBags.java b/forms/qa/integration/forms/FormPropertyBags.java new file mode 100644 index 000000000000..c2cd36289a42 --- /dev/null +++ b/forms/qa/integration/forms/FormPropertyBags.java @@ -0,0 +1,208 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyChangeEvent; +import com.sun.star.beans.PropertyExistException; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertyChangeListener; +import com.sun.star.beans.XPropertyContainer; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.frame.XStorable; +import com.sun.star.lang.EventObject; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XMultiServiceFactory; + +import com.sun.star.util.XCloseable; + +public class FormPropertyBags extends complexlib.ComplexTestCase implements XPropertyChangeListener +{ + private DocumentHelper m_document; + private FormLayer m_formLayer; + private XMultiServiceFactory m_orb; + + private PropertyChangeEvent m_propertyChangeEvent; + + /** Creates a new instance of FormPropertyBags */ + public FormPropertyBags() + { + m_propertyChangeEvent = new PropertyChangeEvent(); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkSomething" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Component Property Bag Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + m_document = DocumentHelper.blankTextDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + private void impl_closeDoc() throws com.sun.star.uno.Exception + { + if ( m_document != null ) + { + XCloseable closeDoc = UnoRuntime.queryInterface( XCloseable.class, m_document.getDocument() ); + closeDoc.close( true ); + } + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + impl_closeDoc(); + } + + /* ------------------------------------------------------------------ */ + public void checkSomething() throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet textFieldModel = m_formLayer.createControlAndShape( "DatabaseTextField", 10, 10, 25, 6 ); + + // check whether adding new properties is successful + XPropertyContainer propContainer = UnoRuntime.queryInterface( + XPropertyContainer.class, textFieldModel ); + assure("XPropertyContainer not supported!", propContainer != null ); + + propContainer.addProperty( "SomeBoundText", PropertyAttribute.BOUND, "InitialBoundText" ); + propContainer.addProperty( "SomeTransientText", PropertyAttribute.TRANSIENT, "InitialTransientProperty" ); + propContainer.addProperty( "SomeReadonlyText", PropertyAttribute.READONLY, "InitialReadonlyText" ); + propContainer.addProperty( "SomeNumericValue", PropertyAttribute.BOUND, new Integer( 42 ) ); + + XPropertySetInfo propertyInfo = textFieldModel.getPropertySetInfo(); + assure( "Per service definition, dynamic properties are expected to be forced to be removeable", + ( propertyInfo.getPropertyByName("SomeBoundText").Attributes & PropertyAttribute.REMOVEABLE ) != 0 ); + + // a second addition of a property with an existent name should be rejected + boolean caughtExpected = false; + try { propContainer.addProperty( "SomeBoundText", PropertyAttribute.BOUND, "InitialBoundText" ); } + catch( PropertyExistException e ) { caughtExpected = true; } + catch( Exception e ) { } + assure( "repeated additions of a property with the same name should be rejected", + caughtExpected ); + + // check whether the properties are bound as expected + impl_checkPropertyValueNotification( textFieldModel ); + + // check property value persistence + impl_checkPropertyPersistence(); + } + + /* ------------------------------------------------------------------ */ + private void impl_checkPropertyValueNotification( XPropertySet _controlModel ) throws com.sun.star.uno.Exception + { + _controlModel.addPropertyChangeListener( "", this ); + + _controlModel.setPropertyValue( "SomeBoundText", "ChangedBoundText" ); + assure( "changes in the bound property are not properly notified", + m_propertyChangeEvent.PropertyName.equals( "SomeBoundText" ) + && m_propertyChangeEvent.OldValue.equals( "InitialBoundText" ) + && m_propertyChangeEvent.NewValue.equals( "ChangedBoundText" ) ); + + m_propertyChangeEvent = null; + _controlModel.setPropertyValue( "SomeTransientText", "ChangedTransientText" ); + assure( "changes in non-bound properties should not be notified", + m_propertyChangeEvent == null ); + + boolean caughtExpected = false; + try { _controlModel.setPropertyValue( "SomeReadonlyText", "ChangedReadonlyText" ); } + catch( PropertyVetoException e ) { caughtExpected = true; } + catch( Exception e ) { } + assure( "trying to write a read-only property did not give the expected result", + caughtExpected ); + + _controlModel.removePropertyChangeListener( "", this ); + } + + /* ------------------------------------------------------------------ */ + private void impl_checkPropertyPersistence() throws com.sun.star.uno.Exception + { + // store the document + XStorable store = UnoRuntime.queryInterface( XStorable.class, m_document.getDocument() ); + String documentURL = util.utils.getOfficeTemp( m_orb ) + "document.odt"; + PropertyValue[] storeArguments = new PropertyValue[] { new PropertyValue() }; + storeArguments[0].Name = "FilterName"; + storeArguments[0].Value = "writer8"; + store.storeAsURL( documentURL, storeArguments ); + + // close and re-load it + impl_closeDoc(); + + m_document = DocumentHelper.loadDocument( m_orb, documentURL ); + m_formLayer = new FormLayer( m_document ); + + XPropertySet textFieldModel = m_formLayer.getControlModel( new int[] { 0, 0 } ); + + // all persistent properties should have the expected values + assure( "persistent properties did not survive reload (1)!", ((String)textFieldModel.getPropertyValue( "SomeBoundText" )).equals( "ChangedBoundText" ) ); + assure( "persistent properties did not survive reload (2)!", ((String)textFieldModel.getPropertyValue( "SomeReadonlyText" )).equals( "InitialReadonlyText" ) ); +// assure( "persistent properties did not survive reload (3)!", ((Integer)textFieldModel.getPropertyValue( "SomeNumericValue" )).equals( new Integer( 42 ) ) ); + // cannot check this until the types really survice - at the moment, integers are converted to doubles ... + + // the transient property should not have survived + boolean caughtExpected = false; + try { textFieldModel.getPropertyValue( "SomeTransientText" ); } + catch( UnknownPropertyException e ) { caughtExpected = true; } + assure( "transient property did survive reload!", caughtExpected ); + + // There would be more things to check. + // For instance, it would be desirable of the property attributes would have survived + // the reload, and the property defaults (XPropertyState). + // However, the file format currently doesn't allow for this, so those information + // is lost when saving the document. + } + + /* ------------------------------------------------------------------ */ + public void propertyChange(PropertyChangeEvent _propertyChangeEvent) + { + m_propertyChangeEvent = _propertyChangeEvent; + } + + /* ------------------------------------------------------------------ */ + public void disposing(EventObject eventObject) + { + // not interested in + } +} diff --git a/forms/qa/integration/forms/ImageComparison.java b/forms/qa/integration/forms/ImageComparison.java new file mode 100644 index 000000000000..87f2c82f928d --- /dev/null +++ b/forms/qa/integration/forms/ImageComparison.java @@ -0,0 +1,73 @@ +/* + * ImageComparison.java + * + * Created on 23. September 2003, 17:40 + */ + +package integration.forms; + +/** + * + * @author fs93730 + */ +public final class ImageComparison implements com.sun.star.awt.XImageConsumer +{ + + private byte[] m_referenceBytes; + private int m_referencePosition; + private java.io.FileOutputStream m_stream; + private Object m_notifyDone; + + public boolean imagesEqual( ) + { + return m_referencePosition == m_referenceBytes.length; + } + + /** Creates a new instance of ImageComparison */ + public ImageComparison( byte[] referenceBytes, Object toNotify ) + { + m_referenceBytes = referenceBytes; + m_referencePosition = 0; + m_notifyDone = toNotify; + } + + public void complete(int param, com.sun.star.awt.XImageProducer xImageProducer) + { + synchronized( m_notifyDone ) + { + m_notifyDone.notify(); + } + } + + public void init(int param, int param1) + { + } + + public void setColorModel(short param, int[] values, int param2, int param3, int param4, int param5) + { + } + + public void setPixelsByBytes(int param, int param1, int param2, int param3, byte[] values, int param5, int param6) + { + if ( m_referencePosition == -1 ) + // already failed + return; + + int i = 0; + while ( ( m_referencePosition < m_referenceBytes.length ) && ( i < values.length ) ) + { + if ( m_referenceBytes[ m_referencePosition ] != values[ i ] ) + { + m_referencePosition = -1; + break; + } + ++i; + ++m_referencePosition; + } + } + + public void setPixelsByLongs(int param, int param1, int param2, int param3, int[] values, int param5, int param6) + { + } + +} diff --git a/forms/qa/integration/forms/ListBox.java b/forms/qa/integration/forms/ListBox.java new file mode 100644 index 000000000000..6e50291d6525 --- /dev/null +++ b/forms/qa/integration/forms/ListBox.java @@ -0,0 +1,290 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.awt.XListBox; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XChild; +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XNameAccess; +import com.sun.star.form.ListSourceType; +import com.sun.star.form.runtime.FormFeature; +import com.sun.star.form.runtime.XFormController; +import com.sun.star.form.runtime.XFormOperations; +import com.sun.star.sdb.CommandType; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XParameters; +import com.sun.star.sdbc.XPreparedStatement; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import connectivity.tools.HsqlColumnDescriptor; +import connectivity.tools.HsqlDatabase; +import connectivity.tools.HsqlTableDescriptor; +import connectivity.tools.sdb.Connection; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +public class ListBox extends TestCase +{ + HsqlDatabase m_database = null; + private final String m_foreignKeyTableName = "foreign_keys"; + + public ListBox() + { + super( DocumentType.WRITER ); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkForeignKeys" + }; + } + + /* ------------------------------------------------------------------ */ + public void checkForeignKeys() throws com.sun.star.uno.Exception, java.lang.Exception + { + try + { + // create the form document + prepareDocument(); + + final XIndexAccess formsCollection = UnoRuntime.queryInterface( XIndexAccess.class, + m_document.getFormComponentTreeRoot() ); + final XNameAccess form = UnoRuntime.queryInterface( XNameAccess.class, formsCollection.getByIndex(0) ); + + final DocumentViewHelper view = m_document.getCurrentView(); + final XFormController formController = view.getFormController( form ); + final XFormOperations formOperations = formController.getFormOperations(); + + // move through all records, and check that the display values in the list boxes are as expected + final String[][] fieldTypesDefinitions = impl_getFieldTypeDefinitions(); + final String[] fieldTypes = fieldTypesDefinitions[0]; + + final String[] displayValues = impl_getDisplayValues(); + + formOperations.execute( FormFeature.MoveToFirst ); + for ( int row=0; row<2; ++row ) + { + StringBuffer failedFieldTypes = new StringBuffer(); + for ( int i=0; i<fieldTypes.length; ++i ) + { + final String columnFKName = fieldTypes[i] + "_fk"; + Object listBoxModel = form.getByName( columnFKName ); + XListBox listBoxControl = UnoRuntime.queryInterface( XListBox.class, + view.getControl( listBoxModel ) ); + if ( !listBoxControl.getSelectedItem().equals( displayValues[row] ) ) + { + if ( failedFieldTypes.length() > 0 ) + failedFieldTypes.append( ", " ); + failedFieldTypes.append( fieldTypes[i] ); + } + } + /*assure( "The following field types do not work when used as bound list box fields: " + failedFieldTypes.toString() + + " (row " + row + ")", failedFieldTypes.length() == 0 );*/ + + formOperations.execute( FormFeature.MoveToNext ); + } + + } + finally + { + closeDocument(); + } + } + + /* ------------------------------------------------------------------ */ + public void before() throws Exception, java.lang.Exception + { + super.before(); + impl_createDatabase(); + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + impl_createForm(); + } + + /* ------------------------------------------------------------------ */ + private String[][] impl_getFieldTypeDefinitions() + { + return new String[][] { + new String[] { + "bigint", "boolean", "date", "decimal", "double", "float", "numeric", "time", "timestamp", "tinyint", "varchar" + }, + new String[] { + null, null, null, "(10,2)", null, null, "(10,2)", null, null, null, "(50)" + } + }; + } + + /* ------------------------------------------------------------------ */ + private String[] impl_getTypedValue( final String _asType, final int _rowNum ) throws SQLException + { + Map< String, String[] > valueMap = new HashMap< String, String[] >(); + valueMap.put( "bigint", new String[] { "1111111111", "222222222" } ); + valueMap.put( "boolean", new String[] { "false", "true" } ); + valueMap.put( "date", new String[] { "2001-01-01", "2002-02-02" } ); + valueMap.put( "decimal", new String[] { "1.11", "2.22" } ); + valueMap.put( "double", new String[] { "1.11", "2.22" } ); + valueMap.put( "float", new String[] { "1.11", "2.22" } ); + valueMap.put( "numeric", new String[] { "1.11", "2.22" } ); + valueMap.put( "time", new String[] { "01:01:01", "02:02:02" } ); + valueMap.put( "timestamp", new String[] { "2001-01-01 01:01:01", "2002-02-02 02:02:02" } ); + valueMap.put( "tinyint", new String[] { "1", "2" } ); + valueMap.put( "varchar", new String[] { "first", "second" } ); + + return valueMap.get( _asType ); + } + + /* ------------------------------------------------------------------ */ + private String[] impl_getDisplayValues() + { + return new String[] { "one", "two" }; + } + + /* ------------------------------------------------------------------ */ + private void impl_createDatabase() throws java.lang.Exception + { + try + { + m_database = new HsqlDatabase( m_orb ); + Connection connection = m_database.defaultConnection(); + System.out.println( m_database.getDocumentURL() ); + + final String[][] fieldDefinitions = impl_getFieldTypeDefinitions(); + final String[] keyTypes = fieldDefinitions[0]; + final String[] keyCreationArgs = fieldDefinitions[1]; + + Vector< HsqlColumnDescriptor > foreignKeyColumns = new Vector< HsqlColumnDescriptor >(); + foreignKeyColumns.add( new HsqlColumnDescriptor( "ID", "integer", HsqlColumnDescriptor.PRIMARY ) ); + + Vector< String[] > foreignKeyValues = new Vector< String[] >(); + + StringBuffer foreignKeyInsertSQL = new StringBuffer(); + foreignKeyInsertSQL.append( "INSERT INTO \"" + m_foreignKeyTableName + "\" VALUES (?" ); + + final String[] displayValues = impl_getDisplayValues(); + + for ( int i=0; i<keyTypes.length; ++i ) + { + final String tableName = keyTypes[i] + "_pk"; + final String columnPKName = keyTypes[i] + "_pk"; + final String columnFKName = keyTypes[i] + "_fk"; + final String columnType = keyTypes[i] + ( keyCreationArgs[i] != null ? keyCreationArgs[i] : "" ); + m_database.createTable( new HsqlTableDescriptor( tableName, + new HsqlColumnDescriptor[] { + new HsqlColumnDescriptor( columnPKName, columnType, HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "content", "varchar(50)" ) + } + ) ); + + // insert a few rows + StringBuffer sql = new StringBuffer(); + sql.append( "INSERT INTO \"" ); + sql.append( tableName ); + sql.append( "\" VALUES (?, ?)"); + XPreparedStatement statement = connection.prepareStatement( sql.toString() ); + XParameters statementParameters = UnoRuntime.queryInterface( XParameters.class, statement ); + + final String[] keyValues = impl_getTypedValue( keyTypes[i], 0 ); + + for ( int row=0; row<displayValues.length; ++row ) + { + statementParameters.setString( 1, keyValues[row] ); + statementParameters.setString( 2, displayValues[row] ); + statement.execute(); + } + + // remember a column descriptor for later creation of the table with the foreign keys + foreignKeyColumns.add( new HsqlColumnDescriptor( columnFKName, columnType, HsqlColumnDescriptor.REQUIRED, + tableName, columnPKName ) ); + + // remember the data to fill into this table + foreignKeyValues.add( keyValues ); + foreignKeyInsertSQL.append( ", ?" ); + } + + // create the table taking all those foreign keys + m_database.createTable( new HsqlTableDescriptor( m_foreignKeyTableName, foreignKeyColumns.toArray( new HsqlColumnDescriptor[0] ) ) ); + // fill in some data + foreignKeyInsertSQL.append( ")" ); + XPreparedStatement statement = connection.prepareStatement( foreignKeyInsertSQL.toString() ); + XParameters statementParameters = UnoRuntime.queryInterface( XParameters.class, statement ); + for ( int row=0; row<2; ++row ) + { + statementParameters.setInt( 1, row ); + for ( int i=0; i<keyTypes.length; ++i ) + { + statementParameters.setString( i+2, foreignKeyValues.get(i)[row] ); + } + statement.execute(); + } + + m_database.defaultConnection().refreshTables(); + } + finally + { + if ( m_database != null ) + m_database.store(); + } + } + + /* ------------------------------------------------------------------ */ + private void impl_createForm() throws java.lang.Exception + { + // a single control for the ID field + XPropertySet controlModel = m_formLayer.insertControlLine( "DatabaseNumericField", "ID", null, 10, 10, 6 ); + // bind the form to the foreign_keys table + XPropertySet form = dbfTools.queryPropertySet( dbfTools.getParent( controlModel, XChild.class ) ); + form.setPropertyValue( "Command", m_foreignKeyTableName ); + form.setPropertyValue( "CommandType", CommandType.TABLE ); + form.setPropertyValue( "DataSourceName", m_database.getDocumentURL() ); + + // create list boxes for the different foreign keys + final String[][] fieldDefinitions = impl_getFieldTypeDefinitions(); + final String[] fieldTypes = fieldDefinitions[0]; + for ( int i=0; i<fieldTypes.length; ++i ) + { + final String tableName = fieldTypes[i] + "_pk"; + final String columnFKName = fieldTypes[i] + "_fk"; + final String columnPKName = fieldTypes[i] + "_pk"; + XPropertySet listBoxModel = m_formLayer.insertControlLine( "DatabaseListBox", columnFKName, null, 10, 20 + 10*i, 6 ); + listBoxModel.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBoxModel.setPropertyValue( "ListSourceType", ListSourceType.SQL ); + listBoxModel.setPropertyValue( "ListSource", new String[] { "SELECT \"content\", \"" + columnPKName + + "\" FROM \"" + tableName + "\"" } ); + listBoxModel.setPropertyValue( "BoundColumn", new Short( (short)1 ) ); + } + + m_document.getCurrentView().toggleFormDesignMode(); + } + } diff --git a/forms/qa/integration/forms/ListSelection.java b/forms/qa/integration/forms/ListSelection.java new file mode 100644 index 000000000000..24a5290dc1d4 --- /dev/null +++ b/forms/qa/integration/forms/ListSelection.java @@ -0,0 +1,298 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.beans.XPropertySet; +import com.sun.star.sheet.XSpreadsheet; +import com.sun.star.sheet.XSpreadsheets; +import com.sun.star.sheet.XSpreadsheetView; +import com.sun.star.container.XNamed; +import com.sun.star.container.XNameContainer; +import com.sun.star.container.XIndexContainer; +import com.sun.star.drawing.XDrawPageSupplier; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XListBox; +import com.sun.star.script.XLibraryContainer; +import com.sun.star.script.XEventAttacherManager; +import com.sun.star.script.ScriptEventDescriptor; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleSelection; +import com.sun.star.frame.XStorable; + +public class ListSelection extends integration.forms.TestCase +{ + /** Creates a new instance of ListSelection */ + public ListSelection() + { + super( DocumentType.CALC ); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkUserListSelection" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control List Selection Test"; + } + + /* ------------------------------------------------------------------ */ + public void checkUserListSelection() throws com.sun.star.uno.Exception, java.lang.Exception + { + boolean interactiveTest = param.getBool( "Interactive" ); + + if ( interactiveTest ) + { + prepareDocument(); + waitForUserInput(); + closeDocumentByUI(); + } + else + { + int runs = param.getInt( "Runs" ); + if ( runs == 0 ) + runs = 10; + + for ( int i = 0; i < runs; ++i ) + { + log.println( "Round " + ( i + 1 ) + " of " + runs ); + prepareDocument(); + impl_clickListBox(); + synchronized( this ) { this.wait( 1000 ); } + closeDocument(); + } + } + } + + /* ------------------------------------------------------------------ */ + final private void impl_clickListBox() + { + try + { + final int runs = 10; + java.util.Random generator = new java.util.Random(); + for ( int i = 0; i < runs; ++i ) + { + // obtain the active sheet + XSpreadsheetView view = (XSpreadsheetView)m_document.getCurrentView().query( XSpreadsheetView.class ); + XSpreadsheet activeSheet = view.getActiveSheet(); + + // Accessibility access to the list box control in this sheet + XAccessible accessibleListBox = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, getListBoxControl( activeSheet ) ); + XAccessibleContext context = accessibleListBox.getAccessibleContext(); + + // the first "accessible child" of a list box is its list + XAccessibleSelection accessibleList = (XAccessibleSelection)UnoRuntime.queryInterface( + XAccessibleSelection.class, context.getAccessibleChild( 1 ) ); + + int selectPosition = generator.nextInt( 5 ); + String selectSheetName = getListBoxControl( activeSheet ).getItem( (short)selectPosition ); + accessibleList.selectAccessibleChild( selectPosition ); + try + { + synchronized( this ) + { + this.wait( 500 ); + } + } + catch( java.lang.InterruptedException e ) { } + + XNamed sheetName = (XNamed)UnoRuntime.queryInterface( XNamed.class, view.getActiveSheet() ); + assure( "sheet was not selected as expected!", sheetName.getName().equals( selectSheetName ) ); + } + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + final private void impl_setupListenerScript() + { + try + { + XPropertySet docProps = dbfTools.queryPropertySet( m_document.getDocument() ); + XLibraryContainer basicLibs = (XLibraryContainer)UnoRuntime.queryInterface( + XLibraryContainer.class, docProps.getPropertyValue( "BasicLibraries" ) ); + XNameContainer basicLib = basicLibs.createLibrary( "default" ); + + String sListSelectionScript = + "Option Explicit\n" + + "\n" + + "Sub onListBoxSelected( oEvent as Object )\n" + + " Dim oView as Object\n" + + " Dim oSheet as Object\n" + + " Dim oSheets as Object\n" + + "\n" + + " Dim oControlModel as Object\n" + + " Dim sSheet as String\n" + + "\n" + + " if ( oEvent.Selected <> 65535 ) Then\n" + + " oControlModel = oEvent.Source.Model\n" + + " sSheet = oControlModel.StringItemList( oEvent.Selected )\n" + + "\n" + + " oSheets = thisComponent.Sheets\n" + + " oSheet = oSheets.getByName(sSheet)\n" + + "\n" + + " oView = thisComponent.CurrentController\n" + + " oView.setActiveSheet( oSheet )\n" + + " End If\n" + + "End Sub\n" + + "\n" + + "Sub onButtonClicked\n" + + " MsgBox \"clicked\"\n" + + "End Sub\n"; + + basicLib.insertByName( "callbacks", sListSelectionScript ); + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + final private void impl_assignStarBasicScript( XPropertySet controlModel, String interfaceName, String interfaceMethod, String scriptCode ) + { + try + { + XIndexContainer parentForm = (XIndexContainer)dbfTools.getParent( controlModel, XIndexContainer.class ); + + XEventAttacherManager manager = (XEventAttacherManager)UnoRuntime.queryInterface( + XEventAttacherManager.class, parentForm ); + + int containerPosition = -1; + for ( int i = 0; i < parentForm.getCount(); ++i ) + { + XPropertySet child = dbfTools.queryPropertySet( parentForm.getByIndex( i ) ); + if ( child.equals( controlModel ) ) + { + containerPosition = i; + break; + } + } + manager.registerScriptEvent( containerPosition, new ScriptEventDescriptor( + interfaceName, + interfaceMethod, + "", + "StarBasic", + scriptCode + ) ); + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + impl_setupListenerScript(); + + SpreadsheetDocument document = (SpreadsheetDocument)m_document; + XSpreadsheets sheets = document.getSheets(); + + // delete all sheets except one + String[] sheetNames = sheets.getElementNames(); + for ( short i = 1; i < sheetNames.length; ++i ) + sheets.removeByName( sheetNames[ i ] ); + + // need 5 sheets + String[] newSheetNames = new String[] { "first", "second", "third", "forth", "fifth" }; + + // give the first one the right name + XNamed sheet = (XNamed)UnoRuntime.queryInterface( XNamed.class, + sheets.getByName( sheetNames[ 0 ] ) + ); + sheet.setName( newSheetNames[ 0 ] ); + + // add some dummy buttons + for ( int i = 0; i < 4; ++i ) + { + XPropertySet buttonModel = m_formLayer.createControlAndShape( "CommandButton", 10, 10 + i * 10, 30, 8 ); + impl_assignStarBasicScript( buttonModel, "XActionListener", "actionPerformed", "document:default.callbacks.onButtonClicked" ); + } + + // and a list box + XPropertySet listBox = m_formLayer.createControlAndShape( "ListBox", 50, 10, 40, 6 ); + listBox.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBox.setPropertyValue( "StringItemList", newSheetNames ); + listBox.setPropertyValue( "Name", "ListBox" ); + + impl_assignStarBasicScript( listBox, "XItemListener", "itemStateChanged", "document:default.callbacks.onListBoxSelected" ); + + // clone this sheet + for ( short i = 1; i < newSheetNames.length; ++i ) + sheets.copyByName( newSheetNames[0], newSheetNames[i], i ); + + // switch the thing to alive mode + m_document.getCurrentView().toggleFormDesignMode(); + + try + { + XStorable storable = (XStorable)m_document.query( XStorable.class ); + java.io.File testFile = java.io.File.createTempFile( getTestObjectName(),".ods"); + storable.storeAsURL( testFile.getAbsoluteFile().toURL().toString(), new com.sun.star.beans.PropertyValue[]{} ); + testFile.deleteOnExit(); + } + catch( java.lang.Throwable e ) + { + e.printStackTrace(); + } + } + + /* ------------------------------------------------------------------ */ + protected XControlModel getListBoxModel( XSpreadsheet sheet ) + { + XDrawPageSupplier suppPage = (XDrawPageSupplier)UnoRuntime.queryInterface( + XDrawPageSupplier.class, sheet ); + FormComponent formsRoot = new FormComponent( suppPage.getDrawPage() ); + XControlModel listBoxModel = (XControlModel)formsRoot.getByIndex( 0 ). + getByName( "ListBox" ).query( XControlModel.class ); + return listBoxModel; + } + + /* ------------------------------------------------------------------ */ + protected XListBox getListBoxControl( XSpreadsheet sheet ) throws com.sun.star.uno.Exception + { + return (XListBox)UnoRuntime.queryInterface( + XListBox.class, m_document.getCurrentView().getControl( getListBoxModel( sheet ) ) ); + } + } diff --git a/forms/qa/integration/forms/ListSelection.props b/forms/qa/integration/forms/ListSelection.props new file mode 100644 index 000000000000..4464e320561c --- /dev/null +++ b/forms/qa/integration/forms/ListSelection.props @@ -0,0 +1,3 @@ +ThreadTimeOut=600000 +Interactive=false +Runs=5 diff --git a/forms/qa/integration/forms/ListSelectionValidator.java b/forms/qa/integration/forms/ListSelectionValidator.java new file mode 100644 index 000000000000..4f25b162712d --- /dev/null +++ b/forms/qa/integration/forms/ListSelectionValidator.java @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +/** + * + * @author fs@openoffice.org + */ +public class ListSelectionValidator extends integration.forms.ControlValidator +{ + /** Creates a new instance of ListSelectionValidator */ + public ListSelectionValidator() + { + } + + public String explainInvalid( Object Value ) + { + try + { + short[] selectionIndexes = (short[])Value; + if ( selectionIndexes.length > 2 ) + return "please 2 entries, at most"; + } + catch( java.lang.Exception e ) + { + return "oops. What's this?"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + short[] selectionIndexes = (short[])Value; + if ( selectionIndexes.length > 2 ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } + +} diff --git a/forms/qa/integration/forms/MasterDetailForms.java b/forms/qa/integration/forms/MasterDetailForms.java new file mode 100644 index 000000000000..cd51abc3e446 --- /dev/null +++ b/forms/qa/integration/forms/MasterDetailForms.java @@ -0,0 +1,435 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.beans.NamedValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XIndexContainer; +import java.lang.reflect.Method; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.container.XNameContainer; +import com.sun.star.embed.XComponentSupplier; +import com.sun.star.form.XGridColumnFactory; +import com.sun.star.form.XGridFieldDataSupplier; +import com.sun.star.form.XLoadable; +import com.sun.star.lang.XComponent; +import com.sun.star.sdb.CommandType; +import com.sun.star.sdb.XFormDocumentsSupplier; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XColumnLocate; +import com.sun.star.ucb.Command; +import com.sun.star.ucb.OpenMode; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.uno.Type; +import com.sun.star.util.XModifiable; +import connectivity.tools.CRMDatabase; +import connectivity.tools.HsqlColumnDescriptor; +import connectivity.tools.HsqlDatabase; +import connectivity.tools.HsqlTableDescriptor; +import org.openoffice.complex.forms.tools.ResultSet; + + +public class MasterDetailForms extends complexlib.ComplexTestCase implements com.sun.star.form.XLoadListener +{ + private XMultiServiceFactory m_orb; + + private XPropertySet m_masterForm; + private XPropertySet m_detailForm; + private ResultSet m_masterResult; + private ResultSet m_detailResult; + + final private Object m_waitForLoad = new Object(); + private boolean m_loaded = false; + + /** Creates a new instance of MasterDetailForms */ + public MasterDetailForms() + { + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkMultipleKeys", + "checkDetailFormDefaults" + }; + } + + /* ------------------------------------------------------------------ */ + public void before() + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control Spreadsheet Cell Binding Test"; + } + + /* ------------------------------------------------------------------ */ + /** creates the table structure needed for the test + */ + private void impl_createTableStructure( final HsqlDatabase _databaseDocument ) throws SQLException + { + HsqlColumnDescriptor[] masterColumns = { + new HsqlColumnDescriptor( "ID1", "INTEGER", HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "ID2", "INTEGER", HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "value", "VARCHAR(50)" ), + }; + HsqlColumnDescriptor[] detailColumns = { + new HsqlColumnDescriptor( "ID", "INTEGER", HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "FK_ID1", "INTEGER", HsqlColumnDescriptor.REQUIRED, "master", "ID1" ), + new HsqlColumnDescriptor( "FK_ID2", "INTEGER", HsqlColumnDescriptor.REQUIRED, "master", "ID2" ), + new HsqlColumnDescriptor( "name", "VARCHAR(50)" ), + }; + _databaseDocument.createTable( new HsqlTableDescriptor( "master", masterColumns ) ); + _databaseDocument.createTable( new HsqlTableDescriptor( "detail", detailColumns ) ); + + _databaseDocument.executeSQL( "INSERT INTO \"master\" VALUES ( 1, 1, 'First Record' )" ); + _databaseDocument.executeSQL( "INSERT INTO \"master\" VALUES ( 1, 2, 'Second Record' )" ); + _databaseDocument.executeSQL( "INSERT INTO \"detail\" VALUES ( 1, 1, 1, 'record 1.1 (1)')"); + _databaseDocument.executeSQL( "INSERT INTO \"detail\" VALUES ( 2, 1, 1, 'record 1.1 (2)')"); + _databaseDocument.executeSQL( "INSERT INTO \"detail\" VALUES ( 3, 1, 2, 'record 1.2 (1)')"); + + _databaseDocument.defaultConnection().refreshTables(); + } + + /* ------------------------------------------------------------------ */ + private void impl_createForms( final HsqlDatabase _databaseDocument ) throws com.sun.star.uno.Exception + { + m_masterForm = dbfTools.queryPropertySet( m_orb.createInstance( "com.sun.star.form.component.DataForm" ) ); + m_masterForm.setPropertyValue( "ActiveConnection", _databaseDocument.defaultConnection().getXConnection() ); + m_masterForm.setPropertyValue( "CommandType", new Integer( com.sun.star.sdb.CommandType.TABLE ) ); + m_masterForm.setPropertyValue( "Command", "master" ); + + m_masterResult = new ResultSet( m_masterForm ); + + m_detailForm = dbfTools.queryPropertySet( m_orb.createInstance( "com.sun.star.form.component.DataForm" ) ); + m_detailForm.setPropertyValue( "ActiveConnection", _databaseDocument.defaultConnection().getXConnection() ); + m_detailForm.setPropertyValue( "CommandType", new Integer( com.sun.star.sdb.CommandType.TABLE ) ); + m_detailForm.setPropertyValue( "Command", "detail" ); + + m_detailResult = new ResultSet( m_detailForm ); + + XNameContainer masterContainer = UnoRuntime.queryInterface( XNameContainer.class, m_masterForm ); + masterContainer.insertByName( "slave", m_detailForm ); + } + + /* ------------------------------------------------------------------ */ + /** checks if master-detail relationships including multiple keys work + */ + public void checkMultipleKeys() throws com.sun.star.uno.Exception, java.lang.Exception + { + HsqlDatabase databaseDocument = null; + try + { + databaseDocument = new HsqlDatabase( m_orb ); + impl_createTableStructure( databaseDocument ); + impl_createForms( databaseDocument ); + + m_detailForm.setPropertyValue( "MasterFields", new String[] { "ID1", "ID2" } ); + m_detailForm.setPropertyValue( "DetailFields", new String[] { "FK_ID1", "FK_ID2" } ); + + XLoadable loadMaster = UnoRuntime.queryInterface( XLoadable.class, m_masterForm ); + XLoadable loadDetail = UnoRuntime.queryInterface( XLoadable.class, m_detailForm ); + loadDetail.addLoadListener( this ); + + // wait until the detail form is loaded + operateMasterAndWaitForDetailForm( loadMaster.getClass().getMethod( "load", new Class[] {} ), loadMaster, new Object[] { } ); + + // okay, now the master form should be on the first record + assure( "wrong form state after loading (ID1)", m_masterResult.getInt(1) == 1 ); + assure( "wrong form state after loading (ID2)", m_masterResult.getInt(2) == 1 ); + assure( "wrong form state after loading (value)", m_masterResult.getString(3).equals( "First Record" ) ); + + // the "XResultSet.next" method + Method methodNext = m_masterResult.getClass().getMethod( "next" , new Class[] {} ); + + // the values in the linked fields should be identical + int expectedDetailRowCounts[] = { 2, 1 }; + do + { + verifyColumnValueIdentity( "ID1", "FK_ID1" ); + verifyColumnValueIdentity( "ID2", "FK_ID2" ); + + m_detailResult.last(); + int masterPos = m_masterResult.getRow(); + assure( "wrong number of records in detail form, for master form at pos " + masterPos, + ((Integer)m_detailForm.getPropertyValue( "RowCount" )).intValue() == expectedDetailRowCounts[ masterPos - 1 ] ); + + operateMasterAndWaitForDetailForm( methodNext, m_masterResult, new Object[] {} ); + } + while ( !m_masterResult.isAfterLast() ); + assure( "wrong number of records in master form", 2 == ((Integer)m_masterForm.getPropertyValue( "RowCount" )).intValue() ); + } + finally + { + if ( databaseDocument != null ) + databaseDocument.closeAndDelete(); + impl_cleanUpStep(); + } + } + + /* ------------------------------------------------------------------ */ + private final void impl_cleanUpStep() + { + if ( m_masterForm != null ) + dbfTools.disposeComponent( m_masterForm ); + if ( m_detailForm != null ) + dbfTools.disposeComponent( m_detailForm ); + m_masterForm = m_detailForm = null; + } + + /* ------------------------------------------------------------------ */ + /** checks whether default values in detail forms work as expected. + * + * Effectively, this test case verifies the issues #i106574# and #i105235# did not creep back in. + */ + public void checkDetailFormDefaults() throws Exception + { + CRMDatabase database = null; + XCommandProcessor subComponentCommands = null; + try + { + // create our standard CRM database document + database = new CRMDatabase( m_orb, true ); + + // create a form document therein + XFormDocumentsSupplier formDocSupp = UnoRuntime.queryInterface( XFormDocumentsSupplier.class, database.getDatabase().getModel() ); + XMultiServiceFactory formFactory = UnoRuntime.queryInterface( XMultiServiceFactory.class, formDocSupp.getFormDocuments() ); + NamedValue[] loadArgs = new NamedValue[] { + new NamedValue( "ActiveConnection", database.getConnection().getXConnection() ), + new NamedValue( "MediaType", "application/vnd.oasis.opendocument.text" ) + }; + + subComponentCommands = UnoRuntime.queryInterface( + XCommandProcessor.class, + formFactory.createInstanceWithArguments( "com.sun.star.sdb.DocumentDefinition", loadArgs ) ); + Command command = new Command(); + command.Name = "openDesign"; + command.Argument = new Short( OpenMode.DOCUMENT ); + + DocumentHelper subDocument = new DocumentHelper( m_orb, + UnoRuntime.queryInterface( XComponent.class, + subComponentCommands.execute( command, subComponentCommands.createCommandIdentifier(), null ) + ) + ); + FormLayer formLayer = new FormLayer( subDocument ); + XPropertySet controlModel = formLayer.insertControlLine( "DatabaseNumericField", "ID", "", 10 ); + formLayer.insertControlLine( "DatabaseTextField", "Name", "", 20 ); + formLayer.insertControlLine( "DatabaseTextField", "Description", "", 30 ); + + m_masterForm = (XPropertySet)dbfTools.getParent( controlModel, XPropertySet.class ); + m_masterForm.setPropertyValue( "Command", "categories" ); + m_masterForm.setPropertyValue( "CommandType", new Integer( CommandType.TABLE ) ); + + // create a detail form + m_detailForm = UnoRuntime.queryInterface( XPropertySet.class, subDocument.createSubForm( m_masterForm, "products" ) ); + m_detailForm.setPropertyValue( "Command", "SELECT \"ID\", \"Name\", \"CategoryID\" FROM \"products\"" ); + m_detailForm.setPropertyValue( "CommandType", new Integer( CommandType.COMMAND ) ); + m_detailForm.setPropertyValue( "MasterFields", new String[] { "ID" } ); + m_detailForm.setPropertyValue( "DetailFields", new String[] { "CategoryID" } ); + + // create a grid control in the detail form, with some columns + XPropertySet gridControlModel = formLayer.createControlAndShape( "GridControl", 20, 40, 130, 50, m_detailForm ); + gridControlModel.setPropertyValue( "Name", "product list" ); + XIndexContainer gridColumns = UnoRuntime.queryInterface( XIndexContainer.class, gridControlModel ); + impl_createGridColumn( gridColumns, "TextField", "ID" ); + XPropertySet nameColumn = impl_createGridColumn( gridColumns, "TextField", "Name" ); + nameColumn.setPropertyValue( "Width", new Integer( 600 ) ); // 6 cm + nameColumn.setPropertyValue( "DefaultText", "default text" ); + + // go live + m_masterResult = new ResultSet( m_masterForm ); + m_detailResult = new ResultSet( m_detailForm ); + + XLoadable loadDetail = UnoRuntime.queryInterface( XLoadable.class, m_detailForm ); + loadDetail.addLoadListener( this ); + + subDocument.getCurrentView().toggleFormDesignMode(); + impl_waitForLoadedEvent(); + + // now that we set up this, do the actual tests + // First, http://www.openoffice.org/issues/show_bug.cgi?id=105235 described the problem + // that default values in the sub form didn't work when the master form was navigated to a row + // for which no detail records were present, and the default of the column/control is the same + // as the last known value. + + // so, take the current value of the "Name" column, and set it as default value ... + String defaultValue = m_detailResult.getString( 2 ); + nameColumn.setPropertyValue( "DefaultText", defaultValue ); + // ... then move to the second main form row ... + m_masterResult.absolute( 2 ); + impl_waitForLoadedEvent(); + // ... which should result in an empty sub form ... + assure( "test precondition not met: The second master form record is expected to have no detail records, " + + "else the test becomes meaningless", impl_isNewRecord( m_detailForm ) ); + // ... and in the "Name" column having the proper text + String actualValue = (String)nameColumn.getPropertyValue( "Text" ); + assureEquals( "#i105235#: default value in sub form not working (not propagated to column model)", defaultValue, actualValue ); + // However, checking the column model's value alone is not enough - we need to ensure it is properly + // propagated to the control. + XGridFieldDataSupplier gridData = (XGridFieldDataSupplier)subDocument.getCurrentView().getControl( + gridControlModel, XGridFieldDataSupplier.class ); + actualValue = (String)(gridData.queryFieldData( 0, Type.STRING )[1]); + assureEquals( "#i105235#: default value in sub form not working (not propagated to column)", defaultValue, actualValue ); + } + finally + { + if ( subComponentCommands != null ) + { + XComponentSupplier componentSupplier = UnoRuntime.queryInterface( XComponentSupplier.class, subComponentCommands ); + XModifiable modifySubComponent = UnoRuntime.queryInterface( XModifiable.class, componentSupplier.getComponent() ); + modifySubComponent.setModified( false ); + Command command = new Command(); + command.Name = "close"; + subComponentCommands.execute( command, subComponentCommands.createCommandIdentifier(), null ); + } + + if ( database != null ) + database.saveAndClose(); + + impl_cleanUpStep(); + } + } + + /* ------------------------------------------------------------------ */ + private boolean impl_isNewRecord( final XPropertySet _rowSet ) + { + boolean isNew = false; + try + { + isNew = ((Boolean)_rowSet.getPropertyValue( "IsNew" )).booleanValue(); + } + catch ( Exception ex ) + { + failed( "obtaining the IsNew property failed" ); + } + return isNew; + } + + /* ------------------------------------------------------------------ */ + private XPropertySet impl_createGridColumn( final XIndexContainer _gridModel, final String _columnType, final String _boundField ) throws Exception + { + final XGridColumnFactory columnFactory = UnoRuntime.queryInterface( XGridColumnFactory.class, _gridModel ); + XPropertySet column = columnFactory.createColumn( _columnType ); + column.setPropertyValue( "DataField", _boundField ); + column.setPropertyValue( "Name", _boundField ); + column.setPropertyValue( "Label", _boundField ); + _gridModel.insertByIndex( _gridModel.getCount(), column ); + return column; + } + + /* ------------------------------------------------------------------ */ + /** executes an operation on the master, and waits until the detail form has been (re)loaded aferwards + */ + private void operateMasterAndWaitForDetailForm( Method _masterMethod, Object _masterInterface, Object[] _methodParameters ) throws SQLException + { + Object result; + try + { + result = _masterMethod.invoke( _masterInterface, _methodParameters ); + } + catch( java.lang.Exception e ) + { + throw new SQLException( "invoking " + _masterMethod.getName() + " failed",new Object(), "", 0, new Object() ); + } + + if ( _masterMethod.getReturnType().getName().equals( "boolean" ) ) + if ( !((Boolean)result).booleanValue() ) + return; + + impl_waitForLoadedEvent(); + } + + private void impl_waitForLoadedEvent() + { + synchronized( m_waitForLoad ) + { + while ( !m_loaded ) + { + try { m_waitForLoad.wait(); } + catch( java.lang.InterruptedException e ) { } + } + // reset the flag for the next time + m_loaded = false; + } + } + + /** assures that the (integer) values in the given columns of our master and detail forms are identical + */ + private void verifyColumnValueIdentity( final String masterColName, final String detailColName ) throws SQLException + { + XColumnLocate locateMasterCols = UnoRuntime.queryInterface( XColumnLocate.class, m_masterForm ); + XColumnLocate locateDetailCols = UnoRuntime.queryInterface( XColumnLocate.class, m_detailForm ); + + int masterValue = m_masterResult.getInt( locateMasterCols.findColumn( masterColName ) ); + int detailValue = m_detailResult.getInt( locateDetailCols.findColumn( detailColName ) ); + + assure( "values in linked column pair " + detailColName + "->" + masterColName + " (" + + detailValue + "->" + masterValue + ") do not match (master position: " + m_masterResult.getRow() + ")!", + masterValue == detailValue ); + } + + public void disposing(com.sun.star.lang.EventObject eventObject) + { + } + + public void loaded(com.sun.star.lang.EventObject eventObject) + { + synchronized( m_waitForLoad ) + { + m_loaded = true; + m_waitForLoad.notify(); + } + } + + public void reloaded(com.sun.star.lang.EventObject eventObject) + { + synchronized( m_waitForLoad ) + { + m_loaded = true; + m_waitForLoad.notify(); + } + } + + public void reloading(com.sun.star.lang.EventObject eventObject) + { + } + + public void unloaded(com.sun.star.lang.EventObject eventObject) + { + } + + public void unloading(com.sun.star.lang.EventObject eventObject) + { + } +} diff --git a/forms/qa/integration/forms/NumericValidator.java b/forms/qa/integration/forms/NumericValidator.java new file mode 100644 index 000000000000..4fed12c4fd2b --- /dev/null +++ b/forms/qa/integration/forms/NumericValidator.java @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class NumericValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public NumericValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + double value = ((Double)Value).doubleValue(); + if ( Double.compare( Double.NaN, value ) == 0 ) + return "This is NotANumber"; + if ( !isProperRange( value ) ) + return "The value must be between 0 and 100"; + if ( !isProperDigitCount( value ) ) + return "The value must have at most one decimal digit"; + } + catch( java.lang.Exception e ) + { + return "This is no valid number"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + double value = ((Double)Value).doubleValue(); + if ( Double.compare( Double.NaN, value ) == 0 ) + return false; + if ( !isProperRange( value ) ) + return false; + if ( !isProperDigitCount( value ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } + + private boolean isProperRange( double value) + { + return ( value >= 0 ) && ( value <= 100 ); + } + + private boolean isProperDigitCount( double value) + { + return ( java.lang.Math.floor( value * 10 ) == value * 10 ); + } +} diff --git a/forms/qa/integration/forms/RadioButtons.java b/forms/qa/integration/forms/RadioButtons.java new file mode 100644 index 000000000000..3ce02787b330 --- /dev/null +++ b/forms/qa/integration/forms/RadioButtons.java @@ -0,0 +1,459 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.awt.XRadioButton; + +import integration.forms.dbfTools; +import integration.forms.DocumentHelper; +import integration.forms.SpreadsheetDocument; + +import util.utils; +import java.util.*; +import java.io.*; +import java.lang.*; + +/** + * + * @author fs@openoffice.org + */ +public class RadioButtons extends complexlib.ComplexTestCase +{ + private DocumentHelper m_document; /// our current test document + private FormLayer m_formLayer; /// quick access to the form layer + private XMultiServiceFactory m_orb; /// our service factory + private XPropertySet m_primaryForm; /// the primary form, to be used in text documents and in the first page of spreadsheets + private XPropertySet m_secondaryForm; /// the secondary form, to be used in the second page of spreadsheets + + /* ------------------------------------------------------------------ */ + public RadioButtons() + { + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkSingleButtons", + "checkThreeGroups", + "checkMultipleForms", + "checkCalcPageSwitch" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Radio Buttons Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet insertRadio( int nXPos, int nYPos, String label, String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return insertRadio( nXPos, nYPos, label, name, refValue, null ); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet insertRadio( int nXPos, int nYPos, String label, String name, String refValue, XPropertySet parentForm ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XIndexContainer parentContainer = dbfTools.queryIndexContainer( parentForm ); + XPropertySet xRadio = m_formLayer.createControlAndShape( "DatabaseRadioButton", nXPos, nYPos, 25, 6, parentContainer ); + xRadio.setPropertyValue( "Label", label ); + xRadio.setPropertyValue( "RefValue", refValue ); + xRadio.setPropertyValue( "Name", name ); + + if ( null == m_primaryForm ) + m_primaryForm = (XPropertySet)dbfTools.getParent( xRadio, XPropertySet.class ); + + return xRadio; + } + + /* ------------------------------------------------------------------ */ + /** this checks whether n groups of radio buttons, consisting of only one button each, + * behave properly + */ + public void checkSingleButtons() throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( false ); + + insertRadio( 20, 30, "group 1", "group 1", "" ); + insertRadio( 20, 38, "group 2", "group 2", "" ); + insertRadio( 20, 46, "group 3", "group 3", "" ); + insertRadio( 20, 54, "group 4", "group 4", "" ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + checkRadio( "group 1", "" ); + verifySingleRadios( 1, 0, 0, 0 ); + + checkRadio( "group 4", "" ); + verifySingleRadios( 1, 0, 0, 1 ); + + checkRadio( "group 2", "" ); + verifySingleRadios( 1, 1, 0, 1 ); + + checkRadio( "group 3", "" ); + verifySingleRadios( 1, 1, 1, 1 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + /** creates three groups of radio buttons in a sample document, and checks whether they're working + */ + public void checkThreeGroups( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( false ); + + insertRadio( 20, 30, "group 1 (a)", "group 1", "a" ); + insertRadio( 20, 38, "group 1 (b)", "group 1", "b" ); + + insertRadio( 20, 50, "group 2 (a)", "group 2", "a" ); + insertRadio( 20, 58, "group 2 (b)", "group 2", "b" ); + + insertRadio( 20, 70, "group 3 (a)", "group 3", "a" ); + insertRadio( 20, 78, "group 3 (b)", "group 3", "b" ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + // initially, after switching to alive mode, all buttons should be unchecked + verifySixPack( 0, 0, 0, 0, 0, 0 ); + + // check one button in every group + checkRadio( "group 1", "a" ); + checkRadio( "group 2", "b" ); + checkRadio( "group 3", "a" ); + // and verify that this worked + verifySixPack( 1, 0, 0, 1, 1, 0 ); + + // check all buttons which are currently unchecked + checkRadio( "group 1", "b" ); + checkRadio( "group 2", "a" ); + checkRadio( "group 3", "b" ); + // this should have reset the previous checks in the respective groups + verifySixPack( 0, 1, 1, 0, 0, 1 ); + + // and back to the previous check state + checkRadio( "group 1", "a" ); + checkRadio( "group 2", "b" ); + checkRadio( "group 3", "a" ); + verifySixPack( 1, 0, 0, 1, 1, 0 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + /** tests whether radio buttons which belong to different forms behave properly + */ + public void checkMultipleForms( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( false ); + + insertRadio( 20, 30, "group 1 (a)", "group 1", "a" ); + insertRadio( 20, 38, "group 1 (b)", "group 1", "b" ); + insertRadio( 20, 46, "group 1 (c)", "group 1", "c" ); + + m_secondaryForm = dbfTools.queryPropertySet( m_document.createSiblingForm( m_primaryForm, "secondary" ) ); + + insertRadio( 70, 30, "group 2 (a)", "group 2", "a", m_secondaryForm ); + insertRadio( 70, 38, "group 2 (b)", "group 2", "b", m_secondaryForm ); + insertRadio( 70, 46, "group 2 (c)", "group 2", "c", m_secondaryForm ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + // play around with different check states + checkRadio( "group 1", "b", m_primaryForm ); + checkRadio( "group 2", "c", m_secondaryForm ); + verifyTwoFormRadios( 0, 1, 0, 0, 0, 1 ); + + checkRadio( "group 1", "c", m_primaryForm ); + verifyTwoFormRadios( 0, 0, 1, 0, 0, 1 ); + + checkRadio( "group 2", "a", m_secondaryForm ); + verifyTwoFormRadios( 0, 0, 1, 1, 0, 0 ); + + checkRadio( "group 1", "a", m_primaryForm ); + verifyTwoFormRadios( 1, 0, 0, 1, 0, 0 ); + + checkRadio( "group 2", "b", m_secondaryForm ); + verifyTwoFormRadios( 1, 0, 0, 0, 1, 0 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + /** tests for a special bug which we once had, where radio buttons lost their state after + * switching spreadsheet pages + */ + public void checkCalcPageSwitch( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( true ); + + m_formLayer.setInsertPage( 0 ); + insertRadio( 15, 20, "group 1 (a)", "group 1", "a" ); + insertRadio( 15, 26, "group 1 (b)", "group 1", "b" ); + + m_formLayer.setInsertPage( 1 ); + XPropertySet xRadio = insertRadio( 15, 20, "group 2 (a)", "group 2", "a" ); + insertRadio( 15, 26, "group 2 (b)", "group 2", "b" ); + m_secondaryForm = (XPropertySet)dbfTools.getParent( xRadio, XPropertySet.class ); + + // switch to alive mode + SpreadsheetView view = (SpreadsheetView)m_document.getCurrentView( ); + view.toggleFormDesignMode( ); + // and do initial checking + checkRadio( "group 1", "a", m_primaryForm ); + view.activateSheet( 1 ); + checkRadio( "group 2", "b", m_secondaryForm ); + + // see whether the check states on the first page survived the page switch + verifySheetRadios( 1, 0, 0, 1 ); + // switch back to the first sheet, and see whether the check states survived + view.activateSheet( 0 ); + verifySheetRadios( 1, 0, 0, 1 ); + // and for completely, check again after switching to third sheet and back to the first + view.activateSheet( 2 ); + view.activateSheet( 1 ); + verifySheetRadios( 1, 0, 0, 1 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + public void after() + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + private void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + } + } + + /* ------------------------------------------------------------------ */ + private void prepareTestStep( boolean useSpreadsheetDocument ) throws com.sun.star.uno.Exception, java.lang.Exception + { + m_primaryForm = null; + + m_document = useSpreadsheetDocument ? new SpreadsheetDocument( m_orb ) : DocumentHelper.blankTextDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + private void cleanupTestStep( ) + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + /** checks or unchecks the radio button (in our primary form) with the given name and the given ref value + */ + private void checkRadio( String groupName, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + checkRadio( groupName, refValue, m_primaryForm ); + } + + /* ------------------------------------------------------------------ */ + /** checks or unchecks the radio button with the given name and the given ref value + */ + private void checkRadio( String groupName, String refValue, XPropertySet form ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet xRadio = getRadioModel( groupName, refValue, form ); + + XRadioButton radioButton = (XRadioButton)UnoRuntime.queryInterface( + XRadioButton.class, m_document.getCurrentView().getControl( xRadio ) ); + radioButton.setState( true ); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet getRadioModel( String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return getRadioModel( name, refValue, m_primaryForm ); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet getRadioModel( String name, String refValue, XPropertySet form ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return m_formLayer.getRadioModelByRefValue( form, name, refValue ); + } + + /* ------------------------------------------------------------------ */ + private String stateString( short[] states ) + { + StringBuffer buf = new StringBuffer(); + for ( int i=0; i<states.length; ++i ) + buf.append( states[i] ); + return buf.toString(); + } + + /* ------------------------------------------------------------------ */ + /** verifies a number of radio buttons for their states + */ + private boolean verifyRadios( XPropertySet[] radios, short[] expectedStates, String errorMessage ) throws com.sun.star.uno.Exception + { + short[] actualStates = new short[radios.length]; + + // collect all current states. This is just to be able to emit them, in case of a failure + for ( int i = 0; i<radios.length; ++i ) + { + actualStates[i] = ((Short)radios[i].getPropertyValue( "State" )).shortValue(); + } + + // now actually check the states + for ( int i = 0; i<radios.length; ++i ) + { + if ( actualStates[i] != expectedStates[i] ) + { + failed( errorMessage + " (expected: " + stateString( expectedStates ) + ", found: " + stateString( actualStates ) + ")" ); + return false; + } + } + + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of the 4 radio buttons from the checkSingleButtons test + */ + private boolean verifySingleRadios( int state1, int state2, int state3, int state4 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[4]; + radios[0] = getRadioModel( "group 1", "" ); + radios[1] = getRadioModel( "group 2", "" ); + radios[2] = getRadioModel( "group 3", "" ); + radios[3] = getRadioModel( "group 4", "" ); + + short[] states = new short[4]; + states[0] = (short)state1; + states[1] = (short)state2; + states[2] = (short)state3; + states[3] = (short)state4; + + return verifyRadios( radios, states, "single-group radio buttons do not work!" ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of 6 radio buttons form the checkThreeGroups test + */ + private boolean verifySixPack( XPropertySet[] radios, String errorMessage, + int state1, int state2, int state3, int state4, int state5, int state6 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + short[] states = new short[6]; + states[0] = (short)state1; + states[1] = (short)state2; + states[2] = (short)state3; + states[3] = (short)state4; + states[4] = (short)state5; + states[5] = (short)state6; + + return verifyRadios( radios, states, errorMessage ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of 6 radio buttons + */ + private boolean verifySixPack( int state1, int state2, int state3, int state4, int state5, int state6 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[6]; + radios[0] = getRadioModel( "group 1", "a" ); + radios[1] = getRadioModel( "group 1", "b" ); + radios[2] = getRadioModel( "group 2", "a" ); + radios[3] = getRadioModel( "group 2", "b" ); + radios[4] = getRadioModel( "group 3", "a" ); + radios[5] = getRadioModel( "group 3", "b" ); + + return verifySixPack( radios, "six radio buttons, forming three different groups, do not properly work!", + state1, state2, state3, state4, state5, state6 ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of the 6 radio buttons in our checkMultipleForms test + */ + private boolean verifyTwoFormRadios( int state1, int state2, int state3, int state4, int state5, int state6 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[6]; + radios[0] = getRadioModel( "group 1", "a", m_primaryForm ); + radios[1] = getRadioModel( "group 1", "b", m_primaryForm ); + radios[2] = getRadioModel( "group 1", "c", m_primaryForm ); + radios[3] = getRadioModel( "group 2", "a", m_secondaryForm ); + radios[4] = getRadioModel( "group 2", "b", m_secondaryForm ); + radios[5] = getRadioModel( "group 2", "c", m_secondaryForm ); + + return verifySixPack( radios, "radio buttons on different forms do not work properly!", + state1, state2, state3, state4, state5, state6 ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of the 4 radio buttons in our spreadsheet document (checkCalcPageSwitch) + */ + private boolean verifySheetRadios( int state1, int state2, int state3, int state4 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[4]; + radios[0] = getRadioModel( "group 1", "a", m_primaryForm ); + radios[1] = getRadioModel( "group 1", "b", m_primaryForm ); + radios[2] = getRadioModel( "group 2", "a", m_secondaryForm ); + radios[3] = getRadioModel( "group 2", "b", m_secondaryForm ); + + short[] states = new short[4]; + states[0] = (short)state1; + states[1] = (short)state2; + states[2] = (short)state3; + states[3] = (short)state4; + + return verifyRadios( radios, states, "seems some of the radio button check states didn't survive the page activation(s)!" ); + } +} + diff --git a/forms/qa/integration/forms/SingleControlValidation.java b/forms/qa/integration/forms/SingleControlValidation.java new file mode 100644 index 000000000000..637e9c9e4e26 --- /dev/null +++ b/forms/qa/integration/forms/SingleControlValidation.java @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.accessibility.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.form.binding.*; +import com.sun.star.form.validation.*; + +import integration.forms.DocumentHelper; + +/** + * + * @author fs@openoffice.org + */ +public class SingleControlValidation implements XFormComponentValidityListener +{ + private DocumentHelper m_document; /// our current test document + private FormLayer m_formLayer; /// quick access to the form layer + private XMultiServiceFactory m_orb; /// our service factory + + private XPropertySet m_inputField; + private XPropertySet m_inputLabel; + private XPropertySet m_statusField; + private XPropertySet m_explanationField; + private XValidator m_validator; + + /* ------------------------------------------------------------------ */ + public SingleControlValidation( DocumentHelper document, int columnPos, int rowPos, String formComponentService, XValidator validator ) + { + m_document = document; + m_validator = validator; + m_formLayer = new FormLayer( m_document ); + createControls( columnPos, rowPos, formComponentService, 1, 0 ); + } + + /* ------------------------------------------------------------------ */ + public SingleControlValidation( DocumentHelper document, int columnPos, int rowPos, String formComponentService, XValidator validator, int controlCount, int controlHeight ) + { + m_document = document; + m_validator = validator; + m_formLayer = new FormLayer( m_document ); + createControls( columnPos, rowPos, formComponentService, controlCount, controlHeight ); + } + + /* ------------------------------------------------------------------ */ + public XPropertySet getInputField() + { + return m_inputField; + } + + /* ------------------------------------------------------------------ */ + public void setExplanatoryText( String text ) + { + try + { + m_inputLabel.setPropertyValue( "Label", text ); + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + private void createControls( int columnPos, int rowPos, String formComponentService, int controlCount, int controlHeight ) + { + try + { + m_inputLabel = m_formLayer.createControlAndShape( "FixedText", columnPos, rowPos, 70, 12, null ); + m_inputLabel.setPropertyValue( "MultiLine", new Boolean( true ) ); + + com.sun.star.awt.FontDescriptor font = (com.sun.star.awt.FontDescriptor)m_inputLabel.getPropertyValue( "FontDescriptor" ); + font.Weight = com.sun.star.awt.FontWeight.BOLD; + m_inputLabel.setPropertyValue( "FontDescriptor", font ); + + if ( controlHeight == 0 ) + controlHeight = 6; + + int controlPos = rowPos + 12; + XPropertySet[] controls = new XPropertySet[ controlCount ]; + for ( int i = 0; i < controlCount; ++i, controlPos += controlHeight ) + { + controls[ i ] = m_formLayer.createControlAndShape( formComponentService, columnPos, controlPos, 25, controlHeight, null ); + controls[ i ].setPropertyValue( "Name", formComponentService ); + controls[ i ].setPropertyValue( "Tag", String.valueOf( i ) ); + + if ( controls[ i ].getPropertySetInfo().hasPropertyByName( "Border" ) ) + controls[ i ].setPropertyValue( "Border", new Short( (short)2 ) ); + + XValidatableFormComponent xComp = (XValidatableFormComponent)UnoRuntime.queryInterface( XValidatableFormComponent.class, + controls[ i ] ); + xComp.addFormComponentValidityListener( this ); + } + m_inputField = controls[ 0 ]; + + // ---------------------------------- + controlPos += 4; + XPropertySet xLabel = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + xLabel.setPropertyValue( "Label", new String( "Status:" ) ); + controlPos += 4; + m_statusField = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + m_statusField.setPropertyValue( "Label", new String( "" ) ); + + // ---------------------------------- + controlPos += 6; + xLabel = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + xLabel.setPropertyValue( "Label", new String( "Explanation for invalidity:" ) ); + controlPos += 4; + m_explanationField = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + m_explanationField.setPropertyValue( "Label", new String( "" ) ); + + XValidatable xValidatable = (XValidatable)UnoRuntime.queryInterface( XValidatable.class, m_inputField ); + xValidatable.setValidator( m_validator ); + } + catch( java.lang.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /* XEventListener overridables */ + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject eventObject ) + { + // not interested in + } + + /* ------------------------------------------------------------------ */ + /* XFormComponentValidityListener overridables */ + /* ------------------------------------------------------------------ */ + public void componentValidityChanged( com.sun.star.lang.EventObject eventObject ) + { + try + { + if ( m_inputField.equals( eventObject.Source ) ) + { + XValidatableFormComponent xComp = (XValidatableFormComponent)UnoRuntime.queryInterface( XValidatableFormComponent.class, + eventObject.Source ); + // the current value + Object value = xComp.getCurrentValue(); + + // the current validity flag + boolean isValid = xComp.isValid(); + + m_statusField.setPropertyValue("Label", isValid ? "valid" : "invalid" ); + m_statusField.setPropertyValue( "TextColor", new Integer( isValid ? 0x008000 : 0x800000 ) ); + + String validityMessage = ""; + if ( !isValid ) + validityMessage = m_validator.explainInvalid( value ); + m_explanationField.setPropertyValue( "Label", validityMessage ); + } + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.out ); + } + } + +} diff --git a/forms/qa/integration/forms/SpreadsheetDocument.java b/forms/qa/integration/forms/SpreadsheetDocument.java new file mode 100644 index 000000000000..8f156fe8e3b6 --- /dev/null +++ b/forms/qa/integration/forms/SpreadsheetDocument.java @@ -0,0 +1,151 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XComponent; +import com.sun.star.table.XCellRange; +import com.sun.star.table.CellAddress; +import com.sun.star.table.CellRangeAddress; +import com.sun.star.container.XIndexAccess; +import com.sun.star.sheet.XSpreadsheetDocument; +import com.sun.star.sheet.XSpreadsheets; +import com.sun.star.beans.NamedValue; + +/** + * + * @author fs93730 + */ +public class SpreadsheetDocument extends DocumentHelper +{ + /** Creates a new blank spreadsheet document */ + /* ------------------------------------------------------------------ */ + public SpreadsheetDocument( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception + { + super( orb, implLoadAsComponent( orb, "private:factory/scalc" ) ); + } + + /* ------------------------------------------------------------------ */ + public SpreadsheetDocument( XMultiServiceFactory orb, XComponent document ) throws com.sun.star.uno.Exception + { + super( orb, document ); + } + + /* ------------------------------------------------------------------ */ + /** returns the sheets collection + */ + public XSpreadsheets getSheets() throws com.sun.star.uno.Exception + { + XSpreadsheetDocument spreadsheetDoc = (XSpreadsheetDocument)UnoRuntime.queryInterface( XSpreadsheetDocument.class, + getDocument() + ); + return spreadsheetDoc.getSheets(); + } + + /* ------------------------------------------------------------------ */ + /** returns the sheet with the given index + */ + public XCellRange getSheet( int index ) throws com.sun.star.uno.Exception + { + XIndexAccess sheets = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + getSheets() + ); + return (XCellRange)UnoRuntime.queryInterface( XCellRange.class, + sheets.getByIndex( index ) + ); + } + + /* ------------------------------------------------------------------ */ + /** creates a value binding for a given cell + */ + public com.sun.star.form.binding.XValueBinding createCellBinding( short sheet, short column, short row ) + { + return createCellBinding( sheet, column, row, false ); + } + + /* ------------------------------------------------------------------ */ + /** creates a value binding which can be used to exchange a list box selection <em>index</em> with a cell + */ + public com.sun.star.form.binding.XValueBinding createListIndexBinding( short sheet, short column, short row ) + { + return createCellBinding( sheet, column, row, true ); + } + + /* ------------------------------------------------------------------ */ + /** creates a value binding for a given cell, with or without support for integer value exchange + */ + private com.sun.star.form.binding.XValueBinding createCellBinding( short sheet, short column, short row, boolean supportIntegerValues ) + { + com.sun.star.form.binding.XValueBinding cellBinding = null; + try + { + CellAddress address = new CellAddress( sheet, column, row ); + Object[] initParam = new Object[] { new NamedValue( "BoundCell", address ) }; + cellBinding = (com.sun.star.form.binding.XValueBinding)UnoRuntime.queryInterface( + com.sun.star.form.binding.XValueBinding.class, + createInstanceWithArguments( + supportIntegerValues ? "com.sun.star.table.ListPositionCellBinding" + : "com.sun.star.table.CellValueBinding", + initParam + ) + ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return cellBinding; + } + + /* ------------------------------------------------------------------ */ + /** creates a source of list entries associated with a (one-column) cell range + */ + public com.sun.star.form.binding.XListEntrySource createListEntrySource( short sheet, short column, + short topRow, short bottomRow ) + { + com.sun.star.form.binding.XListEntrySource entrySource = null; + try + { + CellRangeAddress rangeAddress = new CellRangeAddress( sheet, column, + topRow, column, bottomRow ); + Object[] initParam = new Object[] { new NamedValue( "CellRange", rangeAddress ) }; + entrySource = (com.sun.star.form.binding.XListEntrySource)UnoRuntime.queryInterface( + com.sun.star.form.binding.XListEntrySource.class, + createInstanceWithArguments( + "com.sun.star.table.CellRangeListSource", initParam ) ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return entrySource; + } +} diff --git a/forms/qa/integration/forms/SpreadsheetView.java b/forms/qa/integration/forms/SpreadsheetView.java new file mode 100644 index 000000000000..19f7bd429290 --- /dev/null +++ b/forms/qa/integration/forms/SpreadsheetView.java @@ -0,0 +1,81 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +/* + * SpreadsheetView.java + * + * Created on 2. Oktober 2003, 14:02 + */ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.*; +import com.sun.star.frame.*; +import com.sun.star.sheet.*; +import com.sun.star.container.*; + +import integration.forms.DocumentViewHelper; +import integration.forms.DocumentHelper; + +/** + * + * @author fs93730 + */ +public class SpreadsheetView extends integration.forms.DocumentViewHelper +{ + + /** Creates a new instance of SpreadsheetView */ + public SpreadsheetView( XMultiServiceFactory orb, DocumentHelper document, XController controller ) + { + super( orb, document, controller ); + } + + /** activates the sheet with the given index + */ + void activateSheet( int sheetIndex ) + { + try + { + // get the sheet to activate + XSpreadsheetDocument doc = (XSpreadsheetDocument)UnoRuntime.queryInterface( + XSpreadsheetDocument.class, getDocument().getDocument() ); + XIndexAccess sheets = (XIndexAccess)UnoRuntime.queryInterface( + XIndexAccess.class, doc.getSheets() ); + + XSpreadsheet sheet = (XSpreadsheet)UnoRuntime.queryInterface( + XSpreadsheet.class, sheets.getByIndex( sheetIndex ) ); + + // activate + XSpreadsheetView view = (XSpreadsheetView)UnoRuntime.queryInterface( + XSpreadsheetView.class, getController() ); + view.setActiveSheet( sheet ); + } + catch( com.sun.star.uno.Exception e ) + { + } + } +} diff --git a/forms/qa/integration/forms/TableCellTextBinding.java b/forms/qa/integration/forms/TableCellTextBinding.java new file mode 100644 index 000000000000..6517ed5c90f0 --- /dev/null +++ b/forms/qa/integration/forms/TableCellTextBinding.java @@ -0,0 +1,213 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.table.XCell; +import com.sun.star.util.XModifyListener; +import com.sun.star.beans.XPropertySet; +import com.sun.star.text.XTextRange; +import com.sun.star.form.binding.IncompatibleTypesException; + +/** a value binding to be connected to a form control + + This binding synchronizes the text contained in a table cell (which you must + pass upon construction) to the text in an XBindableValue. + + Well, in real it does not synchronize both directions. The ValueBinding + service has not much room for own activity: It allows notification of changes + in the own value, and it allows external instances to set the current value. + + Note that we implement this binding as a separate thread, which is (more or + less permanently) polling for a new text at the cell. This is unfortunate, but + sadly the Writer table cells do not support actively notifying changes in their + content to other interested parties. +*/ +public class TableCellTextBinding + extends java.lang.Thread + implements com.sun.star.form.binding.XValueBinding, + com.sun.star.util.XModifyBroadcaster +{ + private XTextRange m_cellText; + private Object m_writeSignal; + private String m_newCellText; + private String m_lastKnownCellText; + private boolean m_haveNewCellText; + private java.util.List m_listeners; + + /** Creates a new instance of TableCellTextBinding */ + public TableCellTextBinding( XCell cell ) + { + m_cellText = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, cell ); + + m_newCellText = new String(); + m_listeners = new java.util.LinkedList(); + + start(); + } + + /** retrieves the list of data types which this binding can exchange + */ + public com.sun.star.uno.Type[] getSupportedValueTypes() + { + try + { + // well, only strings here ... + return new Type[] { + getStringType() + }; + } + catch( java.lang.Exception e ) + { + } + return new Type[] { }; + } + + /** retrieves the current value + */ + public Object getValue(com.sun.star.uno.Type type) throws com.sun.star.form.binding.IncompatibleTypesException + { + if ( !type.equals( getStringType() ) ) + throw new com.sun.star.form.binding.IncompatibleTypesException(); + + return m_cellText.getString(); + } + + /** sets a new value + */ + public void setValue(Object obj) throws com.sun.star.form.binding.IncompatibleTypesException + { + String text; + try + { + text = (String)obj; + } + catch( java.lang.ClassCastException e ) + { + throw new com.sun.star.form.binding.IncompatibleTypesException(); + } + // remember the new text + synchronized( m_newCellText ) + { + m_newCellText = text; + m_haveNewCellText = true; + } + // and wake up the thread which is waiting for it + synchronized( m_writeSignal ) + { + m_writeSignal.notify(); + } + } + + /** determines whether a given value type is supported + */ + public boolean supportsType(com.sun.star.uno.Type type) + { + return type.equals( getStringType() ); + } + + /** retrieves the UNO type for the string class + */ + private static final Type getStringType() + { + return new com.sun.star.uno.Type( String.class ); + } + + /** runs the thread + */ + public void run() + { + try + { + m_writeSignal = new Object(); + while ( true ) + { + // go sleep a while + synchronized( m_writeSignal ) + { + m_writeSignal.wait( 200 ); + } + + // if there's new text in the control, propagate it to the cell + synchronized ( m_newCellText ) + { + if ( m_haveNewCellText ) + { + m_cellText.setString( m_newCellText ); + m_lastKnownCellText = m_newCellText; + } + m_haveNewCellText = false; + } + + // if there's new text in the cell, propagate it to the control + String currentCellText = m_cellText.getString(); + if ( !currentCellText.equals( m_lastKnownCellText ) ) + { + m_lastKnownCellText = currentCellText; + // notify the modification + synchronized( m_listeners ) + { + com.sun.star.lang.EventObject eventSource = new com.sun.star.lang.EventObject( this ); + + java.util.Iterator loop = m_listeners.iterator(); + while ( loop.hasNext() ) + { + ((XModifyListener)loop.next()).modified( eventSource ); + } + } + } + } + } + catch( java.lang.Exception e ) + { + e.printStackTrace(System.err); + } + } + + public void addModifyListener(com.sun.star.util.XModifyListener xModifyListener) + { + synchronized( m_listeners ) + { + m_listeners.add( xModifyListener ); + } + } + + public void removeModifyListener(com.sun.star.util.XModifyListener xModifyListener) + { + synchronized( m_listeners ) + { + m_listeners.remove( xModifyListener ); + } + } + + public void disposing(com.sun.star.lang.EventObject eventObject) + { + // not interested in + } +} diff --git a/forms/qa/integration/forms/TestCase.java b/forms/qa/integration/forms/TestCase.java new file mode 100644 index 000000000000..aeaa8048f92c --- /dev/null +++ b/forms/qa/integration/forms/TestCase.java @@ -0,0 +1,158 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XModifiable; + +public abstract class TestCase extends complexlib.ComplexTestCase implements com.sun.star.lang.XEventListener +{ + protected XMultiServiceFactory m_orb; /// our service factory + protected DocumentType m_documentType; /// the type of our document + protected DocumentHelper m_document; /// our current test document + protected FormLayer m_formLayer; + + /** Creates a new instance of TestCase */ + public TestCase( DocumentType docType ) + { + m_documentType = docType; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return this.getClass().getName(); + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one, via (simulated) user input + */ + protected void closeDocumentByUI() + { + try + { + if ( m_document != null ) + { + // first, set the document to "unmodified" + XModifiable docModify = (XModifiable)m_document.query( XModifiable.class ); + docModify.setModified( false ); + + m_document.getCurrentView().dispatch( ".uno:CloseDoc" ); + + // CloseDoc is asynchronous, so wait until it's done - or 1 second, at most + synchronized ( this ) { wait( 1000 ); } + } + } + catch ( java.lang.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + protected void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)m_document.query( XCloseable.class ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /** prepares a new document to work with + */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_document = DocumentHelper.blankDocument( m_orb, m_documentType ); + m_document.getDocument( ).addEventListener( this ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + /* internal methods */ + /* ------------------------------------------------------------------ */ + /** waits for the user to press a key (on the console where she started the java program) + or the document to be closed by the user. + @return + <TRUE/> if the user pressed a key on the console, <FALSE/> if she closed the document + */ + protected boolean waitForUserInput() throws java.lang.Exception + { + synchronized (this) + { + integration.forms.WaitForInput aWait = new integration.forms.WaitForInput( this ); + aWait.start(); + wait(); + + // if the waiter thread is done, the user pressed enter + boolean bKeyPressed = aWait.isDone(); + if ( !bKeyPressed ) + aWait.interrupt(); + + return bKeyPressed; + } + } + + /* ------------------------------------------------------------------ */ + /* XEventListener overridables */ + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject eventObject ) + { + if ( m_document.getDocument().equals( eventObject.Source ) ) + { + // notify ourself that we can stop waiting for user input + synchronized (this) + { + notify(); + } + } + } +} diff --git a/forms/qa/integration/forms/TestSkeleton.java b/forms/qa/integration/forms/TestSkeleton.java new file mode 100644 index 000000000000..2736395ff400 --- /dev/null +++ b/forms/qa/integration/forms/TestSkeleton.java @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.Exception; + +public class TestSkeleton extends TestCase +{ + /** Creates a new instance of TestSkeleton */ + public TestSkeleton() + { + super( DocumentType.WRITER ); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkTestSkeleton" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Test Skeleton"; + } + + /* ------------------------------------------------------------------ */ + public void checkTestSkeleton() throws com.sun.star.uno.Exception, java.lang.Exception + { + } + + /* ------------------------------------------------------------------ */ + public void before() throws Exception, java.lang.Exception + { + super.before(); + } + + /* ------------------------------------------------------------------ */ + public void after() throws Exception, java.lang.Exception + { + super.before(); + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + } + } diff --git a/forms/qa/integration/forms/TextValidator.java b/forms/qa/integration/forms/TextValidator.java new file mode 100644 index 000000000000..db340f93abcc --- /dev/null +++ b/forms/qa/integration/forms/TextValidator.java @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class TextValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public TextValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + String value = (String)Value; + if ( containsZs( value ) ) + return "No Z's allowed here"; + if ( !isProperChunks( value ) ) + return "Need 3 * n characters"; + } + catch( java.lang.Exception e ) + { + return "ooops. Unknown error"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + String value = (String)Value; + if ( containsZs( value ) ) + return false; + if ( !isProperChunks( value ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } + + private boolean isProperChunks( String value ) + { + return ( value.length() % 3 ) == 0; + } + + private boolean containsZs( String value ) + { + if ( ( value.indexOf( 'Z' ) != -1 ) + || ( value.indexOf( 'z' ) != -1 ) + ) + return true; + return false; + } +} diff --git a/forms/qa/integration/forms/TimeValidator.java b/forms/qa/integration/forms/TimeValidator.java new file mode 100644 index 000000000000..116f98455d94 --- /dev/null +++ b/forms/qa/integration/forms/TimeValidator.java @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class TimeValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public TimeValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return "empty input"; + + com.sun.star.util.Time timeValue = (com.sun.star.util.Time)Value; + if ( isInvalidTime( timeValue ) ) + return "this is no valid time"; + if ( !isFullHour( timeValue ) ) + return "time must denote a full hour"; + } + catch( java.lang.Exception e ) + { + return "this is no valid time"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return false; + + com.sun.star.util.Time timeValue = (com.sun.star.util.Time) + com.sun.star.uno.AnyConverter.toObject( + com.sun.star.util.Time.class, Value); + if ( isInvalidTime( timeValue ) ) + return false; + if ( !isFullHour( timeValue ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + e.printStackTrace( System.err ); + } + return false; + } + + private boolean isInvalidTime( com.sun.star.util.Time timeValue ) + { + return ( timeValue.Hours == -1 ) && ( timeValue.Minutes == -1 ) && ( timeValue.Seconds == -1 ) && ( timeValue.HundredthSeconds == -1 ); + } + + private boolean isFullHour( com.sun.star.util.Time timeValue ) + { + return ( timeValue.Minutes == 0 ) && ( timeValue.Seconds == 0 ) && ( timeValue.HundredthSeconds == 0 ); + } +} diff --git a/forms/qa/integration/forms/ValueBinding.java b/forms/qa/integration/forms/ValueBinding.java new file mode 100644 index 000000000000..cec1b6d200c2 --- /dev/null +++ b/forms/qa/integration/forms/ValueBinding.java @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.XPropertySet; +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XText; +import com.sun.star.text.XTextTable; +import com.sun.star.text.XTextCursor; +import com.sun.star.form.binding.XValueBinding; +import com.sun.star.form.binding.XBindableValue; + +import integration.forms.DocumentHelper; +import integration.forms.TableCellTextBinding; + +public class ValueBinding extends integration.forms.TestCase +{ + /** Creates a new instance of ValueBinding */ + public ValueBinding() + { + super( DocumentType.WRITER ); + } + + public static boolean isInteractiveTest() + { + return true; + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkBindingProperties" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control Value Binding Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.before(); + prepareDocument(); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.waitForUserInput(); + super.closeDocument(); + } + + /* ------------------------------------------------------------------ */ + public void checkBindingProperties() throws com.sun.star.uno.Exception, java.lang.Exception + { + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + + // insert a table with exactly one cell. The content of this table will be synced with + // the content of a form control + XTextDocument textDoc = (XTextDocument)UnoRuntime.queryInterface( XTextDocument.class, m_document.getDocument() ); + XText documentText = textDoc.getText(); + XTextCursor textCursor = documentText.createTextCursor(); + + XTextTable table = (XTextTable)UnoRuntime.queryInterface( XTextTable.class, + m_document.createInstance( "com.sun.star.text.TextTable" ) + ); + table.initialize( 1, 1 ); + documentText.insertTextContent( textCursor, table, false ); + + // insert our sample control + XPropertySet textControl = m_formLayer.insertControlLine( "DatabaseTextField", "Test", "", 10 ); + + // create a value binding for the first cell of the table + XValueBinding cellBinding = new TableCellTextBinding( table.getCellByName( "A1" ) ); + // and bind it to the control + XBindableValue bindable = (XBindableValue)UnoRuntime.queryInterface( + XBindableValue.class, textControl + ); + bindable.setValueBinding( cellBinding ); + + // toggle the view to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + } + } diff --git a/forms/qa/integration/forms/WaitForInput.java b/forms/qa/integration/forms/WaitForInput.java new file mode 100644 index 000000000000..f0109aa485d4 --- /dev/null +++ b/forms/qa/integration/forms/WaitForInput.java @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +class WaitForInput extends java.lang.Thread +{ + private Object m_aToNotify; + private boolean m_bDone; + + public WaitForInput( Object aToNotify ) + { + m_aToNotify = aToNotify; + m_bDone = false; + } + + public boolean isDone() + { + return m_bDone; + } + + public void run() + { + try + { + System.out.println( "\npress enter to exit" ); + System.in.read(); + + m_bDone = true; + // notify that the user pressed the key + synchronized (m_aToNotify) + { + m_aToNotify.notify(); + } + } + catch( java.lang.Exception e ) + { + // not really interested in + System.err.println( e ); + } + } +}; + diff --git a/forms/qa/integration/forms/XMLFormSettings.java b/forms/qa/integration/forms/XMLFormSettings.java new file mode 100644 index 000000000000..e3881bfa861d --- /dev/null +++ b/forms/qa/integration/forms/XMLFormSettings.java @@ -0,0 +1,229 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.form.binding.IncompatibleTypesException; +import com.sun.star.form.binding.XBindableValue; +import com.sun.star.form.binding.XValueBinding; +import com.sun.star.frame.XStorable; +import com.sun.star.io.IOException; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.CloseVetoException; +import com.sun.star.util.XCloseable; +import com.sun.star.xml.dom.XNode; +import com.sun.star.xsd.DataTypeClass; +import java.io.File; +import org.openoffice.xforms.Instance; +import org.openoffice.xforms.Model; +import org.openoffice.xforms.XMLDocument; + +public class XMLFormSettings extends complexlib.ComplexTestCase +{ + private XMultiServiceFactory m_orb; + private XMLDocument m_document; + private Model m_defaultModel; + private FormLayer m_formLayer; + private XPropertySet m_stringBinding; + private XPropertySet m_booleanBinding; + private XPropertySet m_dateBinding; + + /** Creates a new instance of XMLFormSettings */ + public XMLFormSettings() + { + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkExternalData" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control Spreadsheet Cell Binding Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws java.lang.Exception + { + // create the document and assign related members + m_orb = (XMultiServiceFactory)param.getMSF(); + m_document = new XMLDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + + // create a simple structure in the DOM tree: an element with two attributes + String[] modelNames = m_document.getXFormModelNames(); + m_defaultModel = m_document.getXFormModel( modelNames[0] ); + Instance defaultInstance = m_defaultModel.getDefaultInstance(); + XNode stringElement = defaultInstance.createElement( "stringElement" ); + XNode booleanAttrib = defaultInstance.createAttribute( stringElement, "booleanAttribute", "true" ); + XNode dateAttrib = defaultInstance.createAttribute( stringElement, "dateAttribute" ); + + // when it comes to saving and loading, only one child of the root element of the instance + // is handled (is this a bug? see xmloff/source/xforms/XFormsInstanceContext.cxx, method + // CreateChildContext). + // So, we remove the default node of the instance which it has all the time + defaultInstance.removeNode( "instanceData" ); + + assure( "booleanAttrib's parent is wrong", + UnoRuntime.areSame( stringElement, booleanAttrib.getParentNode() ) ); + assure( "dateAttrib's parent is wrong", + UnoRuntime.areSame( stringElement, dateAttrib.getParentNode() ) ); + + // also create bindings for the element and its attributes, of the proper type + m_stringBinding = m_defaultModel.createBindingForNode( stringElement, DataTypeClass.STRING ); + m_booleanBinding = m_defaultModel.createBindingForNode( booleanAttrib, DataTypeClass.BOOLEAN ); + m_dateBinding = m_defaultModel.createBindingForNode( dateAttrib, DataTypeClass.DATE ); + + // TODO: set up the bindings so that the date bindings is relevant if and only if + // the boolean value is true + + // store the document + File tempFile = File.createTempFile( "xmlforms", ".odt" ); + tempFile.deleteOnExit(); + String fileURL = tempFile.toURL().toExternalForm(); + XStorable store = (XStorable)UnoRuntime.queryInterface( XStorable.class, + m_document.getDocument() ); + store.storeAsURL( fileURL, new PropertyValue[] {} ); + assure( "document still modified after saving it", !m_document.isModified() ); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + impl_closeDocument(); + } + + /* ------------------------------------------------------------------ */ + private void impl_closeDocument() throws CloseVetoException + { + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + + /* ------------------------------------------------------------------ */ + private static void impl_bind( XPropertySet _control, XPropertySet _binding ) throws IncompatibleTypesException + { + XBindableValue bindableControl = (XBindableValue)UnoRuntime.queryInterface( + XBindableValue.class, _control ); + XValueBinding binding = (XValueBinding)UnoRuntime.queryInterface( + XValueBinding.class, _binding ); + bindableControl.setValueBinding( binding ); + } + + /* ------------------------------------------------------------------ */ + /** checks if master-detail relationships including multiple keys work + */ + public void checkExternalData() throws com.sun.star.uno.Exception, java.lang.Exception + { + // some controls + XPropertySet stringControl = m_formLayer.createLabeledControl( + "DatabaseTextField", "Task", 10, 10, 6 ); + impl_bind( stringControl, m_stringBinding ); + + XPropertySet booleanControl = m_formLayer.createControlAndShape( + "DatabaseCheckBox", 35, 18, 25, 6 ); + booleanControl.setPropertyValue( "Label", "has due date" ); + impl_bind( booleanControl, m_booleanBinding ); + + XPropertySet dateControl = m_formLayer.createControlAndShape( + "DatabaseDateField", 40, 26, 25, 6 ); + dateControl.setPropertyValue( "Dropdown", new Boolean( true ) ); + impl_bind( dateControl, m_dateBinding ); + + m_document.getCurrentView( ).toggleFormDesignMode( ); + + // ensure the model is set up as containing "document-internal" data + m_defaultModel.setIsDocumentInternalData( true ); + assure( "setting up the document to contain 'internal data' failed", + m_defaultModel.getIsDocumentInternalData() ); + impl_storeDocument(); + + // okay, here we go ... + // what this particular test is about is to check whether we can set up the model + // so that any changes to any controls bound to any data in this model actually marks + // the containing document as modified + m_formLayer.userTextInput( stringControl, "don't break this test" ); + assure( "model data changed, but document is not modified", + m_document.isModified() ); + + // TODO: do this with the other control/binding types, too + + // no the other way round: set up the model to contain "document-external" data + m_defaultModel.setIsDocumentInternalData( false ); + assure( "setting up the document to contain 'internal data' failed", + !m_defaultModel.getIsDocumentInternalData() ); + impl_storeDocument(); + + // and check that now, changes in the controls / model data are not reflected in + // document's modified state + m_formLayer.userTextInput( stringControl, "(or any other test, that is)" ); + assure( "model data changed, but document is modified", + !m_document.isModified() ); + + // ................................................................. + // finally, check whether the flag survives loading and saving + Model internalDataModel = m_document.addXFormModel( "internalData" ); + internalDataModel.setIsDocumentInternalData( true ); + Model externalDataModel = m_document.addXFormModel( "externalData" ); + externalDataModel.setIsDocumentInternalData( false ); + + impl_storeDocument(); + m_document.reload(); + + internalDataModel = m_document.getXFormModel( "internalData" ); + externalDataModel = m_document.getXFormModel( "externalData" ); + + assure( "setting up a model to contain 'internal data' did not survive reloading", + internalDataModel.getIsDocumentInternalData() ); + assure( "setting up a model to contain 'external data' did not survive reloading", + !externalDataModel.getIsDocumentInternalData() ); + } + + /* ------------------------------------------------------------------ */ + /** stores our document + * @throws com.sun.star.io.IOException + */ + private void impl_storeDocument() throws IOException + { + XStorable store = (XStorable)UnoRuntime.queryInterface( XStorable.class, + m_document.getDocument() ); + store.store(); + assure( "document still modified after saving it", !m_document.isModified() ); + } +} diff --git a/forms/qa/integration/forms/dbfTools.java b/forms/qa/integration/forms/dbfTools.java new file mode 100644 index 000000000000..8588cf8a0f55 --- /dev/null +++ b/forms/qa/integration/forms/dbfTools.java @@ -0,0 +1,55 @@ +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.*; +import com.sun.star.beans.*; +import com.sun.star.container.*; + +/** provides global helpers +*/ +class dbfTools +{ + /* ------------------------------------------------------------------ */ + /** disposes the component given + */ + static public void disposeComponent( Object xComp ) throws java.lang.RuntimeException + { + XComponent xComponent = queryComponent( xComp ); + if ( null != xComponent ) + xComponent.dispose(); + } + + /* ------------------------------------------------------------------ */ + /** queries an object for the XPropertySet interface + */ + static public XPropertySet queryPropertySet( Object aComp ) + { + return UnoRuntime.queryInterface( XPropertySet.class, aComp ); + } + + /* ------------------------------------------------------------------ */ + /** queries an object for the XIndexContainer interface + */ + static public XIndexContainer queryIndexContainer( Object aComp ) + { + return UnoRuntime.queryInterface( XIndexContainer.class, aComp ); + } + + /* ------------------------------------------------------------------ */ + /** queries an object for the XComponent interface + */ + static public XComponent queryComponent( Object aComp ) + { + return UnoRuntime.queryInterface( XComponent.class, aComp ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the parent of the given object + */ + @SuppressWarnings("unchecked") + static Object getParent( Object aComponent, Class aInterfaceClass ) + { + XChild xAsChild = UnoRuntime.queryInterface( XChild.class, aComponent ); + return UnoRuntime.queryInterface( aInterfaceClass, xAsChild.getParent() ); + } +}; diff --git a/forms/qa/makefile.mk b/forms/qa/makefile.mk new file mode 100644 index 000000000000..1f12a8cf4a74 --- /dev/null +++ b/forms/qa/makefile.mk @@ -0,0 +1,91 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = .. +TARGET = FormIntegrationTest +PRJNAME = forms + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +.IF "$(BUILD_QADEVOOO)" == "YES" +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar ConnectivityTools.jar +JAVAFILES := $(shell @$(FIND) org -name "*.java") \ + $(shell @$(FIND) integration -name "*.java") +JAVACLASSFILES := $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(i:d)$/$(i:b).class) + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +#JARCLASSDIRS = +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE + +# --- Runner Settings ---------------------------------------------- + +# classpath and argument list +RUNNER_CLASSPATH = -cp "$(CLASSPATH)$(PATH_SEPERATOR)$(SOLARBINDIR)$/OOoRunner.jar$(PATH_SEPERATOR)$(SOLARBINDIR)$/ConnectivityTools.jar" +RUNNER_ARGS = org.openoffice.Runner -TestBase java_complex +.END + +# --- Targets ------------------------------------------------------ + +.IF "$(depend)" == "" +ALL : ALLTAR + @echo ----------------------------------------------------- + @echo - do a 'dmake show_targets' to show available targets + @echo ----------------------------------------------------- +.ELSE +ALL: ALLDEP +.ENDIF + +.INCLUDE : target.mk + +test: + echo $(SOLARBINDIR) + +.IF "$(BUILD_QADEVOOO)" == "YES" +show_targets: + +@$(AUGMENT_LIBRARY_PATH) java $(RUNNER_CLASSPATH) complexlib.ShowTargets $(foreach,i,$(JAVAFILES) $(i:s/.\$///:s/.java//)) + +run: + +$(COPY) integration$/forms$/*.props $(CLASSDIR)$/$(PACKAGE) && $(AUGMENT_LIBRARY_PATH) java $(RUNNER_CLASSPATH) $(RUNNER_ARGS) -sce forms_all.sce + +run_%: + +$(COPY) integration$/forms$/*.props $(CLASSDIR)$/$(PACKAGE) && $(AUGMENT_LIBRARY_PATH) java $(RUNNER_CLASSPATH) $(RUNNER_ARGS) -o integration.$(PRJNAME).$(@:s/run_//) + +.ELSE +run: show_targets + +show_targets: + +@echo "Built without qadevOOo, no QA tests" + +.ENDIF diff --git a/forms/qa/org/openoffice/complex/forms/tools/ResultSet.java b/forms/qa/org/openoffice/complex/forms/tools/ResultSet.java new file mode 100644 index 000000000000..7763afe6b262 --- /dev/null +++ b/forms/qa/org/openoffice/complex/forms/tools/ResultSet.java @@ -0,0 +1,264 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.complex.forms.tools; + +import com.sun.star.container.XNameAccess; +import com.sun.star.io.XInputStream; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XArray; +import com.sun.star.sdbc.XBlob; +import com.sun.star.sdbc.XClob; +import com.sun.star.sdbc.XRef; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.sdbc.XRow; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.Date; +import com.sun.star.util.DateTime; +import com.sun.star.util.Time; + +/** + * + * @author frank.schoenheit@sun.com + */ +public class ResultSet implements XResultSet, XRow +{ + private final XResultSet m_resultSet; + private final XRow m_row; + + public ResultSet( final Object _resultSet ) + { + m_resultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, _resultSet ); + m_row = (XRow)UnoRuntime.queryInterface( XRow.class, _resultSet ); + } + + public + boolean next() throws SQLException + { + return m_resultSet.next(); + } + + public + boolean isBeforeFirst() throws SQLException + { + return m_resultSet.isBeforeFirst(); + } + + public + boolean isAfterLast() throws SQLException + { + return m_resultSet.isAfterLast(); + } + + public + boolean isFirst() throws SQLException + { + return m_resultSet.isFirst(); + } + + public + boolean isLast() throws SQLException + { + return m_resultSet.isLast(); + } + + public + void beforeFirst() throws SQLException + { + m_resultSet.beforeFirst(); + } + + public + void afterLast() throws SQLException + { + m_resultSet.afterLast(); + } + + public + boolean first() throws SQLException + { + return m_resultSet.first(); + } + + public + boolean last() throws SQLException + { + return m_resultSet.last(); + } + + public + int getRow() throws SQLException + { + return m_resultSet.getRow(); + } + + public + boolean absolute( int _row ) throws SQLException + { + return m_resultSet.absolute( _row ); + } + + public + boolean relative( int _offset ) throws SQLException + { + return m_resultSet.relative( _offset ); + } + + public + boolean previous() throws SQLException + { + return m_resultSet.previous(); + } + + public + void refreshRow() throws SQLException + { + m_resultSet.refreshRow(); + } + + public + boolean rowUpdated() throws SQLException + { + return m_resultSet.rowUpdated(); + } + + public + boolean rowInserted() throws SQLException + { + return m_resultSet.rowInserted(); + } + + public + boolean rowDeleted() throws SQLException + { + return m_resultSet.rowDeleted(); + } + + public + Object getStatement() throws SQLException + { + return m_resultSet.getStatement(); + } + + public + boolean wasNull() throws SQLException + { + return m_row.wasNull(); + } + + public + String getString( int _colIndex ) throws SQLException + { + return m_row.getString( _colIndex ); + } + + public + boolean getBoolean( int _colIndex ) throws SQLException + { + return m_row.getBoolean( _colIndex ); + } + + public + byte getByte( int _colIndex ) throws SQLException + { + return m_row.getByte( _colIndex ); + } + + public + short getShort( int _colIndex ) throws SQLException + { + return m_row.getShort( _colIndex ); + } + + public + int getInt( int _colIndex ) throws SQLException + { + return m_row.getInt( _colIndex ); + } + + public + long getLong( int _colIndex ) throws SQLException + { + return m_row.getLong( _colIndex ); + } + + public + float getFloat( int _colIndex ) throws SQLException + { + return m_row.getFloat( _colIndex ); + } + + public + double getDouble( int _colIndex ) throws SQLException + { + return m_row.getDouble( _colIndex ); + } + + public + byte[] getBytes( int _colIndex ) throws SQLException + { + return m_row.getBytes( _colIndex ); + } + + public + Date getDate( int _colIndex ) throws SQLException + { + return m_row.getDate( _colIndex ); + } + + public + Time getTime( int _colIndex ) throws SQLException + { + return m_row.getTime( _colIndex ); + } + + public + DateTime getTimestamp( int _colIndex ) throws SQLException + { + return m_row.getTimestamp( _colIndex ); + } + + public + XInputStream getBinaryStream( int _colIndex ) throws SQLException + { + return m_row.getBinaryStream( _colIndex ); + } + + public + XInputStream getCharacterStream( int _colIndex ) throws SQLException + { + return m_row.getCharacterStream( _colIndex ); + } + + public + Object getObject( int _colIndex, XNameAccess _typeMap ) throws SQLException + { + return m_row.getObject( _colIndex, _typeMap ); + } + + public + XRef getRef( int _colIndex ) throws SQLException + { + return m_row.getRef( _colIndex ); + } + + public + XBlob getBlob( int _colIndex ) throws SQLException + { + return m_row.getBlob( _colIndex ); + } + + public + XClob getClob( int _colIndex ) throws SQLException + { + return m_row.getClob( _colIndex ); + } + + public + XArray getArray( int _colIndex ) throws SQLException + { + return m_row.getArray( _colIndex ); + } +} diff --git a/forms/qa/org/openoffice/xforms/Instance.java b/forms/qa/org/openoffice/xforms/Instance.java new file mode 100644 index 000000000000..5e4e04741995 --- /dev/null +++ b/forms/qa/org/openoffice/xforms/Instance.java @@ -0,0 +1,198 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.xforms; + +import com.sun.star.xml.dom.DOMException; +import com.sun.star.xml.dom.XDocument; +import com.sun.star.xml.dom.XNode; +import com.sun.star.xml.dom.XNodeList; +import java.util.NoSuchElementException; + +/** + * + * @author fs93730 + */ +public class Instance +{ + private Model m_model; + private XDocument m_domInstance; + + protected Instance( Model _model, XDocument _domInstance ) + { + m_model = _model; + m_domInstance = _domInstance; + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below the root node of the instance. + * + * @param _elementName + * the name of the to-be-created element + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( String _elementName ) throws DOMException + { + return createElement( m_domInstance, _elementName, null ); + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below the root node of the instance. + * + * @param _elementName + * the name of the to-be-created element + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( String _elementName, String _initialNodeValue ) throws DOMException + { + return createElement( m_domInstance, _elementName, _initialNodeValue ); + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below a given XNode. + * + * @param _parentElement + * the node whose child shall be created + * @param _elementName + * the name of the to-be-created element + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( XNode _parentElement, String _elementName ) throws DOMException + { + return createElement( _parentElement, _elementName, null ); + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below a given XNode. + * + * @param _parentElement + * the node whose child shall be created + * @param _elementName + * the name of the to-be-created element + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( XNode _parentElement, String _elementName, String _initialNodeValue ) throws DOMException + { + XNode node = _parentElement.appendChild( + m_model.getUIHelper().createElement( _parentElement, _elementName ) + ); + if ( _initialNodeValue != null ) + node.setNodeValue( _initialNodeValue ); + return node; + } + + /** removes a child of the root-level node from the instance + * + * @param _elementName + * the name of the to-be-removed child + */ + public XNode removeNode( String _elementName ) throws DOMException + { + return removeNode( m_domInstance, _elementName ); + } + + /** removes a node from the instance + * + * @param _parentElement + * the node whose child is to be removed + * @param _elementName + * the name of the to-be-removed child + */ + public XNode removeNode( XNode _parentElement, String _elementName ) throws DOMException + { + XNodeList nodes = _parentElement.getChildNodes(); + for ( int i=0; i<nodes.getLength(); ++i ) + { + XNode node = nodes.item(i); + if ( node.getLocalName().equals( _elementName ) ) + { + _parentElement.removeChild( node ); + return node; + } + } + throw new NoSuchElementException(); + } + + /** creates an attribute for the root node of the instance + * + * @param _attribName + * the name of the to-be-created attribute + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( String _attribName ) throws DOMException + { + return createAttribute( m_domInstance, _attribName, null ); + } + + /** creates an attribute for the root node of the instance + * + * @param _attribName + * the name of the to-be-created attribute + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( String _attribName, String _initialNodeValue ) throws DOMException + { + return createAttribute( m_domInstance, _attribName, _initialNodeValue ); + } + + /** creates an attribute for the given node + * + * @param _parentElement + * the element at which the attribute should be created + * @param _attribName + * the name of the to-be-created attribute + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( XNode _parentElement, String _attribName ) throws DOMException + { + return createAttribute( _parentElement, _attribName, null ); + } + + /** creates an attribute for the given node + * + * @param _parentElement + * the element at which the attribute should be created + * @param _attribName + * the name of the to-be-created attribute + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( XNode _parentElement, String _attribName, String _initialNodeValue ) throws DOMException + { + XNode node = _parentElement.appendChild( + m_model.getUIHelper().createAttribute( _parentElement, _attribName ) + ); + if ( _initialNodeValue != null ) + node.setNodeValue( _initialNodeValue ); + return node; + } +} diff --git a/forms/qa/org/openoffice/xforms/Model.java b/forms/qa/org/openoffice/xforms/Model.java new file mode 100644 index 000000000000..ee4ed6caa7e8 --- /dev/null +++ b/forms/qa/org/openoffice/xforms/Model.java @@ -0,0 +1,100 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.xforms; + +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.xforms.XFormsUIHelper1; +import com.sun.star.xforms.XModel; +import com.sun.star.xml.dom.XNode; + +/** encapsulates an XForms model + * + * @author fs93730 + */ +public class Model +{ + private XModel m_model; + private XPropertySet m_modelProps; + private XFormsUIHelper1 m_helper; + + protected Model( Object _model ) + { + m_model = (XModel)UnoRuntime.queryInterface( XModel.class, _model ); + m_modelProps = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, _model ); + m_helper = (XFormsUIHelper1)UnoRuntime.queryInterface( XFormsUIHelper1.class, + m_model ); + } + + protected XModel getXModel() + { + return m_model; + } + + protected XFormsUIHelper1 getUIHelper() + { + return m_helper; + } + + public Instance getDefaultInstance() + { + return new Instance( this, m_model.getDefaultInstance() ); + } + + /** creates a binding for the given DOM node + * + * @param _node + * the DOM node to create a binding for + * @param _dataType + * the data type to be used for the binding + * @return + */ + public XPropertySet createBindingForNode( XNode _node, short _dataTypeClass ) + { + XPropertySet binding = m_helper.getBindingForNode(_node, true); + try + { + String basicTypeName = (String)m_model.getDataTypeRepository().getBasicDataType( _dataTypeClass ). + getPropertyValue( "Name" ); + binding.setPropertyValue( "Type", basicTypeName ); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + return binding; + } + + public void setIsDocumentInternalData( boolean _internalData ) + { + try + { + m_modelProps.setPropertyValue("ExternalData", new Boolean(!_internalData)); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + public boolean getIsDocumentInternalData() + { + boolean isInternalData = false; + try + { + isInternalData = !((Boolean)m_modelProps.getPropertyValue( "ExternalData" )).booleanValue(); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + return isInternalData; + } +} diff --git a/forms/qa/org/openoffice/xforms/XMLDocument.java b/forms/qa/org/openoffice/xforms/XMLDocument.java new file mode 100644 index 000000000000..9ca35b3801da --- /dev/null +++ b/forms/qa/org/openoffice/xforms/XMLDocument.java @@ -0,0 +1,96 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.xforms; + +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XNameContainer; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.xforms.XFormsSupplier; +import com.sun.star.xforms.XFormsUIHelper1; +import com.sun.star.xforms.XModel; +import integration.forms.DocumentType; + +/** + * + * @author fs93730 + */ +public class XMLDocument extends integration.forms.DocumentHelper +{ + private XFormsSupplier m_formsSupplier; + private XNameContainer m_forms; + + /* ------------------------------------------------------------------ */ + public XMLDocument( XMultiServiceFactory _orb ) throws Exception + { + super( _orb, implLoadAsComponent( _orb, getDocumentFactoryURL( DocumentType.XMLFORM ) ) ); + impl_initialize( getDocument() ); + } + + /* ------------------------------------------------------------------ */ + public XMLDocument( XMultiServiceFactory _orb, XComponent _document ) + { + super( _orb, _document ); + impl_initialize( _document ); + } + + /* ------------------------------------------------------------------ */ + private void impl_initialize( XComponent _document ) + { + m_formsSupplier = (XFormsSupplier)UnoRuntime.queryInterface( XFormsSupplier.class, + _document ); + + if ( m_formsSupplier == null ) + throw new IllegalArgumentException(); + + m_forms = m_formsSupplier.getXForms(); + } + + /* ------------------------------------------------------------------ */ + public String[] getXFormModelNames() + { + return m_forms.getElementNames(); + } + + /* ------------------------------------------------------------------ */ + public Model getXFormModel( String _modelName ) throws NoSuchElementException + { + try + { + return new Model(m_forms.getByName(_modelName)); + } + catch (WrappedTargetException ex) + { + throw new NoSuchElementException(); + } + } + + /* ------------------------------------------------------------------ */ + public Model addXFormModel( String _modelName ) + { + XModel newModel = null; + try + { + newModel = (XModel) UnoRuntime.queryInterface( XModel.class, + getOrb().createInstance( "com.sun.star.xforms.Model" ) ); + newModel.setID(_modelName); + XFormsUIHelper1 modelHelper = (XFormsUIHelper1) UnoRuntime.queryInterface( + XFormsUIHelper1.class, newModel ); + modelHelper.newInstance( "Instance 1", new String(), true ); + newModel.initialize(); + + m_forms.insertByName(_modelName, newModel); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + return new Model( newModel ); + } +} diff --git a/forms/qa/unoapi/forms.sce b/forms/qa/unoapi/forms.sce new file mode 100644 index 000000000000..97e9c7422f35 --- /dev/null +++ b/forms/qa/unoapi/forms.sce @@ -0,0 +1,40 @@ +-o forms.OButtonControl +-o forms.OButtonModel +-o forms.OCheckBoxControl +-o forms.OCheckBoxModel +-o forms.OComboBoxControl +-o forms.OComboBoxModel +-o forms.OCurrencyControl +-o forms.OCurrencyModel +#-o forms.ODatabaseForm +-o forms.ODateControl +-o forms.ODateModel +-o forms.OEditControl +-o forms.OEditModel +-o forms.OFileControlModel +-o forms.OFixedTextModel +-o forms.OFormattedControl +-o forms.OFormattedFieldWrapper +# LäSST EIN DOKUMENT OFFEN -o forms.OFormsCollection +-o forms.OGridControlModel +-o forms.OGroupBoxControl +-o forms.OGroupBoxModel +-o forms.OHiddenModel +-o forms.OImageButtonControl +-o forms.OImageButtonModel +-o forms.OImageControlControl +-o forms.OImageControlModel +-o forms.OListBoxControl +-o forms.OListBoxModel +-o forms.ONavigationBarControl +-o forms.ONavigationBarModel +-o forms.ONumericControl +-o forms.ONumericModel +-o forms.OPatternControl +-o forms.OPatternModel +-o forms.ORadioButtonControl +-o forms.ORadioButtonModel +-o forms.OScrollBarModel +-o forms.OSpinButtonModel +-o forms.OTimeControl +-o forms.OTimeModel diff --git a/forms/qa/unoapi/knownissues.xcl b/forms/qa/unoapi/knownissues.xcl new file mode 100644 index 000000000000..1cec8ac106a2 --- /dev/null +++ b/forms/qa/unoapi/knownissues.xcl @@ -0,0 +1,118 @@ +### i45204 ### +forms.OCurrencyModel::com::sun::star::form::XUpdateBroadcaster + +### i84235 ### +forms.ODatabaseForm::com::sun::star::sdbc::XWarningsSupplier + +### i45204 ### +forms.OCurrencyModel::com::sun::star::form::XUpdateBroadcaster + +### i79098 ### +forms.OScrollBarModel::com::sun::star::awt::UnoControlScrollBarModel + +### i79100 ### +forms.ORadioButtonModel::com::sun::star::awt::UnoControlRadioButtonModel + +### i79108 ### +forms.OButtonControl::com::sun::star::form::submission::XSubmission + +### i79108 ### +forms.OImageButtonControl::com::sun::star::form::submission::XSubmission + +### i79109 ### +forms.OFixedTextModel::com::sun::star::awt::UnoControlFixedTextModel + +### i79110 ### +forms.OCheckBoxModel::com::sun::star::awt::UnoControlCheckBoxModel + +### i79111 ### +forms.OButtonModel::com::sun::star::awt::UnoControlButtonModel + +### i84283 ### +forms.ODatabaseForm::com::sun::star::form::XDatabaseParameterBroadcaster + +### i84298 ### +forms.ODatabaseForm::com::sun::star::sdbc::XParameters + +### i73994 ### +forms.OEditModel::com::sun::star::style::ParagraphProperties + +### i84311 ### +forms.OFixedTextModel::com::sun::star::beans::XMultiPropertySet + +### i84311 ### +forms.OFixedTextModel::com::sun::star::beans::XFastPropertySet + +### i84314 ### +forms.OImageButtonModel::com::sun::star::awt::UnoControlImageControlModel + +### i84315 ### +forms.OImageControlModel::com::sun::star::awt::UnoControlImageControlModel + +### i84316 ### +forms.ONumericModel::com::sun::star::form::XUpdateBroadcaster + +### i46489 ### +forms.ORadioButtonControl::com::sun::star::awt::XWindow +forms.OCheckBoxControl::com::sun::star::awt::XWindow +forms.OGroupBoxControl::com::sun::star::awt::XWindow +forms.OListBoxControl::com::sun::star::awt::XWindow +forms.OComboBoxControl::com::sun::star::awt::XWindow +forms.OEditControl::com::sun::star::awt::XWindow +forms.ODateControl::com::sun::star::awt::XWindow +forms.OTimeControl::com::sun::star::awt::XWindow +forms.ONumericControl::com::sun::star::awt::XWindow +forms.OCurrencyControl::com::sun::star::awt::XWindow +forms.OPatternControl::com::sun::star::awt::XWindow +forms.OFormattedControl::com::sun::star::awt::XWindow +forms.OButtonControl::com::sun::star::awt::XWindow +forms.OImageButtonControl::com::sun::star::awt::XWindow +forms.OImageControlControl::com::sun::star::awt::XWindow +forms.ONavigationBarControl::com::sun::star::awt::XWindow + +### i87212 ### +forms.ONavigationBarControl::com::sun::star::lang::XComponent + +### i87213 ### +forms.OGroupBoxControl::com::sun::star::awt::XView +forms.OListBoxControl::com::sun::star::awt::XView +forms.OEditControl::com::sun::star::awt::XView +forms.ORadioButtonControl::com::sun::star::awt::XView +forms.OButtonControl::com::sun::star::awt::XView +forms.OPatternControl::com::sun::star::awt::XView +forms.OCheckBoxControl::com::sun::star::awt::XView +forms.OTimeControl::com::sun::star::awt::XView +forms.OCurrencyControl::com::sun::star::awt::XView +forms.OFormattedControl::com::sun::star::awt::XView +forms.ONumericControl::com::sun::star::awt::XView +forms.OImageButtonControl::com::sun::star::awt::XView +forms.OComboBoxControl::com::sun::star::awt::XView +forms.ODateControl::com::sun::star::awt::XView +forms.OImageControlControl::com::sun::star::awt::XView +forms.ONavigationBarControl::com::sun::star::awt::XView + +### i87214 ### +forms.OEditControl::com::sun::star::form::XChangeBroadcaster + +### i87215 ### +forms.OListBoxControl::com::sun::star::form::XChangeBroadcaster + +### i87861 ### +forms.OEditModel::com::sun::star::form::XUpdateBroadcaster + +### i89421 ### +forms.OGroupBoxModel::com::sun::star::lang::XComponent + +### i89422 ### +forms.OHiddenModel::com::sun::star::form::component::HiddenControl + +### i90352 ### +forms.OListBoxControl::com::sun::star::lang::XComponent + +### i94950 ### +forms.OTimeModel::com::sun::star::form::XUpdateBroadcaster +forms.OPatternModel::com::sun::star::form::XUpdateBroadcaster +forms.OListBoxModel::com::sun::star::form::XUpdateBroadcaster +forms.OFormattedFieldWrapper::com::sun::star::form::XUpdateBroadcaster +forms.ODateModel::com::sun::star::form::XUpdateBroadcaster +forms.OComboBoxModel::com::sun::star::form::XUpdateBroadcaster diff --git a/forms/qa/unoapi/makefile.mk b/forms/qa/unoapi/makefile.mk new file mode 100644 index 000000000000..9f033d058ce7 --- /dev/null +++ b/forms/qa/unoapi/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=forms +TARGET=qa_unoapi + +.INCLUDE: settings.mk + +.INCLUDE: target.mk + +ALLTAR : UNOAPI_TEST + +UNOAPI_TEST: + +$(SOLARENV)$/bin$/checkapi -sce forms.sce -xcl knownissues.xcl -DOCPTH $(PWD)$/testdocuments -THRCNT 1 -tdoc $(PWD)$/testdocuments + @echo ======================================================================= + @echo Problems with controls might me focus problems during the run of XView + @echo these seems to appear by chance ... just re-run those testcases with + @echo $(SOLARENV)$/bin$/checkapi -o componentName -xcl knownissues.xcl -DOCPTH $(PWD)$/testdocuments -THRCNT 1 -tdoc $(PWD)$/testdocuments + @echo ======================================================================= + +run_%: + +$(SOLARENV)$/bin$/checkapi -o $(PRJNAME).$(@:s/run_//) -xcl knownissues.xcl -DOCPTH $(PWD)$/testdocuments -THRCNT 1 -tdoc $(PWD)$/testdocuments diff --git a/forms/qa/unoapi/testdocuments/TestDB/testDB.dbf b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbf Binary files differnew file mode 100644 index 000000000000..aa3c8262a5e0 --- /dev/null +++ b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbf diff --git a/forms/qa/unoapi/testdocuments/TestDB/testDB.dbt b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbt Binary files differnew file mode 100644 index 000000000000..2183ea7ba67d --- /dev/null +++ b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbt diff --git a/forms/source/component/BaseListBox.hxx b/forms/source/component/BaseListBox.hxx new file mode 100644 index 000000000000..4e7d112bac80 --- /dev/null +++ b/forms/source/component/BaseListBox.hxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_BASELISTBOX_HXX_ +#define _FORMS_BASELISTBOX_HXX_ + +//......................................................................... +namespace frm +{ + +const sal_uInt16 ENTRY_NOT_FOUND = 0xFFFF; +const sal_uInt16 BOUNDCOLUMN = 0x0001; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_BASELISTBOX_HXX_ + diff --git a/forms/source/component/Button.cxx b/forms/source/component/Button.cxx new file mode 100644 index 000000000000..6a326f749bdc --- /dev/null +++ b/forms/source/component/Button.cxx @@ -0,0 +1,780 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Button.hxx" + +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> +#include <tools/diagnose_ex.h> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using ::com::sun::star::frame::XDispatchProviderInterceptor; + +//================================================================== +//= OButtonModel +//================================================================== +DBG_NAME(OButtonModel) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OButtonModel(_rxFactory)); +} + +//------------------------------------------------------------------ +OButtonModel::OButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseModel( _rxFactory, VCL_CONTROLMODEL_COMMANDBUTTON, FRM_SUN_CONTROL_COMMANDBUTTON ) + // use the old control name for compatibility reasons + ,m_aResetHelper( *this, m_aMutex ) + ,m_eDefaultState( STATE_NOCHECK ) +{ + DBG_CTOR( OButtonModel, NULL ); + m_nClassId = FormComponentType::COMMANDBUTTON; +} + +//------------------------------------------------------------------ +Any SAL_CALL OButtonModel::queryAggregation( const Type& _type ) throw(RuntimeException) +{ + Any aReturn = OClickableImageBaseModel::queryAggregation( _type ); + if ( !aReturn.hasValue() ) + aReturn = OButtonModel_Base::queryInterface( _type ); + return aReturn; +} + +//------------------------------------------------------------------ +Sequence< Type > OButtonModel::_getTypes() +{ + return ::comphelper::concatSequences( + OClickableImageBaseModel::_getTypes(), + OButtonModel_Base::getTypes() + ); +} + +//------------------------------------------------------------------ +OButtonModel::OButtonModel( const OButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OClickableImageBaseModel( _pOriginal, _rxFactory ) + ,m_aResetHelper( *this, m_aMutex ) + ,m_eDefaultState( _pOriginal->m_eDefaultState ) +{ + DBG_CTOR( OButtonModel, NULL ); + m_nClassId = FormComponentType::COMMANDBUTTON; + + implInitializeImageURL(); +} + +//------------------------------------------------------------------------------ +OButtonModel::~OButtonModel() +{ + DBG_DTOR(OButtonModel, NULL); +} + +//------------------------------------------------------------------------------ +void OButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 6, OClickableImageBaseModel ) + DECL_PROP1( BUTTONTYPE, FormButtonType, BOUND ); + DECL_PROP1( DEFAULT_STATE, sal_Int16, BOUND ); + DECL_PROP1( DISPATCHURLINTERNAL, sal_Bool, BOUND ); + DECL_PROP1( TARGET_URL, ::rtl::OUString, BOUND ); + DECL_PROP1( TARGET_FRAME, ::rtl::OUString, BOUND ); + DECL_PROP1( TABINDEX, sal_Int16, BOUND ); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OButtonModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OButtonModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseModel::getSupportedServiceNames(); + aSupported.realloc( aSupported.getLength() + 1 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_COMMANDBUTTON; + + return aSupported; +} + +//------------------------------------------------------------------------------ +::rtl::OUString OButtonModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_COMMANDBUTTON; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OClickableImageBaseModel::write(_rxOutStream); + + _rxOutStream->writeShort(0x0003); // Version + + { + OStreamSection aSection( _rxOutStream.get() ); + // this will allow readers to skip unknown bytes in their dtor + + _rxOutStream->writeShort( (sal_uInt16)m_eButtonType ); + + ::rtl::OUString sTmp = INetURLObject::decode( m_sTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS); + _rxOutStream << sTmp; + _rxOutStream << m_sTargetFrame; + writeHelpTextCompatibly(_rxOutStream); + _rxOutStream << isDispatchUrlInternal(); + } +} + +//------------------------------------------------------------------------------ +void OButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OClickableImageBaseModel::read(_rxInStream); + + sal_uInt16 nVersion = _rxInStream->readShort(); // Version + switch (nVersion) + { + case 0x0001: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + } + break; + + case 0x0002: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + readHelpTextCompatibly(_rxInStream); + } + break; + + case 0x0003: + { + OStreamSection aSection( _rxInStream.get() ); + // this will skip any unknown bytes in it's dtor + + // button type + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + + // URL + _rxInStream >> m_sTargetURL; + + // target frame + _rxInStream >> m_sTargetFrame; + + // help text + readHelpTextCompatibly(_rxInStream); + + // DispatchInternal + sal_Bool bDispath; + _rxInStream >> bDispath; + setDispatchUrlInternal(bDispath); + } + break; + + default: + DBG_ERROR("OButtonModel::read : unknown version !"); + m_eButtonType = FormButtonType_PUSH; + m_sTargetURL = ::rtl::OUString(); + m_sTargetFrame = ::rtl::OUString(); + break; + } +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::disposing() +{ + m_aResetHelper.disposing(); + OClickableImageBaseModel::disposing(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::reset() throw (RuntimeException) +{ + if ( !m_aResetHelper.approveReset() ) + return; + + impl_resetNoBroadcast_nothrow(); + + m_aResetHelper.notifyResetted(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::addResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException) +{ + m_aResetHelper.addResetListener( _listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::removeResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException) +{ + m_aResetHelper.removeResetListener( _listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const +{ + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + _rValue <<= (sal_Int16)m_eDefaultState; + break; + + default: + OClickableImageBaseModel::getFastPropertyValue( _rValue, _nHandle ); + break; + } +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) +{ + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + { + sal_Int16 nDefaultState( (sal_Int16)STATE_NOCHECK ); + OSL_VERIFY( _rValue >>= nDefaultState ); + m_eDefaultState = (ToggleState)nDefaultState; + impl_resetNoBroadcast_nothrow(); + } + break; + + default: + OClickableImageBaseModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + break; + } +} + +//-------------------------------------------------------------------- +sal_Bool SAL_CALL OButtonModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified = sal_False; + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_eDefaultState ); + break; + + default: + bModified = OClickableImageBaseModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; +} + +//-------------------------------------------------------------------- +Any OButtonModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + Any aDefault; + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + aDefault <<= (sal_Int16)STATE_NOCHECK; + break; + + default: + aDefault = OClickableImageBaseModel::getPropertyDefaultByHandle( _nHandle ); + break; + } + return aDefault; +} + +//-------------------------------------------------------------------- +void OButtonModel::impl_resetNoBroadcast_nothrow() +{ + try + { + setPropertyValue( PROPERTY_STATE, getPropertyValue( PROPERTY_DEFAULT_STATE ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//================================================================== +// OButtonControl +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OButtonControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OButtonControl::_getTypes() +{ + return ::comphelper::concatSequences( + OButtonControl_BASE::getTypes(), + OClickableImageBaseControl::_getTypes(), + OFormNavigationHelper::getTypes() + ); +} + +//------------------------------------------------------------------------------ +StringSequence OButtonControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMMANDBUTTON; + return aSupported; +} + +//------------------------------------------------------------------------------ +OButtonControl::OButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseControl(_rxFactory, VCL_CONTROL_COMMANDBUTTON) + ,OFormNavigationHelper( _rxFactory ) + ,m_nClickEvent( 0 ) + ,m_nTargetUrlFeatureId( -1 ) + ,m_bEnabledByPropertyValue( sal_False ) +{ + increment(m_refCount); + { + // als ActionListener anmelden + Reference<XButton> xButton; + query_aggregation( m_xAggregate, xButton); + if (xButton.is()) + xButton->addActionListener(this); + } + // Refcount bei 1 fuer Listener + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +OButtonControl::~OButtonControl() +{ + if (m_nClickEvent) + Application::RemoveUserEvent(m_nClickEvent); +} + +// UNO Anbindung +//------------------------------------------------------------------------------ +Any SAL_CALL OButtonControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + // if asked for the XTypeProvider, don't let OButtonControl_BASE do this + Any aReturn; + if ( !_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) ) + aReturn = OButtonControl_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OClickableImageBaseControl::queryAggregation( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OFormNavigationHelper::queryInterface( _rType ); + + return aReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::disposing() +{ + startOrStopModelPropertyListening( false ); + + OClickableImageBaseControl::disposing(); + OFormNavigationHelper::dispose(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::disposing( const EventObject& _rSource ) throw( RuntimeException ) +{ + OControl::disposing( _rSource ); + OFormNavigationHelper::disposing( _rSource ); +} + +// ActionListener +//------------------------------------------------------------------------------ +void OButtonControl::actionPerformed(const ActionEvent& /*rEvent*/) throw ( ::com::sun::star::uno::RuntimeException) +{ + // Asynchron fuer starutil::URL-Button + sal_uInt32 n = Application::PostUserEvent( LINK(this, OButtonControl,OnClick) ); + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_nClickEvent = n; + } +} + +//------------------------------------------------------------------------------ +IMPL_LINK( OButtonControl, OnClick, void*, EMPTYARG ) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + m_nClickEvent = 0; + + if (m_aApproveActionListeners.getLength()) + { + // if there are listeners, start the action in an own thread, to not allow + // them to block us here (we're in the application's main thread) + getImageProducerThread()->addEvent(); + } + else + { + // Sonst nicht. Dann darf man aber auf keinen Fal die Listener + // benachrichtigen, auch dann nicht, wenn er spaeter hinzukommt. + aGuard.clear(); + + // recognize the button type + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (!xSet.is()) + return 0L; + + if (FormButtonType_PUSH == *(FormButtonType*)xSet->getPropertyValue(PROPERTY_BUTTONTYPE).getValue()) + { + // notify the action listeners for a push button + ::cppu::OInterfaceIteratorHelper aIter(m_aActionListeners); + ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); + while(aIter.hasMoreElements() ) + { + // catch exceptions + // and catch them on a per-listener basis - if one listener fails, the others still need + // to get notified + // 97676 - 21.02.2002 - fs@openoffice.org + try + { + static_cast< XActionListener* >( aIter.next() )->actionPerformed(aEvt); + } +#ifdef DBG_UTIL + catch( const RuntimeException& ) + { + // silent this + } +#endif + catch( const Exception& ) + { + DBG_ERROR( "OButtonControl::OnClick: caught a exception other than RuntimeException!" ); + } + } + } + else + actionPerformed_Impl( sal_False, ::com::sun::star::awt::MouseEvent() ); + } + return 0L; +} + +//------------------------------------------------------------------------------ +void OButtonControl::actionPerformed_Impl( sal_Bool _bNotifyListener, const ::com::sun::star::awt::MouseEvent& _rEvt ) +{ + { + sal_Int16 nFeatureId = -1; + { + ::osl::MutexGuard aGuard( m_aMutex ); + nFeatureId = m_nTargetUrlFeatureId; + } + + if ( nFeatureId != -1 ) + { + if ( !approveAction() ) + return; + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + dispatch( nFeatureId ); + return; + } + } + + OClickableImageBaseControl::actionPerformed_Impl( _bNotifyListener, _rEvt ); +} + +// XButton +//------------------------------------------------------------------------------ +void OButtonControl::setLabel(const ::rtl::OUString& Label) throw( RuntimeException ) +{ + Reference<XButton> xButton; + query_aggregation( m_xAggregate, xButton ); + if (xButton.is()) + xButton->setLabel(Label); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::setActionCommand(const ::rtl::OUString& _rCommand) throw( RuntimeException ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_aActionCommand = _rCommand; + } + + Reference<XButton> xButton; + query_aggregation( m_xAggregate, xButton); + if (xButton.is()) + xButton->setActionCommand(_rCommand); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::addActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException ) +{ + m_aActionListeners.addInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::removeActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException ) +{ + m_aActionListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +class DoPropertyListening +{ +private: + Reference< XPropertySet > m_xProps; + Reference< XPropertyChangeListener > m_xListener; + bool m_bStartListening; + +public: + DoPropertyListening( + const Reference< XInterface >& _rxComponent, + const Reference< XPropertyChangeListener >& _rxListener, + bool _bStart + ); + + void handleListening( const ::rtl::OUString& _rPropertyName ); +}; + +//.............................................................................. +DoPropertyListening::DoPropertyListening( + const Reference< XInterface >& _rxComponent, const Reference< XPropertyChangeListener >& _rxListener, + bool _bStart ) + :m_xProps( _rxComponent, UNO_QUERY ) + ,m_xListener( _rxListener ) + ,m_bStartListening( _bStart ) +{ + DBG_ASSERT( m_xProps.is() || !_rxComponent.is(), "DoPropertyListening::DoPropertyListening: valid component, but no property set!" ); + DBG_ASSERT( m_xListener.is(), "DoPropertyListening::DoPropertyListening: invalid listener!" ); +} + +//.............................................................................. +void DoPropertyListening::handleListening( const ::rtl::OUString& _rPropertyName ) +{ + if ( m_xProps.is() ) + { + if ( m_bStartListening ) + m_xProps->addPropertyChangeListener( _rPropertyName, m_xListener ); + else + m_xProps->removePropertyChangeListener( _rPropertyName, m_xListener ); + } +} + +//------------------------------------------------------------------------------ +void OButtonControl::startOrStopModelPropertyListening( bool _bStart ) +{ + DoPropertyListening aListeningHandler( getModel(), this, _bStart ); + aListeningHandler.handleListening( PROPERTY_TARGET_URL ); + aListeningHandler.handleListening( PROPERTY_BUTTONTYPE ); + aListeningHandler.handleListening( PROPERTY_ENABLED ); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OButtonControl::setModel( const Reference< XControlModel >& _rxModel ) throw ( RuntimeException ) +{ + startOrStopModelPropertyListening( false ); + sal_Bool bResult = OClickableImageBaseControl::setModel( _rxModel ); + startOrStopModelPropertyListening( true ); + + m_bEnabledByPropertyValue = sal_True; + Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY ); + if ( xModelProps.is() ) + xModelProps->getPropertyValue( PROPERTY_ENABLED ) >>= m_bEnabledByPropertyValue; + + modelFeatureUrlPotentiallyChanged( ); + + return bResult; +} + +//------------------------------------------------------------------------------ +void OButtonControl::modelFeatureUrlPotentiallyChanged( ) +{ + sal_Int16 nOldUrlFeatureId = m_nTargetUrlFeatureId; + + // doe we have another TargetURL now? If so, we need to update our dispatches + m_nTargetUrlFeatureId = getModelUrlFeatureId( ); + if ( nOldUrlFeatureId != m_nTargetUrlFeatureId ) + { + invalidateSupportedFeaturesSet(); + if ( !isDesignMode() ) + updateDispatches( ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::propertyChange( const PropertyChangeEvent& _rEvent ) throw ( RuntimeException ) +{ + if ( _rEvent.PropertyName.equals( PROPERTY_TARGET_URL ) + || _rEvent.PropertyName.equals( PROPERTY_BUTTONTYPE ) + ) + { + modelFeatureUrlPotentiallyChanged( ); + } + else if ( _rEvent.PropertyName.equals( PROPERTY_ENABLED ) ) + { + _rEvent.NewValue >>= m_bEnabledByPropertyValue; + } +} + +//------------------------------------------------------------------------------ +namespace +{ + bool isFormControllerURL( const ::rtl::OUString& _rURL ) + { + const sal_Int32 nPrefixLen = URL_CONTROLLER_PREFIX.length; + return ( _rURL.getLength() > nPrefixLen ) + && ( _rURL.compareToAscii( URL_CONTROLLER_PREFIX, nPrefixLen ) == 0 ); + } +} + +//------------------------------------------------------------------------------ +sal_Int16 OButtonControl::getModelUrlFeatureId( ) const +{ + sal_Int16 nFeatureId = -1; + + // some URL related properties of the model + ::rtl::OUString sUrl; + FormButtonType eButtonType = FormButtonType_PUSH; + + Reference< XPropertySet > xModelProps( const_cast< OButtonControl* >( this )->getModel(), UNO_QUERY ); + if ( xModelProps.is() ) + { + xModelProps->getPropertyValue( PROPERTY_TARGET_URL ) >>= sUrl; + xModelProps->getPropertyValue( PROPERTY_BUTTONTYPE ) >>= eButtonType; + } + + // are we an URL button? + if ( eButtonType == FormButtonType_URL ) + { + // is it a feature URL? + if ( isFormControllerURL( sUrl ) ) + { + OFormNavigationMapper aMapper( m_aContext.getLegacyServiceFactory() ); + nFeatureId = aMapper.getFeatureId( sUrl ); + } + } + + return nFeatureId; +} + +//------------------------------------------------------------------ +void SAL_CALL OButtonControl::setDesignMode( sal_Bool _bOn ) throw( RuntimeException ) +{ + OClickableImageBaseControl::setDesignMode( _bOn ); + + if ( _bOn ) + disconnectDispatchers(); + else + connectDispatchers(); + // this will connect if not already connected and just update else +} + +//------------------------------------------------------------------------------ +void OButtonControl::getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ) +{ + if ( -1 != m_nTargetUrlFeatureId ) + _rFeatureIds.push_back( m_nTargetUrlFeatureId ); +} + +//------------------------------------------------------------------ +void OButtonControl::featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ) +{ + if ( _nFeatureId == m_nTargetUrlFeatureId ) + { + // enable or disable our peer, according to the new state + Reference< XVclWindowPeer > xPeer( getPeer(), UNO_QUERY ); + if ( xPeer.is() ) + xPeer->setProperty( PROPERTY_ENABLED, makeAny( m_bEnabledByPropertyValue ? _bEnabled : sal_False ) ); + // if we're disabled according to our model's property, then + // we don't care for the feature state, but *are* disabled. + // If the model's property states that we're enabled, then we *do* + // care for the feature state + } + + // base class + OFormNavigationHelper::featureStateChanged( _nFeatureId, _bEnabled ); +} + +//------------------------------------------------------------------ +void OButtonControl::allFeatureStatesChanged( ) +{ + if ( -1 != m_nTargetUrlFeatureId ) + // we have only one supported feature, so simulate it has changed ... + featureStateChanged( m_nTargetUrlFeatureId, isEnabled( m_nTargetUrlFeatureId ) ); + + // base class + OFormNavigationHelper::allFeatureStatesChanged( ); +} + +//------------------------------------------------------------------ +bool OButtonControl::isEnabled( sal_Int16 _nFeatureId ) const +{ + if ( const_cast< OButtonControl* >( this )->isDesignMode() ) + // TODO: the model property? + return true; + + return OFormNavigationHelper::isEnabled( _nFeatureId ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) +{ + OClickableImageBaseControl::registerDispatchProviderInterceptor( _rxInterceptor ); + OFormNavigationHelper::registerDispatchProviderInterceptor( _rxInterceptor ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) +{ + OClickableImageBaseControl::releaseDispatchProviderInterceptor( _rxInterceptor ); + OFormNavigationHelper::releaseDispatchProviderInterceptor( _rxInterceptor ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Button.hxx b/forms/source/component/Button.hxx new file mode 100644 index 000000000000..c3528f9f86d2 --- /dev/null +++ b/forms/source/component/Button.hxx @@ -0,0 +1,210 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_BUTTON_HXX_ +#define _FRM_BUTTON_HXX_ + +#include "clickableimage.hxx" +#include "togglestate.hxx" +#include "formnavigation.hxx" +#include "resettable.hxx" + +#include <com/sun/star/awt/MouseEvent.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/awt/ActionEvent.hpp> +#include <com/sun/star/awt/XActionListener.hpp> +#include <com/sun/star/awt/XButton.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> + +#include <cppuhelper/implbase1.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OButtonModel +//================================================================== +typedef ::cppu::ImplHelper1 < ::com::sun::star::form::XReset + > OButtonModel_Base; +class OButtonModel :public OClickableImageBaseModel + ,public OButtonModel_Base +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OButtonModel ); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS( OButtonModel, OClickableImageBaseModel ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OButtonModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + +// ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XReset + virtual void SAL_CALL reset( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // XPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // OComponentHelper + virtual void SAL_CALL disposing(); + +protected: + DECLARE_XCLONEABLE(); + +private: + void impl_resetNoBroadcast_nothrow(); + + using ::cppu::OPropertySetHelper::getFastPropertyValue; + +private: + ResetHelper m_aResetHelper; + + // <properties> + ToggleState m_eDefaultState; // the default check state + // </properties> +protected: + using OClickableImageBaseModel::disposing; +}; + +//================================================================== +// OButtonControl +//================================================================== +typedef ::cppu::ImplHelper3 < ::com::sun::star::awt::XButton + , ::com::sun::star::awt::XActionListener + , ::com::sun::star::beans::XPropertyChangeListener + > OButtonControl_BASE; + +class OButtonControl :public OButtonControl_BASE + ,public OClickableImageBaseControl + ,public OFormNavigationHelper +{ +private: + sal_uInt32 m_nClickEvent; + sal_Int16 m_nTargetUrlFeatureId; + /// caches the value of the "Enabled" property of our model + sal_Bool m_bEnabledByPropertyValue; + +protected: + + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OButtonControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OButtonControl(); + + // XServiceInfo + IMPLEMENTATION_NAME(OButtonControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OButtonControl, OClickableImageBaseControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XActionListener + virtual void SAL_CALL actionPerformed(const ::com::sun::star::awt::ActionEvent& rEvent) throw ( ::com::sun::star::uno::RuntimeException); + + // XButton + virtual void SAL_CALL addActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLabel(const ::rtl::OUString& Label) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setActionCommand(const ::rtl::OUString& _rCommand) throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XControl + virtual sal_Bool SAL_CALL setModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& _rxModel ) throw ( ::com::sun::star::uno::RuntimeException ); + void SAL_CALL setDesignMode(sal_Bool bOn) throw (::com::sun::star::uno::RuntimeException); + +protected: + // OFormNavigationHelper overriables + virtual void getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ); + virtual void featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ); + virtual void allFeatureStatesChanged( ); + virtual bool isEnabled( sal_Int16 _nFeatureId ) const; + + // XDispatchProviderInterception disambiguaiton + virtual void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + + // OImageControl overridables + virtual void actionPerformed_Impl( sal_Bool bNotifyListener, const ::com::sun::star::awt::MouseEvent& _rEvt ); + +private: + DECL_LINK( OnClick, void* ); + + /** to be called whenever the feature URL represented by our model has potentially changed + */ + void modelFeatureUrlPotentiallyChanged( ); + + /** retrieves the feature id (see OFormNavigationHelper) of the TargetURL of + the model. + */ + sal_Int16 getModelUrlFeatureId( ) const; + + /** starts or stops listening for changes in model properties we're interested in + */ + void startOrStopModelPropertyListening( bool _bStart ); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_BUTTON_HXX_ + diff --git a/forms/source/component/CheckBox.cxx b/forms/source/component/CheckBox.cxx new file mode 100644 index 000000000000..3e2531f92f5c --- /dev/null +++ b/forms/source/component/CheckBox.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "CheckBox.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/basicio.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//================================================================== +//= OCheckBoxControl +//================================================================== + +//------------------------------------------------------------------ +OCheckBoxControl::OCheckBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_CHECKBOX) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OCheckBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OCheckBoxControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCheckBoxControl::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_CHECKBOX; + return aSupported; +} + +//================================================================== +//= OCheckBoxModel +//================================================================== + +//================================================================== +InterfaceRef SAL_CALL OCheckBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OCheckBoxModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OCheckBoxModel ) +//------------------------------------------------------------------ +OCheckBoxModel::OCheckBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OReferenceValueComponent( _rxFactory, VCL_CONTROLMODEL_CHECKBOX, FRM_SUN_CONTROL_CHECKBOX, sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( OCheckBoxModel, NULL ); + + m_nClassId = FormComponentType::CHECKBOX; + initValueProperty( PROPERTY_STATE, PROPERTY_ID_STATE ); +} + +//------------------------------------------------------------------ +OCheckBoxModel::OCheckBoxModel( const OCheckBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OReferenceValueComponent( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OCheckBoxModel, NULL ); +} + +//------------------------------------------------------------------------------ +OCheckBoxModel::~OCheckBoxModel() +{ + DBG_DTOR( OCheckBoxModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OCheckBoxModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCheckBoxModel::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported = OReferenceValueComponent::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_CHECKBOX; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_CHECKBOX; + *pStoreTo++ = BINDABLE_DATABASE_CHECK_BOX; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void OCheckBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 1, OReferenceValueComponent ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OCheckBoxModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_CHECKBOX; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OCheckBoxModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) + throw(stario::IOException, RuntimeException) +{ + OReferenceValueComponent::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0003); + // Properties + _rxOutStream << getReferenceValue(); + _rxOutStream << (sal_Int16)getDefaultChecked(); + writeHelpTextCompatibly(_rxOutStream); + // from version 0x0003 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OCheckBoxModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw(stario::IOException, RuntimeException) +{ + OReferenceValueComponent::read(_rxInStream); + osl::MutexGuard aGuard(m_aMutex); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + + ::rtl::OUString sReferenceValue; + sal_Int16 nDefaultChecked( 0 ); + switch ( nVersion ) + { + case 0x0001: + _rxInStream >> sReferenceValue; + nDefaultChecked = _rxInStream->readShort(); + break; + case 0x0002: + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly( _rxInStream ); + break; + case 0x0003: + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly(_rxInStream); + readCommonProperties(_rxInStream); + break; + default: + DBG_ERROR("OCheckBoxModel::read : unknown version !"); + defaultCommonProperties(); + break; + } + setReferenceValue( sReferenceValue ); + setDefaultChecked( static_cast< ToggleState >( nDefaultChecked ) ); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); +} + +//------------------------------------------------------------------------------ +Any OCheckBoxModel::translateDbColumnToControlValue() +{ + Any aValue; + + ////////////////////////////////////////////////////////////////// + // Wert an ControlModel setzen + sal_Bool bValue = m_xColumn->getBoolean(); + if ( m_xColumn->wasNull() ) + { + sal_Bool bTriState = sal_True; + if ( m_xAggregateSet.is() ) + m_xAggregateSet->getPropertyValue( PROPERTY_TRISTATE ) >>= bTriState; + aValue <<= (sal_Int16)( bTriState ? STATE_DONTKNOW : getDefaultChecked() ); + } + else + aValue <<= (sal_Int16)( bValue ? STATE_CHECK : STATE_NOCHECK ); + + return aValue; +} + +//----------------------------------------------------------------------------- +sal_Bool OCheckBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + OSL_PRECOND( m_xColumnUpdate.is(), "OCheckBoxModel::commitControlValueToDbColumn: not bound!" ); + if ( m_xColumnUpdate.is() ) + { + Any aControlValue( m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) ); + try + { + sal_Int16 nValue = STATE_DONTKNOW; + aControlValue >>= nValue; + switch (nValue) + { + case STATE_DONTKNOW: + m_xColumnUpdate->updateNull(); + break; + case STATE_CHECK: + m_xColumnUpdate->updateBoolean( sal_True ); + break; + case STATE_NOCHECK: + m_xColumnUpdate->updateBoolean( sal_False ); + break; + default: + DBG_ERROR("OCheckBoxModel::commitControlValueToDbColumn: invalid value !"); + } + } + catch(Exception&) + { + DBG_ERROR("OCheckBoxModel::commitControlValueToDbColumn: could not commit !"); + } + } + return sal_True; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/CheckBox.hxx b/forms/source/component/CheckBox.hxx new file mode 100644 index 000000000000..21073c27306d --- /dev/null +++ b/forms/source/component/CheckBox.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_CHECKBOX_HXX_ +#define _FORMS_CHECKBOX_HXX_ + +#include "refvaluecomponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OCheckBoxModel +//================================================================== +class OCheckBoxModel :public OReferenceValueComponent +{ +protected: + sal_Int16 getState(const ::com::sun::star::uno::Any& rValue); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OCheckBoxModel ); + + // XServiceInfo + IMPLEMENTATION_NAME(OCheckBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + DECLARE_XCLONEABLE(); + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); +}; + +//================================================================== +//= OCheckBoxControl +//================================================================== +class OCheckBoxControl : public OBoundControl +{ +public: + OCheckBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OCheckBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_CHECKBOX_HXX_ + diff --git a/forms/source/component/Columns.cxx b/forms/source/component/Columns.cxx new file mode 100644 index 000000000000..ae1cbc2b7a5b --- /dev/null +++ b/forms/source/component/Columns.cxx @@ -0,0 +1,592 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Columns.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "property.hxx" +#include "ids.hxx" +#include "findpos.hxx" +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <comphelper/sequence.hxx> +#include <comphelper/property.hxx> +#include <comphelper/basicio.hxx> +#include "services.hxx" +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif +#include <tools/debug.hxx> +#include <rtl/uuid.h> +#include <rtl/memory.h> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +const sal_uInt16 WIDTH = 0x0001; +const sal_uInt16 ALIGN = 0x0002; +const sal_uInt16 OLD_HIDDEN = 0x0004; +const sal_uInt16 COMPATIBLE_HIDDEN = 0x0008; + +//------------------------------------------------------------------------------ +const StringSequence& getColumnTypes() +{ + static StringSequence aColumnTypes(10); + if (!aColumnTypes.getConstArray()[0].getLength()) + { + ::rtl::OUString* pNames = aColumnTypes.getArray(); + pNames[TYPE_CHECKBOX] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CheckBox" ) ); + pNames[TYPE_COMBOBOX] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ComboBox" ) ); + pNames[TYPE_CURRENCYFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CurrencyField" ) ); + pNames[TYPE_DATEFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateField" ) ); + pNames[TYPE_FORMATTEDFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FormattedField" ) ); + pNames[TYPE_LISTBOX] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListBox" ) ); + pNames[TYPE_NUMERICFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NumericField" ) ); + pNames[TYPE_PATTERNFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PatternField" ) ); + pNames[TYPE_TEXTFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TextField" ) ); + pNames[TYPE_TIMEFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TimeField" ) ); + } + return aColumnTypes; +} + +//------------------------------------------------------------------------------ +sal_Int32 getColumnTypeByModelName(const ::rtl::OUString& aModelName) +{ + const ::rtl::OUString aModelPrefix = ::rtl::OUString::createFromAscii("com.sun.star.form.component."); + const ::rtl::OUString aCompatibleModelPrefix = ::rtl::OUString::createFromAscii("stardiv.one.form.component."); + + sal_Int32 nTypeId = -1; + if (aModelName == FRM_COMPONENT_EDIT) + nTypeId = TYPE_TEXTFIELD; + else + { + sal_Int32 nPrefixPos = aModelName.indexOf(aModelPrefix); +#ifdef DBG_UTIL + sal_Int32 nCompatiblePrefixPos = aModelName.indexOf(aCompatibleModelPrefix); +#endif + DBG_ASSERT( (nPrefixPos != -1) || (nCompatiblePrefixPos != -1), + "::getColumnTypeByModelName() : wrong servivce !"); + + ::rtl::OUString aColumnType = (nPrefixPos != -1) + ? aModelName.copy(aModelPrefix.getLength()) + : aModelName.copy(aCompatibleModelPrefix.getLength()); + + const StringSequence& rColumnTypes = getColumnTypes(); + nTypeId = ::detail::findPos(aColumnType, rColumnTypes); + } + return nTypeId; +} + +/*************************************************************************/ + +//------------------------------------------------------------------ +const Sequence<sal_Int8>& OGridColumn::getUnoTunnelImplementationId() +{ + static Sequence< sal_Int8 > * pSeq = 0; + if( !pSeq ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +//------------------------------------------------------------------ +sal_Int64 SAL_CALL OGridColumn::getSomething( const Sequence<sal_Int8>& _rIdentifier) throw(RuntimeException) +{ + sal_Int64 nReturn(0); + + if ( (_rIdentifier.getLength() == 16) + && (0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 )) + ) + { + nReturn = reinterpret_cast<sal_Int64>(this); + } + else + { + Reference< XUnoTunnel > xAggTunnel; + if ( query_aggregation( m_xAggregate, xAggTunnel ) ) + return xAggTunnel->getSomething( _rIdentifier ); + } + return nReturn; +} + +//------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL OGridColumn::getImplementationId() throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL OGridColumn::getTypes() throw(RuntimeException) +{ + Reference<XTypeProvider> xProv; + + if (query_aggregation(m_xAggregate, xProv)) + return concatSequences(OGridColumn_BASE::getTypes(), xProv->getTypes()); + return OGridColumn_BASE::getTypes(); +} + +//------------------------------------------------------------------ +Any SAL_CALL OGridColumn::queryAggregation( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn; + // some functionality at our aggregate cannot be reasonably fullfilled here. + if ( _rType.equals(::getCppuType(static_cast< Reference< XFormComponent >* >(NULL))) + || _rType.equals(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) + || _rType.equals(::getCppuType(static_cast< Reference< XBindableValue >* >(NULL))) + || _rType.equals(::getCppuType(static_cast< Reference< XPropertyContainer >* >(NULL))) + ) + return aReturn; + + aReturn = OGridColumn_BASE::queryAggregation(_rType); + if (!aReturn.hasValue()) + { + aReturn = OPropertySetAggregationHelper::queryInterface(_rType); + if (!aReturn.hasValue() && m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + + return aReturn; +} + +DBG_NAME(OGridColumn); +//------------------------------------------------------------------------------ +OGridColumn::OGridColumn( const comphelper::ComponentContext& _rContext, const ::rtl::OUString& _sModelName ) + :OGridColumn_BASE(m_aMutex) + ,OPropertySetAggregationHelper(OGridColumn_BASE::rBHelper) + ,m_aHidden( makeAny( sal_False ) ) + ,m_aContext( _rContext ) + ,m_aModelName(_sModelName) +{ + DBG_CTOR(OGridColumn,NULL); + + // Anlegen des UnoControlModels + if ( m_aModelName.getLength() ) // is there a to-be-aggregated model? + { + increment( m_refCount ); + + { + m_xAggregate.set( m_aContext.createComponent( m_aModelName ), UNO_QUERY ); + setAggregation( m_xAggregate ); + } + + if ( m_xAggregate.is() ) + { // don't omit those brackets - they ensure that the following temporary is properly deleted + m_xAggregate->setDelegator( static_cast< ::cppu::OWeakObject* >( this ) ); + } + + // Refcount wieder bei NULL + decrement( m_refCount ); + } +} + +//------------------------------------------------------------------------------ +OGridColumn::OGridColumn( const OGridColumn* _pOriginal ) + :OGridColumn_BASE( m_aMutex ) + ,OPropertySetAggregationHelper( OGridColumn_BASE::rBHelper ) + ,m_aContext( _pOriginal->m_aContext ) +{ + DBG_CTOR(OGridColumn,NULL); + + m_aWidth = _pOriginal->m_aWidth; + m_aAlign = _pOriginal->m_aAlign; + m_aHidden = _pOriginal->m_aHidden; + m_aModelName = _pOriginal->m_aModelName; + m_aLabel = _pOriginal->m_aLabel; + + increment( m_refCount ); + { + { + m_xAggregate = createAggregateClone( _pOriginal ); + setAggregation( m_xAggregate ); + } + + if ( m_xAggregate.is() ) + { // don't omit this brackets - they ensure that the following temporary is properly deleted + m_xAggregate->setDelegator( static_cast< ::cppu::OWeakObject* >( this ) ); + } + } + decrement( m_refCount ); +} + +//------------------------------------------------------------------------------ +OGridColumn::~OGridColumn() +{ + if (!OGridColumn_BASE::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + // freigeben der Agg + if (m_xAggregate.is()) + { + InterfaceRef xIface; + m_xAggregate->setDelegator(xIface); + } + + DBG_DTOR(OGridColumn,NULL); +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OGridColumn::disposing(const EventObject& _rSource) throw(RuntimeException) +{ + OPropertySetAggregationHelper::disposing(_rSource); + + Reference<XEventListener> xEvtLstner; + if (query_aggregation(m_xAggregate, xEvtLstner)) + xEvtLstner->disposing(_rSource); +} + +// OGridColumn_BASE +//----------------------------------------------------------------------------- +void OGridColumn::disposing() +{ + OGridColumn_BASE::disposing(); + OPropertySetAggregationHelper::disposing(); + + Reference<XComponent> xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->dispose(); +} + +//------------------------------------------------------------------------------ +void OGridColumn::clearAggregateProperties( Sequence< Property >& _rProps, sal_Bool bAllowDropDown ) +{ + // some properties are not to be exposed to the outer world + ::std::set< ::rtl::OUString > aForbiddenProperties; + aForbiddenProperties.insert( PROPERTY_ALIGN ); + aForbiddenProperties.insert( PROPERTY_AUTOCOMPLETE ); + aForbiddenProperties.insert( PROPERTY_BACKGROUNDCOLOR ); + aForbiddenProperties.insert( PROPERTY_BORDER ); + aForbiddenProperties.insert( PROPERTY_BORDERCOLOR ); + aForbiddenProperties.insert( PROPERTY_ECHO_CHAR ); + aForbiddenProperties.insert( PROPERTY_FILLCOLOR ); + aForbiddenProperties.insert( PROPERTY_FONT ); + aForbiddenProperties.insert( PROPERTY_FONT_NAME ); + aForbiddenProperties.insert( PROPERTY_FONT_STYLENAME ); + aForbiddenProperties.insert( PROPERTY_FONT_FAMILY ); + aForbiddenProperties.insert( PROPERTY_FONT_CHARSET ); + aForbiddenProperties.insert( PROPERTY_FONT_HEIGHT ); + aForbiddenProperties.insert( PROPERTY_FONT_WEIGHT ); + aForbiddenProperties.insert( PROPERTY_FONT_SLANT ); + aForbiddenProperties.insert( PROPERTY_FONT_UNDERLINE ); + aForbiddenProperties.insert( PROPERTY_FONT_STRIKEOUT ); + aForbiddenProperties.insert( PROPERTY_FONT_WORDLINEMODE ); + aForbiddenProperties.insert( PROPERTY_TEXTLINECOLOR ); + aForbiddenProperties.insert( PROPERTY_FONTEMPHASISMARK ); + aForbiddenProperties.insert( PROPERTY_FONTRELIEF ); + aForbiddenProperties.insert( PROPERTY_HARDLINEBREAKS ); + aForbiddenProperties.insert( PROPERTY_HSCROLL ); + aForbiddenProperties.insert( PROPERTY_LABEL ); + aForbiddenProperties.insert( PROPERTY_LINECOLOR ); + aForbiddenProperties.insert( PROPERTY_MULTISELECTION ); + aForbiddenProperties.insert( PROPERTY_PRINTABLE ); + aForbiddenProperties.insert( PROPERTY_TABINDEX ); + aForbiddenProperties.insert( PROPERTY_TABSTOP ); + aForbiddenProperties.insert( PROPERTY_TEXTCOLOR ); + aForbiddenProperties.insert( PROPERTY_VSCROLL ); + aForbiddenProperties.insert( PROPERTY_CONTROLLABEL ); + aForbiddenProperties.insert( PROPERTY_RICH_TEXT ); + aForbiddenProperties.insert( PROPERTY_VERTICAL_ALIGN ); + aForbiddenProperties.insert( PROPERTY_IMAGE_URL ); + aForbiddenProperties.insert( PROPERTY_IMAGE_POSITION ); + aForbiddenProperties.insert( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EnableVisible" ) ) ); + if ( !bAllowDropDown ) + aForbiddenProperties.insert( PROPERTY_DROPDOWN ); + + Sequence< Property > aNewProps( _rProps.getLength() ); + Property* pNewProps = aNewProps.getArray(); + + const Property* pProps = _rProps.getConstArray(); + const Property* pPropsEnd = pProps + _rProps.getLength(); + for ( ; pProps != pPropsEnd; ++pProps ) + { + if ( aForbiddenProperties.find( pProps->Name ) == aForbiddenProperties.end() ) + *pNewProps++ = *pProps; + } + + aNewProps.realloc( pNewProps - aNewProps.getArray() ); + _rProps = aNewProps; +} + +//------------------------------------------------------------------------------ +void OGridColumn::setOwnProperties(Sequence<Property>& aDescriptor) +{ + aDescriptor.realloc(5); + Property* pProperties = aDescriptor.getArray(); + DECL_PROP1(LABEL, ::rtl::OUString, BOUND); + DECL_PROP3(WIDTH, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT); + DECL_PROP3(ALIGN, sal_Int16, BOUND, MAYBEVOID, MAYBEDEFAULT); + DECL_BOOL_PROP2(HIDDEN, BOUND, MAYBEDEFAULT); + DECL_PROP1(COLUMNSERVICENAME, ::rtl::OUString, READONLY); +} + +// Reference<XPropertySet> +//------------------------------------------------------------------------------ +void OGridColumn::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_COLUMNSERVICENAME: + rValue <<= m_aModelName; + break; + case PROPERTY_ID_LABEL: + rValue <<= m_aLabel; + break; + case PROPERTY_ID_WIDTH: + rValue = m_aWidth; + break; + case PROPERTY_ID_ALIGN: + rValue = m_aAlign; + break; + case PROPERTY_ID_HIDDEN: + rValue = m_aHidden; + break; + default: + OPropertySetAggregationHelper::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OGridColumn::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue )throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_LABEL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aLabel); + break; + case PROPERTY_ID_WIDTH: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aWidth, ::getCppuType((const sal_Int32*)NULL)); + break; + case PROPERTY_ID_ALIGN: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aAlign, ::getCppuType( (const sal_Int32*)NULL ) ); + // strange enough, css.awt.TextAlign is a 32-bit integer, while the Align property (both here for grid controls + // and for ordinary toolkit controls) is a 16-bit integer. So, allow for 32 bit, but normalize it to 16 bit + if ( bModified ) + { + sal_Int32 nAlign( 0 ); + if ( rConvertedValue >>= nAlign ) + rConvertedValue <<= (sal_Int16)nAlign; + } + break; + case PROPERTY_ID_HIDDEN: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, getBOOL(m_aHidden)); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OGridColumn::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_LABEL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "invalid type" ); + rValue >>= m_aLabel; + break; + case PROPERTY_ID_WIDTH: + m_aWidth = rValue; + break; + case PROPERTY_ID_ALIGN: + m_aAlign = rValue; + break; + case PROPERTY_ID_HIDDEN: + m_aHidden = rValue; + break; + } +} + + +// XPropertyState +//------------------------------------------------------------------------------ +Any OGridColumn::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_WIDTH: + case PROPERTY_ID_ALIGN: + return Any(); + case PROPERTY_ID_HIDDEN: + return makeAny((sal_Bool)sal_False); + default: + return OPropertySetAggregationHelper::getPropertyDefaultByHandle(nHandle); + } +} + +// XCloneable +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OGridColumn::createClone( ) throw (RuntimeException) +{ + OGridColumn* pNewColumn = createCloneColumn(); + return pNewColumn; +} + +//XPersistObject +//------------------------------------------------------------------------------ +void SAL_CALL OGridColumn::write(const Reference<XObjectOutputStream>& _rxOutStream) +{ + // 1. Schreiben des UnoControls + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + sal_Int32 nMark = xMark->createMark(); + + sal_Int32 nLen = 0; + _rxOutStream->writeLong(nLen); + + Reference<XPersistObject> xPersist; + if (query_aggregation(m_xAggregate, xPersist)) + xPersist->write(_rxOutStream); + + // feststellen der Laenge + nLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + + // 2. Schreiben einer VersionsNummer + _rxOutStream->writeShort(0x0002); + + sal_uInt16 nAnyMask = 0; + if (m_aWidth.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= WIDTH; + + if (m_aAlign.getValueTypeClass() == TypeClass_SHORT) + nAnyMask |= ALIGN; + + nAnyMask |= COMPATIBLE_HIDDEN; + + _rxOutStream->writeShort(nAnyMask); + + if (nAnyMask & WIDTH) + _rxOutStream->writeLong(getINT32(m_aWidth)); + if (nAnyMask & ALIGN) + _rxOutStream->writeShort(getINT16(m_aAlign)); + + // Name + _rxOutStream << m_aLabel; + + // the new place for the hidden flag : after m_aLabel, so older office version read the correct label, too + if (nAnyMask & COMPATIBLE_HIDDEN) + _rxOutStream->writeBoolean(getBOOL(m_aHidden)); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGridColumn::read(const Reference<XObjectInputStream>& _rxInStream) +{ + // 1. Lesen des UnoControls + sal_Int32 nLen = _rxInStream->readLong(); + if (nLen) + { + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + sal_Int32 nMark = xMark->createMark(); + Reference<XPersistObject> xPersist; + if (query_aggregation(m_xAggregate, xPersist)) + xPersist->read(_rxInStream); + + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nLen); + xMark->deleteMark(nMark); + } + + // 2. Lesen des Versionsnummer + sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion; + sal_uInt16 nAnyMask = _rxInStream->readShort(); + + if (nAnyMask & WIDTH) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aWidth <<= (sal_Int32)nValue; + } + + if (nAnyMask & ALIGN) + { + sal_Int16 nValue = _rxInStream->readShort(); + m_aAlign <<= nValue; + } + if (nAnyMask & OLD_HIDDEN) + { + sal_Bool bValue = _rxInStream->readBoolean(); + m_aHidden <<= (sal_Bool)bValue; + } + + // Name + _rxInStream >> m_aLabel; + + if (nAnyMask & COMPATIBLE_HIDDEN) + { + sal_Bool bValue = _rxInStream->readBoolean(); + m_aHidden <<= (sal_Bool)bValue; + } +} + +//------------------------------------------------------------------------------ +IMPL_COLUMN(TextFieldColumn, FRM_SUN_COMPONENT_TEXTFIELD, sal_False); +IMPL_COLUMN(PatternFieldColumn, FRM_SUN_COMPONENT_PATTERNFIELD, sal_False); +IMPL_COLUMN(DateFieldColumn, FRM_SUN_COMPONENT_DATEFIELD, sal_True); +IMPL_COLUMN(TimeFieldColumn, FRM_SUN_COMPONENT_TIMEFIELD, sal_False); +IMPL_COLUMN(NumericFieldColumn, FRM_SUN_COMPONENT_NUMERICFIELD, sal_False); +IMPL_COLUMN(CurrencyFieldColumn, FRM_SUN_COMPONENT_CURRENCYFIELD, sal_False); +IMPL_COLUMN(CheckBoxColumn, FRM_SUN_COMPONENT_CHECKBOX, sal_False); +IMPL_COLUMN(ComboBoxColumn, FRM_SUN_COMPONENT_COMBOBOX, sal_False); +IMPL_COLUMN(ListBoxColumn, FRM_SUN_COMPONENT_LISTBOX, sal_False); +IMPL_COLUMN(FormattedFieldColumn, FRM_SUN_COMPONENT_FORMATTEDFIELD, sal_False); + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Columns.hxx b/forms/source/component/Columns.hxx new file mode 100644 index 000000000000..f52d8db1afa9 --- /dev/null +++ b/forms/source/component/Columns.hxx @@ -0,0 +1,221 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_COLUMNS_HXX +#define _FRM_COLUMNS_HXX + +#include "cloneable.hxx" +#include "frm_strings.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/util/XCloneable.hpp> +/** === end UNO includes === **/ + +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/propagg.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/component.hxx> + +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OGridColumn +//================================================================== +typedef ::cppu::WeakAggComponentImplHelper2 < ::com::sun::star::lang::XUnoTunnel + , ::com::sun::star::util::XCloneable > OGridColumn_BASE; +class OGridColumn :public ::comphelper::OBaseMutex + ,public OGridColumn_BASE + ,public OPropertySetAggregationHelper + ,public OCloneableAggregation +{ +protected: +// [properties] + ::com::sun::star::uno::Any m_aWidth; // column width + ::com::sun::star::uno::Any m_aAlign; // column alignment + ::com::sun::star::uno::Any m_aHidden; // column hidden? +// [properties] + + ::comphelper::ComponentContext m_aContext; + ::rtl::OUString m_aModelName; + +// [properties] + ::rtl::OUString m_aLabel; // Name der Spalte +// [properties] + +public: + OGridColumn(const ::comphelper::ComponentContext& _rContext, const ::rtl::OUString& _sModelName = ::rtl::OUString()); + OGridColumn(const OGridColumn* _pOriginal ); + virtual ~OGridColumn(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OGridControlModel, OGridColumn_BASE); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + static const ::com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelImplementationId(); + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence<sal_Int8>& _rIdentifier) throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + + // XPropertySet + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() = 0; + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + + using OPropertySetAggregationHelper::getFastPropertyValue; + + // ::com::sun::star::beans::XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + + const ::rtl::OUString& getModelName() const { return m_aModelName; } + +protected: + static void clearAggregateProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps, sal_Bool bAllowDropDown); + static void setOwnProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps); + + virtual OGridColumn* createCloneColumn() const = 0; +}; + +#define DECL_COLUMN(ClassName) \ +class ClassName \ + :public OGridColumn \ + ,public OAggregationArrayUsageHelper< ClassName > \ +{ \ +public: \ + ClassName(const ::comphelper::ComponentContext& _rContext ); \ + ClassName(const ClassName* _pCloneFrom); \ + \ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException); \ + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); \ + \ + virtual void fillProperties( \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps, \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps \ + ) const; \ + \ + virtual OGridColumn* createCloneColumn() const; \ +}; + + +#define IMPL_COLUMN(ClassName, Model, bAllowDropDown) \ + ClassName::ClassName( const ::comphelper::ComponentContext& _rContext ) \ + :OGridColumn(_rContext, Model) \ +{ \ +} \ +ClassName::ClassName( const ClassName* _pCloneFrom ) \ + :OGridColumn( _pCloneFrom ) \ +{ \ +} \ +::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> ClassName::getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException) \ +{ \ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) ); \ + return xInfo; \ +} \ +::cppu::IPropertyArrayHelper& ClassName::getInfoHelper() \ +{ \ + return *const_cast<ClassName*>(this)->getArrayHelper(); \ +} \ +void ClassName::fillProperties( \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps, \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps \ + ) const \ +{ \ + if (m_xAggregateSet.is()) \ + { \ + _rAggregateProps = m_xAggregateSet->getPropertySetInfo()->getProperties(); \ + clearAggregateProperties(_rAggregateProps, bAllowDropDown); \ + setOwnProperties(_rProps); \ + } \ +} \ +OGridColumn* ClassName::createCloneColumn() const \ +{ \ + return new ClassName( this ); \ +} \ + \ +// column type ids +#define TYPE_CHECKBOX 0 +#define TYPE_COMBOBOX 1 +#define TYPE_CURRENCYFIELD 2 +#define TYPE_DATEFIELD 3 +#define TYPE_FORMATTEDFIELD 4 +#define TYPE_LISTBOX 5 +#define TYPE_NUMERICFIELD 6 +#define TYPE_PATTERNFIELD 7 +#define TYPE_TEXTFIELD 8 +#define TYPE_TIMEFIELD 9 + +// liste aller bekannten columns +const StringSequence& getColumnTypes(); +sal_Int32 getColumnTypeByModelName(const ::rtl::OUString& aModelName); + +// Columns +DECL_COLUMN(TextFieldColumn) +DECL_COLUMN(PatternFieldColumn) +DECL_COLUMN(DateFieldColumn) +DECL_COLUMN(TimeFieldColumn) +DECL_COLUMN(NumericFieldColumn) +DECL_COLUMN(CurrencyFieldColumn) +DECL_COLUMN(CheckBoxColumn) +DECL_COLUMN(ComboBoxColumn) +DECL_COLUMN(ListBoxColumn) +DECL_COLUMN(FormattedFieldColumn) + +#endif // _FRM_COLUMNS_HXX + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/ComboBox.cxx b/forms/source/component/ComboBox.cxx new file mode 100644 index 000000000000..4dfdb61cbb2b --- /dev/null +++ b/forms/source/component/ComboBox.cxx @@ -0,0 +1,931 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "ComboBox.hxx" +#include "property.hxx" +#include "property.hrc" +#include "services.hxx" + +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "BaseListBox.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/SQLErrorEvent.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +/** === end UNO includes === **/ + +#include <comphelper/numbers.hxx> +#include <comphelper/basicio.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbconversion.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> + +#include <limits.h> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//======================================================================== +// class OComboBoxModel +//======================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OComboBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return (*new OComboBoxModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OComboBoxModel::_getTypes() +{ + return ::comphelper::concatSequences( + OBoundControlModel::_getTypes(), + OEntryListHelper::getTypes(), + OErrorBroadcaster::getTypes() + ); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OComboBoxModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_COMBOBOX; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_COMBOBOX; + *pStoreTo++ = BINDABLE_DATABASE_COMBO_BOX; + + return aSupported; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OComboBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControlModel::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OEntryListHelper::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OErrorBroadcaster::queryInterface( _rType ); + return aReturn; +} + +//------------------------------------------------------------------ +DBG_NAME( OComboBoxModel ) +//------------------------------------------------------------------ +OComboBoxModel::OComboBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_COMBOBOX, FRM_SUN_CONTROL_COMBOBOX, sal_True, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OEntryListHelper( (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_eListSourceType(ListSourceType_TABLE) + ,m_bEmptyIsNull(sal_True) +{ + DBG_CTOR( OComboBoxModel, NULL ); + + m_nClassId = FormComponentType::COMBOBOX; + initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT ); +} + +//------------------------------------------------------------------ +OComboBoxModel::OComboBoxModel( const OComboBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + ,OEntryListHelper( *_pOriginal, (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_aListSource( _pOriginal->m_aListSource ) + ,m_aDefaultText( _pOriginal->m_aDefaultText ) + ,m_eListSourceType( _pOriginal->m_eListSourceType ) + ,m_bEmptyIsNull( _pOriginal->m_bEmptyIsNull ) +{ + DBG_CTOR( OComboBoxModel, NULL ); +} + +//------------------------------------------------------------------ +OComboBoxModel::~OComboBoxModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR( OComboBoxModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OComboBoxModel ) + +//------------------------------------------------------------------------------ +void OComboBoxModel::disposing() +{ + OBoundControlModel::disposing(); + OEntryListHelper::disposing(); + OErrorBroadcaster::disposing(); + m_xFormatter = NULL; +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + switch (_nHandle) + { + case PROPERTY_ID_LISTSOURCETYPE: + _rValue <<= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE: + _rValue <<= m_aListSource; + break; + + case PROPERTY_ID_EMPTY_IS_NULL: + _rValue <<= m_bEmptyIsNull; + break; + + case PROPERTY_ID_DEFAULT_TEXT: + _rValue <<= m_aDefaultText; + break; + + case PROPERTY_ID_STRINGITEMLIST: + _rValue <<= getStringItemList(); + break; + + default: + OBoundControlModel::getFastPropertyValue(_rValue, _nHandle); + } +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) + throw (Exception) +{ + switch (_nHandle) + { + case PROPERTY_ID_LISTSOURCETYPE : + DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType*>(NULL))), + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING, + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_aListSource; + // die ListSource hat sich geaendert -> neu laden + if (ListSourceType_VALUELIST != m_eListSourceType) + { + if ( m_xCursor.is() && !hasField() && !hasExternalListSource() ) + // combo box is already connected to a database, and no external list source + // data source changed -> refresh + loadData( false ); + } + break; + + case PROPERTY_ID_EMPTY_IS_NULL : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_bEmptyIsNull; + break; + + case PROPERTY_ID_DEFAULT_TEXT : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING, + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_aDefaultText; + resetNoBroadcast(); + break; + + case PROPERTY_ID_STRINGITEMLIST: + { + ControlModelLock aLock( *this ); + setNewStringItemList( _rValue, aLock ); + // TODO: this is bogus. setNewStringItemList expects a guard which has the *only* + // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with + // a lock - so we effectively has two locks here, of which setNewStringItemList can + // only control one. + } + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OComboBoxModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_LISTSOURCETYPE : + bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType); + break; + + case PROPERTY_ID_LISTSOURCE : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aListSource); + break; + + case PROPERTY_ID_EMPTY_IS_NULL : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bEmptyIsNull); + break; + + case PROPERTY_ID_DEFAULT_TEXT : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultText); + break; + + case PROPERTY_ID_STRINGITEMLIST: + bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 6, OBoundControlModel ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND); + DECL_PROP1(LISTSOURCE, ::rtl::OUString, BOUND); + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(DEFAULT_TEXT, ::rtl::OUString, BOUND); + DECL_PROP1(STRINGITEMLIST, Sequence< ::rtl::OUString >,BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OBoundControlModel::describeAggregateProperties( _rAggregateProps ); + + // superseded properties: + RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST ); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OComboBoxModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_COMBOBOX; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OComboBoxModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) + throw(stario::IOException, RuntimeException) +{ + OBoundControlModel::write(_rxOutStream); + + // Version + // Version 0x0002: EmptyIsNull + // Version 0x0003: ListSource->Seq + // Version 0x0004: DefaultText + // Version 0x0005: HelpText + _rxOutStream->writeShort(0x0006); + + // Maskierung fuer any + sal_uInt16 nAnyMask = 0; + if (m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT) + nAnyMask |= BOUNDCOLUMN; + _rxOutStream << nAnyMask; + + StringSequence aListSourceSeq(&m_aListSource, 1); + _rxOutStream << aListSourceSeq; + _rxOutStream << (sal_Int16)m_eListSourceType; + + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nBoundColumn = 0; + m_aBoundColumn >>= nBoundColumn; + _rxOutStream << nBoundColumn; + } + + _rxOutStream << (sal_Bool)m_bEmptyIsNull; + _rxOutStream << m_aDefaultText; + writeHelpTextCompatibly(_rxOutStream); + + // from version 0x0006 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OComboBoxModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw(stario::IOException, RuntimeException) +{ + OBoundControlModel::read(_rxInStream); + ControlModelLock aLock( *this ); + + // since we are "overwriting" the StringItemList of our aggregate (means we have + // an own place to store the value, instead of relying on our aggregate storing it), + // we need to respect what the aggregate just read for the StringItemList property. + try + { + if ( m_xAggregateSet.is() ) + setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" ); + } + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + DBG_ASSERT(nVersion > 0, "OComboBoxModel::read : version 0 ? this should never have been written !"); + + if (nVersion > 0x0006) + { + DBG_ERROR("OComboBoxModel::read : invalid (means unknown) version !"); + m_aListSource = ::rtl::OUString(); + m_aBoundColumn <<= (sal_Int16)0; + m_aDefaultText = ::rtl::OUString(); + m_eListSourceType = ListSourceType_TABLE; + m_bEmptyIsNull = sal_True; + defaultCommonProperties(); + return; + } + + // Maskierung fuer any + sal_uInt16 nAnyMask; + _rxInStream >> nAnyMask; + + // ListSource + if (nVersion < 0x0003) + { + ::rtl::OUString sListSource; + _rxInStream >> m_aListSource; + } + else // nVersion == 4 + { + m_aListSource = ::rtl::OUString(); + StringSequence aListSource; + _rxInStream >> aListSource; + const ::rtl::OUString* pToken = aListSource.getConstArray(); + sal_Int32 nLen = aListSource.getLength(); + for (sal_Int32 i = 0; i < nLen; ++i, ++pToken) + m_aListSource += *pToken; + } + + sal_Int16 nListSourceType; + _rxInStream >> nListSourceType; + m_eListSourceType = (ListSourceType)nListSourceType; + + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nValue; + _rxInStream >> nValue; + m_aBoundColumn <<= nValue; + } + + if (nVersion > 0x0001) + { + sal_Bool bNull; + _rxInStream >> bNull; + m_bEmptyIsNull = bNull; + } + + if (nVersion > 0x0003) // nVersion == 4 + _rxInStream >> m_aDefaultText; + + // Stringliste muss geleert werden, wenn eine Listenquelle gesetzt ist + // dieses kann der Fall sein wenn im alive modus gespeichert wird + if ( m_aListSource.getLength() + && !hasExternalListSource() + ) + { + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); + } + + if (nVersion > 0x0004) + readHelpTextCompatibly(_rxInStream); + + if (nVersion > 0x0005) + readCommonProperties(_rxInStream); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + { + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); + } +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::loadData( bool _bForce ) +{ + DBG_ASSERT(m_eListSourceType != ListSourceType_VALUELIST, "OComboBoxModel::loadData : do not call for a value list !"); + DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::loadData: cannot load from DB when I have an external list source!" ); + + if ( hasExternalListSource() ) + return; + + // Connection holen + Reference<XRowSet> xForm(m_xCursor, UNO_QUERY); + if (!xForm.is()) + return; + Reference<XConnection> xConnection = getConnection(xForm); + if (!xConnection.is()) + return; + + Reference<XServiceInfo> xServiceInfo(xConnection, UNO_QUERY); + if (!xServiceInfo.is() || !xServiceInfo->supportsService(SRV_SDB_CONNECTION)) + { + DBG_ERROR("OComboBoxModel::loadData : invalid connection !"); + return; + } + + if (!m_aListSource.getLength() || m_eListSourceType == ListSourceType_VALUELIST) + return; + + ::utl::SharedUNOComponent< XResultSet > xListCursor; + try + { + m_aListRowSet.setConnection( xConnection ); + + bool bExecuteRowSet( false ); + switch (m_eListSourceType) + { + case ListSourceType_TABLEFIELDS: + // don't work with a statement here, the fields will be collected below + break; + case ListSourceType_TABLE: + { + // does the bound field belong to the table ? + // if we use an alias for the bound field, we won't find it + // in that case we use the first field of the table + + Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, m_aListSource); + Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY); + + ::rtl::OUString aFieldName; + if ( xFieldsByName.is() && xFieldsByName->hasByName( getControlSource() ) ) + { + aFieldName = getControlSource(); + } + else + { + // otherwise look for the alias + Reference<XSQLQueryComposerFactory> xFactory(xConnection, UNO_QUERY); + if (!xFactory.is()) + break; + + Reference<XSQLQueryComposer> xComposer = xFactory->createQueryComposer(); + try + { + Reference<XPropertySet> xFormAsSet(xForm, UNO_QUERY); + ::rtl::OUString aStatement; + xFormAsSet->getPropertyValue(PROPERTY_ACTIVECOMMAND) >>= aStatement; + xComposer->setQuery(aStatement); + } + catch(Exception&) + { + disposeComponent(xComposer); + break; + } + + // search the field + Reference< XColumnsSupplier > xSupplyFields(xComposer, UNO_QUERY); + DBG_ASSERT(xSupplyFields.is(), "OComboBoxModel::loadData : invalid query composer !"); + + Reference< XNameAccess > xFieldNames = xSupplyFields->getColumns(); + if ( xFieldNames->hasByName( getControlSource() ) ) + { + Reference< XPropertySet > xComposerFieldAsSet; + xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet; + if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet)) + xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName; + } + + disposeComponent(xComposer); + } + + if (!aFieldName.getLength()) + break; + + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + OSL_ENSURE(xMeta.is(),"No database meta data!"); + if ( xMeta.is() ) + { + ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString(); + + ::rtl::OUString sCatalog, sSchema, sTable; + qualifiedNameComponents( xMeta, m_aListSource, sCatalog, sSchema, sTable, eInDataManipulation ); + + ::rtl::OUStringBuffer aStatement; + aStatement.appendAscii( "SELECT DISTINCT " ); + aStatement.append ( quoteName( aQuote, aFieldName ) ); + aStatement.appendAscii( " FROM " ); + aStatement.append ( composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) ); + + m_aListRowSet.setEscapeProcessing( sal_False ); + m_aListRowSet.setCommand( aStatement.makeStringAndClear() ); + bExecuteRowSet = true; + } + } break; + case ListSourceType_QUERY: + { + m_aListRowSet.setCommandFromQuery( m_aListSource ); + bExecuteRowSet = true; + } + break; + + default: + { + m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType ); + m_aListRowSet.setCommand( m_aListSource ); + bExecuteRowSet = true; + } + } + + if ( bExecuteRowSet ) + { + if ( !_bForce && !m_aListRowSet.isDirty() ) + { + // if none of the settings of the row set changed, compared to the last + // invocation of loadData, then don't re-fill the list. Instead, assume + // the list entries are the same. + return; + } + xListCursor.reset( m_aListRowSet.execute() ); + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + ::std::vector< ::rtl::OUString > aStringList; + aStringList.reserve(16); + try + { + OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ), + "OComboBoxModel::loadData: logic error!" ); + if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) ) + return; + + switch (m_eListSourceType) + { + case ListSourceType_SQL: + case ListSourceType_SQLPASSTHROUGH: + case ListSourceType_TABLE: + case ListSourceType_QUERY: + { + // die XDatabaseVAriant der ersten Spalte + Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY); + DBG_ASSERT(xSupplyCols.is(), "OComboBoxModel::loadData : cursor supports the row set service but is no column supplier?!"); + Reference<XIndexAccess> xColumns; + if (xSupplyCols.is()) + { + xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY); + DBG_ASSERT(xColumns.is(), "OComboBoxModel::loadData : no columns supplied by the row set !"); + } + Reference< XPropertySet > xDataField; + if ( xColumns.is() ) + xColumns->getByIndex(0) >>= xDataField; + if ( !xDataField.is() ) + return; + + ::dbtools::FormattedColumnValue aValueFormatter( getContext(), xForm, xDataField ); + + // Listen fuellen + sal_Int16 i = 0; + // per definitionem the list cursor is positioned _before_ the first row at the moment + while (xListCursor->next() && (i++<SHRT_MAX)) // max anzahl eintraege + { + aStringList.push_back( aValueFormatter.getFormattedValue() ); + } + } + break; + case ListSourceType_TABLEFIELDS: + { + Reference<XNameAccess> xFieldNames = getTableFields(xConnection, m_aListSource); + if (xFieldNames.is()) + { + StringSequence seqNames = xFieldNames->getElementNames(); + sal_Int32 nFieldsCount = seqNames.getLength(); + const ::rtl::OUString* pustrNames = seqNames.getConstArray(); + + for (sal_Int32 k=0; k<nFieldsCount; ++k) + aStringList.push_back(pustrNames[k]); + } + } + break; + default: + OSL_ENSURE( false, "OComboBoxModel::loadData: unreachable!" ); + break; + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + // String-Sequence fuer ListBox erzeugen + StringSequence aStringSeq(aStringList.size()); + ::rtl::OUString* pStringAry = aStringSeq.getArray(); + for (sal_Int32 i = 0; i<aStringSeq.getLength(); ++i) + pStringAry[i] = aStringList[i]; + + // String-Sequence an ListBox setzen + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( aStringSeq ) ); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + Reference<XPropertySet> xField = getField(); + if ( xField.is() ) + m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) ); + getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= m_aDesignModeStringItems; + + // Daten nur laden, wenn eine Listenquelle angegeben wurde + if ( m_aListSource.getLength() && m_xCursor.is() && !hasExternalListSource() ) + loadData( false ); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::onDisconnectedDbColumn() +{ + m_pValueFormatter.reset(); + + // reset the string item list + if ( !hasExternalListSource() ) + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( m_aDesignModeStringItems ) ); + + m_aListRowSet.dispose(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OComboBoxModel::reloaded( const EventObject& aEvent ) throw(RuntimeException) +{ + OBoundControlModel::reloaded(aEvent); + + // reload data if we have a list source + if ( m_aListSource.getLength() && m_xCursor.is() && !hasExternalListSource() ) + loadData( false ); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::resetNoBroadcast() +{ + OBoundControlModel::resetNoBroadcast(); + m_aLastKnownValue.clear(); +} + +//----------------------------------------------------------------------------- +sal_Bool OComboBoxModel::commitControlValueToDbColumn( bool _bPostReset ) +{ + Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + + ::rtl::OUString sNewValue; + aNewValue >>= sNewValue; + + bool bModified = ( aNewValue != m_aLastKnownValue ); + if ( bModified ) + { + if ( !aNewValue.hasValue() + || ( !sNewValue.getLength() // an empty string + && m_bEmptyIsNull // which should be interpreted as NULL + ) + ) + { + m_xColumnUpdate->updateNull(); + } + else + { + try + { + OSL_PRECOND( m_pValueFormatter.get(), "OComboBoxModel::commitControlValueToDbColumn: no value formatter!" ); + if ( m_pValueFormatter.get() ) + { + if ( !m_pValueFormatter->setFormattedValue( sNewValue ) ) + return sal_False; + } + else + m_xColumnUpdate->updateString( sNewValue ); + } + catch ( const Exception& ) + { + return sal_False; + } + } + + m_aLastKnownValue = aNewValue; + } + + // add the new value to the list + sal_Bool bAddToList = bModified && !_bPostReset; + // (only if this is not the "commit" triggered by a "reset") + + if ( bAddToList ) + { + StringSequence aStringItemList; + if ( getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aStringItemList ) + { + const ::rtl::OUString* pStringItems = aStringItemList.getConstArray(); + sal_Int32 i; + for (i=0; i<aStringItemList.getLength(); ++i, ++pStringItems) + { + if ( pStringItems->equals( sNewValue ) ) + break; + } + + // not found -> add + if (i >= aStringItemList.getLength()) + { + sal_Int32 nOldLen = aStringItemList.getLength(); + aStringItemList.realloc( nOldLen + 1 ); + aStringItemList.getArray()[ nOldLen ] = sNewValue; + + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( aStringItemList ) ); + } + } + } + + return sal_True; +} + +// XPropertiesChangeListener +//------------------------------------------------------------------------------ +Any OComboBoxModel::translateDbColumnToControlValue() +{ + OSL_PRECOND( m_pValueFormatter.get(), "OComboBoxModel::translateDbColumnToControlValue: no value formatter!" ); + if ( m_pValueFormatter.get() ) + { + ::rtl::OUString sValue( m_pValueFormatter->getFormattedValue() ); + if ( !sValue.getLength() + && m_pValueFormatter->getColumn().is() + && m_pValueFormatter->getColumn()->wasNull() + ) + { + m_aLastKnownValue.clear(); + } + else + { + + m_aLastKnownValue <<= sValue; + } + } + else + m_aLastKnownValue.clear(); + + return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( ::rtl::OUString() ); + // (m_aLastKnownValue is alllowed to be VOID, the control value isn't) +} + +//------------------------------------------------------------------------------ +Any OComboBoxModel::getDefaultForReset() const +{ + return makeAny( m_aDefaultText ); +} + +//-------------------------------------------------------------------- +void OComboBoxModel::stringItemListChanged( ControlModelLock& /*_rInstanceLock*/ ) +{ + if ( m_xAggregateSet.is() ) + m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) ); +} + +//-------------------------------------------------------------------- +void OComboBoxModel::connectedExternalListSource( ) +{ + // TODO? +} + +//-------------------------------------------------------------------- +void OComboBoxModel::disconnectedExternalListSource( ) +{ + // TODO? +} + +//-------------------------------------------------------------------- +void OComboBoxModel::refreshInternalEntryList() +{ + DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::refreshInternalEntryList: invalid call!" ); + + if ( !hasExternalListSource( ) + && ( m_eListSourceType != ListSourceType_VALUELIST ) + && ( m_xCursor.is() ) + ) + { + loadData( true ); + } +} + +//-------------------------------------------------------------------- +void SAL_CALL OComboBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException ) +{ + if ( !OEntryListHelper::handleDisposing( _rSource ) ) + OBoundControlModel::disposing( _rSource ); +} + +//======================================================================== +//= OComboBoxControl +//======================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OComboBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OComboBoxControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +OComboBoxControl::OComboBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_COMBOBOX) +{ +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OComboBoxControl::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMBOBOX; + return aSupported; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/ComboBox.hxx b/forms/source/component/ComboBox.hxx new file mode 100644 index 000000000000..55ebcbe168e2 --- /dev/null +++ b/forms/source/component/ComboBox.hxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_COMBOBOX_HXX_ +#define _FORMS_COMBOBOX_HXX_ + +#include "FormComponent.hxx" +#include "errorbroadcaster.hxx" +#include "entrylisthelper.hxx" +#include "cachedrowset.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/awt/XItemListener.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +/** === end UNO includes === **/ + +#include <connectivity/formattedcolumnvalue.hxx> + +#include <cppuhelper/interfacecontainer.hxx> + +#include <vcl/timer.hxx> + +#include <tools/date.hxx> + +//......................................................................... +namespace frm +{ + +//================================================================== +// OComboBoxModel +//================================================================== +class OComboBoxModel + :public OBoundControlModel + ,public OEntryListHelper + ,public OErrorBroadcaster +{ + CachedRowSet m_aListRowSet; // the row set to fill the list + ::com::sun::star::uno::Any m_aBoundColumn; // obsolet + ::rtl::OUString m_aListSource; // + ::rtl::OUString m_aDefaultText; // DefaultText + ::com::sun::star::uno::Any m_aLastKnownValue; + + StringSequence m_aDesignModeStringItems; + // upon loading, in some cases we reset fill our string item list ourself. We don't want + // to lose the user's items then, so we remember them here. + + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter> m_xFormatter; + + ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source + sal_Bool m_bEmptyIsNull; // LeerString wird als NULL interpretiert + + ::std::auto_ptr< ::dbtools::FormattedColumnValue > + m_pValueFormatter; + + + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OComboBoxModel ); + + virtual void SAL_CALL disposing(); + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + + // XLoadListener + virtual void SAL_CALL reloaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OComboBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS(OComboBoxModel, OBoundControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OBoundControlModel::getFastPropertyValue; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void resetNoBroadcast(); + + // OEntryListHelper overriables + virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ); + virtual void connectedExternalListSource( ); + virtual void disconnectedExternalListSource( ); + virtual void refreshInternalEntryList(); + +protected: + void loadData( bool _bForce ); + + DECLARE_XCLONEABLE(); +}; + +//================================================================== +// OComboBoxControl +//================================================================== + +class OComboBoxControl : public OBoundControl +{ +public: + OComboBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OComboBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_COMBOBOX_HXX_ + diff --git a/forms/source/component/Currency.cxx b/forms/source/component/Currency.cxx new file mode 100644 index 000000000000..89a3b93b4a43 --- /dev/null +++ b/forms/source/component/Currency.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Currency.hxx" +#include <tools/debug.hxx> +#include <unotools/localedatawrapper.hxx> +#include <vcl/svapp.hxx> +#include <unotools/syslocale.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +// OCurrencyControl +//================================================================== +//------------------------------------------------------------------ +OCurrencyControl::OCurrencyControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_CURRENCYFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OCurrencyControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OCurrencyControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OCurrencyControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCurrencyControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_CURRENCYFIELD; + return aSupported; +} + +//================================================================== +// OCurrencyModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OCurrencyModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OCurrencyModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OCurrencyModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +void OCurrencyModel::implConstruct() +{ + if (m_xAggregateSet.is()) + { + try + { + // get the system international informations + const LocaleDataWrapper& aLocaleInfo = SvtSysLocale().GetLocaleData(); + + ::rtl::OUString sCurrencySymbol; + sal_Bool bPrependCurrencySymbol; + switch ( aLocaleInfo.getCurrPositiveFormat() ) + { + case 0: // $1 + sCurrencySymbol = String(aLocaleInfo.getCurrSymbol()); + bPrependCurrencySymbol = sal_True; + break; + case 1: // 1$ + sCurrencySymbol = String(aLocaleInfo.getCurrSymbol()); + bPrependCurrencySymbol = sal_False; + break; + case 2: // $ 1 + sCurrencySymbol = ::rtl::OUString(String(aLocaleInfo.getCurrSymbol())) + ::rtl::OUString::createFromAscii(" "); + bPrependCurrencySymbol = sal_True; + break; + case 3: // 1 $ + sCurrencySymbol = ::rtl::OUString::createFromAscii(" ") + ::rtl::OUString(String(aLocaleInfo.getCurrSymbol())); + bPrependCurrencySymbol = sal_False; + break; + } + if (sCurrencySymbol.getLength()) + { + m_xAggregateSet->setPropertyValue(PROPERTY_CURRENCYSYMBOL, makeAny(sCurrencySymbol)); + m_xAggregateSet->setPropertyValue(PROPERTY_CURRSYM_POSITION, makeAny(bPrependCurrencySymbol)); + } + } + catch(Exception&) + { + DBG_ERROR( "OCurrencyModel::implConstruct: caught an exception while initializing the aggregate!" ); + } + } +} + +//------------------------------------------------------------------ +DBG_NAME( OCurrencyModel ) +//------------------------------------------------------------------ +OCurrencyModel::OCurrencyModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_CURRENCYFIELD, FRM_SUN_CONTROL_CURRENCYFIELD, sal_False, sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( OCurrencyModel, NULL ); + + m_nClassId = FormComponentType::CURRENCYFIELD; + initValueProperty( PROPERTY_VALUE, PROPERTY_ID_VALUE ); + + implConstruct(); +} + +//------------------------------------------------------------------ +OCurrencyModel::OCurrencyModel( const OCurrencyModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OCurrencyModel, NULL ); + implConstruct(); +} + +//------------------------------------------------------------------ +OCurrencyModel::~OCurrencyModel() +{ + DBG_DTOR( OCurrencyModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OCurrencyModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCurrencyModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 4 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_CURRENCYFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_CURRENCYFIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void OCurrencyModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OEditBaseModel ) + // Value auf transient setzen +// ModifyPropertyAttributes(_rAggregateProps, PROPERTY_VALUE, PropertyAttribute::TRANSIENT, 0); + + DECL_PROP3(DEFAULT_VALUE, double, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OCurrencyModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_CURRENCYFIELD; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +sal_Bool OCurrencyModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( aControlValue.getValueType().getTypeClass() == TypeClass_VOID ) + m_xColumnUpdate->updateNull(); + else + { + try + { + m_xColumnUpdate->updateDouble( getDouble( aControlValue ) ); + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +Any OCurrencyModel::translateDbColumnToControlValue() +{ + m_aSaveValue <<= m_xColumn->getDouble(); + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + return m_aSaveValue; +} + +// XReset +//------------------------------------------------------------------------------ +Any OCurrencyModel::getDefaultForReset() const +{ + Any aValue; + if ( m_aDefault.getValueType().getTypeClass() == TypeClass_DOUBLE ) + aValue = m_aDefault; + + return aValue; +} + +//------------------------------------------------------------------------------ +void OCurrencyModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Currency.hxx b/forms/source/component/Currency.hxx new file mode 100644 index 000000000000..f35840933240 --- /dev/null +++ b/forms/source/component/Currency.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_CURRENCY_HXX_ +#define _FORMS_CURRENCY_HXX_ + +#include "EditBase.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= OCurrencyModel +//================================================================== +class OCurrencyModel + :public OEditBaseModel +{ + ::com::sun::star::uno::Any m_aSaveValue; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OCurrencyModel ); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OCurrencyModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun ::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); + + void implConstruct(); +}; + +//================================================================== +//= OCurrencyControl +//================================================================== +class OCurrencyControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OCurrencyControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OCurrencyControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_CURRENCY_HXX_ + diff --git a/forms/source/component/DatabaseForm.cxx b/forms/source/component/DatabaseForm.cxx new file mode 100644 index 000000000000..5f3f04d45618 --- /dev/null +++ b/forms/source/component/DatabaseForm.cxx @@ -0,0 +1,4160 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "componenttools.hxx" +#include "DatabaseForm.hxx" +#include "EventThread.hxx" +#include "frm_module.hxx" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "GroupManager.hxx" +#include "property.hrc" +#include "property.hxx" +#include "services.hxx" + +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/form/DataSelectionType.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/TabulatorCycle.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/XModifiable2.hpp> + +#include <comphelper/basicio.hxx> +#include <comphelper/container.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/uno3.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/implbase2.hxx> +#include <osl/mutex.hxx> +#include <rtl/math.hxx> +#include <rtl/tencinfo.h> +#include <svl/inetstrm.hxx> +#include <svl/inettype.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/fsys.hxx> +#include <tools/inetmsg.hxx> +#include <tools/urlobj.hxx> +#include <unotools/ucblockbytes.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <vos/mutex.hxx> + +#include <ctype.h> +#include <hash_map> + +// compatiblity: DatabaseCursorType is dead, but for compatiblity reasons we still have to write it ... +namespace com { +namespace sun { +namespace star { +namespace data { + +enum DatabaseCursorType +{ + DatabaseCursorType_FORWARD = 0, + DatabaseCursorType_SNAPSHOT = 1, + DatabaseCursorType_KEYSET = 2, + DatabaseCursorType_DYNAMIC = 3, + DatabaseCursorType_MAKE_FIXED_SIZE = SAL_MAX_ENUM +}; + +} } } } + +using namespace ::dbtools; +using namespace ::comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::data; +using namespace ::com::sun::star::util; + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ODatabaseForm() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ODatabaseForm > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= DocumentModifyGuard +//================================================================== +class DocumentModifyGuard +{ +public: + DocumentModifyGuard( const Reference< XInterface >& _rxFormComponent ) + :m_xDocumentModify( getXModel( _rxFormComponent ), UNO_QUERY ) + { + impl_changeModifiableFlag_nothrow( false ); + } + ~DocumentModifyGuard() + { + impl_changeModifiableFlag_nothrow( true ); + } + +private: + void impl_changeModifiableFlag_nothrow( const bool _enable ) + { + try + { + if ( m_xDocumentModify.is() ) + _enable ? m_xDocumentModify->enableSetModified() : m_xDocumentModify->disableSetModified(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +private: + Reference< XModifiable2 > m_xDocumentModify; +}; + +//================================================================== +//= OFormSubmitResetThread +//=----------------------------------------------------------------- +//= submitting and resetting html-forms asynchronously +//================================================================== + +//------------------------------------------------------------------ +class OFormSubmitResetThread: public OComponentEventThread +{ +protected: + + // duplicate an event with respect to it's type + virtual EventObject *cloneEvent( const EventObject *pEvt ) const; + + // process an event. while processing the mutex isn't locked, and pCompImpl + // is made sure to remain valid + virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl, + const EventObject* _pEvt, + const Reference<XControl>& _rControl, + sal_Bool _bSubmit); + +public: + + OFormSubmitResetThread(ODatabaseForm* pControl) : OComponentEventThread(pControl) { } +}; + +//------------------------------------------------------------------ +EventObject* OFormSubmitResetThread::cloneEvent( + const EventObject *pEvt ) const +{ + return new ::com::sun::star::awt::MouseEvent( *(::com::sun::star::awt::MouseEvent *)pEvt ); +} + +//------------------------------------------------------------------ +void OFormSubmitResetThread::processEvent( + ::cppu::OComponentHelper* pCompImpl, + const EventObject *_pEvt, + const Reference<XControl>& _rControl, + sal_Bool _bSubmit) +{ + if (_bSubmit) + ((ODatabaseForm *)pCompImpl)->submit_impl(_rControl, *static_cast<const ::com::sun::star::awt::MouseEvent*>(_pEvt), true); + else + ((ODatabaseForm *)pCompImpl)->reset_impl(true); +} + +//================================================================== +//= ODatabaseForm +//================================================================== + +//------------------------------------------------------------------ +Reference< XInterface > SAL_CALL ODatabaseForm::Create( const Reference< XMultiServiceFactory >& _rxFactory ) +{ + return *( new ODatabaseForm( _rxFactory ) ); +} + +//------------------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL ODatabaseForm::getImplementationId() throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL ODatabaseForm::getTypes() throw(RuntimeException) +{ + // ask the aggregate + Sequence<Type> aAggregateTypes; + Reference<XTypeProvider> xAggregateTypes; + if (query_aggregation(m_xAggregate, xAggregateTypes)) + aAggregateTypes = xAggregateTypes->getTypes(); + + Sequence< Type > aRet = concatSequences( + aAggregateTypes, ODatabaseForm_BASE1::getTypes(), OFormComponents::getTypes() + ); + aRet = concatSequences( aRet, ODatabaseForm_BASE2::getTypes(), ODatabaseForm_BASE3::getTypes() ); + return concatSequences( aRet, OPropertySetAggregationHelper::getTypes() ); +} + +//------------------------------------------------------------------ +Any SAL_CALL ODatabaseForm::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = ODatabaseForm_BASE1::queryInterface(_rType); + // our own interfaces + if (!aReturn.hasValue()) + { + aReturn = ODatabaseForm_BASE2::queryInterface(_rType); + // property set related interfaces + if (!aReturn.hasValue()) + { + aReturn = OPropertySetAggregationHelper::queryInterface(_rType); + + // form component collection related interfaces + if (!aReturn.hasValue()) + { + aReturn = OFormComponents::queryAggregation(_rType); + + // interfaces already present in the aggregate which we want to reroute + // only available if we could create the aggregate + if (!aReturn.hasValue() && m_xAggregateAsRowSet.is()) + aReturn = ODatabaseForm_BASE3::queryInterface(_rType); + + // aggregate interfaces + // (ask the aggregated object _after_ the OComponentHelper (base of OFormComponents), + // so calls to the XComponent interface reach us and not the aggreagtion) + if (!aReturn.hasValue() && m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + } + } + + return aReturn; +} + +DBG_NAME(ODatabaseForm); +//------------------------------------------------------------------ +ODatabaseForm::ODatabaseForm(const Reference<XMultiServiceFactory>& _rxFactory) + :OFormComponents(_rxFactory) + ,OPropertySetAggregationHelper(OComponentHelper::rBHelper) + ,OPropertyChangeListener(m_aMutex) + ,m_aLoadListeners(m_aMutex) + ,m_aRowSetApproveListeners(m_aMutex) + ,m_aRowSetListeners(m_aMutex) + ,m_aSubmitListeners(m_aMutex) + ,m_aErrorListeners(m_aMutex) + ,m_aResetListeners( *this, m_aMutex ) + ,m_aPropertyBagHelper( *this ) + ,m_pAggregatePropertyMultiplexer(NULL) + ,m_pGroupManager( NULL ) + ,m_aParameterManager( m_aMutex, _rxFactory ) + ,m_aFilterManager( _rxFactory ) + ,m_pLoadTimer(NULL) + ,m_pThread(NULL) + ,m_nResetsPending(0) + ,m_nPrivileges(0) + ,m_bInsertOnly( sal_False ) + ,m_eSubmitMethod(FormSubmitMethod_GET) + ,m_eSubmitEncoding(FormSubmitEncoding_URL) + ,m_eNavigation(NavigationBarMode_CURRENT) + ,m_bAllowInsert(sal_True) + ,m_bAllowUpdate(sal_True) + ,m_bAllowDelete(sal_True) + ,m_bLoaded(sal_False) + ,m_bSubForm(sal_False) + ,m_bForwardingConnection(sal_False) + ,m_bSharingConnection( sal_False ) +{ + DBG_CTOR( ODatabaseForm, NULL ); + impl_construct(); +} + +//------------------------------------------------------------------ +ODatabaseForm::ODatabaseForm( const ODatabaseForm& _cloneSource ) + :OFormComponents( _cloneSource ) + ,OPropertySetAggregationHelper( OComponentHelper::rBHelper ) + ,OPropertyChangeListener( m_aMutex ) + ,ODatabaseForm_BASE1() + ,ODatabaseForm_BASE2() + ,ODatabaseForm_BASE3() + ,IPropertyBagHelperContext() + ,m_aLoadListeners( m_aMutex ) + ,m_aRowSetApproveListeners( m_aMutex ) + ,m_aRowSetListeners( m_aMutex ) + ,m_aSubmitListeners( m_aMutex ) + ,m_aErrorListeners( m_aMutex ) + ,m_aResetListeners( *this, m_aMutex ) + ,m_aPropertyBagHelper( *this ) + ,m_pAggregatePropertyMultiplexer( NULL ) + ,m_pGroupManager( NULL ) + ,m_aParameterManager( m_aMutex, _cloneSource.m_xServiceFactory ) + ,m_aFilterManager( _cloneSource.m_xServiceFactory ) + ,m_pLoadTimer( NULL ) + ,m_pThread( NULL ) + ,m_nResetsPending( 0 ) + ,m_nPrivileges( 0 ) + ,m_bInsertOnly( _cloneSource.m_bInsertOnly ) + ,m_aControlBorderColorFocus( _cloneSource.m_aControlBorderColorFocus ) + ,m_aControlBorderColorMouse( _cloneSource.m_aControlBorderColorMouse ) + ,m_aControlBorderColorInvalid( _cloneSource.m_aControlBorderColorInvalid ) + ,m_aDynamicControlBorder( _cloneSource.m_aDynamicControlBorder ) + ,m_sName( _cloneSource.m_sName ) + ,m_aTargetURL( _cloneSource.m_aTargetURL ) + ,m_aTargetFrame( _cloneSource.m_aTargetFrame ) + ,m_eSubmitMethod( _cloneSource.m_eSubmitMethod ) + ,m_eSubmitEncoding( _cloneSource.m_eSubmitEncoding ) + ,m_eNavigation( _cloneSource.m_eNavigation ) + ,m_bAllowInsert( _cloneSource.m_bAllowInsert ) + ,m_bAllowUpdate( _cloneSource.m_bAllowUpdate ) + ,m_bAllowDelete( _cloneSource.m_bAllowDelete ) + ,m_bLoaded( sal_False ) + ,m_bSubForm( sal_False ) + ,m_bForwardingConnection( sal_False ) + ,m_bSharingConnection( sal_False ) +{ + DBG_CTOR( ODatabaseForm, NULL ); + + impl_construct(); + + osl_incrementInterlockedCount( &m_refCount ); + { + // our aggregated rowset itself is not cloneable, so simply copy the properties + ::comphelper::copyProperties( _cloneSource.m_xAggregateSet, m_xAggregateSet ); + + // also care for the dynamic properties: If the clone source has properties which we do not have, + // then add them + try + { + Reference< XPropertySet > xSourceProps( const_cast< ODatabaseForm& >( _cloneSource ).queryAggregation( + XPropertySet::static_type() ), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xSourcePSI( xSourceProps->getPropertySetInfo(), UNO_SET_THROW ); + Reference< XPropertyState > xSourcePropState( xSourceProps, UNO_QUERY ); + + Reference< XPropertySetInfo > xDestPSI( getPropertySetInfo(), UNO_QUERY_THROW ); + + Sequence< Property > aSourceProperties( xSourcePSI->getProperties() ); + for ( const Property* pSourceProperty = aSourceProperties.getConstArray(); + pSourceProperty != aSourceProperties.getConstArray() + aSourceProperties.getLength(); + ++pSourceProperty + ) + { + if ( xDestPSI->hasPropertyByName( pSourceProperty->Name ) ) + continue; + + // the initial value passed to XPropertyContainer is also used as default, usually. So, try + // to retrieve the default of the source property + Any aInitialValue; + if ( xSourcePropState.is() ) + { + aInitialValue = xSourcePropState->getPropertyDefault( pSourceProperty->Name ); + } + else + { + aInitialValue = xSourceProps->getPropertyValue( pSourceProperty->Name ); + } + addProperty( pSourceProperty->Name, pSourceProperty->Attributes, aInitialValue ); + setPropertyValue( pSourceProperty->Name, xSourceProps->getPropertyValue( pSourceProperty->Name ) ); + } + } + catch( const Exception& ) + { + throw WrappedTargetException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not clone the given database form." ) ), + *const_cast< ODatabaseForm* >( &_cloneSource ), + ::cppu::getCaughtException() + ); + } + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//------------------------------------------------------------------ +void ODatabaseForm::impl_construct() +{ + // aggregate a row set + increment(m_refCount); + { + m_xAggregate = Reference< XAggregation >( m_xServiceFactory->createInstance( SRV_SDB_ROWSET ), UNO_QUERY_THROW ); + m_xAggregateAsRowSet.set( m_xAggregate, UNO_QUERY_THROW ); + setAggregation( m_xAggregate ); + } + + // listen for the properties, important for Parameters + if ( m_xAggregateSet.is() ) + { + m_pAggregatePropertyMultiplexer = new OPropertyChangeMultiplexer(this, m_xAggregateSet, sal_False); + m_pAggregatePropertyMultiplexer->acquire(); + m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_COMMAND); + m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_ACTIVE_CONNECTION); + } + + { + Reference< XWarningsSupplier > xRowSetWarnings( m_xAggregate, UNO_QUERY ); + m_aWarnings.setExternalWarnings( xRowSetWarnings ); + } + + if ( m_xAggregate.is() ) + { + m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); + } + + { + m_aFilterManager.initialize( m_xAggregateSet ); + m_aParameterManager.initialize( this, m_xAggregate ); + + declareForwardedProperty( PROPERTY_ID_ACTIVE_CONNECTION ); + } + decrement( m_refCount ); + + m_pGroupManager = new OGroupManager( this ); + m_pGroupManager->acquire(); +} + +//------------------------------------------------------------------ +ODatabaseForm::~ODatabaseForm() +{ + DBG_DTOR(ODatabaseForm,NULL); + + m_pGroupManager->release(); + m_pGroupManager = NULL; + + if (m_xAggregate.is()) + m_xAggregate->setDelegator( NULL ); + + m_aWarnings.setExternalWarnings( NULL ); + + if (m_pAggregatePropertyMultiplexer) + { + m_pAggregatePropertyMultiplexer->dispose(); + m_pAggregatePropertyMultiplexer->release(); + m_pAggregatePropertyMultiplexer = NULL; + } +} + +//============================================================================== +// html tools +//------------------------------------------------------------------------ +::rtl::OUString ODatabaseForm::GetDataURLEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + return GetDataEncoded(true,SubmitButton,MouseEvt); +} +// ----------------------------------------------------------------------------- +::rtl::OUString ODatabaseForm::GetDataEncoded(bool _bURLEncoded,const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + // Liste von successful Controls fuellen + HtmlSuccessfulObjList aSuccObjList; + FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt ); + + + // Liste zu ::rtl::OUString zusammensetzen + ::rtl::OUStringBuffer aResult; + ::rtl::OUString aName; + ::rtl::OUString aValue; + + for ( HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin(); + pSuccObj < aSuccObjList.end(); + ++pSuccObj + ) + { + aName = pSuccObj->aName; + aValue = pSuccObj->aValue; + if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE && aValue.getLength() ) + { + // Bei File-URLs wird der Dateiname und keine URL uebertragen, + // weil Netscape dies so macht. + INetURLObject aURL; + aURL.SetSmartProtocol(INET_PROT_FILE); + aURL.SetSmartURL(aValue); + if( INET_PROT_FILE == aURL.GetProtocol() ) + aValue = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS); + } + Encode( aName ); + Encode( aValue ); + + aResult.append(aName); + aResult.append(sal_Unicode('=')); + aResult.append(aValue); + + if (pSuccObj < aSuccObjList.end() - 1) + { + if ( _bURLEncoded ) + aResult.append(sal_Unicode('&')); + else + aResult.appendAscii("\r\n"); + } + } + + + aSuccObjList.clear(); + + return aResult.makeStringAndClear(); +} + +//============================================================================== +// html tools +//------------------------------------------------------------------------ +::rtl::OUString ODatabaseForm::GetDataTextEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + return GetDataEncoded(false,SubmitButton,MouseEvt); +} + +//------------------------------------------------------------------------ +Sequence<sal_Int8> ODatabaseForm::GetDataMultiPartEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, ::rtl::OUString& rContentType) +{ + + // Parent erzeugen + INetMIMEMessage aParent; + aParent.EnableAttachChild( INETMSG_MULTIPART_FORM_DATA ); + + + // Liste von successful Controls fuellen + HtmlSuccessfulObjList aSuccObjList; + FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt ); + + + // Liste zu ::rtl::OUString zusammensetzen + ::rtl::OUString aResult; + for ( HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin(); + pSuccObj < aSuccObjList.end(); + ++pSuccObj + ) + { + if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_TEXT ) + InsertTextPart( aParent, pSuccObj->aName, pSuccObj->aValue ); + else if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE ) + InsertFilePart( aParent, pSuccObj->aName, pSuccObj->aValue ); + } + + + // Liste loeschen + aSuccObjList.clear(); + + // Fuer Parent MessageStream erzeugen + INetMIMEMessageStream aMessStream; + aMessStream.SetSourceMessage( &aParent ); + aMessStream.GenerateHeader( sal_False ); + + // MessageStream in SvStream kopieren + SvMemoryStream aMemStream; + char* pBuf = new char[1025]; + int nRead; + while( (nRead = aMessStream.Read(pBuf, 1024)) > 0 ) + aMemStream.Write( pBuf, nRead ); + delete[] pBuf; + + aMemStream.Flush(); + aMemStream.Seek( 0 ); + void* pData = (void*)aMemStream.GetData(); + sal_Int32 nLen = aMemStream.Seek(STREAM_SEEK_TO_END); + + rContentType = UniString(aParent.GetContentType()); + return Sequence<sal_Int8>((sal_Int8*)pData, nLen); +} + +//------------------------------------------------------------------------ +namespace +{ + static void appendDigits( sal_Int32 _nNumber, sal_Int8 nDigits, ::rtl::OUStringBuffer& _rOut ) + { + sal_Int32 nCurLen = _rOut.getLength(); + _rOut.append( _nNumber ); + while ( _rOut.getLength() - nCurLen < nDigits ) + _rOut.insert( nCurLen, (sal_Unicode)'0' ); + } +} + +//------------------------------------------------------------------------ +void ODatabaseForm::AppendComponent(HtmlSuccessfulObjList& rList, const Reference<XPropertySet>& xComponentSet, const ::rtl::OUString& rNamePrefix, + const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + if (!xComponentSet.is()) + return; + + // MIB 25.6.98: Geschachtelte Formulare abfangen ... oder muesste + // man sie submitten? + if (!hasProperty(PROPERTY_CLASSID, xComponentSet)) + return; + + // Namen ermitteln + if (!hasProperty(PROPERTY_NAME, xComponentSet)) + return; + + sal_Int16 nClassId = 0; + xComponentSet->getPropertyValue(PROPERTY_CLASSID) >>= nClassId; + ::rtl::OUString aName; + xComponentSet->getPropertyValue( PROPERTY_NAME ) >>= aName; + if( !aName.getLength() && nClassId != FormComponentType::IMAGEBUTTON) + return; + else // Name um den Prefix erweitern + aName = rNamePrefix + aName; + + switch( nClassId ) + { + // Buttons + case FormComponentType::COMMANDBUTTON: + { + // Es wird nur der gedrueckte Submit-Button ausgewertet + // MIB: Sofern ueberhaupt einer uebergeben wurde + if( rxSubmitButton.is() ) + { + Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY); + if (xSubmitButtonComponent == xComponentSet && hasProperty(PROPERTY_LABEL, xComponentSet)) + { + // <name>=<label> + ::rtl::OUString aLabel; + xComponentSet->getPropertyValue( PROPERTY_LABEL ) >>= aLabel; + rList.push_back( HtmlSuccessfulObj(aName, aLabel) ); + } + } + } break; + + // ImageButtons + case FormComponentType::IMAGEBUTTON: + { + // Es wird nur der gedrueckte Submit-Button ausgewertet + // MIB: Sofern ueberhaupt einer uebergeben wurde + if( rxSubmitButton.is() ) + { + Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY); + if (xSubmitButtonComponent == xComponentSet) + { + // <name>.x=<pos.X>&<name>.y=<pos.Y> + ::rtl::OUString aLhs = aName; + ::rtl::OUString aRhs = ::rtl::OUString::valueOf( MouseEvt.X ); + + // nur wenn ein Name vorhanden ist, kann ein name.x + aLhs += aName.getLength() ? UniString::CreateFromAscii(".x") : UniString::CreateFromAscii("x"); + rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) ); + + aLhs = aName; + aRhs = ::rtl::OUString::valueOf( MouseEvt.Y ); + aLhs += aName.getLength() ? UniString::CreateFromAscii(".y") : UniString::CreateFromAscii("y"); + rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) ); + + } + } + } break; + + // CheckBoxen / RadioButtons + case FormComponentType::CHECKBOX: + case FormComponentType::RADIOBUTTON: + { + // <name>=<refValue> + if( !hasProperty(PROPERTY_STATE, xComponentSet) ) + break; + sal_Int16 nChecked = 0; + xComponentSet->getPropertyValue( PROPERTY_STATE ) >>= nChecked; + if( nChecked != 1 ) + break; + + ::rtl::OUString aStrValue; + if( hasProperty(PROPERTY_REFVALUE, xComponentSet) ) + xComponentSet->getPropertyValue( PROPERTY_REFVALUE ) >>= aStrValue; + + rList.push_back( HtmlSuccessfulObj(aName, aStrValue) ); + } break; + + // Edit + case FormComponentType::TEXTFIELD: + { + // <name>=<text> + if( !hasProperty(PROPERTY_TEXT, xComponentSet) ) + break; + + // MIB: Spezial-Behandlung fuer Multiline-Edit nur dann, wenn + // es auch ein Control dazu gibt. + Any aTmp = xComponentSet->getPropertyValue( PROPERTY_MULTILINE ); + sal_Bool bMulti = rxSubmitButton.is() + && (aTmp.getValueType().getTypeClass() == TypeClass_BOOLEAN) + && getBOOL(aTmp); + ::rtl::OUString sText; + if ( bMulti ) // Bei MultiLineEdit Text am Control abholen + { + + Reference<XControlContainer> xControlContainer(rxSubmitButton->getContext(), UNO_QUERY); + if( !xControlContainer.is() ) break; + + Sequence<Reference<XControl> > aControlSeq = xControlContainer->getControls(); + Reference<XControl> xControl; + Reference<XFormComponent> xControlComponent; + + // Richtiges Control suchen + sal_Int32 i; + for( i=0; i<aControlSeq.getLength(); i++ ) + { + xControl = aControlSeq.getConstArray()[i]; + Reference<XPropertySet> xModel(xControl->getModel(), UNO_QUERY); + if (xModel == xComponentSet) + { + Reference<XTextComponent> xTextComponent(xControl, UNO_QUERY); + if( xTextComponent.is() ) + sText = xTextComponent->getText(); + break; + } + } + // Control nicht gefunden oder nicht existent, (Edit im Grid) + if (i == aControlSeq.getLength()) + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText; + } + else + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText; + + rList.push_back( HtmlSuccessfulObj(aName, sText) ); + } break; + + // ComboBox, Patternfield + case FormComponentType::COMBOBOX: + case FormComponentType::PATTERNFIELD: + { + // <name>=<text> + if( hasProperty(PROPERTY_TEXT, xComponentSet) ) + { + ::rtl::OUString aText; + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText; + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + case FormComponentType::CURRENCYFIELD: + case FormComponentType::NUMERICFIELD: + { + // <name>=<wert> // wert wird als double mit Punkt als Decimaltrenner + // kein Wert angegeben (NULL) -> wert leer + if( hasProperty(PROPERTY_VALUE, xComponentSet) ) + { + ::rtl::OUString aText; + Any aVal = xComponentSet->getPropertyValue( PROPERTY_VALUE ); + + double aDoubleVal = 0; + if (aVal >>= aDoubleVal) + { + sal_Int16 nScale = 0; + xComponentSet->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) >>= nScale; + aText = ::rtl::math::doubleToUString(aDoubleVal, rtl_math_StringFormat_F, nScale, '.', sal_True); + } + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + case FormComponentType::DATEFIELD: + { + // <name>=<wert> // Wert wird als Datum im Format (MM-DD-YYYY) + // kein Wert angegeben (NULL) -> wert leer + if( hasProperty(PROPERTY_DATE, xComponentSet) ) + { + ::rtl::OUString aText; + Any aVal = xComponentSet->getPropertyValue( PROPERTY_DATE ); + sal_Int32 nInt32Val = 0; + if (aVal >>= nInt32Val) + { + ::Date aDate( nInt32Val ); + ::rtl::OUStringBuffer aBuffer; + appendDigits( aDate.GetMonth(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aDate.GetDay(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aDate.GetYear(), 4, aBuffer ); + aText = aBuffer.makeStringAndClear(); + } + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + case FormComponentType::TIMEFIELD: + { + // <name>=<wert> // Wert wird als Zeit im Format (HH:MM:SS) angegeben + // kein Wert angegeben (NULL) -> wert leer + if( hasProperty(PROPERTY_TIME, xComponentSet) ) + { + ::rtl::OUString aText; + Any aVal = xComponentSet->getPropertyValue( PROPERTY_TIME ); + sal_Int32 nInt32Val = 0; + if (aVal >>= nInt32Val) + { + ::Time aTime(nInt32Val); + ::rtl::OUStringBuffer aBuffer; + appendDigits( aTime.GetHour(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aTime.GetMin(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aTime.GetSec(), 2, aBuffer ); + aText = aBuffer.makeStringAndClear(); + } + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + + // starform + case FormComponentType::HIDDENCONTROL: + { + + // <name>=<value> + if( hasProperty(PROPERTY_HIDDEN_VALUE, xComponentSet) ) + { + ::rtl::OUString aText; + xComponentSet->getPropertyValue( PROPERTY_HIDDEN_VALUE ) >>= aText; + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + + // starform + case FormComponentType::FILECONTROL: + { + // <name>=<text> + if( hasProperty(PROPERTY_TEXT, xComponentSet) ) + { + + ::rtl::OUString aText; + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText; + rList.push_back( HtmlSuccessfulObj(aName, aText, SUCCESSFUL_REPRESENT_FILE) ); + } + } break; + + // starform + case FormComponentType::LISTBOX: + { + + // <name>=<Token0>&<name>=<Token1>&...&<name>=<TokenN> (Mehrfachselektion) + if (!hasProperty(PROPERTY_SELECT_SEQ, xComponentSet) || + !hasProperty(PROPERTY_STRINGITEMLIST, xComponentSet)) + break; + + // angezeigte Werte + Sequence< ::rtl::OUString > aVisibleList; + xComponentSet->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aVisibleList; + sal_Int32 nStringCnt = aVisibleList.getLength(); + const ::rtl::OUString* pStrings = aVisibleList.getConstArray(); + + // Werte-Liste + Sequence< ::rtl::OUString > aValueList; + xComponentSet->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueList; + sal_Int32 nValCnt = aValueList.getLength(); + const ::rtl::OUString* pVals = aValueList.getConstArray(); + + // Selektion + Sequence<sal_Int16> aSelectList; + xComponentSet->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectList; + sal_Int32 nSelCount = aSelectList.getLength(); + const sal_Int16* pSels = aSelectList.getConstArray(); + + // Einfach- oder Mehrfach-Selektion + // Bei Einfach-Selektionen beruecksichtigt MT nur den ersten Eintrag + // in der Liste. + if (nSelCount > 1 && !getBOOL(xComponentSet->getPropertyValue(PROPERTY_MULTISELECTION))) + nSelCount = 1; + + // Die Indizes in der Selektions-Liste koennen auch ungueltig sein, + // also muss man die gueltigen erstmal raussuchen um die Laenge + // der neuen Liste zu bestimmen. + sal_Int32 nCurCnt = 0; + sal_Int32 i; + for( i=0; i<nSelCount; ++i ) + { + if( pSels[i] < nStringCnt ) + ++nCurCnt; + } + + ::rtl::OUString aSubValue; + for(i=0; i<nCurCnt; ++i ) + { + sal_Int16 nSelPos = pSels[i]; + if (nSelPos < nValCnt && pVals[nSelPos].getLength()) + { + aSubValue = pVals[nSelPos]; + } + else + { + aSubValue = pStrings[nSelPos]; + } + rList.push_back( HtmlSuccessfulObj(aName, aSubValue) ); + } + } break; + case FormComponentType::GRIDCONTROL: + { + // Die einzelnen Spaltenwerte werden verschickt, + // der Name wird mit dem Prefix des Names des Grids erweitert + Reference<XIndexAccess> xContainer(xComponentSet, UNO_QUERY); + if (!xContainer.is()) + break; + + aName += UniString('.'); + + Reference<XPropertySet> xSet; + sal_Int32 nCount = xContainer->getCount(); + // we know already how many objects should be appended, + // so why not allocate the space for them + rList.reserve( nCount + rList.capacity() ); // not size() + for (sal_Int32 i = 0; i < nCount; ++i) + { + xContainer->getByIndex(i) >>= xSet; + if (xSet.is()) + AppendComponent(rList, xSet, aName, rxSubmitButton, MouseEvt); + } + } + } +} + +//------------------------------------------------------------------------ +void ODatabaseForm::FillSuccessfulList( HtmlSuccessfulObjList& rList, + const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt ) +{ + // Liste loeschen + rList.clear(); + // Ueber Components iterieren + Reference<XPropertySet> xComponentSet; + ::rtl::OUString aPrefix; + + // we know already how many objects should be appended, + // so why not allocate the space for them + rList.reserve( getCount() ); + for( sal_Int32 nIndex=0; nIndex < getCount(); nIndex++ ) + { + getByIndex( nIndex ) >>= xComponentSet; + AppendComponent(rList, xComponentSet, aPrefix, rxSubmitButton, MouseEvt); + } +} + +//------------------------------------------------------------------------ +void ODatabaseForm::Encode( ::rtl::OUString& rString ) const +{ + ::rtl::OUString aResult; + + // Immer ANSI #58641 +// rString.Convert(CHARSET_SYSTEM, CHARSET_ANSI); + + + // Zeilenendezeichen werden als CR dargestellt + UniString sConverter = rString; + sConverter.ConvertLineEnd( LINEEND_CR ); + rString = sConverter; + + + // Jeden einzelnen Character ueberpruefen + sal_Int32 nStrLen = rString.getLength(); + sal_Unicode nCharCode; + for( sal_Int32 nCurPos=0; nCurPos < nStrLen; ++nCurPos ) + { + nCharCode = rString[nCurPos]; + + // Behandlung fuer chars, die kein alphanumerisches Zeichen sind + // und CharacterCodes > 127 + if( (!isalnum(nCharCode) && nCharCode != (sal_Unicode)' ') || nCharCode > 127 ) + { + switch( nCharCode ) + { + case 13: // CR + aResult += ::rtl::OUString::createFromAscii("%0D%0A"); // Hex-Darstellung CR LF + break; + + + // Netscape Sonderbehandlung + case 42: // '*' + case 45: // '-' + case 46: // '.' + case 64: // '@' + case 95: // '_' + aResult += UniString(nCharCode); + break; + + default: + { + // In Hex umrechnen + short nHi = ((sal_Int16)nCharCode) / 16; + short nLo = ((sal_Int16)nCharCode) - (nHi*16); + if( nHi > 9 ) nHi += (int)'A'-10; else nHi += (int)'0'; + if( nLo > 9 ) nLo += (int)'A'-10; else nLo += (int)'0'; + aResult += UniString('%'); + aResult += UniString((sal_Unicode)nHi); + aResult += UniString((sal_Unicode)nLo); + } + } + } + else + aResult += UniString(nCharCode); + } + + + // Spaces durch '+' ersetzen + aResult = aResult.replace(' ', '+'); + + rString = aResult; +} + +//------------------------------------------------------------------------ +void ODatabaseForm::InsertTextPart( INetMIMEMessage& rParent, const ::rtl::OUString& rName, + const ::rtl::OUString& rData ) +{ + + // Part als Message-Child erzeugen + INetMIMEMessage* pChild = new INetMIMEMessage(); + + + // Header + ::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii("form-data; name=\""); + aContentDisp += rName; + aContentDisp += UniString('\"'); + pChild->SetContentDisposition( aContentDisp ); + pChild->SetContentType( UniString::CreateFromAscii("text/plain") ); + + rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding(); + const sal_Char* pBestMatchingEncoding = rtl_getBestMimeCharsetFromTextEncoding( eSystemEncoding ); + UniString aBestMatchingEncoding = UniString::CreateFromAscii( pBestMatchingEncoding ); + pChild->SetContentTransferEncoding(aBestMatchingEncoding); + + // Body + SvMemoryStream* pStream = new SvMemoryStream; + pStream->WriteLine( ByteString( UniString(rData), rtl_getTextEncodingFromMimeCharset(pBestMatchingEncoding) ) ); + pStream->Flush(); + pStream->Seek( 0 ); + pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) ); + rParent.AttachChild( *pChild ); +} + +//------------------------------------------------------------------------ +sal_Bool ODatabaseForm::InsertFilePart( INetMIMEMessage& rParent, const ::rtl::OUString& rName, + const ::rtl::OUString& rFileName ) +{ + UniString aFileName( rFileName ); + UniString aContentType(UniString::CreateFromAscii(CONTENT_TYPE_STR_TEXT_PLAIN)); + SvStream *pStream = 0; + + if( aFileName.Len() ) + { + // Bisher koennen wir nur File-URLs verarbeiten + INetURLObject aURL; + aURL.SetSmartProtocol(INET_PROT_FILE); + aURL.SetSmartURL(rFileName); + if( INET_PROT_FILE == aURL.GetProtocol() ) + { + aFileName = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS); + DirEntry aDirEntry( aFileName ); + if( aDirEntry.Exists() ) + { + pStream = ::utl::UcbStreamHelper::CreateStream(aFileName, STREAM_READ); + if (!pStream || (pStream->GetError() != ERRCODE_NONE)) + { + delete pStream; + pStream = 0; + } + } + INetContentType eContentType = INetContentTypes::GetContentType4Extension( + aDirEntry.GetExtension() ); + if (eContentType != CONTENT_TYPE_UNKNOWN) + aContentType = INetContentTypes::GetContentType(eContentType); + } + } + + // Wenn irgendetwas nicht geklappt hat, legen wir einen leeren + // MemoryStream an + if( !pStream ) + pStream = new SvMemoryStream; + + + // Part als Message-Child erzeugen + INetMIMEMessage* pChild = new INetMIMEMessage; + + + // Header + ::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii( "form-data; name=\"" ); + aContentDisp += rName; + aContentDisp += UniString('\"'); + aContentDisp += ::rtl::OUString::createFromAscii("; filename=\""); + aContentDisp += aFileName; + aContentDisp += UniString('\"'); + pChild->SetContentDisposition( aContentDisp ); + pChild->SetContentType( aContentType ); + pChild->SetContentTransferEncoding( UniString(::rtl::OUString::createFromAscii("8bit")) ); + + + // Body + pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) ); + rParent.AttachChild( *pChild ); + + return sal_True; +} + +//============================================================================== +// internals +//------------------------------------------------------------------------------ +void ODatabaseForm::onError( const SQLErrorEvent& _rEvent ) +{ + m_aErrorListeners.notifyEach( &XSQLErrorListener::errorOccured, _rEvent ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::onError( const SQLException& _rException, const ::rtl::OUString& _rContextDescription ) +{ + if ( !m_aErrorListeners.getLength() ) + return; + + SQLErrorEvent aEvent( *this, makeAny( prependErrorInfo( _rException, *this, _rContextDescription ) ) ); + onError( aEvent ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::updateParameterInfo() +{ + m_aParameterManager.updateParameterInfo( m_aFilterManager ); +} + +//------------------------------------------------------------------------------ +bool ODatabaseForm::hasValidParent() const +{ + // do we have to fill the parameters again? + if (m_bSubForm) + { + Reference<XResultSet> xResultSet(m_xParent, UNO_QUERY); + if (!xResultSet.is()) + { + DBG_ERROR("ODatabaseForm::hasValidParent() : no parent resultset !"); + return false; + } + try + { + Reference< XPropertySet > xSet( m_xParent, UNO_QUERY ); + Reference< XLoadable > xLoad( m_xParent, UNO_QUERY ); + if ( xLoad->isLoaded() + && ( xResultSet->isBeforeFirst() + || xResultSet->isAfterLast() + || getBOOL( xSet->getPropertyValue( PROPERTY_ISNEW ) ) + ) + ) + // the parent form is loaded and on a "virtual" row -> not valid + return false; + } + catch(Exception&) + { + // parent could be forwardonly? + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ +bool ODatabaseForm::fillParameters( ::osl::ResettableMutexGuard& _rClearForNotifies, const Reference< XInteractionHandler >& _rxCompletionHandler ) +{ + // do we have to fill the parameters again? + if ( !m_aParameterManager.isUpToDate() ) + updateParameterInfo(); + + // is there a valid parent? + if ( m_bSubForm && !hasValidParent() ) + return true; + + // ensure we're connected + if ( !implEnsureConnection() ) + return false; + + if ( m_aParameterManager.isUpToDate() ) + return m_aParameterManager.fillParameterValues( _rxCompletionHandler, _rClearForNotifies ); + + return true; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::saveInsertOnlyState( ) +{ + OSL_ENSURE( !m_aIgnoreResult.hasValue(), "ODatabaseForm::saveInsertOnlyState: overriding old value!" ); + m_aIgnoreResult = m_xAggregateSet->getPropertyValue( PROPERTY_INSERTONLY ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::restoreInsertOnlyState( ) +{ + if ( m_aIgnoreResult.hasValue() ) + { + m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, m_aIgnoreResult ); + m_aIgnoreResult = Any(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler) +{ + if (!m_xAggregateAsRowSet.is()) + return sal_False; + + if (!fillParameters(_rClearForNotifies, _rxCompletionHandler)) + return sal_False; + + restoreInsertOnlyState( ); + + // ensure the aggregated row set has the correct properties + sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY; + + // if we have a parent, who is not positioned on a valid row + // we can't be updatable! + if (m_bSubForm && !hasValidParent()) + { + nConcurrency = ResultSetConcurrency::READ_ONLY; + + // don't use any parameters if we don't have a valid parent + m_aParameterManager.setAllParametersNull(); + + // switch to "insert only" mode + saveInsertOnlyState( ); + m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( sal_True ) ); + } + else if (m_bAllowInsert || m_bAllowUpdate || m_bAllowDelete) + nConcurrency = ResultSetConcurrency::UPDATABLE; + else + nConcurrency = ResultSetConcurrency::READ_ONLY; + + m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_CONCURRENCY, makeAny( (sal_Int32)nConcurrency ) ); + m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( (sal_Int32)ResultSetType::SCROLL_SENSITIVE ) ); + + sal_Bool bSuccess = sal_False; + try + { + m_xAggregateAsRowSet->execute(); + bSuccess = sal_True; + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + } + catch(SQLException& eDb) + { + _rClearForNotifies.clear(); + if (m_sCurrentErrorContext.getLength()) + onError(eDb, m_sCurrentErrorContext); + else + onError(eDb, FRM_RES_STRING(RID_STR_READERROR)); + _rClearForNotifies.reset(); + + restoreInsertOnlyState( ); + } + + if (bSuccess) + { + // adjust the privilege property + // m_nPrivileges; + m_xAggregateSet->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + if (!m_bAllowInsert) + m_nPrivileges &= ~Privilege::INSERT; + if (!m_bAllowUpdate) + m_nPrivileges &= ~Privilege::UPDATE; + if (!m_bAllowDelete) + m_nPrivileges &= ~Privilege::DELETE; + + if (bMoveToFirst) + { + // the row set is positioned _before_ the first row (per definitionem), so move the set ... + try + { + // if we have an insert only rowset we move to the insert row + next(); + if (((m_nPrivileges & Privilege::INSERT) == Privilege::INSERT) + && isAfterLast()) + { + // move on the insert row of set + // resetting must be done later, after the load events have been posted + // see :moveToInsertRow and load , reload + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->moveToInsertRow(); + } + } + catch(SQLException& eDB) + { + _rClearForNotifies.clear(); + if (m_sCurrentErrorContext.getLength()) + onError(eDB, m_sCurrentErrorContext); + else + onError(eDB, FRM_RES_STRING(RID_STR_READERROR)); + _rClearForNotifies.reset(); + bSuccess = sal_False; + } + } + } + return bSuccess; +} + +//------------------------------------------------------------------ +void ODatabaseForm::disposing() +{ + if (m_pAggregatePropertyMultiplexer) + m_pAggregatePropertyMultiplexer->dispose(); + + if (m_bLoaded) + unload(); + + // cancel the submit/reset-thread + { + ::osl::MutexGuard aGuard( m_aMutex ); + if (m_pThread) + { + m_pThread->release(); + m_pThread = NULL; + } + } + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aLoadListeners.disposeAndClear(aEvt); + m_aRowSetApproveListeners.disposeAndClear(aEvt); + m_aParameterManager.disposing( aEvt ); + m_aResetListeners.disposing(); + m_aSubmitListeners.disposeAndClear(aEvt); + m_aErrorListeners.disposeAndClear(aEvt); + + m_aParameterManager.dispose(); // (to free any references it may have to me) + m_aFilterManager.dispose(); // (dito) + + OFormComponents::disposing(); + OPropertySetAggregationHelper::disposing(); + + // stop listening on the aggregate + if (m_xAggregateAsRowSet.is()) + m_xAggregateAsRowSet->removeRowSetListener(this); + + // dispose the active connection + Reference<XComponent> xAggregationComponent; + if (query_aggregation(m_xAggregate, xAggregationComponent)) + xAggregationComponent->dispose(); + + m_aPropertyBagHelper.dispose(); +} + +//------------------------------------------------------------------------------ +Reference< XConnection > ODatabaseForm::getConnection() +{ + Reference< XConnection > xConn; + m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConn; + return xConn; +} + +//------------------------------------------------------------------------------ +::osl::Mutex& ODatabaseForm::getMutex() +{ + return m_aMutex; +} + +//============================================================================== +// property handling +//------------------------------------------------------------------------------ +void ODatabaseForm::describeFixedAndAggregateProperties( + Sequence< Property >& _rProps, + Sequence< Property >& _rAggregateProps ) const +{ + BEGIN_DESCRIBE_AGGREGATION_PROPERTIES(22, m_xAggregateSet) + // we want to "override" the privileges, since we have additional "AllowInsert" etc. properties + RemoveProperty( _rAggregateProps, PROPERTY_PRIVILEGES ); + + // InsertOnly is also to be overridden, since we sometimes change it ourself + RemoveProperty( _rAggregateProps, PROPERTY_INSERTONLY ); + + // we remove and re-declare the DataSourceName property, 'cause we want it to be constrained, and the + // original property of our aggregate isn't + RemoveProperty( _rAggregateProps, PROPERTY_DATASOURCE ); + + // for connection sharing, we need to override the ActiveConnection property, too + RemoveProperty( _rAggregateProps, PROPERTY_ACTIVE_CONNECTION ); + + // the Filter property is also overwritten, since we have some implicit filters + // (e.g. the ones which result from linking master fields to detail fields + // via column names instead of parameters) + RemoveProperty( _rAggregateProps, PROPERTY_FILTER ); + RemoveProperty( _rAggregateProps, PROPERTY_APPLYFILTER ); + + DECL_IFACE_PROP4(ACTIVE_CONNECTION, XConnection, BOUND, TRANSIENT, MAYBEVOID, CONSTRAINED); + DECL_BOOL_PROP2 ( APPLYFILTER, BOUND, MAYBEDEFAULT ); + DECL_PROP1 ( NAME, ::rtl::OUString, BOUND ); + DECL_PROP1 ( MASTERFIELDS, Sequence< ::rtl::OUString >, BOUND ); + DECL_PROP1 ( DETAILFIELDS, Sequence< ::rtl::OUString >, BOUND ); + DECL_PROP2 ( DATASOURCE, ::rtl::OUString, BOUND, CONSTRAINED ); + DECL_PROP3 ( CYCLE, TabulatorCycle, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP2 ( FILTER, ::rtl::OUString, BOUND, MAYBEDEFAULT ); + DECL_BOOL_PROP2 ( INSERTONLY, BOUND, MAYBEDEFAULT ); + DECL_PROP1 ( NAVIGATION, NavigationBarMode, BOUND ); + DECL_BOOL_PROP1 ( ALLOWADDITIONS, BOUND ); + DECL_BOOL_PROP1 ( ALLOWEDITS, BOUND ); + DECL_BOOL_PROP1 ( ALLOWDELETIONS, BOUND ); + DECL_PROP2 ( PRIVILEGES, sal_Int32, TRANSIENT, READONLY ); + DECL_PROP1 ( TARGET_URL, ::rtl::OUString, BOUND ); + DECL_PROP1 ( TARGET_FRAME, ::rtl::OUString, BOUND ); + DECL_PROP1 ( SUBMIT_METHOD, FormSubmitMethod, BOUND ); + DECL_PROP1 ( SUBMIT_ENCODING, FormSubmitEncoding, BOUND ); + DECL_BOOL_PROP3 ( DYNAMIC_CONTROL_BORDER, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP3 ( CONTROL_BORDER_COLOR_FOCUS, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP3 ( CONTROL_BORDER_COLOR_MOUSE, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP3 ( CONTROL_BORDER_COLOR_INVALID, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT ); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +Reference< XMultiPropertySet > ODatabaseForm::getPropertiesInterface() +{ + return Reference< XMultiPropertySet >( *this, UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ODatabaseForm::getInfoHelper() +{ + return m_aPropertyBagHelper.getInfoHelper(); +} + +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > ODatabaseForm::getPropertySetInfo() throw( RuntimeException ) +{ + return createPropertySetInfo( getInfoHelper() ); +} + +//-------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) +{ + m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue ); +} + +//-------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) +{ + m_aPropertyBagHelper.removeProperty( _rName ); +} + +//-------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL ODatabaseForm::getPropertyValues() throw (RuntimeException) +{ + return m_aPropertyBagHelper.getPropertyValues(); +} + +//-------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + m_aPropertyBagHelper.setPropertyValues( _rProps ); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL ODatabaseForm::getWarnings( ) throw (SQLException, RuntimeException) +{ + return m_aWarnings.getWarnings(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::clearWarnings( ) throw (SQLException, RuntimeException) +{ + m_aWarnings.clearWarnings(); +} + +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL ODatabaseForm::createClone( ) throw (RuntimeException) +{ + ODatabaseForm* pClone = new ODatabaseForm( *this ); + osl_incrementInterlockedCount( &pClone->m_refCount ); + pClone->clonedFrom( *this ); + osl_decrementInterlockedCount( &pClone->m_refCount ); + return pClone; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::fire( sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues, sal_Int32 nCount, sal_Bool bVetoable ) +{ + // same as in getFastPropertyValue(INT32) : if we're resetting currently don't fire any changes of the + // IsModified property from FALSE to TRUE, as this is only temporary 'til the reset is done + if (m_nResetsPending > 0) + { + // look for the PROPERTY_ID_ISMODIFIED + sal_Int32 nPos = 0; + for (nPos=0; nPos<nCount; ++nPos) + if (pnHandles[nPos] == PROPERTY_ID_ISMODIFIED) + break; + + if ((nPos < nCount) && (pNewValues[nPos].getValueType().getTypeClass() == TypeClass_BOOLEAN) && getBOOL(pNewValues[nPos])) + { // yeah, we found it, and it changed to TRUE + if (nPos == 0) + { // just cut the first element + ++pnHandles; + ++pNewValues; + ++pOldValues; + --nCount; + } + else if (nPos == nCount - 1) + // just cut the last element + --nCount; + else + { // split into two base class calls + OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nPos, bVetoable); + ++nPos; + OPropertySetAggregationHelper::fire(pnHandles + nPos, pNewValues + nPos, pOldValues + nPos, nCount - nPos, bVetoable); + return; + } + } + } + + OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nCount, bVetoable); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL ODatabaseForm::getFastPropertyValue( sal_Int32 nHandle ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + if ((nHandle == PROPERTY_ID_ISMODIFIED) && (m_nResetsPending > 0)) + return ::cppu::bool2any((sal_False)); + // don't allow the aggregate which is currently being reset to return a (temporary) "yes" + else + return OPropertySetAggregationHelper::getFastPropertyValue(nHandle); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + rValue <<= m_bInsertOnly; + break; + + case PROPERTY_ID_FILTER: + rValue <<= m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ); + break; + + case PROPERTY_ID_APPLYFILTER: + rValue <<= m_aFilterManager.isApplyPublicFilter(); + break; + + case PROPERTY_ID_DATASOURCE: + rValue = m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ); + break; + + case PROPERTY_ID_TARGET_URL: + rValue <<= m_aTargetURL; + break; + case PROPERTY_ID_TARGET_FRAME: + rValue <<= m_aTargetFrame; + break; + case PROPERTY_ID_SUBMIT_METHOD: + rValue <<= m_eSubmitMethod; + break; + case PROPERTY_ID_SUBMIT_ENCODING: + rValue <<= m_eSubmitEncoding; + break; + case PROPERTY_ID_NAME: + rValue <<= m_sName; + break; + case PROPERTY_ID_MASTERFIELDS: + rValue <<= m_aMasterFields; + break; + case PROPERTY_ID_DETAILFIELDS: + rValue <<= m_aDetailFields; + break; + case PROPERTY_ID_CYCLE: + rValue = m_aCycle; + break; + case PROPERTY_ID_NAVIGATION: + rValue <<= m_eNavigation; + break; + case PROPERTY_ID_ALLOWADDITIONS: + rValue <<= (sal_Bool)m_bAllowInsert; + break; + case PROPERTY_ID_ALLOWEDITS: + rValue <<= (sal_Bool)m_bAllowUpdate; + break; + case PROPERTY_ID_ALLOWDELETIONS: + rValue <<= (sal_Bool)m_bAllowDelete; + break; + case PROPERTY_ID_PRIVILEGES: + rValue <<= (sal_Int32)m_nPrivileges; + break; + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + rValue = m_aDynamicControlBorder; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + rValue = m_aControlBorderColorFocus; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + rValue = m_aControlBorderColorMouse; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + rValue = m_aControlBorderColorInvalid; + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) ) + m_aPropertyBagHelper.getDynamicFastPropertyValue( nHandle, rValue ); + else + OPropertySetAggregationHelper::getFastPropertyValue( rValue, nHandle ); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bInsertOnly ); + break; + + case PROPERTY_ID_FILTER: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ) ); + break; + + case PROPERTY_ID_APPLYFILTER: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.isApplyPublicFilter() ); + break; + + case PROPERTY_ID_DATASOURCE: + { + Any aAggregateProperty; + getFastPropertyValue(aAggregateProperty, PROPERTY_ID_DATASOURCE); + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, aAggregateProperty, ::getCppuType(static_cast<const ::rtl::OUString*>(NULL))); + } + break; + case PROPERTY_ID_TARGET_URL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetURL); + break; + case PROPERTY_ID_TARGET_FRAME: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetFrame); + break; + case PROPERTY_ID_SUBMIT_METHOD: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitMethod); + break; + case PROPERTY_ID_SUBMIT_ENCODING: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitEncoding); + break; + case PROPERTY_ID_NAME: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sName); + break; + case PROPERTY_ID_MASTERFIELDS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aMasterFields); + break; + case PROPERTY_ID_DETAILFIELDS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDetailFields); + break; + case PROPERTY_ID_CYCLE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL))); + break; + case PROPERTY_ID_NAVIGATION: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eNavigation); + break; + case PROPERTY_ID_ALLOWADDITIONS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowInsert); + break; + case PROPERTY_ID_ALLOWEDITS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowUpdate); + break; + case PROPERTY_ID_ALLOWDELETIONS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowDelete); + break; + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aDynamicControlBorder, ::getBooleanCppuType() ); + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorFocus, getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorMouse, getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorInvalid, getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle ( nHandle ) ) + bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( nHandle, rValue, rConvertedValue, rOldValue ); + else + bModified = OPropertySetAggregationHelper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw( Exception ) +{ + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + rValue >>= m_bInsertOnly; + if ( m_aIgnoreResult.hasValue() ) + m_aIgnoreResult <<= m_bInsertOnly; + else + m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( m_bInsertOnly ) ); + break; + + case PROPERTY_ID_FILTER: + { + ::rtl::OUString sNewFilter; + rValue >>= sNewFilter; + m_aFilterManager.setFilterComponent( FilterManager::fcPublicFilter, sNewFilter ); + } + break; + + case PROPERTY_ID_APPLYFILTER: + { + sal_Bool bApply = sal_True; + rValue >>= bApply; + m_aFilterManager.setApplyPublicFilter( bApply ); + } + break; + + case PROPERTY_ID_DATASOURCE: + { + Reference< XConnection > xSomeConnection; + if ( ::dbtools::isEmbeddedInDatabase( getParent(), xSomeConnection ) ) + throw PropertyVetoException(); + + try + { + m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, rValue); + } + catch(Exception&) { } + } + break; + case PROPERTY_ID_TARGET_URL: + rValue >>= m_aTargetURL; + break; + case PROPERTY_ID_TARGET_FRAME: + rValue >>= m_aTargetFrame; + break; + case PROPERTY_ID_SUBMIT_METHOD: + rValue >>= m_eSubmitMethod; + break; + case PROPERTY_ID_SUBMIT_ENCODING: + rValue >>= m_eSubmitEncoding; + break; + case PROPERTY_ID_NAME: + rValue >>= m_sName; + break; + case PROPERTY_ID_MASTERFIELDS: + rValue >>= m_aMasterFields; + invlidateParameters(); + break; + case PROPERTY_ID_DETAILFIELDS: + rValue >>= m_aDetailFields; + invlidateParameters(); + break; + case PROPERTY_ID_CYCLE: + m_aCycle = rValue; + break; + case PROPERTY_ID_NAVIGATION: + rValue >>= m_eNavigation; + break; + case PROPERTY_ID_ALLOWADDITIONS: + m_bAllowInsert = getBOOL(rValue); + break; + case PROPERTY_ID_ALLOWEDITS: + m_bAllowUpdate = getBOOL(rValue); + break; + case PROPERTY_ID_ALLOWDELETIONS: + m_bAllowDelete = getBOOL(rValue); + break; + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + m_aDynamicControlBorder = rValue; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + m_aControlBorderColorFocus = rValue; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + m_aControlBorderColorMouse = rValue; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + m_aControlBorderColorInvalid = rValue; + break; + + case PROPERTY_ID_ACTIVE_CONNECTION: + { + Reference< XConnection > xOuterConnection; + if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) ) + { + if ( xOuterConnection != Reference< XConnection >( rValue, UNO_QUERY ) ) + // somebody's trying to set a connection which is not equal the connection + // implied by the database we're embedded in + throw PropertyVetoException(); + } + OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + break; + } + + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) ) + m_aPropertyBagHelper.setDynamicFastPropertyValue( nHandle, rValue ); + else + OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + break; + } +} + +//------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::forwardingPropertyValue( sal_Int32 _nHandle ) +{ + OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardingPropertyValue: unexpected property!" ); + if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) + { + if ( m_bSharingConnection ) + stopSharingConnection( ); + m_bForwardingConnection = sal_True; + } +} + +//------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::forwardedPropertyValue( sal_Int32 _nHandle, bool /*_bSuccess*/ ) +{ + OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardedPropertyValue: unexpected property!" ); + if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) + { + m_bForwardingConnection = sal_False; + } +} + +//============================================================================== +// com::sun::star::beans::XPropertyState +//------------------------------------------------------------------ +PropertyState ODatabaseForm::getPropertyStateByHandle(sal_Int32 nHandle) +{ + PropertyState eState; + switch (nHandle) + { + case PROPERTY_ID_NAVIGATION: + return (NavigationBarMode_CURRENT == m_eNavigation) ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; + + case PROPERTY_ID_CYCLE: + eState = m_aCycle.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_INSERTONLY: + eState = m_bInsertOnly ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_FILTER: + if ( !m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ).getLength() ) + eState = PropertyState_DEFAULT_VALUE; + else + eState = PropertyState_DIRECT_VALUE; + break; + + case PROPERTY_ID_APPLYFILTER: + eState = m_aFilterManager.isApplyPublicFilter() ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; + break; + + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + eState = m_aDynamicControlBorder.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + eState = m_aControlBorderColorFocus.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + eState = m_aControlBorderColorMouse.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + eState = m_aControlBorderColorInvalid.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + default: + eState = OPropertySetAggregationHelper::getPropertyStateByHandle(nHandle); + } + return eState; +} + +//------------------------------------------------------------------ +void ODatabaseForm::setPropertyToDefaultByHandle(sal_Int32 nHandle) +{ + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + case PROPERTY_ID_FILTER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_NAVIGATION: + case PROPERTY_ID_CYCLE: + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + setFastPropertyValue( nHandle, getPropertyDefaultByHandle( nHandle ) ); + break; + + default: + OPropertySetAggregationHelper::setPropertyToDefaultByHandle(nHandle); + } +} + +//------------------------------------------------------------------ +Any ODatabaseForm::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + Any aReturn; + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + aReturn <<= sal_False; + break; + + case PROPERTY_ID_FILTER: + aReturn <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_APPLYFILTER: + aReturn <<= sal_True; + break; + + case PROPERTY_ID_NAVIGATION: + aReturn = makeAny(NavigationBarMode_CURRENT); + break; + + case PROPERTY_ID_CYCLE: + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + break; + + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) ) + m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( nHandle, aReturn ); + else + aReturn = OPropertySetAggregationHelper::getPropertyDefaultByHandle( nHandle ); + break; + } + return aReturn; +} + +//============================================================================== +// com::sun::star::form::XReset +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reset() throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + if (isLoaded()) + { + ::osl::MutexGuard aResetGuard(m_aResetSafety); + ++m_nResetsPending; + reset_impl(true); + return; + } + + if ( !m_aResetListeners.empty() ) + { + ::osl::MutexGuard aResetGuard(m_aResetSafety); + ++m_nResetsPending; + // create an own thread if we have (approve-)reset-listeners (so the listeners can't do that much damage + // to this thread which is probably the main one) + if (!m_pThread) + { + m_pThread = new OFormSubmitResetThread(this); + m_pThread->acquire(); + m_pThread->create(); + } + EventObject aEvt; + m_pThread->addEvent(&aEvt, sal_False); + } + else + { + // direct call without any approving by the listeners + aGuard.clear(); + + ::osl::MutexGuard aResetGuard(m_aResetSafety); + ++m_nResetsPending; + reset_impl(false); + } +} + +//----------------------------------------------------------------------------- +void ODatabaseForm::reset_impl(bool _bAproveByListeners) +{ + if ( _bAproveByListeners ) + if ( !m_aResetListeners.approveReset() ) + return; + + ::osl::ResettableMutexGuard aResetGuard(m_aResetSafety); + // do we have a database connected form and stay on the insert row + sal_Bool bInsertRow = sal_False; + if (m_xAggregateSet.is()) + bInsertRow = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)); + if (bInsertRow) + { + try + { + // Iterate through all columns and set the default value + Reference< XColumnsSupplier > xColsSuppl( m_xAggregateSet, UNO_QUERY ); + Reference< XIndexAccess > xIndexCols( xColsSuppl->getColumns(), UNO_QUERY ); + for (sal_Int32 i = 0; i < xIndexCols->getCount(); ++i) + { + Reference< XPropertySet > xColProps; + xIndexCols->getByIndex(i) >>= xColProps; + + Reference< XColumnUpdate > xColUpdate( xColProps, UNO_QUERY ); + if ( !xColUpdate.is() ) + continue; + + Reference< XPropertySetInfo > xPSI; + if ( xColProps.is() ) + xPSI = xColProps->getPropertySetInfo( ); + + static const ::rtl::OUString PROPERTY_CONTROLDEFAULT( RTL_CONSTASCII_USTRINGPARAM( "ControlDefault" ) ); + if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_CONTROLDEFAULT ) ) + { + Any aDefault = xColProps->getPropertyValue( PROPERTY_CONTROLDEFAULT ); + + sal_Bool bReadOnly = sal_False; + if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) ) + xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= bReadOnly; + + if ( !bReadOnly ) + { + try + { + if ( aDefault.hasValue() ) + xColUpdate->updateObject( aDefault ); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + } + } + catch(Exception&) + { + } + + if (m_bSubForm) + { + Reference< XColumnsSupplier > xParentColSupp( m_xParent, UNO_QUERY ); + Reference< XNameAccess > xParentCols; + if ( xParentColSupp.is() ) + xParentCols = xParentColSupp->getColumns(); + + if ( xParentCols.is() && xParentCols->hasElements() && m_aMasterFields.getLength() ) + { + try + { + // analyze our parameters + if ( !m_aParameterManager.isUpToDate() ) + updateParameterInfo(); + + m_aParameterManager.resetParameterValues( ); + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "ODatabaseForm::reset_impl: could not initialize the master-detail-driven parameters!"); + } + } + } + } + + aResetGuard.clear(); + // iterate through all components. don't use an XIndexAccess as this will cause massive + // problems with the count. + Reference<XEnumeration> xIter = createEnumeration(); + while (xIter->hasMoreElements()) + { + Reference<XReset> xReset; + xIter->nextElement() >>= xReset; + if (xReset.is()) + { + // TODO : all reset-methods have to be thread-safe + xReset->reset(); + } + } + + aResetGuard.reset(); + // ensure that the row isn't modified + // (do this _before_ the listeners are notified ! their reaction (maybe asynchronous) may depend + // on the modified state of the row + // 21.02.00 - 73265 - FS) + if (bInsertRow) + m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any(sal_Bool(sal_False))); + + aResetGuard.clear(); + { + m_aResetListeners.resetted(); + } + + aResetGuard.reset(); + // and again : ensure the row isn't modified + // we already did this after we (and maybe our dependents) resetted the values, but the listeners may have changed the row, too + if (bInsertRow) + m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any((sal_False))); + + --m_nResetsPending; +} + +//----------------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::addResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException ) +{ + m_aResetListeners.addTypedListener( _rListener ); +} + +//----------------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::removeResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException ) +{ + m_aResetListeners.removeTypedListener( _rListener ); +} + +//============================================================================== +// com::sun::star::form::XSubmit +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::submit( const Reference<XControl>& Control, + const ::com::sun::star::awt::MouseEvent& MouseEvt ) throw( RuntimeException ) +{ + { + ::osl::MutexGuard aGuard(m_aMutex); + // Sind Controls und eine Submit-URL vorhanden? + if( !getCount() || !m_aTargetURL.getLength() ) + return; + } + + ::osl::ClearableMutexGuard aGuard(m_aMutex); + if (m_aSubmitListeners.getLength()) + { + // create an own thread if we have (approve-)submit-listeners (so the listeners can't do that much damage + // to this thread which is probably the main one) + if (!m_pThread) + { + m_pThread = new OFormSubmitResetThread(this); + m_pThread->acquire(); + m_pThread->create(); + } + m_pThread->addEvent(&MouseEvt, Control, sal_True); + } + else + { + // direct call without any approving by the listeners + aGuard.clear(); + submit_impl( Control, MouseEvt, true ); + } +} +// ----------------------------------------------------------------------------- +void lcl_dispatch(const Reference< XFrame >& xFrame,const Reference<XURLTransformer>& xTransformer,const ::rtl::OUString& aURLStr,const ::rtl::OUString& aReferer,const ::rtl::OUString& aTargetName + ,const ::rtl::OUString& aData,rtl_TextEncoding _eEncoding) +{ + URL aURL; + aURL.Complete = aURLStr; + xTransformer->parseStrict(aURL); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS); + + if (xDisp.is()) + { + Sequence<PropertyValue> aArgs(2); + aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs.getArray()[0].Value <<= aReferer; + + // build a sequence from the to-be-submitted string + ByteString a8BitData(aData.getStr(), (sal_uInt16)aData.getLength(), _eEncoding); + // always ANSI #58641 + Sequence< sal_Int8 > aPostData((sal_Int8*)a8BitData.GetBuffer(), a8BitData.Len()); + Reference< XInputStream > xPostData = new SequenceInputStream(aPostData); + + aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("PostData"); + aArgs.getArray()[1].Value <<= xPostData; + + xDisp->dispatch(aURL, aArgs); + } // if (xDisp.is()) +} +//------------------------------------------------------------------------------ +void ODatabaseForm::submit_impl(const Reference<XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners) +{ + + if (_bAproveByListeners) + { + ::cppu::OInterfaceIteratorHelper aIter(m_aSubmitListeners); + EventObject aEvt(static_cast<XWeak*>(this)); + sal_Bool bCanceled = sal_False; + while (aIter.hasMoreElements() && !bCanceled) + { + if (!((XSubmitListener*)aIter.next())->approveSubmit(aEvt)) + bCanceled = sal_True; + } + + if (bCanceled) + return; + } + + FormSubmitEncoding eSubmitEncoding; + FormSubmitMethod eSubmitMethod; + ::rtl::OUString aURLStr; + ::rtl::OUString aReferer; + ::rtl::OUString aTargetName; + Reference< XModel > xModel; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + // starform->Forms + + Reference<XChild> xParent(m_xParent, UNO_QUERY); + + if (xParent.is()) + xModel = getXModel(xParent->getParent()); + + if (xModel.is()) + aReferer = xModel->getURL(); + + // TargetItem + aTargetName = m_aTargetFrame; + + eSubmitEncoding = m_eSubmitEncoding; + eSubmitMethod = m_eSubmitMethod; + aURLStr = m_aTargetURL; + } + + if (!xModel.is()) + return; + Reference< XFrame > xFrame = xModel->getCurrentController()->getFrame(); + if (!xFrame.is()) + return; + + Reference<XURLTransformer> + xTransformer(m_xServiceFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY); + DBG_ASSERT(xTransformer.is(), "ODatabaseForm::submit_impl : could not create an URL transformer !"); + + // URL-Encoding + if( eSubmitEncoding == FormSubmitEncoding_URL ) + { + ::rtl::OUString aData; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + aData = GetDataURLEncoded( Control, MouseEvt ); + } + + URL aURL; + // FormMethod GET + if( eSubmitMethod == FormSubmitMethod_GET ) + { + INetURLObject aUrlObj( aURLStr, INetURLObject::WAS_ENCODED ); + aUrlObj.SetParam( aData, INetURLObject::ENCODE_ALL ); + aURL.Complete = aUrlObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ); + if (xTransformer.is()) + xTransformer->parseStrict(aURL); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS); + + if (xDisp.is()) + { + Sequence<PropertyValue> aArgs(1); + aArgs.getArray()->Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs.getArray()->Value <<= aReferer; + xDisp->dispatch(aURL, aArgs); + } + } + // FormMethod POST + else if( eSubmitMethod == FormSubmitMethod_POST ) + { + lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,RTL_TEXTENCODING_MS_1252); + } + } + else if( eSubmitEncoding == FormSubmitEncoding_MULTIPART ) + { + URL aURL; + aURL.Complete = aURLStr; + xTransformer->parseStrict(aURL); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS); + + if (xDisp.is()) + { + ::rtl::OUString aContentType; + Sequence<sal_Int8> aData; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + aData = GetDataMultiPartEncoded(Control, MouseEvt, aContentType); + } + if (!aData.getLength()) + return; + + Sequence<PropertyValue> aArgs(3); + aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs.getArray()[0].Value <<= aReferer; + aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("ContentType"); + aArgs.getArray()[1].Value <<= aContentType; + + // build a sequence from the to-be-submitted string + Reference< XInputStream > xPostData = new SequenceInputStream(aData); + + aArgs.getArray()[2].Name = ::rtl::OUString::createFromAscii("PostData"); + aArgs.getArray()[2].Value <<= xPostData; + + xDisp->dispatch(aURL, aArgs); + } + } + else if( eSubmitEncoding == FormSubmitEncoding_TEXT ) + { + ::rtl::OUString aData; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + aData = GetDataTextEncoded( Reference<XControl> (), MouseEvt ); + } + + lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,osl_getThreadTextEncoding()); + } + else { + DBG_ERROR("ODatabaseForm::submit_Impl : wrong encoding !"); + } + +} + +// XSubmit +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException ) +{ + m_aSubmitListeners.addInterface(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException ) +{ + m_aSubmitListeners.removeInterface(_rListener); +} + +//============================================================================== +// com::sun::star::sdbc::XSQLErrorBroadcaster +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException ) +{ + m_aErrorListeners.addInterface(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException ) +{ + m_aErrorListeners.removeInterface(_rListener); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::invlidateParameters() +{ + ::osl::MutexGuard aGuard(m_aMutex); + m_aParameterManager.clearAllParameterInformation(); +} + +//============================================================================== +// OChangeListener +//------------------------------------------------------------------------------ +void ODatabaseForm::_propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException ) +{ + if ((0 == evt.PropertyName.compareToAscii(PROPERTY_ACTIVE_CONNECTION)) && !m_bForwardingConnection) + { + // the rowset changed its active connection itself (without interaction from our side), so + // we need to fire this event, too + sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION; + fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False); + } + else // it was one of the statement relevant props + { + // if the statement has changed we have to delete the parameter info + invlidateParameters(); + } +} + +//============================================================================== +// smartXChild +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setParent(const InterfaceRef& Parent) throw ( ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + Reference<XForm> xParentForm(getParent(), UNO_QUERY); + if (xParentForm.is()) + { + try + { + Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW ); + xParentApprBroadcast->removeRowSetApproveListener( this ); + + Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW ); + xParentLoadable->removeLoadListener( this ); + + Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW ); + xParentProperties->removePropertyChangeListener( PROPERTY_ISNEW, this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + OFormComponents::setParent(Parent); + + xParentForm.set(getParent(), UNO_QUERY); + if ( xParentForm.is() ) + { + try + { + Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW ); + xParentApprBroadcast->addRowSetApproveListener( this ); + + Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW ); + xParentLoadable->addLoadListener( this ); + + Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW ); + xParentProperties->addPropertyChangeListener( PROPERTY_ISNEW, this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + Reference< XConnection > xOuterConnection; + sal_Bool bIsEmbedded = ::dbtools::isEmbeddedInDatabase( Parent, xOuterConnection ); + + // clear the guard before setting property values, because of the notifications + // which are triggered there + aGuard.clear(); + if ( bIsEmbedded ) + m_xAggregateSet->setPropertyValue( PROPERTY_DATASOURCE, makeAny( ::rtl::OUString() ) ); +} + +//============================================================================== +// smartXTabControllerModel +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::getGroupControl() throw(com::sun::star::uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + // Sollen Controls in einer TabOrder gruppe zusammengefasst werden? + if (m_aCycle.hasValue()) + { + sal_Int32 nCycle = 0; + ::cppu::enum2int(nCycle, m_aCycle); + return nCycle != TabulatorCycle_PAGE; + } + + if (isLoaded() && getConnection().is()) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setControlModels(const Sequence<Reference<XControlModel> >& rControls) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + // TabIndex in der Reihenfolge der Sequence setzen + const Reference<XControlModel>* pControls = rControls.getConstArray(); + sal_Int16 nTabIndex = 1; + sal_Int32 nCount = getCount(); + sal_Int32 nNewCount = rControls.getLength(); + + // HiddenControls und Formulare werden nicht aufgefuehrt + if (nNewCount <= nCount) + { + Any aElement; + for (sal_Int32 i=0; i < nNewCount; ++i, ++pControls) + { + Reference<XFormComponent> xComp(*pControls, UNO_QUERY); + if (xComp.is()) + { + // suchen der Componente in der Liste + for (sal_Int32 j = 0; j < nCount; ++j) + { + Reference<XFormComponent> xElement; + ::cppu::extractInterface(xElement, getByIndex(j)); + if (xComp == xElement) + { + Reference<XPropertySet> xSet(xComp, UNO_QUERY); + if (xSet.is() && hasProperty(PROPERTY_TABINDEX, xSet)) + xSet->setPropertyValue( PROPERTY_TABINDEX, makeAny(nTabIndex++) ); + break; + } + } + } + } + } +} + +//------------------------------------------------------------------------------ +Sequence<Reference<XControlModel> > SAL_CALL ODatabaseForm::getControlModels() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_pGroupManager->getControlModels(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setGroup( const Sequence<Reference<XControlModel> >& _rGroup, const ::rtl::OUString& Name ) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + + // Die Controls werden gruppiert, indem ihr Name dem Namen des ersten + // Controls der Sequenz angepasst wird + const Reference<XControlModel>* pControls = _rGroup.getConstArray(); + Reference< XPropertySet > xSet; + ::rtl::OUString sGroupName( Name ); + + for( sal_Int32 i=0; i<_rGroup.getLength(); ++i, ++pControls ) + { + xSet = xSet.query( *pControls ); + if ( !xSet.is() ) + { + // can't throw an exception other than a RuntimeException (which would not be appropriate), + // so we ignore (and only assert) this + OSL_ENSURE( sal_False, "ODatabaseForm::setGroup: invalid arguments!" ); + continue; + } + + if (!sGroupName.getLength()) + xSet->getPropertyValue(PROPERTY_NAME) >>= sGroupName; + else + xSet->setPropertyValue(PROPERTY_NAME, makeAny(sGroupName)); + } +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL ODatabaseForm::getGroupCount() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_pGroupManager->getGroupCount(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::getGroup( sal_Int32 nGroup, Sequence<Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName ) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + _rGroup.realloc(0); + _rName = ::rtl::OUString(); + + if ((nGroup < 0) || (nGroup >= m_pGroupManager->getGroupCount())) + return; + m_pGroupManager->getGroup( nGroup, _rGroup, _rName ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::getGroupByName(const ::rtl::OUString& Name, Sequence< Reference<XControlModel> >& _rGroup) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + _rGroup.realloc(0); + m_pGroupManager->getGroupByName( Name, _rGroup ); +} + +//============================================================================== +// com::sun::star::lang::XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::disposing(const EventObject& Source) throw( RuntimeException ) +{ + // does the call come from the connection which we are sharing with our parent? + if ( isSharingConnection() ) + { + Reference< XConnection > xConnSource( Source.Source, UNO_QUERY ); + if ( xConnSource.is() ) + { +#if OSL_DEBUG_LEVEL > 0 + Reference< XConnection > xActiveConn; + m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xActiveConn; + OSL_ENSURE( xActiveConn.get() == xConnSource.get(), "ODatabaseForm::disposing: where did this come from?" ); + // there should be exactly one XConnection object we're listening at - our aggregate connection +#endif + disposingSharedConnection( xConnSource ); + } + } + + OInterfaceContainer::disposing(Source); + + // does the disposing come from the aggregate ? + if (m_xAggregate.is()) + { // no -> forward it + com::sun::star::uno::Reference<com::sun::star::lang::XEventListener> xListener; + if (query_aggregation(m_xAggregate, xListener)) + xListener->disposing(Source); + } +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::impl_createLoadTimer() +{ + OSL_PRECOND( m_pLoadTimer == NULL, "ODatabaseForm::impl_createLoadTimer: timer already exists!" ); + m_pLoadTimer = new Timer(); + m_pLoadTimer->SetTimeout(100); + m_pLoadTimer->SetTimeoutHdl(LINK(this,ODatabaseForm,OnTimeout)); +} + +//============================================================================== +// com::sun::star::form::XLoadListener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::loaded(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW ); + xParentRowSet->addRowSetListener( this ); + + impl_createLoadTimer(); + } + + load_impl( sal_True ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::unloading(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + { + // now stop the rowset listening if we are a subform + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pLoadTimer && m_pLoadTimer->IsActive() ) + m_pLoadTimer->Stop(); + DELETEZ( m_pLoadTimer ); + + Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW ); + xParentRowSet->removeRowSetListener( this ); + } + + unload(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::unloaded(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + // nothing to do +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reloading(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + // now stop the rowset listening if we are a subform + ::osl::MutexGuard aGuard(m_aMutex); + Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY); + if (xParentRowSet.is()) + xParentRowSet->removeRowSetListener(this); + + if (m_pLoadTimer && m_pLoadTimer->IsActive()) + m_pLoadTimer->Stop(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + reload_impl(sal_True); + { + ::osl::MutexGuard aGuard(m_aMutex); + Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY); + if (xParentRowSet.is()) + xParentRowSet->addRowSetListener(this); + } +} + +//------------------------------------------------------------------------------ +IMPL_LINK( ODatabaseForm, OnTimeout, void*, EMPTYARG ) +{ + reload_impl(sal_True); + return 1; +} + +//============================================================================== +// com::sun::star::form::XLoadable +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::load() throw( RuntimeException ) +{ + load_impl(sal_False); +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::canShareConnection( const Reference< XPropertySet >& _rxParentProps ) +{ + // our own data source + ::rtl::OUString sOwnDatasource; + m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= sOwnDatasource; + + // our parents data source + ::rtl::OUString sParentDataSource; + OSL_ENSURE( _rxParentProps.is() && _rxParentProps->getPropertySetInfo().is() && _rxParentProps->getPropertySetInfo()->hasPropertyByName( PROPERTY_DATASOURCE ), + "ODatabaseForm::doShareConnection: invalid parent form!" ); + if ( _rxParentProps.is() ) + _rxParentProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sParentDataSource; + + sal_Bool bCanShareConnection = sal_False; + + // both rowsets share are connected to the same data source + if ( sParentDataSource == sOwnDatasource ) + { + if ( 0 != sParentDataSource.getLength() ) + // and it's really a data source name (not empty) + bCanShareConnection = sal_True; + else + { // the data source name is empty + // -> ook for the URL + ::rtl::OUString sParentURL; + ::rtl::OUString sMyURL; + _rxParentProps->getPropertyValue( PROPERTY_URL ) >>= sParentURL; + m_xAggregateSet->getPropertyValue( PROPERTY_URL ) >>= sMyURL; + + bCanShareConnection = (sParentURL == sMyURL); + } + } + + if ( bCanShareConnection ) + { + // check for the user/password + + // take the user property on the rowset (if any) into account + ::rtl::OUString sParentUser, sParentPwd; + _rxParentProps->getPropertyValue( PROPERTY_USER ) >>= sParentUser; + _rxParentProps->getPropertyValue( PROPERTY_PASSWORD ) >>= sParentPwd; + + ::rtl::OUString sMyUser, sMyPwd; + m_xAggregateSet->getPropertyValue( PROPERTY_USER ) >>= sMyUser; + m_xAggregateSet->getPropertyValue( PROPERTY_PASSWORD ) >>= sMyPwd; + + bCanShareConnection = + ( sParentUser == sMyUser ) + && ( sParentPwd == sMyPwd ); + } + + return bCanShareConnection; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::doShareConnection( const Reference< XPropertySet >& _rxParentProps ) +{ + // get the conneciton of the parent + Reference< XConnection > xParentConn; + _rxParentProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xParentConn; + OSL_ENSURE( xParentConn.is(), "ODatabaseForm::doShareConnection: we're a valid sub-form, but the parent has no connection?!" ); + + if ( xParentConn.is() ) + { + // add as dispose listener to the connection + Reference< XComponent > xParentConnComp( xParentConn, UNO_QUERY ); + OSL_ENSURE( xParentConnComp.is(), "ODatabaseForm::doShareConnection: invalid connection!" ); + xParentConnComp->addEventListener( static_cast< XLoadListener* >( this ) ); + + // forward the connection to our own aggreagte + m_bForwardingConnection = sal_True; + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xParentConn ) ); + m_bForwardingConnection = sal_False; + + m_bSharingConnection = sal_True; + } + else + m_bSharingConnection = sal_False; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::disposingSharedConnection( const Reference< XConnection >& /*_rxConn*/ ) +{ + stopSharingConnection(); + + // TODO: we could think about whether or not to re-connect. + unload( ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::stopSharingConnection( ) +{ + OSL_ENSURE( m_bSharingConnection, "ODatabaseForm::stopSharingConnection: invalid call!" ); + + if ( m_bSharingConnection ) + { + // get the connection + Reference< XConnection > xSharedConn; + m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xSharedConn; + OSL_ENSURE( xSharedConn.is(), "ODatabaseForm::stopSharingConnection: there's no conn!" ); + + // remove ourself as event listener + Reference< XComponent > xSharedConnComp( xSharedConn, UNO_QUERY ); + if ( xSharedConnComp.is() ) + xSharedConnComp->removeEventListener( static_cast< XLoadListener* >( this ) ); + + // no need to dispose the conn: we're not the owner, this is our parent + // (in addition, this method may be called if the connection is beeing disposed while we use it) + + // reset the property + xSharedConn.clear(); + m_bForwardingConnection = sal_True; + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xSharedConn ) ); + m_bForwardingConnection = sal_False; + + // reset the flag + m_bSharingConnection = sal_False; + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::implEnsureConnection() +{ + try + { + if ( getConnection( ).is() ) + // if our aggregate already has a connection, nothing needs to be done about it + return sal_True; + + // see whether we're an embedded form + Reference< XConnection > xOuterConnection; + if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) ) + { + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xOuterConnection ) ); + return xOuterConnection.is(); + } + + m_bSharingConnection = sal_False; + + // if we're a sub form, we try to re-use the connection of our parent + if (m_bSubForm) + { + OSL_ENSURE( Reference< XForm >( getParent(), UNO_QUERY ).is(), + "ODatabaseForm::implEnsureConnection: m_bSubForm is TRUE, but the parent is no form?" ); + + Reference< XPropertySet > xParentProps( getParent(), UNO_QUERY ); + + // can we re-use (aka share) the connection of the parent? + if ( canShareConnection( xParentProps ) ) + { + // yep -> do it + doShareConnection( xParentProps ); + // success? + if ( m_bSharingConnection ) + // yes -> outta here + return sal_True; + } + } + + if (m_xAggregateSet.is()) + { + Reference< XConnection > xConnection = connectRowset( + Reference<XRowSet> (m_xAggregate, UNO_QUERY), + m_xServiceFactory, + sal_True // set a calculated connection as ActiveConnection + ); + return xConnection.is(); + } + } + catch(SQLException& eDB) + { + onError(eDB, FRM_RES_STRING(RID_STR_CONNECTERROR)); + } + catch( Exception ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sal_False; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + // are we already loaded? + if (isLoaded()) + return; + + m_bSubForm = bCausedByParentForm; + + // if we don't have a connection, we are not intended to be a database form or the aggregate was not able + // to establish a connection + sal_Bool bConnected = implEnsureConnection(); + + // we don't have to execute if we do not have a command to execute + sal_Bool bExecute = bConnected && m_xAggregateSet.is() && getString(m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND)).getLength(); + + // a database form always uses caching + // we use starting fetchsize with at least 10 rows + if (bConnected) + m_xAggregateSet->setPropertyValue(PROPERTY_FETCHSIZE, makeAny((sal_Int32)10)); + + // if we're loaded as sub form we got a "rowSetChanged" from the parent rowset _before_ we got the "loaded" + // so we don't need to execute the statement again, this was already done + // (and there were no relevant changes between these two listener calls, the "load" of a form is quite an + // atomar operation.) + + sal_Bool bSuccess = sal_False; + if (bExecute) + { + m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_LOADING_FORM); + bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler); + } + + if (bSuccess) + { + m_bLoaded = sal_True; + aGuard.clear(); + EventObject aEvt(static_cast<XWeak*>(this)); + m_aLoadListeners.notifyEach( &XLoadListener::loaded, aEvt ); + + // if we are on the insert row, we have to reset all controls + // to set the default values + if (bExecute && getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW))) + reset(); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::unload() throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + if (!isLoaded()) + return; + + DELETEZ(m_pLoadTimer); + + aGuard.clear(); + EventObject aEvt(static_cast<XWeak*>(this)); + m_aLoadListeners.notifyEach( &XLoadListener::unloading, aEvt ); + + if (m_xAggregateAsRowSet.is()) + { + // we may have reset the InsertOnly property on the aggregate - restore it + restoreInsertOnlyState( ); + + // clear the parameters if there are any + invlidateParameters(); + + try + { + // close the aggregate + Reference<XCloseable> xCloseable; + query_aggregation( m_xAggregate, xCloseable); + aGuard.clear(); + if (xCloseable.is()) + xCloseable->close(); + } + catch( const SQLException& e ) + { + (void)e; + } + aGuard.reset(); + } + + m_bLoaded = sal_False; + + // if the connection we used while we were loaded is only shared with our parent, we + // reset it + if ( isSharingConnection() ) + stopSharingConnection(); + + aGuard.clear(); + m_aLoadListeners.notifyEach( &XLoadListener::unloaded, aEvt ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reload() throw( RuntimeException ) +{ + reload_impl(sal_True); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::reload_impl(sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + if (!isLoaded()) + return; + + DocumentModifyGuard aModifyGuard( *this ); + // ensures the document is not marked as "modified" just because we change some control's content during + // reloading ... + + EventObject aEvent(static_cast<XWeak*>(this)); + { + // only if there is no approve listener we can post the event at this time + // otherwise see approveRowsetChange + // the aprrovement is done by the aggregate + if (!m_aRowSetApproveListeners.getLength()) + { + ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners); + aGuard.clear(); + + while (aIter.hasMoreElements()) + ((XLoadListener*)aIter.next())->reloading(aEvent); + + aGuard.reset(); + } + } + + sal_Bool bSuccess = sal_True; + try + { + m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_REFRESHING_FORM); + bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler); + } + catch( const SQLException& e ) + { + DBG_ERROR("ODatabaseForm::reload_impl : shouldn't executeRowSet catch this exception?"); + (void)e; + } + + if (bSuccess) + { + ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners); + aGuard.clear(); + while (aIter.hasMoreElements()) + ((XLoadListener*)aIter.next())->reloaded(aEvent); + + // if we are on the insert row, we have to reset all controls + // to set the default values + if (getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW))) + reset(); + } + else + m_bLoaded = sal_False; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isLoaded() throw( RuntimeException ) +{ + return m_bLoaded; +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException ) +{ + m_aLoadListeners.addInterface(aListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException ) +{ + m_aLoadListeners.removeInterface(aListener); +} + +//============================================================================== +// com::sun::star::sdbc::XCloseable +//============================================================================== +void SAL_CALL ODatabaseForm::close() throw( SQLException, RuntimeException ) +{ + // unload will close the aggregate + unload(); +} + +//============================================================================== +// com::sun::star::sdbc::XRowSetListener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::cursorMoved(const EventObject& /*event*/) throw( RuntimeException ) +{ + // reload the subform with the new parameters of the parent + // do this handling delayed to provide of execute too many SQL Statements + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + DBG_ASSERT( m_pLoadTimer, "ODatabaseForm::cursorMoved: how can this happen?!" ); + if ( !m_pLoadTimer ) + impl_createLoadTimer(); + + if ( m_pLoadTimer->IsActive() ) + m_pLoadTimer->Stop(); + + // and start the timer again + m_pLoadTimer->Start(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::rowChanged(const EventObject& /*event*/) throw( RuntimeException ) +{ + // ignore it +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException ) +{ + // not interested in : + // if our parent is an ODatabaseForm, too, then after this rowSetChanged we'll get a "reloaded" + // or a "loaded" event. + // If somebody gave us another parent which is an XRowSet but doesn't handle an execute as + // "load" respectivly "reload" ... can't do anything .... +} + +//------------------------------------------------------------------------------ +bool ODatabaseForm::impl_approveRowChange_throw( const EventObject& _rEvent, const bool _bAllowSQLException, + ::osl::ClearableMutexGuard& _rGuard ) +{ + ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners ); + _rGuard.clear(); + while ( aIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + if ( !xListener->approveRowSetChange( _rEvent ) ) + return false; + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const SQLException& ) + { + if ( _bAllowSQLException ) + throw; + DBG_UNHANDLED_EXCEPTION(); + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return true; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::approveCursorMove(const EventObject& event) throw( RuntimeException ) +{ + // is our aggregate calling? + if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) + { + // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface + // for XRowSetApproveBroadcaster-interface. + // So we have to multiplex this approve request. + ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners ); + while ( aIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + if ( !xListener->approveCursorMove( event ) ) + return sal_False; + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return true; + } + else + { + // this is a call from our parent ... + // a parent's cursor move will result in a re-execute of our own row-set, so we have to + // ask our own RowSetChangesListeners, too + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( !impl_approveRowChange_throw( event, false, aGuard ) ) + return sal_False; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::approveRowChange(const RowChangeEvent& event) throw( RuntimeException ) +{ + // is our aggregate calling? + if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) + { + // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface + // for XRowSetApproveBroadcaster-interface. + // So we have to multiplex this approve request. + ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners ); + while ( aIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + if ( !xListener->approveRowChange( event ) ) + return false; + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return true; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::approveRowSetChange(const EventObject& event) throw( RuntimeException ) +{ + if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) // ignore our aggregate as we handle this approve ourself + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + bool bWasLoaded = isLoaded(); + if ( !impl_approveRowChange_throw( event, false, aGuard ) ) + return sal_False; + + if ( bWasLoaded ) + { + m_aLoadListeners.notifyEach( &XLoadListener::reloading, event ); + } + } + else + { + // this is a call from our parent ... + // a parent's cursor move will result in a re-execute of our own row-set, so we have to + // ask our own RowSetChangesListeners, too + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( !impl_approveRowChange_throw( event, false, aGuard ) ) + return sal_False; + } + return sal_True; +} + +//============================================================================== +// com::sun::star::sdb::XRowSetApproveBroadcaster +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + m_aRowSetApproveListeners.addInterface(_rListener); + + // do we have to multiplex ? + if (m_aRowSetApproveListeners.getLength() == 1) + { + Reference<XRowSetApproveBroadcaster> xBroadcaster; + if (query_aggregation( m_xAggregate, xBroadcaster)) + { + Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this); + xBroadcaster->addRowSetApproveListener(xListener); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + // do we have to remove the multiplex ? + m_aRowSetApproveListeners.removeInterface(_rListener); + if ( m_aRowSetApproveListeners.getLength() == 0 ) + { + Reference<XRowSetApproveBroadcaster> xBroadcaster; + if (query_aggregation( m_xAggregate, xBroadcaster)) + { + Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this); + xBroadcaster->removeRowSetApproveListener(xListener); + } + } +} + +//============================================================================== +// com::sun:star::form::XDatabaseParameterBroadcaster +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + m_aParameterManager.addParameterListener( _rListener ); +} +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + m_aParameterManager.removeParameterListener( _rListener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + ODatabaseForm::addDatabaseParameterListener( _rListener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + ODatabaseForm::removeDatabaseParameterListener( _rListener ); +} + +//============================================================================== +// com::sun::star::sdb::XCompletedExecution +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard(m_aMutex); + // the difference between execute and load is, that we position on the first row in case of load + // after execute we remain before the first row + if (!isLoaded()) + { + aGuard.clear(); + load_impl(sal_False, sal_False, _rxHandler); + } + else + { + EventObject event(static_cast< XWeak* >(this)); + if ( !impl_approveRowChange_throw( event, true, aGuard ) ) + return; + + // we're loaded and somebody want's to execute ourself -> this means a reload + reload_impl(sal_False, _rxHandler); + } +} + +//============================================================================== +// com::sun::star::sdbc::XRowSet +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::execute() throw( SQLException, RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + // if somebody calls an execute and we're not loaded we reroute this call to our load method. + + // the difference between execute and load is, that we position on the first row in case of load + // after execute we remain before the first row + if (!isLoaded()) + { + aGuard.clear(); + load_impl(sal_False, sal_False); + } + else + { + EventObject event(static_cast< XWeak* >(this)); + if ( !impl_approveRowChange_throw( event, true, aGuard ) ) + return; + + // we're loaded and somebody want's to execute ourself -> this means a reload + reload_impl(sal_False); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException ) +{ + if (m_xAggregateAsRowSet.is()) + m_xAggregateAsRowSet->addRowSetListener(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException ) +{ + if (m_xAggregateAsRowSet.is()) + m_xAggregateAsRowSet->removeRowSetListener(_rListener); +} + +//============================================================================== +// com::sun::star::sdbc::XResultSet +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::next() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->next(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isBeforeFirst() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isBeforeFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isAfterLast() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isAfterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isFirst() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isLast() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isLast(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::beforeFirst() throw( SQLException, RuntimeException ) +{ + m_xAggregateAsRowSet->beforeFirst(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::afterLast() throw( SQLException, RuntimeException ) +{ + m_xAggregateAsRowSet->afterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::first() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->first(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::last() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->last(); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL ODatabaseForm::getRow() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->getRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::absolute(sal_Int32 row) throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->absolute(row); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::relative(sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->relative(rows); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::previous() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->previous(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::refreshRow() throw( SQLException, RuntimeException ) +{ + m_xAggregateAsRowSet->refreshRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::rowUpdated() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->rowUpdated(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::rowInserted() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->rowInserted(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::rowDeleted() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->rowDeleted(); +} + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL ODatabaseForm::getStatement() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->getStatement(); +} + +// com::sun::star::sdbc::XResultSetUpdate +// exceptions during insert update and delete will be forwarded to the errorlistener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::insertRow() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->insertRow(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::updateRow() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->updateRow(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_UPDATERECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::deleteRow() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->deleteRow(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::cancelRowUpdates() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->cancelRowUpdates(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::moveToInsertRow() throw( SQLException, RuntimeException ) +{ + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + { + // _always_ move to the insert row + // + // Formerly, the following line was conditioned with a "not is new", means we did not move the aggregate + // to the insert row if it was already positioned there. + // + // This prevented the RowSet implementation from resetting it's column values. We, ourself, formerly + // did this reset of columns in reset_impl, where we set every column to the ControlDefault, or, if this + // was not present, to NULL. However, the problem with setting to NULL was #88888#, the problem with + // _not_ setting to NULL (which was the original fix for #88888#) was #97955#. + // + // So now we + // * move our aggregate to the insert row + // * in reset_impl + // - set the control defaults into the columns if not void + // - do _not_ set the columns to NULL if no control default is set + // This fixes both #88888# and #97955# + // + // Still, there is #72756#. During fixing this bug, DG introduced not calling the aggregate here. So + // in theory, we re-introduced #72756#. But the bug described therein does not happen anymore, as the + // preliminaries for it changed (no display of guessed values for new records with autoinc fields) + // + // BTW: the public Issuezilla bug for #97955# is #i2815# + // + // 16.04.2002 - 97955 - fs@openoffice.org + xUpdate->moveToInsertRow(); + + // then set the default values and the parameters given from the parent + reset(); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::moveToCurrentRow() throw( SQLException, RuntimeException ) +{ + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->moveToCurrentRow(); +} + +// com::sun::star::sdbcx::XDeleteRows +//------------------------------------------------------------------------------ +Sequence<sal_Int32> SAL_CALL ODatabaseForm::deleteRows(const Sequence<Any>& rows) throw( SQLException, RuntimeException ) +{ + try + { + Reference<XDeleteRows> xDelete; + if (query_aggregation( m_xAggregate, xDelete)) + return xDelete->deleteRows(rows); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; // make compiler happy + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORDS)); + throw; + } + + return Sequence< sal_Int32 >(); +} + +// com::sun::star::sdbc::XParameters +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setNull(parameterIndex, sqlType); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBoolean(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setByte(sal_Int32 parameterIndex, sal_Int8 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setByte(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setShort(sal_Int32 parameterIndex, sal_Int16 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setShort(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setInt(sal_Int32 parameterIndex, sal_Int32 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setInt(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setLong(sal_Int32 parameterIndex, sal_Int64 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setLong(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setFloat(sal_Int32 parameterIndex, float x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setFloat(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setDouble(sal_Int32 parameterIndex, double x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setDouble(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setString(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBytes(sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBytes(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setDate(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setTime(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setTimestamp(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBinaryStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBinaryStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setCharacterStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setCharacterStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setObjectWithInfo(sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setObject(sal_Int32 parameterIndex, const Any& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObject(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setRef(sal_Int32 parameterIndex, const Reference<XRef>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setRef(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBlob(sal_Int32 parameterIndex, const Reference<XBlob>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBlob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setClob(sal_Int32 parameterIndex, const Reference<XClob>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setClob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setArray(sal_Int32 parameterIndex, const Reference<XArray>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setArray(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::clearParameters() throw( SQLException, RuntimeException ) +{ + m_aParameterManager.clearParameters(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException) +{ + if ( evt.Source == m_xParent ) + { + if ( evt.PropertyName == PROPERTY_ISNEW ) + { + sal_Bool bCurrentIsNew( sal_False ); + OSL_VERIFY( evt.NewValue >>= bCurrentIsNew ); + if ( !bCurrentIsNew ) + reload_impl( sal_True ); + } + return; + } + OFormComponents::propertyChange( evt ); +} + +// com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName_Static() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.ODatabaseForm" ) ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCompatibleServiceNames_Static() +{ + Sequence< ::rtl::OUString > aServices( 1 ); + ::rtl::OUString* pServices = aServices.getArray(); + + *pServices++ = FRM_COMPONENT_FORM; + + return aServices; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCurrentServiceNames_Static() +{ + Sequence< ::rtl::OUString > aServices( 5 ); + ::rtl::OUString* pServices = aServices.getArray(); + + *pServices++ = FRM_SUN_FORMCOMPONENT; + *pServices++ = ::rtl::OUString::createFromAscii("com.sun.star.form.FormComponents"); + *pServices++ = FRM_SUN_COMPONENT_FORM; + *pServices++ = FRM_SUN_COMPONENT_HTMLFORM; + *pServices++ = FRM_SUN_COMPONENT_DATAFORM; + + return aServices; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames_Static() +{ + return ::comphelper::concatSequences( + getCurrentServiceNames_Static(), + getCompatibleServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName() throw( RuntimeException ) +{ + return getImplementationName_Static(); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames() throw( RuntimeException ) +{ + // the services of our aggregate + Sequence< ::rtl::OUString > aServices; + Reference< XServiceInfo > xInfo; + if (query_aggregation(m_xAggregate, xInfo)) + aServices = xInfo->getSupportedServiceNames(); + + // concat with out own services + return ::comphelper::concatSequences( + getCurrentServiceNames_Static(), + aServices + ); + // use getCurrentXXX instead of getSupportedXXX, because at runtime, we do not want to have + // the compatible names + // This is maily to be consistent with the implementation before fixing #97083#, though the + // better solution _may_ be to return the compatible names at runtime, too + // 04.03.2002 - fs@openoffice.org +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::supportsService(const ::rtl::OUString& ServiceName) throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSupported.getConstArray(); + for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray ) + if( pArray->equals( ServiceName ) ) + return sal_True; + return sal_False; +} + +//============================================================================== +// com::sun::star::io::XPersistObject +//------------------------------------------------------------------------------ + +const sal_uInt16 CYCLE = 0x0001; +const sal_uInt16 DONTAPPLYFILTER = 0x0002; + +//------------------------------------------------------------------------------ +::rtl::OUString ODatabaseForm::getServiceName() throw( RuntimeException ) +{ + return FRM_COMPONENT_FORM; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException ) +{ + DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::write : only to be called if the aggregate exists !"); + + // all children + OFormComponents::write(_rxOutStream); + + // version + _rxOutStream->writeShort(0x0003); + + // Name + _rxOutStream << m_sName; + + ::rtl::OUString sDataSource; + if (m_xAggregateSet.is()) + m_xAggregateSet->getPropertyValue(PROPERTY_DATASOURCE) >>= sDataSource; + _rxOutStream << sDataSource; + + // former CursorSource + ::rtl::OUString sCommand; + if (m_xAggregateSet.is()) + m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + _rxOutStream << sCommand; + + // former MasterFields + _rxOutStream << m_aMasterFields; + // former DetailFields + _rxOutStream << m_aDetailFields; + + // former DataSelectionType + DataSelectionType eTranslated = DataSelectionType_TABLE; + if (m_xAggregateSet.is()) + { + sal_Int32 nCommandType = 0; + m_xAggregateSet->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nCommandType; + switch (nCommandType) + { + case CommandType::TABLE : eTranslated = DataSelectionType_TABLE; break; + case CommandType::QUERY : eTranslated = DataSelectionType_QUERY; break; + case CommandType::COMMAND: + { + sal_Bool bEscapeProcessing = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)); + eTranslated = bEscapeProcessing ? DataSelectionType_SQL : DataSelectionType_SQLPASSTHROUGH; + } + break; + default : DBG_ERROR("ODatabaseForm::write : wrong CommandType !"); + } + } + _rxOutStream->writeShort((sal_Int16)eTranslated); // former DataSelectionType + + // very old versions expect a CursorType here + _rxOutStream->writeShort(DatabaseCursorType_KEYSET); + + _rxOutStream->writeBoolean(m_eNavigation != NavigationBarMode_NONE); + + // former DataEntry + if (m_xAggregateSet.is()) + _rxOutStream->writeBoolean(getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_INSERTONLY))); + else + _rxOutStream->writeBoolean(sal_False); + + _rxOutStream->writeBoolean(m_bAllowInsert); + _rxOutStream->writeBoolean(m_bAllowUpdate); + _rxOutStream->writeBoolean(m_bAllowDelete); + + // html form stuff + ::rtl::OUString sTmp = INetURLObject::decode( m_aTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS); + _rxOutStream << sTmp; + _rxOutStream->writeShort( (sal_Int16)m_eSubmitMethod ); + _rxOutStream->writeShort( (sal_Int16)m_eSubmitEncoding ); + _rxOutStream << m_aTargetFrame; + + // version 2 didn't know some options and the "default" state + sal_Int32 nCycle = TabulatorCycle_RECORDS; + if (m_aCycle.hasValue()) + { + ::cppu::enum2int(nCycle, m_aCycle); + if (m_aCycle == TabulatorCycle_PAGE) + // unknown in earlier versions + nCycle = TabulatorCycle_RECORDS; + } + _rxOutStream->writeShort((sal_Int16) nCycle); + + _rxOutStream->writeShort((sal_Int16)m_eNavigation); + + ::rtl::OUString sFilter; + ::rtl::OUString sOrder; + if (m_xAggregateSet.is()) + { + m_xAggregateSet->getPropertyValue(PROPERTY_FILTER) >>= sFilter; + m_xAggregateSet->getPropertyValue(PROPERTY_SORT) >>= sOrder; + } + _rxOutStream << sFilter; + _rxOutStream << sOrder; + + + // version 3 + sal_uInt16 nAnyMask = 0; + if (m_aCycle.hasValue()) + nAnyMask |= CYCLE; + + if (m_xAggregateSet.is() && !getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_APPLYFILTER))) + nAnyMask |= DONTAPPLYFILTER; + + _rxOutStream->writeShort(nAnyMask); + + if (nAnyMask & CYCLE) + { + sal_Int32 nRealCycle = 0; + ::cppu::enum2int(nRealCycle, m_aCycle); + _rxOutStream->writeShort((sal_Int16)nRealCycle); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException ) +{ + DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::read : only to be called if the aggregate exists !"); + + OFormComponents::read(_rxInStream); + + // version + sal_uInt16 nVersion = _rxInStream->readShort(); + + _rxInStream >> m_sName; + + ::rtl::OUString sAggregateProp; + _rxInStream >> sAggregateProp; + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, makeAny(sAggregateProp)); + _rxInStream >> sAggregateProp; + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND, makeAny(sAggregateProp)); + + _rxInStream >> m_aMasterFields; + _rxInStream >> m_aDetailFields; + + sal_Int16 nCursorSourceType = _rxInStream->readShort(); + sal_Int32 nCommandType = 0; + switch ((DataSelectionType)nCursorSourceType) + { + case DataSelectionType_TABLE : nCommandType = CommandType::TABLE; break; + case DataSelectionType_QUERY : nCommandType = CommandType::QUERY; break; + case DataSelectionType_SQL: + case DataSelectionType_SQLPASSTHROUGH: + { + nCommandType = CommandType::COMMAND; + sal_Bool bEscapeProcessing = ((DataSelectionType)nCursorSourceType) != DataSelectionType_SQLPASSTHROUGH; + m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, makeAny((sal_Bool)bEscapeProcessing)); + } + break; + default : DBG_ERROR("ODatabaseForm::read : wrong CommandType !"); + } + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_COMMANDTYPE, makeAny(nCommandType)); + + // obsolete + _rxInStream->readShort(); + + // navigation mode was a boolean in version 1 + // war in der version 1 ein sal_Bool + sal_Bool bNavigation = _rxInStream->readBoolean(); + if (nVersion == 1) + m_eNavigation = bNavigation ? NavigationBarMode_CURRENT : NavigationBarMode_NONE; + + sal_Bool bInsertOnly = _rxInStream->readBoolean(); + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_INSERTONLY, makeAny(bInsertOnly)); + + m_bAllowInsert = _rxInStream->readBoolean(); + m_bAllowUpdate = _rxInStream->readBoolean(); + m_bAllowDelete = _rxInStream->readBoolean(); + + // html stuff + ::rtl::OUString sTmp; + _rxInStream >> sTmp; + m_aTargetURL = INetURLObject::decode( sTmp, '%', INetURLObject::DECODE_UNAMBIGUOUS); + m_eSubmitMethod = (FormSubmitMethod)_rxInStream->readShort(); + m_eSubmitEncoding = (FormSubmitEncoding)_rxInStream->readShort(); + _rxInStream >> m_aTargetFrame; + + if (nVersion > 1) + { + sal_Int32 nCycle = _rxInStream->readShort(); + m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL))); + m_eNavigation = (NavigationBarMode)_rxInStream->readShort(); + + _rxInStream >> sAggregateProp; + setPropertyValue(PROPERTY_FILTER, makeAny(sAggregateProp)); + + _rxInStream >> sAggregateProp; + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_SORT, makeAny(sAggregateProp)); + } + + sal_uInt16 nAnyMask = 0; + if (nVersion > 2) + { + nAnyMask = _rxInStream->readShort(); + if (nAnyMask & CYCLE) + { + sal_Int32 nCycle = _rxInStream->readShort(); + m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL))); + } + else + m_aCycle.clear(); + } + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_APPLYFILTER, makeAny((sal_Bool)((nAnyMask & DONTAPPLYFILTER) == 0))); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::implInserted( const ElementDescription* _pElement ) +{ + OFormComponents::implInserted( _pElement ); + + Reference< XSQLErrorBroadcaster > xBroadcaster( _pElement->xInterface, UNO_QUERY ); + Reference< XForm > xForm ( _pElement->xInterface, UNO_QUERY ); + + if ( xBroadcaster.is() && !xForm.is() ) + { // the object is an error broadcaster, but no form itself -> add ourself as listener + xBroadcaster->addSQLErrorListener( this ); + } +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::implRemoved(const InterfaceRef& _rxObject) +{ + OFormComponents::implRemoved( _rxObject ); + + Reference<XSQLErrorBroadcaster> xBroadcaster(_rxObject, UNO_QUERY); + Reference<XForm> xForm(_rxObject, UNO_QUERY); + if (xBroadcaster.is() && !xForm.is()) + { // the object is an error broadcaster, but no form itself -> remove ourself as listener + xBroadcaster->removeSQLErrorListener(this); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::errorOccured(const SQLErrorEvent& _rEvent) throw( RuntimeException ) +{ + // give it to my own error listener + onError(_rEvent); + // TODO : think about extending the chain with an SQLContext object saying + // "this was an error of one of my children" +} + +// com::sun::star::container::XNamed +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseForm::getName() throw( RuntimeException ) +{ + ::rtl::OUString sReturn; + OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= sReturn; + return sReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setName(const ::rtl::OUString& aName) throw( RuntimeException ) +{ + setFastPropertyValue(PROPERTY_ID_NAME, makeAny(aName)); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/DatabaseForm.hxx b/forms/source/component/DatabaseForm.hxx new file mode 100644 index 000000000000..af506aa305d2 --- /dev/null +++ b/forms/source/component/DatabaseForm.hxx @@ -0,0 +1,569 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_DATABASEFORM_HXX_ +#define _FRM_DATABASEFORM_HXX_ + +#include "propertybaghelper.hxx" +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdb/XSQLErrorListener.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <com/sun/star/form/FormSubmitMethod.hpp> +#include <com/sun/star/form/FormSubmitEncoding.hpp> +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/form/XDatabaseParameterBroadcaster2.hpp> +#include <com/sun/star/sdb/XCompletedExecution.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <com/sun/star/sdb/XRowSetApproveListener.hpp> +#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp> +#include <com/sun/star/form/NavigationBarMode.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/form/XLoadListener.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/awt/XTabControllerModel.hpp> +#include <com/sun/star/script/XEventAttacherManager.hpp> +#include <com/sun/star/sdbc/XRowSetListener.hpp> +#include <com/sun/star/sdb/XResultSetAccess.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> + + +#include <tools/link.hxx> +#include "InterfaceContainer.hxx" + +#include <connectivity/parameters.hxx> +#include <connectivity/filtermanager.hxx> +#include <connectivity/warningscontainer.hxx> + +#ifndef FORMS_SOURCE_MISC_LISTENERCONTAINERS_HXX +#include "listenercontainers.hxx" +#endif +#include "ids.hxx" +#include <comphelper/propmultiplex.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/proparrhlp.hxx> +#include <cppuhelper/implbase12.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/implbase7.hxx> + +namespace com { namespace sun { namespace star { namespace sdbc { + class SQLException; +} } } } + +class Timer; +class INetMIMEMessage; + +//......................................................................... +namespace frm +{ +//......................................................................... + +//======================================================================== +//= html tools +//======================================================================== + +const sal_uInt16 SUCCESSFUL_REPRESENT_TEXT = 0x0001; +const sal_uInt16 SUCCESSFUL_REPRESENT_FILE = 0x0002; + +//------------------------------------------------------------------------------ +class HtmlSuccessfulObj +{ +public: + ::rtl::OUString aName; + ::rtl::OUString aValue; + sal_uInt16 nRepresentation; + + HtmlSuccessfulObj( const ::rtl::OUString& _rName, const ::rtl::OUString& _rValue, + sal_uInt16 _nRepresent = SUCCESSFUL_REPRESENT_TEXT ) + :aName( _rName ) + ,aValue( _rValue ) + ,nRepresentation( _nRepresent ) + { + } + + HtmlSuccessfulObj() + { + } +}; + + +DECLARE_STL_VECTOR(HtmlSuccessfulObj, HtmlSuccessfulObjList); + +//======================================================================== +class OGroupManager; +class OFormSubmitResetThread; +typedef ::cppu::ImplHelper12 < ::com::sun::star::form::XForm + , ::com::sun::star::awt::XTabControllerModel + , ::com::sun::star::form::XLoadListener + , ::com::sun::star::sdbc::XRowSetListener + , ::com::sun::star::sdb::XRowSetApproveListener + , ::com::sun::star::form::XDatabaseParameterBroadcaster2 + , ::com::sun::star::sdb::XSQLErrorListener + , ::com::sun::star::sdb::XSQLErrorBroadcaster + , ::com::sun::star::form::XReset + , ::com::sun::star::form::XSubmit + , ::com::sun::star::form::XLoadable + , ::com::sun::star::container::XNamed + > ODatabaseForm_BASE1; + + +typedef ::cppu::ImplHelper4 < ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::beans::XPropertyContainer + , ::com::sun::star::beans::XPropertyAccess + , ::com::sun::star::sdbc::XWarningsSupplier + > ODatabaseForm_BASE2; + +typedef ::cppu::ImplHelper7< ::com::sun::star::sdbc::XCloseable, + ::com::sun::star::sdbc::XRowSet, + ::com::sun::star::sdb::XCompletedExecution, + ::com::sun::star::sdb::XRowSetApproveBroadcaster, + ::com::sun::star::sdbc::XResultSetUpdate, + ::com::sun::star::sdbcx::XDeleteRows, + ::com::sun::star::sdbc::XParameters > ODatabaseForm_BASE3; + + +class ODatabaseForm :public OFormComponents + ,public OPropertySetAggregationHelper + ,public OPropertyChangeListener + ,public ODatabaseForm_BASE1 + ,public ODatabaseForm_BASE2 + ,public ODatabaseForm_BASE3 + ,public IPropertyBagHelperContext +{ + friend class OFormSubmitResetThread; + + OImplementationIdsRef m_aHoldIdHelper; + + // listener administration + ::cppu::OInterfaceContainerHelper m_aLoadListeners; + ::cppu::OInterfaceContainerHelper m_aRowSetApproveListeners; + ::cppu::OInterfaceContainerHelper m_aRowSetListeners; + ::cppu::OInterfaceContainerHelper m_aSubmitListeners; + ::cppu::OInterfaceContainerHelper m_aErrorListeners; + ResetListeners m_aResetListeners; + ::osl::Mutex m_aResetSafety; + ::com::sun::star::uno::Any m_aCycle; + ::com::sun::star::uno::Any m_aIgnoreResult; // set when we are a subform and our master form positioned on a new row + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aMasterFields; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aDetailFields; + + // the object doin' most of the work - an SDB-rowset + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; + // same object, interface as member because of performance reasons + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet> m_xAggregateAsRowSet; + + PropertyBagHelper m_aPropertyBagHelper; + ::dbtools::WarningsContainer m_aWarnings; + OPropertyChangeMultiplexer* m_pAggregatePropertyMultiplexer; + // Verwaltung der ControlGruppen + OGroupManager* m_pGroupManager; + ::dbtools::ParameterManager m_aParameterManager; + ::dbtools::FilterManager m_aFilterManager; + Timer* m_pLoadTimer; + + OFormSubmitResetThread* m_pThread; + ::rtl::OUString m_sCurrentErrorContext; + // will be used as additional context information + // when an exception is catched and forwarded to the listeners + + INT32 m_nResetsPending; +// <overwritten_properties> + sal_Int32 m_nPrivileges; + sal_Bool m_bInsertOnly; +// </overwritten_properties> + +// <properties> + ::com::sun::star::uno::Any m_aControlBorderColorFocus; + ::com::sun::star::uno::Any m_aControlBorderColorMouse; + ::com::sun::star::uno::Any m_aControlBorderColorInvalid; + ::com::sun::star::uno::Any m_aDynamicControlBorder; + ::rtl::OUString m_sName; + ::rtl::OUString m_aTargetURL; + ::rtl::OUString m_aTargetFrame; + ::com::sun::star::form::FormSubmitMethod m_eSubmitMethod; + ::com::sun::star::form::FormSubmitEncoding m_eSubmitEncoding; + ::com::sun::star::form::NavigationBarMode m_eNavigation; + sal_Bool m_bAllowInsert : 1; + sal_Bool m_bAllowUpdate : 1; + sal_Bool m_bAllowDelete : 1; +// </properties> + sal_Bool m_bLoaded : 1; + sal_Bool m_bSubForm : 1; + sal_Bool m_bForwardingConnection : 1; // sal_True if we're setting the ActiveConnection on the aggregate + sal_Bool m_bSharingConnection : 1; // sal_True if the connection we're using is shared with out parent + +public: + ODatabaseForm(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + ODatabaseForm( const ODatabaseForm& _cloneSource ); + ~ODatabaseForm(); + + // UNO binding + DECLARE_UNO3_AGG_DEFAULTS(ODatabaseForm, OFormComponents); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XComponent + virtual void SAL_CALL disposing(); + + // property handling + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception ); + + ::com::sun::star::uno::Any SAL_CALL getFastPropertyValue( sal_Int32 nHandle ) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + void fire( sal_Int32 * pnHandles, const ::com::sun::star::uno::Any * pNewValues, const ::com::sun::star::uno::Any * pOldValues, sal_Int32 nCount, sal_Bool bVetoable ); + + // IPropertyBagHelperContext + virtual ::osl::Mutex& getMutex(); + virtual void describeFixedAndAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rFixedProperties, + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rAggregateProperties + ) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet > + getPropertiesInterface(); + + // com::sun::star::beans::XPropertyState + virtual ::com::sun::star::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle); + virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle); + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const; + + // com::sun::star::sdbc::XSQLErrorBroadcaster + virtual void SAL_CALL addSQLErrorListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSQLErrorListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::XForm + // nothing to implement + + // com::sun::star::form::XReset + virtual void SAL_CALL reset() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::XSubmit + virtual void SAL_CALL submit(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& aControl, const ::com::sun::star::awt::MouseEvent& aMouseEvt) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSubmitListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XSubmitListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSubmitListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XSubmitListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::container::XChild + virtual InterfaceRef SAL_CALL getParent() throw ( ::com::sun::star::uno::RuntimeException) { return OFormComponents::getParent(); } + virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw ( :: com::sun::star::lang::NoSupportException , ::com::sun::star::uno::RuntimeException); + + // com::sun::star::container::XNamed + virtual ::rtl::OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setName(const ::rtl::OUString& aName) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::awt::XTabControllerModel + virtual sal_Bool SAL_CALL getGroupControl() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setGroupControl(sal_Bool /*_bGroupControl*/) throw(::com::sun::star::uno::RuntimeException) { } + virtual void SAL_CALL setControlModels(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rControls) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > SAL_CALL getControlModels() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setGroup(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rGroup, const ::rtl::OUString& _rGroupName) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getGroupCount() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL getGroup(sal_Int32 _nGroup, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rxGroup, ::rtl::OUString& _rName) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL getGroupByName(const ::rtl::OUString& _rName, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rxGroup) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::XLoadListener + virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& aEvent) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unloading(const ::com::sun::star::lang::EventObject& aEvent) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unloaded(const ::com::sun::star::lang::EventObject& aEvent) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reloading(const ::com::sun::star::lang::EventObject& aEvent) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reloaded(const ::com::sun::star::lang::EventObject& aEvent) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::XLoadable + virtual void SAL_CALL load() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unload() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reload() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLoaded() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addLoadListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeLoadListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XRowSetListener + virtual void SAL_CALL cursorMoved(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowChanged(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowSetChanged(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdb::XRowSetApproveListener + virtual sal_Bool SAL_CALL approveCursorMove(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL approveRowChange(const ::com::sun::star::sdb::RowChangeEvent& event) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL approveRowSetChange(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdb::XRowSetApproveBroadcaster + virtual void SAL_CALL addRowSetApproveListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetApproveListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun:star::form::XDatabaseParameterBroadcaster2 + virtual void SAL_CALL addDatabaseParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeDatabaseParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun:star::form::XDatabaseParameterBroadcaster + virtual void SAL_CALL addParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdb::XCompletedExecution + virtual void SAL_CALL executeWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute(sal_Int32 row) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative(sal_Int32 rows) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual InterfaceRef SAL_CALL getStatement() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& rows) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getCurrentServiceNames_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getCompatibleServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + // com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XSQLErrorListener + virtual void SAL_CALL errorOccured(const ::com::sun::star::sdb::SQLErrorEvent& aEvent) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XParameters + virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearParameters() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException); + + // XPropertyContainer + virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, ::sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException); + + // XPropertyAccess + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPropertyValues( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aProps ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + using OPropertySetAggregationHelper::setPropertyValues; + + // XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + + inline void submitNBC( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt ); + +protected: + // OPropertySetAggregationHelper overridables + virtual void SAL_CALL forwardingPropertyValue( sal_Int32 _nHandle ); + virtual void SAL_CALL forwardedPropertyValue( sal_Int32 _nHandle, bool _bSuccess ); + + // OInterfaceContainer overridables + virtual void implInserted( const ElementDescription* _pElement ); + virtual void implRemoved(const InterfaceRef& _rxObject); + + // OPropertyChangeListener + virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& ) throw(::com::sun::star::uno::RuntimeException); + +private: + sal_Bool executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst = sal_True, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()); + bool fillParameters(::osl::ResettableMutexGuard& _rClearForNotifies, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()); + void updateParameterInfo(); + bool hasValidParent() const; + + // impl methods + void load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst = sal_True, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()) + throw(::com::sun::star::uno::RuntimeException); + void reload_impl(sal_Bool bMoveToFirst, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()) + throw(::com::sun::star::uno::RuntimeException); + void submit_impl(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners); + void reset_impl(bool _bAproveByListeners); + + sal_Bool implEnsureConnection(); + + // connection sharing + + /// checks if we can re-use (aka share) the connection of the given parent + sal_Bool canShareConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxParentProps ); + + /// starts sharing the connection with the parent + void doShareConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxParentProps ); + + /// stops sharing the connection with the parent + void stopSharingConnection( ); + + /// called when the connection which we share with our parent is beeing disposed + void disposingSharedConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn ); + + /// checks if we currently share our connection with our parent + sal_Bool isSharingConnection( ) const { return m_bSharingConnection; } + + /** calls our row set approval listeners + + @param _rEvent + the event to notify + @param _bAllowSQLException + <TRUE/> if SQLExceptions are allowed to leave the method + @param _rGuard + the guard to be cleared before actually calling into the listeners, but after making + a copy of the listeners array to operate on. + @return + <TRUE/> if and only if the execution has been approved + */ + bool impl_approveRowChange_throw( + const ::com::sun::star::lang::EventObject& _rEvent, + const bool _bAllowSQLException, + ::osl::ClearableMutexGuard& _rGuard + ); + + /// invalidate all our parameter-related stuff + void invlidateParameters(); + + void saveInsertOnlyState( ); + void restoreInsertOnlyState( ); + + // error handling + void onError(const ::com::sun::star::sdb::SQLErrorEvent& _rEvent); + void onError(const ::com::sun::star::sdbc::SQLException&, const ::rtl::OUString& _rContextDescription); + + // html tools + ::rtl::OUString GetDataEncoded(bool _bURLEncoded,const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + ::rtl::OUString GetDataURLEncoded(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + ::rtl::OUString GetDataTextEncoded(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + ::com::sun::star::uno::Sequence<sal_Int8> GetDataMultiPartEncoded(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, + ::rtl::OUString& rContentType); + + void AppendComponent(HtmlSuccessfulObjList& rList, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& xComponentSet, const ::rtl::OUString& rNamePrefix, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + + void FillSuccessfulList(HtmlSuccessfulObjList& rList, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + + void InsertTextPart(INetMIMEMessage& rParent, const ::rtl::OUString& rName, const ::rtl::OUString& rData); + sal_Bool InsertFilePart(INetMIMEMessage& rParent, const ::rtl::OUString& rName, const ::rtl::OUString& rFileName); + void Encode(::rtl::OUString& rString) const; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > getConnection(); + + void impl_createLoadTimer(); + + void impl_construct(); + + DECL_LINK( OnTimeout, void* ); +protected: + using OPropertySetHelper::getPropertyValues; +}; + +inline void ODatabaseForm::submitNBC(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + submit_impl(Control, MouseEvt, sal_False); +} + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_DATABASEFORM_HXX_ + + diff --git a/forms/source/component/Date.cxx b/forms/source/component/Date.cxx new file mode 100644 index 000000000000..1e04a63bfb0b --- /dev/null +++ b/forms/source/component/Date.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Date.hxx" +#include <tools/debug.hxx> +#include <tools/date.hxx> +#include <connectivity/dbconversion.hxx> +#include <com/sun/star/sdbc/DataType.hpp> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; + +//------------------------------------------------------------------ +ODateControl::ODateControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_DATEFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ODateControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ODateControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ODateControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ODateControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_DATEFIELD; + return aSupported; +} + +/*************************************************************************/ +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ODateModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ODateModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ODateModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( ODateModel ) +//------------------------------------------------------------------ +ODateModel::ODateModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_DATEFIELD, FRM_SUN_CONTROL_DATEFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OLimitedFormats( _rxFactory, FormComponentType::DATEFIELD ) +{ + DBG_CTOR( ODateModel, NULL ); + + m_nClassId = FormComponentType::DATEFIELD; + initValueProperty( PROPERTY_DATE, PROPERTY_ID_DATE ); + + setAggregateSet(m_xAggregateFastSet, getOriginalHandle(PROPERTY_ID_DATEFORMAT)); + + osl_incrementInterlockedCount( &m_refCount ); + try + { + if ( m_xAggregateSet.is() ) + m_xAggregateSet->setPropertyValue( PROPERTY_DATEMIN, makeAny( (sal_Int32)( ::Date( 1, 1, 1800 ).GetDate() ) ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ODateModel::ODateModel: caught an exception!" ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//------------------------------------------------------------------------------ +ODateModel::ODateModel( const ODateModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,OLimitedFormats( _rxFactory, FormComponentType::DATEFIELD ) +{ + DBG_CTOR( ODateModel, NULL ); + + setAggregateSet( m_xAggregateFastSet, getOriginalHandle( PROPERTY_ID_DATEFORMAT ) ); +} + +//------------------------------------------------------------------------------ +ODateModel::~ODateModel( ) +{ + setAggregateSet(Reference< XFastPropertySet >(), -1); + DBG_DTOR( ODateModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( ODateModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ODateModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_DATEFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_DATEFIELD; + *pStoreTo++ = BINDABLE_DATABASE_DATE_FIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODateModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_DATEFIELD; // old (non-sun) name for compatibility ! +} + +// XPropertySet +//------------------------------------------------------------------------------ +void ODateModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 4, OEditBaseModel ) + DECL_PROP3(DEFAULT_DATE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP1(FORMATKEY, sal_Int32, TRANSIENT); + DECL_IFACE_PROP2(FORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODateModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle ) const +{ + switch (_nHandle) + { + case PROPERTY_ID_FORMATKEY: + getFormatKeyPropertyValue(_rValue); + break; + case PROPERTY_ID_FORMATSSUPPLIER: + _rValue <<= getFormatsSupplier(); + break; + default: + OEditBaseModel::getFastPropertyValue(_rValue, _nHandle); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODateModel::convertFastPropertyValue(Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + return convertFormatKeyPropertyValue(_rConvertedValue, _rOldValue, _rValue); + else + return OEditBaseModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODateModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw ( ::com::sun::star::uno::Exception) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + setFormatKeyPropertyValue(_rValue); + else + OEditBaseModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); +} + +// XLoadListener +//------------------------------------------------------------------------------ +void ODateModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OBoundControlModel::onConnectedDbColumn( _rxForm ); + Reference<XPropertySet> xField = getField(); + if (xField.is()) + { + m_bDateTimeField = sal_False; + try + { + sal_Int32 nFieldType = 0; + xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nFieldType; + m_bDateTimeField = (nFieldType == DataType::TIMESTAMP); + } + catch(Exception&) + { + } + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODateModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( !aControlValue.hasValue() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + util::Date aDate; + if ( !( aControlValue >>= aDate ) ) + { + sal_Int32 nAsInt(0); + aControlValue >>= nAsInt; + aDate = DBTypeConversion::toDate(nAsInt); + } + + if ( !m_bDateTimeField ) + m_xColumnUpdate->updateDate( aDate ); + else + { + util::DateTime aDateTime = m_xColumn->getTimestamp(); + aDateTime.Day = aDate.Day; + aDateTime.Month = aDate.Month; + aDateTime.Year = aDate.Year; + m_xColumnUpdate->updateTimestamp( aDateTime ); + } + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +void ODateModel::impl_translateControlValueToUNODate( Any& _rUNOValue ) const +{ + _rUNOValue = getControlValue(); + if ( _rUNOValue.hasValue() ) + { + sal_Int32 nDate = 0; + OSL_VERIFY( _rUNOValue >>= nDate ); + _rUNOValue <<= DBTypeConversion::toDate( nDate ); + } +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateControlValueToExternalValue( ) const +{ + Any aExternalValue; + impl_translateControlValueToUNODate( aExternalValue ); + return aExternalValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue; + if ( _rExternalValue.hasValue() ) + { + util::Date aDate; + OSL_VERIFY( _rExternalValue >>= aDate ); + aControlValue <<= DBTypeConversion::toINT32( aDate ); + } + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateControlValueToValidatableValue( ) const +{ + Any aValidatableValue; + impl_translateControlValueToUNODate( aValidatableValue ); + return aValidatableValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateDbColumnToControlValue() +{ + util::Date aDate = m_xColumn->getDate(); + if (m_xColumn->wasNull()) + m_aSaveValue.clear(); + else + // the aggregated set expects an Int32 as value ... + m_aSaveValue <<= DBTypeConversion::toINT32(aDate); + + return m_aSaveValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::getDefaultForReset() const +{ + return m_aDefault; +} + +//------------------------------------------------------------------------------ +void ODateModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//------------------------------------------------------------------------------ +Sequence< Type > ODateModel::getSupportedBindingTypes() +{ + return Sequence< Type >( &::getCppuType( static_cast< util::Date* >( NULL ) ), 1 ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Date.hxx b/forms/source/component/Date.hxx new file mode 100644 index 000000000000..8ff6d1433508 --- /dev/null +++ b/forms/source/component/Date.hxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_DATE_HXX_ +#define _FORMS_DATE_HXX_ + +#include "EditBase.hxx" +#include "limitedformats.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= ODateModel +//================================================================== +class ODateModel + :public OEditBaseModel + ,public OLimitedFormats +{ + ::com::sun::star::uno::Any m_aSaveValue; + sal_Bool m_bDateTimeField; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( ODateModel ); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::beans::XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + // XServiceInfo + IMPLEMENTATION_NAME(ODateModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // XPropertySet + using OEditBaseModel::getFastPropertyValue; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void resetNoBroadcast(); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + +protected: + DECLARE_XCLONEABLE(); + +private: + /** translates the control value (the VCL-internal integer representation of a date) into + a UNO-Date. + */ + void impl_translateControlValueToUNODate( + ::com::sun::star::uno::Any& _rUNOValue ) const; +}; + +//================================================================== +//= ODateControl +//================================================================== +class ODateControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + ODateControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + DECLARE_UNO3_AGG_DEFAULTS(ODateControl, OBoundControl); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(ODateControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_DATE_HXX_ + diff --git a/forms/source/component/Edit.cxx b/forms/source/component/Edit.cxx new file mode 100644 index 000000000000..3a36078a7fed --- /dev/null +++ b/forms/source/component/Edit.cxx @@ -0,0 +1,766 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Edit.hxx" + +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +#include <vcl/svapp.hxx> +#include <vcl/wintypes.hxx> + +#include <connectivity/dbtools.hxx> +#include <connectivity/formattedcolumnvalue.hxx> +#include <connectivity/dbconversion.hxx> + +#include <tools/diagnose_ex.h> +#include <tools/debug.hxx> + +#include <comphelper/container.hxx> +#include <comphelper/numbers.hxx> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OEditControl_CreateInstance(const Reference< XMultiServiceFactory > & _rxFactory) +{ + return *(new OEditControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OEditControl::_getTypes() +{ + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + { + // my two base classes + aTypes = concatSequences(OBoundControl::_getTypes(), OEditControl_BASE::getTypes()); + } + return aTypes; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OEditControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OEditControl_BASE::queryInterface(_rType); + + return aReturn; +} + +DBG_NAME(OEditControl); +//------------------------------------------------------------------------------ +OEditControl::OEditControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl( _rxFactory, FRM_SUN_CONTROL_RICHTEXTCONTROL ) + ,m_aChangeListeners(m_aMutex) + ,m_nKeyEvent( 0 ) +{ + DBG_CTOR(OEditControl,NULL); + + increment(m_refCount); + { + Reference<XWindow> xComp; + if (query_aggregation(m_xAggregate, xComp)) + { + xComp->addFocusListener(this); + xComp->addKeyListener(this); + } + } + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +OEditControl::~OEditControl() +{ + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OEditControl,NULL); +} + +// XChangeBroadcaster +//------------------------------------------------------------------------------ +void OEditControl::addChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aChangeListeners.addInterface( l ); +} + +//------------------------------------------------------------------------------ +void OEditControl::removeChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aChangeListeners.removeInterface( l ); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OEditControl::disposing() +{ + OBoundControl::disposing(); + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aChangeListeners.disposeAndClear(aEvt); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OEditControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_TEXTFIELD; + return aSupported; +} + +// XEventListener +//------------------------------------------------------------------------------ +void OEditControl::disposing(const EventObject& Source) throw( RuntimeException ) +{ + OBoundControl::disposing(Source); +} + +// XFocusListener +//------------------------------------------------------------------------------ +void OEditControl::focusGained( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + xSet->getPropertyValue( PROPERTY_TEXT ) >>= m_aHtmlChangeValue; +} + +//------------------------------------------------------------------------------ +void OEditControl::focusLost( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + { + ::rtl::OUString sNewHtmlChangeValue; + xSet->getPropertyValue( PROPERTY_TEXT ) >>= sNewHtmlChangeValue; + if( sNewHtmlChangeValue != m_aHtmlChangeValue ) + { + EventObject aEvt( *this ); + m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvt ); + } + } +} + +// XKeyListener +//------------------------------------------------------------------------------ +void OEditControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 ) + return; + + // Steht das Control in einem Formular mit einer Submit-URL? + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if( !xSet.is() ) + return; + + // nicht fuer multiline edits + Any aTmp( xSet->getPropertyValue(PROPERTY_MULTILINE)); + if ((aTmp.getValueType().equals(::getBooleanCppuType())) && getBOOL(aTmp)) + return; + + Reference<XFormComponent> xFComp(xSet, UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + if( !xParent.is() ) + return; + + Reference<XPropertySet> xFormSet(xParent, UNO_QUERY); + if( !xFormSet.is() ) + return; + + aTmp = xFormSet->getPropertyValue( PROPERTY_TARGET_URL ); + if (!aTmp.getValueType().equals(::getCppuType((const ::rtl::OUString*)NULL)) || + !getString(aTmp).getLength() ) + return; + + Reference<XIndexAccess> xElements(xParent, UNO_QUERY); + sal_Int32 nCount = xElements->getCount(); + if( nCount > 1 ) + { + Reference<XPropertySet> xFCSet; + for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ ) + { + // Any aElement(xElements->getByIndex(nIndex)); + xElements->getByIndex(nIndex) >>= xFCSet; + OSL_ENSURE(xFCSet.is(),"OEditControl::keyPressed: No XPropertySet!"); + + if (hasProperty(PROPERTY_CLASSID, xFCSet) && + getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD) + { + // Noch ein weiteres Edit gefunden ==> dann nicht submitten + if (xFCSet != xSet) + return; + } + } + } + + // Da wir noch im Haender stehen, submit asynchron ausloesen + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + m_nKeyEvent = Application::PostUserEvent( LINK(this, OEditControl,OnKeyPressed) ); +} + +//------------------------------------------------------------------------------ +void OEditControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +IMPL_LINK(OEditControl, OnKeyPressed, void*, /*EMPTYARG*/) +{ + m_nKeyEvent = 0; + + Reference<XFormComponent> xFComp(getModel(), UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + Reference<XSubmit> xSubmit(xParent, UNO_QUERY); + if (xSubmit.is()) + xSubmit->submit( Reference<XControl>(), ::com::sun::star::awt::MouseEvent() ); + return 0L; +} + +//------------------------------------------------------------------ +void SAL_CALL OEditControl::createPeer( const Reference< XToolkit>& _rxToolkit, const Reference< XWindowPeer>& _rxParent ) throw ( RuntimeException ) +{ + OBoundControl::createPeer(_rxToolkit, _rxParent); +} + +/*************************************************************************/ +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OEditModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OEditModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OEditModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + + +DBG_NAME(OEditModel); +//------------------------------------------------------------------ +OEditModel::OEditModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, FRM_SUN_COMPONENT_RICHTEXTCONTROL, FRM_SUN_CONTROL_TEXTFIELD, sal_True, sal_True ) + ,m_bMaxTextLenModified(sal_False) + ,m_bWritingFormattedFake(sal_False) +{ + DBG_CTOR(OEditModel,NULL); + + m_nClassId = FormComponentType::TEXTFIELD; + initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT ); +} + +//------------------------------------------------------------------ +OEditModel::OEditModel( const OEditModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,m_bMaxTextLenModified(sal_False) + ,m_bWritingFormattedFake(sal_False) +{ + DBG_CTOR( OEditModel, NULL ); + + // Note that most of the properties are not clone from the original object: + // Things as the format key, it's type, and such, depend on the field being part of a loaded form + // (they're initialized in onConnectedDbColumn). Even if the original object _is_ part of such a form, we ourself + // certainly aren't, so these members are defaulted. If we're inserted into a form which is already loaded, + // they will be set to new values, anyway .... +} + +//------------------------------------------------------------------ +OEditModel::~OEditModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OEditModel,NULL); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OEditModel ) + +//------------------------------------------------------------------------------ +void OEditModel::disposing() +{ + OEditBaseModel::disposing(); + m_pValueFormatter.reset(); +} + +// XPersistObject +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OEditModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_EDIT; // old (non-sun) name for compatibility ! +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OEditModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_TEXTFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_TEXTFIELD; + *pStoreTo++ = BINDABLE_DATABASE_TEXT_FIELD; + + return aSupported; +} + +// XPropertySet +void SAL_CALL OEditModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const +{ + if ( PROPERTY_ID_PERSISTENCE_MAXTEXTLENGTH == nHandle ) + { + if ( m_bMaxTextLenModified ) + rValue <<= sal_Int16(0); + else if ( m_xAggregateSet.is() ) + rValue = m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN); + } + else + { + OEditBaseModel::getFastPropertyValue(rValue, nHandle ); + } +} + +//------------------------------------------------------------------------------ +void OEditModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 5, OEditBaseModel ) + DECL_PROP2(PERSISTENCE_MAXTEXTLENGTH,sal_Int16, READONLY, TRANSIENT); + DECL_PROP2(DEFAULT_TEXT, ::rtl::OUString, BOUND, MAYBEDEFAULT); + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_BOOL_PROP2(FILTERPROPOSAL, BOUND, MAYBEDEFAULT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OEditModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OEditBaseModel::describeAggregateProperties( _rAggregateProps ); + + // our aggregate is a rich text model, which also derives from OControlModel, as + // do we, so we need to remove some duplicate properties + RemoveProperty( _rAggregateProps, PROPERTY_TABINDEX ); + RemoveProperty( _rAggregateProps, PROPERTY_CLASSID ); + RemoveProperty( _rAggregateProps, PROPERTY_NAME ); + RemoveProperty( _rAggregateProps, PROPERTY_TAG ); + RemoveProperty( _rAggregateProps, PROPERTY_NATIVE_LOOK ); + +} + +//------------------------------------------------------------------------------ +bool OEditModel::implActsAsRichText( ) const +{ + sal_Bool bActAsRichText = sal_False; + if ( m_xAggregateSet.is() ) + { + OSL_VERIFY( m_xAggregateSet->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bActAsRichText ); + } + return bActAsRichText; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OEditModel::reset( ) throw(RuntimeException) +{ + // no reset if we currently act as rich text control + if ( implActsAsRichText() ) + return; + + OEditBaseModel::reset(); +} + +//------------------------------------------------------------------------------ +namespace +{ + void lcl_transferProperties( const Reference< XPropertySet >& _rxSource, const Reference< XPropertySet >& _rxDest ) + { + try + { + Reference< XPropertySetInfo > xSourceInfo; + if ( _rxSource.is() ) + xSourceInfo = _rxSource->getPropertySetInfo(); + + Reference< XPropertySetInfo > xDestInfo; + if ( _rxDest.is() ) + xDestInfo = _rxDest->getPropertySetInfo(); + + if ( !xSourceInfo.is() || !xDestInfo.is() ) + { + OSL_ENSURE( sal_False, "lcl_transferProperties: invalid property set(s)!" ); + return; + } + + Sequence< Property > aSourceProps( xSourceInfo->getProperties() ); + const Property* pSourceProps = aSourceProps.getConstArray(); + const Property* pSourcePropsEnd = aSourceProps.getConstArray() + aSourceProps.getLength(); + while ( pSourceProps != pSourcePropsEnd ) + { + if ( !xDestInfo->hasPropertyByName( pSourceProps->Name ) ) + { + ++pSourceProps; + continue; + } + + Property aDestProp( xDestInfo->getPropertyByName( pSourceProps->Name ) ); + if ( 0 != ( aDestProp.Attributes & PropertyAttribute::READONLY ) ) + { + ++pSourceProps; + continue; + } + + try + { + _rxDest->setPropertyValue( pSourceProps->Name, _rxSource->getPropertyValue( pSourceProps->Name ) ); + } + catch( IllegalArgumentException e ) + { +#if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sMessage( "could not transfer the property named '" ); + sMessage += ::rtl::OString( pSourceProps->Name.getStr(), pSourceProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US ); + sMessage += ::rtl::OString( "'." ); + if ( e.Message.getLength() ) + { + sMessage += ::rtl::OString( "\n\nMessage:\n" ); + sMessage += ::rtl::OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US ); + } + OSL_ENSURE( sal_False, sMessage.getStr() ); +#endif + } + + ++pSourceProps; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//------------------------------------------------------------------------------ +void OEditModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const +{ + // we need to fake the writing of our aggregate. Since #i24387#, we have another aggregate, + // but for compatibility, we need to use an "old" aggregate for writing and reading + + Reference< XPropertySet > xFakedAggregate( + getContext().createComponent( (rtl::OUString)VCL_CONTROLMODEL_EDIT ), + UNO_QUERY + ); + OSL_ENSURE( xFakedAggregate.is(), "OEditModel::writeAggregate: could not create an old EditControlModel!" ); + if ( !xFakedAggregate.is() ) + return; + + lcl_transferProperties( m_xAggregateSet, xFakedAggregate ); + + Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY ); + OSL_ENSURE( xFakedPersist.is(), "OEditModel::writeAggregate: no XPersistObject!" ); + if ( xFakedPersist.is() ) + xFakedPersist->write( _rxOutStream ); +} + +//------------------------------------------------------------------------------ +void OEditModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream ) +{ + // we need to fake the reading of our aggregate. Since #i24387#, we have another aggregate, + // but for compatibility, we need to use an "old" aggregate for writing and reading + + Reference< XPropertySet > xFakedAggregate( + getContext().createComponent( (rtl::OUString)VCL_CONTROLMODEL_EDIT ), + UNO_QUERY + ); + Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY ); + OSL_ENSURE( xFakedPersist.is(), "OEditModel::readAggregate: no XPersistObject, or no faked aggregate at all!" ); + if ( xFakedPersist.is() ) + { + xFakedPersist->read( _rxInStream ); + lcl_transferProperties( xFakedAggregate, m_xAggregateSet ); + } +} + +//------------------------------------------------------------------------------ +void OEditModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + Any aCurrentText; + sal_Int16 nOldTextLen = 0; + // bin ich gerade loaded und habe dazu zeitweilig die MaxTextLen umgesetzt ? + if ( m_bMaxTextLenModified ) + { // -> fuer die Dauer des Speicherns meinem aggregierten Model die alte TextLen einreden + + // before doing this we have to save the current text value of the aggregate, as this may be affected by resetting the text len + // FS - 08.12.99 - 70606 + aCurrentText = m_xAggregateSet->getPropertyValue(PROPERTY_TEXT); + + m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN) >>= nOldTextLen; + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny((sal_Int16)0)); + } + + OEditBaseModel::write(_rxOutStream); + + if ( m_bMaxTextLenModified ) + { // wieder zuruecksetzen + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny(nOldTextLen)); + // and reset the text + // First we set it to an empty string : Without this the second setPropertyValue would not do anything as it thinks + // we aren't changing the prop (it didn't notify the - implicite - change of the text prop while setting the max text len) + // This seems to be a bug with in toolkit's EditControl-implementation. + m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, makeAny(::rtl::OUString())); + m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, aCurrentText); + } +} + +//------------------------------------------------------------------------------ +void OEditModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OEditBaseModel::read(_rxInStream); + + // Some versions (5.1 'til about 552) wrote a wrong DefaultControl-property value which is unknown + // to older versions (5.0). + // correct this ... + if (m_xAggregateSet.is()) + { + Any aDefaultControl = m_xAggregateSet->getPropertyValue(PROPERTY_DEFAULTCONTROL); + if ( (aDefaultControl.getValueType().getTypeClass() == TypeClass_STRING) + && (getString(aDefaultControl).compareTo(STARDIV_ONE_FORM_CONTROL_TEXTFIELD) == COMPARE_EQUAL) + ) + { + m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( (::rtl::OUString)STARDIV_ONE_FORM_CONTROL_EDIT ) ); + // Older as well as current versions should understand this : the former knew only the STARDIV_ONE_FORM_CONTROL_EDIT, + // the latter are registered for both STARDIV_ONE_FORM_CONTROL_EDIT and STARDIV_ONE_FORM_CONTROL_TEXTFIELD. + } + } +} + +//------------------------------------------------------------------------------ +sal_uInt16 OEditModel::getPersistenceFlags() const +{ + sal_uInt16 nFlags = OEditBaseModel::getPersistenceFlags(); + + if (m_bWritingFormattedFake) + nFlags |= PF_FAKE_FORMATTED_FIELD; + + return nFlags; +} + +//------------------------------------------------------------------------------ +void OEditModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + Reference< XPropertySet > xField = getField(); + if ( xField.is() ) + { + m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) ); + + if ( m_pValueFormatter->getKeyType() != NumberFormat::SCIENTIFIC ) + { + m_bMaxTextLenModified = getINT16(m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN)) != 0; + if ( !m_bMaxTextLenModified ) + { + sal_Int32 nFieldLen = 0; + xField->getPropertyValue(::rtl::OUString::createFromAscii("Precision")) >>= nFieldLen; + + if (nFieldLen && nFieldLen <= USHRT_MAX) + { + Any aVal; + aVal <<= (sal_Int16)nFieldLen; + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal); + + m_bMaxTextLenModified = sal_True; + } + } + else + m_bMaxTextLenModified = sal_False; // to get sure that the text len won't be set in unloaded + } + } +} + +//------------------------------------------------------------------------------ +void OEditModel::onDisconnectedDbColumn() +{ + OEditBaseModel::onDisconnectedDbColumn(); + + m_pValueFormatter.reset(); + + if ( hasField() && m_bMaxTextLenModified ) + { + Any aVal; + aVal <<= (sal_Int16)0; // nur wenn es 0 war, habe ich es in onConnectedDbColumn umgesetzt + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal); + m_bMaxTextLenModified = sal_False; + } +} + +//------------------------------------------------------------------------------ +sal_Bool OEditModel::approveDbColumnType( sal_Int32 _nColumnType ) +{ + // if we act as rich text curently, we do not allow binding to a database column + if ( implActsAsRichText() ) + return sal_False; + + return OEditBaseModel::approveDbColumnType( _nColumnType ); +} + +//------------------------------------------------------------------------------ +void OEditModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aLastKnownValue.clear(); +} + +//------------------------------------------------------------------------------ +sal_Bool OEditModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + + if ( aNewValue != m_aLastKnownValue ) + { + ::rtl::OUString sNewValue; + aNewValue >>= sNewValue; + + if ( !aNewValue.hasValue() + || ( !sNewValue.getLength() // an empty string + && m_bEmptyIsNull // which should be interpreted as NULL + ) + ) + { + m_xColumnUpdate->updateNull(); + } + else + { + OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::commitControlValueToDbColumn: no value formatter!" ); + try + { + if ( m_pValueFormatter.get() ) + { + if ( !m_pValueFormatter->setFormattedValue( sNewValue ) ) + return sal_False; + } + else + m_xColumnUpdate->updateString( sNewValue ); + } + catch ( const Exception& ) + { + return sal_False; + } + } + m_aLastKnownValue = aNewValue; + } + + return sal_True; +} + +//------------------------------------------------------------------------------ +Any OEditModel::translateDbColumnToControlValue() +{ + OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::translateDbColumnToControlValue: no value formatter!" ); + if ( m_pValueFormatter.get() ) + { + ::rtl::OUString sValue( m_pValueFormatter->getFormattedValue() ); + if ( !sValue.getLength() + && m_pValueFormatter->getColumn().is() + && m_pValueFormatter->getColumn()->wasNull() + ) + { + m_aLastKnownValue.clear(); + } + else + { + // #i2817# OJ + sal_uInt16 nMaxTextLen = getINT16( m_xAggregateSet->getPropertyValue( PROPERTY_MAXTEXTLEN ) ); + if ( nMaxTextLen && sValue.getLength() > nMaxTextLen ) + { + sal_Int32 nDiff = sValue.getLength() - nMaxTextLen; + sValue = sValue.replaceAt( nMaxTextLen, nDiff, ::rtl::OUString() ); + } + + m_aLastKnownValue <<= sValue; + } + } + else + m_aLastKnownValue.clear(); + + return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( ::rtl::OUString() ); + // (m_aLastKnownValue is alllowed to be VOID, the control value isn't) +} + +//------------------------------------------------------------------------------ +Any OEditModel::getDefaultForReset() const +{ + return makeAny( m_aDefaultText ); +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/Edit.hxx b/forms/source/component/Edit.hxx new file mode 100644 index 000000000000..5b4146b82d06 --- /dev/null +++ b/forms/source/component/Edit.hxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_EDIT_HXX_ +#define _FORMS_EDIT_HXX_ + +#include "EditBase.hxx" + +#include <cppuhelper/implbase3.hxx> + +namespace dbtools { class FormattedColumnValue; } + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OEditModel +//================================================================== +class OEditModel + :public OEditBaseModel +{ + ::com::sun::star::uno::Any m_aLastKnownValue; + ::std::auto_ptr< ::dbtools::FormattedColumnValue > + m_pValueFormatter; + sal_Bool m_bMaxTextLenModified : 1; // set to <TRUE/> when we change the MaxTextLen of the aggregate + + sal_Bool m_bWritingFormattedFake : 1; + // are we writing something which should be interpreted as formatted upon reading? + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + DECLARE_DEFAULT_LEAF_XTOR( OEditModel ); + + void enableFormattedWriteFake() { m_bWritingFormattedFake = sal_True; } + void disableFormattedWriteFake() { m_bWritingFormattedFake = sal_False; } + sal_Bool lastReadWasFormattedFake() const { return (getLastReadVersion() & PF_FAKE_FORMATTED_FIELD) != 0; } + + friend InterfaceRef SAL_CALL OEditModel_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + friend class OFormattedFieldWrapper; + friend class OFormattedModel; // temporary + +public: + virtual void SAL_CALL disposing(); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + + // XPersistObject + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // XPropertySet + using OBoundControlModel::getFastPropertyValue; + + // XReset + virtual void SAL_CALL reset( ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OEditModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XEventListener + using OBoundControlModel::disposing; + +protected: + // OControlModel overridables + virtual void writeAggregate( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& _rxOutStream ) const; + virtual void readAggregate( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& _rxInStream ); + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual sal_Bool approveDbColumnType( sal_Int32 _nColumnType ); + + virtual void resetNoBroadcast(); + +protected: + virtual sal_uInt16 getPersistenceFlags() const; + + DECLARE_XCLONEABLE(); + +private: + bool implActsAsRichText( ) const; +}; + +//================================================================== +//= OEditControl +//================================================================== +typedef ::cppu::ImplHelper3< ::com::sun::star::awt::XFocusListener, + ::com::sun::star::awt::XKeyListener, + ::com::sun::star::form::XChangeBroadcaster > OEditControl_BASE; + +class OEditControl : public OBoundControl + ,public OEditControl_BASE +{ + ::cppu::OInterfaceContainerHelper + m_aChangeListeners; + + ::rtl::OUString m_aHtmlChangeValue; + sal_uInt32 m_nKeyEvent; + +public: + OEditControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OEditControl(); + + DECLARE_UNO3_AGG_DEFAULTS(OEditControl, OBoundControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OEditControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + +// ::com::sun::star::form::XChangeBroadcaster + virtual void SAL_CALL addChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::awt::XFocusListener + virtual void SAL_CALL focusGained( const ::com::sun::star::awt::FocusEvent& e ) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL focusLost( const ::com::sun::star::awt::FocusEvent& e ) throw ( ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::awt::XKeyListener + virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // XControl + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit >& _rxToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _rxParent ) throw ( ::com::sun::star::uno::RuntimeException ); + +private: + DECL_LINK( OnKeyPressed, void* ); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_EDIT_HXX_ + diff --git a/forms/source/component/EditBase.cxx b/forms/source/component/EditBase.cxx new file mode 100644 index 000000000000..b8dcbb336ebb --- /dev/null +++ b/forms/source/component/EditBase.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "EditBase.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/basicio.hxx> +#include <cppuhelper/queryinterface.hxx> +#include "frm_resource.hxx" +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +const sal_uInt16 DEFAULT_LONG = 0x0001; +const sal_uInt16 DEFAULT_DOUBLE = 0x0002; +const sal_uInt16 FILTERPROPOSAL = 0x0004; + +DBG_NAME( OEditBaseModel ) +//------------------------------------------------------------------ +OEditBaseModel::OEditBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& rUnoControlModelName, + const ::rtl::OUString& rDefault, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation ) + :OBoundControlModel( _rxFactory, rUnoControlModelName, rDefault, sal_True, _bSupportExternalBinding, _bSupportsValidation ) + ,m_nLastReadVersion(0) + ,m_bEmptyIsNull(sal_True) + ,m_bFilterProposal(sal_False) +{ + DBG_CTOR( OEditBaseModel, NULL ); +} + +//------------------------------------------------------------------ +OEditBaseModel::OEditBaseModel( const OEditBaseModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + ,m_nLastReadVersion(0) +{ + DBG_CTOR( OEditBaseModel, NULL ); + + m_bFilterProposal = _pOriginal->m_bFilterProposal; + m_bEmptyIsNull = _pOriginal->m_bEmptyIsNull; + m_aDefault = _pOriginal->m_aDefault; + m_aDefaultText = _pOriginal->m_aDefaultText; +} + +//------------------------------------------------------------------ +OEditBaseModel::~OEditBaseModel( ) +{ + DBG_DTOR( OEditBaseModel, NULL ); +} + +// XPersist +//------------------------------------------------------------------------------ +void OEditBaseModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OBoundControlModel::write(_rxOutStream); + + // Version + sal_uInt16 nVersionId = 0x0005; + DBG_ASSERT((getPersistenceFlags() & ~PF_SPECIAL_FLAGS) == 0, + "OEditBaseModel::write : invalid special version flags !"); + // please don't use other flags, older versions can't interpret them ! + + nVersionId |= getPersistenceFlags(); + _rxOutStream->writeShort(nVersionId); + + // Name + _rxOutStream->writeShort(0); // obsolete + _rxOutStream << m_aDefaultText; + + // Maskierung fuer any + sal_uInt16 nAnyMask = 0; + if (m_aDefault.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= DEFAULT_LONG; + else if (m_aDefault.getValueType().getTypeClass() == TypeClass_DOUBLE) + nAnyMask |= DEFAULT_DOUBLE; + + if (m_bFilterProposal) // da boolean, kein Wert speichern + nAnyMask |= FILTERPROPOSAL; + + _rxOutStream->writeBoolean(m_bEmptyIsNull); + _rxOutStream->writeShort(nAnyMask); + + if ((nAnyMask & DEFAULT_LONG) == DEFAULT_LONG) + _rxOutStream->writeLong(getINT32(m_aDefault)); + else if ((nAnyMask & DEFAULT_DOUBLE) == DEFAULT_DOUBLE) + _rxOutStream->writeDouble(getDouble(m_aDefault)); + + // since version 5 we write the help text + writeHelpTextCompatibly(_rxOutStream); + // (that's potentially bad : at the time I added the above line we had two derived classes : OEditModel and + // OFormattedModel. The first one does not have an own version handling, so it can't write the help text itself, + // the second one does it's own writing (reading) after calling our method, so normally we shouldn't write any + // additional members as this is not compatible to older office versions. + // We decided to place the writing of the help text here as it seems the less worse alternative. There is no delivered + // office version including formatted controls (and thus the OFormattedModel), and the OFormattedModel::read seems + // robust against this change (as it will read a wrong and unknown file version and thus set it's members to defaults). + + if ((nVersionId & PF_HANDLE_COMMON_PROPS) != 0) + writeCommonEditProperties(_rxOutStream); + + // !!! properties common to all OEditBaseModel derived classes should be written in writeCommonEditProperties !!! +} + +//------------------------------------------------------------------------------ +sal_uInt16 OEditBaseModel::getPersistenceFlags() const +{ + return PF_HANDLE_COMMON_PROPS; +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OBoundControlModel::read(_rxInStream); + ::osl::MutexGuard aGuard(m_aMutex); + + // Version eigene Versionsnummer + sal_uInt16 nVersion = _rxInStream->readShort(); + m_nLastReadVersion = nVersion; + + sal_Bool bHandleCommonProps = (nVersion & PF_HANDLE_COMMON_PROPS) != 0; + nVersion = nVersion & ~PF_SPECIAL_FLAGS; + + // obsolete + _rxInStream->readShort(); + + _rxInStream >> m_aDefaultText; + + if (nVersion >= 0x0003) + { + m_bEmptyIsNull = _rxInStream->readBoolean(); + + sal_uInt16 nAnyMask = _rxInStream->readShort(); + if ((nAnyMask & DEFAULT_LONG) == DEFAULT_LONG) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aDefault <<= (sal_Int32)nValue; + } + else if ((nAnyMask & DEFAULT_DOUBLE) == DEFAULT_DOUBLE) + { + double fValue = _rxInStream->readDouble(); + m_aDefault <<= (double)fValue; + } + + if ((nAnyMask & FILTERPROPOSAL) == FILTERPROPOSAL) + m_bFilterProposal = sal_True; + } + + if (nVersion > 4) + readHelpTextCompatibly(_rxInStream); + + if (bHandleCommonProps) + readCommonEditProperties(_rxInStream); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then) + resetNoBroadcast(); +}; + +//------------------------------------------------------------------------------ +void OEditBaseModel::defaultCommonEditProperties() +{ + OBoundControlModel::defaultCommonProperties(); + // no own common properties at the moment +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::readCommonEditProperties(const Reference<XObjectInputStream>& _rxInStream) +{ + sal_Int32 nLen = _rxInStream->readLong(); + + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // read properties common to all OBoundControlModels + OBoundControlModel::readCommonProperties(_rxInStream); + + // read properties common to all OEditBaseModels + + // skip the remaining bytes + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nLen); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::writeCommonEditProperties(const Reference<XObjectOutputStream>& _rxOutStream) +{ + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OEditBaseModel::writeCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // a placeholder where we will write the overall length (later in this method) + sal_Int32 nLen = 0; + _rxOutStream->writeLong(nLen); + + // write properties common to all OBoundControlModels + OBoundControlModel::writeCommonProperties(_rxOutStream); + + // write properties common to all OEditBaseModels + + // close the block - write the correct length at the beginning + nLen = xMark->offsetToMark(nMark) - sizeof(nLen); + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_EMPTY_IS_NULL: + rValue <<= (sal_Bool)m_bEmptyIsNull; + break; + case PROPERTY_ID_FILTERPROPOSAL: + rValue <<= (sal_Bool)m_bFilterProposal; + break; + case PROPERTY_ID_DEFAULT_TEXT: + rValue <<= m_aDefaultText; + break; + case PROPERTY_ID_DEFAULT_VALUE: + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + rValue = m_aDefault; + break; + default: + OBoundControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OEditBaseModel::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_EMPTY_IS_NULL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEmptyIsNull); + break; + case PROPERTY_ID_FILTERPROPOSAL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bFilterProposal); + break; + case PROPERTY_ID_DEFAULT_TEXT: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefaultText); + break; + case PROPERTY_ID_DEFAULT_VALUE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefault, ::getCppuType((const double*)0)); + break; + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefault, ::getCppuType((const sal_Int32*)0)); + break; + default: + bModified = OBoundControlModel::convertFastPropertyValue( + rConvertedValue, + rOldValue, + nHandle, + rValue); + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_EMPTY_IS_NULL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "invalid type" ); + m_bEmptyIsNull = getBOOL(rValue); + break; + case PROPERTY_ID_FILTERPROPOSAL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "invalid type" ); + m_bFilterProposal = getBOOL(rValue); + break; + // Aenderung der defaultwerte fuehrt zu reset + case PROPERTY_ID_DEFAULT_TEXT: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "invalid type" ); + rValue >>= m_aDefaultText; + resetNoBroadcast(); + break; + case PROPERTY_ID_DEFAULT_VALUE: + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + m_aDefault = rValue; + resetNoBroadcast(); + break; + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue ); + } +} + +//XPropertyState +//------------------------------------------------------------------------------ +Any OEditBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT: + return makeAny(::rtl::OUString()); + case PROPERTY_ID_FILTERPROPOSAL: + return Any(makeAny((sal_Bool)sal_False)); + case PROPERTY_ID_DEFAULT_VALUE: + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + return Any(); + default: + return OBoundControlModel::getPropertyDefaultByHandle(nHandle); + } +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/EditBase.hxx b/forms/source/component/EditBase.hxx new file mode 100644 index 000000000000..bfa51cb2d1ee --- /dev/null +++ b/forms/source/component/EditBase.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_EDITBASE_HXX_ +#define _FORMS_EDITBASE_HXX_ + +#include "FormComponent.hxx" +#include <tools/date.hxx> +#include <tools/link.hxx> +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XKeyListener.hpp> +#include <com/sun/star/form/XChangeBroadcaster.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> + +// persistence flags for use with the version id +#define PF_HANDLE_COMMON_PROPS 0x8000 + // Derived classes which use their own persistence methods (read/write) and have an own + // version handling therein may want to clear this flag in getPersistenceFlags. + // If done so, this class will write an version without a call to writeCommonEditProperties. +#define PF_FAKE_FORMATTED_FIELD 0x4000 + // .... hmmm .... a fake, as the name suggests. see OFormattedFieldWrapper +#define PF_RESERVED_2 0x2000 +#define PF_RESERVED_3 0x1000 +#define PF_RESERVED_4 0x0800 +#define PF_RESERVED_5 0x0400 +#define PF_RESERVED_6 0x0200 +#define PF_RESERVED_7 0x0100 + +#define PF_SPECIAL_FLAGS 0xFF00 + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OEditBaseModel +//================================================================== +class OEditBaseModel : public OBoundControlModel +{ + sal_Int16 m_nLastReadVersion; + +protected: +// [properties] fuer all Editierfelder + ::com::sun::star::uno::Any m_aDefault; + ::rtl::OUString m_aDefaultText; // default value + sal_Bool m_bEmptyIsNull : 1; // empty string will be interepreted as NULL when committing + sal_Bool m_bFilterProposal : 1; // use a list of possible value in filtermode +// [properties] + + sal_Int16 getLastReadVersion() const { return m_nLastReadVersion; } + +public: + DECLARE_DEFAULT_BOUND_XTOR( OEditBaseModel ); + + // XPersistObject + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + using ::cppu::OPropertySetHelper::getFastPropertyValue; + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + +protected: + // new properties common to all edit models should be handled with the following two methods + void SAL_CALL readCommonEditProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + void SAL_CALL writeCommonEditProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + void defaultCommonEditProperties(); + + virtual sal_uInt16 getPersistenceFlags() const; + // derived classes may use this if they want this base class to write additinal version flags + // (one of the PF_.... constants). After ::read they may ask for that flags with getLastReadVersion +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_EDITBASE_HXX_ + diff --git a/forms/source/component/EventThread.cxx b/forms/source/component/EventThread.cxx new file mode 100644 index 000000000000..504a180f6ee5 --- /dev/null +++ b/forms/source/component/EventThread.cxx @@ -0,0 +1,251 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "EventThread.hxx" +#include <comphelper/guarding.hxx> +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; + +DBG_NAME( OComponentEventThread ) +OComponentEventThread::OComponentEventThread( ::cppu::OComponentHelper* pCompImpl ) : + m_pCompImpl( pCompImpl ) +{ + DBG_CTOR( OComponentEventThread, NULL ); + + increment(m_refCount); + + // Eine Referenz des Controls halten + { + InterfaceRef xIFace(static_cast<XWeak*>(pCompImpl)); + query_interface(xIFace, m_xComp); + } + + // und uns an dem Control anmelden + { + Reference<XEventListener> xEvtLstnr = static_cast<XEventListener*>(this); + m_xComp->addEventListener( xEvtLstnr ); + } + + decrement(m_refCount); +} + +OComponentEventThread::~OComponentEventThread() +{ + DBG_DTOR( OComponentEventThread, NULL ); + + DBG_ASSERT( m_aEvents.size() == 0, + "OComponentEventThread::~OComponentEventThread: Kein dispose gerufen?" ); + + impl_clearEventQueue(); +} + +Any SAL_CALL OComponentEventThread::queryInterface(const Type& _rType) throw (RuntimeException) +{ + Any aReturn; + + aReturn = OWeakObject::queryInterface(_rType); + + if (!aReturn.hasValue()) + aReturn = ::cppu::queryInterface(_rType, + static_cast<XEventListener*>(this) + ); + + return aReturn; +} + +void OComponentEventThread::impl_clearEventQueue() +{ + while ( m_aEvents.size() ) + { + delete *m_aEvents.begin(); + m_aEvents.erase( m_aEvents.begin() ); + } + m_aControls.erase( m_aControls.begin(), m_aControls.end() ); + m_aFlags.erase( m_aFlags.begin(), m_aFlags.end() ); +} + +void OComponentEventThread::disposing( const EventObject& evt ) throw ( ::com::sun::star::uno::RuntimeException) +{ + if( evt.Source == m_xComp ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // Event-Listener abmelden + Reference<XEventListener> xEvtLstnr = static_cast<XEventListener*>(this); + m_xComp->removeEventListener( xEvtLstnr ); + + // Event-Queue loeschen + impl_clearEventQueue(); + + // Das Control loslassen und pCompImpl auf 0 setzen, damit der + // Thread weiss, dass er sich beenden soll. + m_xComp = 0; + m_pCompImpl = 0; + + // Den Thread aufwecken und beenden. + m_aCond.set(); + terminate(); + } +} + +void OComponentEventThread::addEvent( const EventObject* _pEvt, sal_Bool bFlag ) +{ + Reference<XControl> xTmp; + addEvent( _pEvt, xTmp, bFlag ); +} + +void OComponentEventThread::addEvent( const EventObject* _pEvt, + const Reference<XControl>& rControl, + sal_Bool bFlag ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + // Daten in die Queue stellen + m_aEvents.push_back( cloneEvent( _pEvt ) ); + + Reference<XWeak> xWeakControl(rControl, UNO_QUERY); + Reference<XAdapter> xControlAdapter = xWeakControl.is() ? xWeakControl->queryAdapter() : Reference<XAdapter>(); + m_aControls.push_back( xControlAdapter ); + + m_aFlags.push_back( bFlag ); + + // Thread aufwecken + m_aCond.set(); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:48:15 ----------------------------------------------- + +void OComponentEventThread::implStarted( ) +{ + acquire( ); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:48:16 ----------------------------------------------- + +void OComponentEventThread::implTerminated( ) +{ + release( ); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:47:31 ----------------------------------------------- + +void SAL_CALL OComponentEventThread::kill() +{ + OComponentEventThread_TBASE::kill(); + + implTerminated( ); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:47:33 ----------------------------------------------- + +void SAL_CALL OComponentEventThread::onTerminated() +{ + OComponentEventThread_TBASE::onTerminated(); + + implTerminated( ); +} + +void OComponentEventThread::run() +{ + implStarted( ); + + // uns selbst festhalten, damit wir nicht geloescht werden, + // wenn zwischendrinne mal ein dispose gerufen wird. + InterfaceRef xThis(static_cast<XWeak*>(this)); + + do + { + ::osl::MutexGuard aGuard(m_aMutex); + + while( m_aEvents.size() > 0 ) + { + // Das Control holen und festhalten, damit es waehrend des + // actionPerformed nicht geloescht werden kann. + Reference<XComponent> xComp = m_xComp; + ::cppu::OComponentHelper *pCompImpl = m_pCompImpl; + + ThreadEvents::iterator firstEvent( m_aEvents.begin() ); + EventObject* pEvt = *firstEvent; + m_aEvents.erase( firstEvent ); + + ThreadObjects::iterator firstControl( m_aControls.begin() ); + Reference<XAdapter> xControlAdapter = *firstControl; + m_aControls.erase( firstControl ); + + ThreadBools::iterator firstFlag( m_aFlags.begin() ); + sal_Bool bFlag = *firstFlag; + m_aFlags.erase( firstFlag ); + + { + MutexRelease aReleaseOnce(m_aMutex); + // Weil ein queryHardRef eine Exception schmeissen kann sollte + // es nicht bei gelocktem Mutex aufgerufen werden. + Reference<XControl> xControl; + if ( xControlAdapter.is() ) + query_interface(xControlAdapter->queryAdapted(), xControl); + + if( xComp.is() ) + processEvent( pCompImpl, pEvt, xControl, bFlag ); + } + + delete pEvt; + }; + + // Nach einem dispose kennen wir das Control nicht mehr. Dann darf + // auch nicht gewartet werden. + if( !m_xComp.is() ) + return; + + // Warte-Bedingung zuruecksetzen + m_aCond.reset(); + { + MutexRelease aReleaseOnce(m_aMutex); + // und warten ... falls nicht zwischenzeitlich doch noch ein + // Event eingetroffen ist. + m_aCond.wait(); + } + } + while( sal_True ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/EventThread.hxx b/forms/source/component/EventThread.hxx new file mode 100644 index 000000000000..b36743f85b47 --- /dev/null +++ b/forms/source/component/EventThread.hxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_EVENT_THREAD_HXX_ +#define _FRM_EVENT_THREAD_HXX_ + +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <vos/thread.hxx> + + +#include <osl/conditn.hxx> +#include <cppuhelper/component.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/uno3.hxx> +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + +// *************************************************************************************************** +// *************************************************************************************************** + +typedef ::vos::OThread OComponentEventThread_TBASE; +class OComponentEventThread + :public OComponentEventThread_TBASE + ,public ::com::sun::star::lang::XEventListener + ,public ::cppu::OWeakObject +{ + DECLARE_STL_VECTOR(::com::sun::star::lang::EventObject*, ThreadEvents); + DECLARE_STL_VECTOR(::com::sun::star::uno::Reference< ::com::sun::star::uno::XAdapter> , ThreadObjects); + DECLARE_STL_VECTOR(sal_Bool, ThreadBools); + + ::osl::Mutex m_aMutex; + ::osl::Condition m_aCond; // Queue gefuellt? + ThreadEvents m_aEvents; // Event-Queue + ThreadObjects m_aControls; // Control fuer Submit + ThreadBools m_aFlags; // Flags fuer Submit/Reset + + ::cppu::OComponentHelper* m_pCompImpl; // Implementierung des Controls + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> m_xComp; // ::com::sun::star::lang::XComponent des Controls + +protected: + + // XThread + virtual void SAL_CALL run(); + + virtual void SAL_CALL kill(); + virtual void SAL_CALL onTerminated(); + + // Die folgende Methode wird gerufen um das Event unter Beruecksichtigung + // seines Typs zu duplizieren. + virtual ::com::sun::star::lang::EventObject* cloneEvent(const ::com::sun::star::lang::EventObject* _pEvt) const = 0; + + // Ein Event bearbeiten. Der Mutex ist dabei nicht gelockt, pCompImpl + // bleibt aber in jedem Fall gueltig. Bei pEvt kann es sich auch um + // einen abgeleiteten Typ handeln, naemlich den, den cloneEvent + // zurueckgibt. rControl ist nur gesetzt, wenn beim addEvent ein + // Control uebergeben wurde. Da das Control nur als WeakRef gehalten + // wird kann es auch zwischenzeitlich verschwinden. + virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl, + const ::com::sun::star::lang::EventObject* _pEvt, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& _rControl, + sal_Bool _bFlag) = 0; + +public: + + // UNO Anbindung + DECLARE_UNO3_DEFAULTS(OComponentEventThread, OWeakObject); + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type& _rType) throw (::com::sun::star::uno::RuntimeException); + + OComponentEventThread(::cppu::OComponentHelper* pCompImpl); + virtual ~OComponentEventThread(); + + void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, sal_Bool bFlag = sal_False ); + void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rControl, + sal_Bool bFlag = sal_False ); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + +/* resolve ambiguity : both OWeakObject and OObject have these memory operators */ + void * SAL_CALL operator new( size_t size ) throw() { return OThread::operator new(size); } + void SAL_CALL operator delete( void * p ) throw() { OThread::operator delete(p); } + +private: + void implStarted( ); + void implTerminated( ); + + void impl_clearEventQueue(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_EVENT_THREAD_HXX_ + diff --git a/forms/source/component/File.cxx b/forms/source/component/File.cxx new file mode 100644 index 000000000000..d92386b26405 --- /dev/null +++ b/forms/source/component/File.cxx @@ -0,0 +1,307 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "File.hxx" + +#include <com/sun/star/form/FormComponentType.hpp> + +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/container.hxx> +#include <comphelper/basicio.hxx> +#include <comphelper/guarding.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFileControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFileControlModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OFileControlModel::_getTypes() +{ + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + { + // my base class + Sequence<Type> aBaseClassTypes = OControlModel::_getTypes(); + + Sequence<Type> aOwnTypes(1); + Type* pOwnTypes = aOwnTypes.getArray(); + pOwnTypes[0] = getCppuType((Reference<XReset>*)NULL); + + aTypes = concatSequences(aBaseClassTypes, aOwnTypes); + } + return aTypes; +} + + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OFileControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_FILECONTROL; + return aSupported; +} + +//------------------------------------------------------------------ +DBG_NAME( OFileControlModel ) +//------------------------------------------------------------------ +OFileControlModel::OFileControlModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, VCL_CONTROLMODEL_FILECONTROL) + ,m_aResetListeners(m_aMutex) +{ + DBG_CTOR( OFileControlModel, NULL ); + m_nClassId = FormComponentType::FILECONTROL; +} + +//------------------------------------------------------------------ +OFileControlModel::OFileControlModel( const OFileControlModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,m_aResetListeners( m_aMutex ) +{ + DBG_CTOR( OFileControlModel, NULL ); + + m_sDefaultValue = _pOriginal->m_sDefaultValue; +} + +//------------------------------------------------------------------ +OFileControlModel::~OFileControlModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + DBG_DTOR( OFileControlModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OFileControlModel ) + +//------------------------------------------------------------------------------ +Any SAL_CALL OFileControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OControlModel::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = ::cppu::queryInterface(_rType + ,static_cast<XReset*>(this) + ); + + return aReturn; +} + +// OComponentHelper +//----------------------------------------------------------------------------- +void OFileControlModel::disposing() +{ + OControlModel::disposing(); + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aResetListeners.disposeAndClear(aEvt); +} + +//------------------------------------------------------------------------------ +Any OFileControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + Any aReturn; + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_TEXT: + return makeAny( ::rtl::OUString() ); + } + return OControlModel::getPropertyDefaultByHandle( _nHandle ); +} + +//------------------------------------------------------------------------------ +void OFileControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT : rValue <<= m_sDefaultValue; break; + default: + OControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +void OFileControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OFileControlModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_sDefaultValue; + break; + default: + OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OFileControlModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sDefaultValue); + default: + return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +void OFileControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OControlModel ) + DECL_PROP1(DEFAULT_TEXT, ::rtl::OUString, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFileControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_FILECONTROL; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OFileControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::write(_rxOutStream); + + ::osl::MutexGuard aGuard(m_aMutex); + + // Version + _rxOutStream->writeShort(0x0002); + // Default-Wert + _rxOutStream << m_sDefaultValue; + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void OFileControlModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::read(_rxInStream); + ::osl::MutexGuard aGuard(m_aMutex); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + // Default-Wert + switch (nVersion) + { + case 1: + _rxInStream >> m_sDefaultValue; break; + case 2: + _rxInStream >> m_sDefaultValue; + readHelpTextCompatibly(_rxInStream); + break; + default: + DBG_ERROR("OFileControlModel::read : unknown version !"); + m_sDefaultValue = ::rtl::OUString(); + } + + // Nach dem Lesen die Defaultwerte anzeigen +// _reset(); +} + +//----------------------------------------------------------------------------- +void SAL_CALL OFileControlModel::reset() throw ( ::com::sun::star::uno::RuntimeException) +{ + ::cppu::OInterfaceIteratorHelper aIter(m_aResetListeners); + EventObject aEvt(static_cast<XWeak*>(this)); + sal_Bool bContinue = sal_True; + while (aIter.hasMoreElements() && bContinue) + bContinue =((XResetListener*)aIter.next())->approveReset(aEvt); + + if (bContinue) + { + { + // Wenn Models threadSave + ::osl::MutexGuard aGuard(m_aMutex); + _reset(); + } + m_aResetListeners.notifyEach( &XResetListener::resetted, aEvt ); + } +} + +//----------------------------------------------------------------------------- +void OFileControlModel::addResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.addInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void OFileControlModel::removeResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void OFileControlModel::_reset() +{ + { // release our mutex once (it's acquired in the calling method !), as setting aggregate properties + // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with + // our own mutex locked + // FS - 72451 - 31.01.00 + MutexRelease aRelease(m_aMutex); + m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, makeAny(m_sDefaultValue)); + } +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/File.hxx b/forms/source/component/File.hxx new file mode 100644 index 000000000000..200cac5545ea --- /dev/null +++ b/forms/source/component/File.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_FILE_HXX_ +#define _FORMS_FILE_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OFileControlModel +//================================================================== +class OFileControlModel + :public OControlModel + ,public ::com::sun::star::form::XReset +{ + ::cppu::OInterfaceContainerHelper m_aResetListeners; + ::rtl::OUString m_sDefaultValue; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OFileControlModel ); + + DECLARE_UNO3_AGG_DEFAULTS(OFileControlModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OFileControlModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const; + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com ::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com ::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XReset + virtual void SAL_CALL reset() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + +protected: + virtual void _reset(); + + DECLARE_XCLONEABLE(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_FILE_HXX_ + diff --git a/forms/source/component/Filter.cxx b/forms/source/component/Filter.cxx new file mode 100644 index 000000000000..32d9ad54b4a4 --- /dev/null +++ b/forms/source/component/Filter.cxx @@ -0,0 +1,935 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "Filter.hxx" +#include "FormComponent.hxx" +#include "frm_module.hxx" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "property.hrc" +#include "property.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/VclWindowPeerAttribute.hpp> +#include <com/sun/star/awt/XCheckBox.hpp> +#include <com/sun/star/awt/XComboBox.hpp> +#include <com/sun/star/awt/XListBox.hpp> +#include <com/sun/star/awt/XRadioButton.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +/** === end UNO includes === **/ + +#include <comphelper/numbers.hxx> +#include <comphelper/property.hxx> +#include <connectivity/dbconversion.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/predicateinput.hxx> +#include <rtl/ustrbuf.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/localedatawrapper.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wintypes.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_OFilterControl() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::OFilterControl > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::ui::dialogs; + + using namespace ::connectivity; + + //===================================================================== + // OFilterControl + //===================================================================== + //--------------------------------------------------------------------- + OFilterControl::OFilterControl( const Reference< XMultiServiceFactory >& _rxORB ) + :m_aTextListeners( *this ) + ,m_xORB( _rxORB ) + ,m_aParser( _rxORB ) + ,m_nControlClass( FormComponentType::TEXTFIELD ) + ,m_bFilterList( sal_False ) + ,m_bMultiLine( sal_False ) + ,m_bFilterListFilled( sal_False ) + { + } + + //--------------------------------------------------------------------- + sal_Bool OFilterControl::ensureInitialized( ) + { + if ( !m_xField.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no field!" ); + return sal_False; + } + + if ( !m_xConnection.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no connection!" ); + return sal_False; + } + + if ( !m_xFormatter.is() ) + { + // we can create one from the connection, if it's an SDB connection + Reference< XNumberFormatsSupplier > xFormatSupplier = ::dbtools::getNumberFormats( m_xConnection, sal_True, m_xORB ); + + if ( xFormatSupplier.is() ) + { + m_xFormatter = m_xFormatter.query( + m_xORB->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.NumberFormatter" ) ) ) ); + if ( m_xFormatter.is() ) + m_xFormatter->attachNumberFormatsSupplier( xFormatSupplier ); + } + } + if ( !m_xFormatter.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: no number formatter!" ); + // no fallback anymore + return sal_False; + } + + return sal_True; + } + + //--------------------------------------------------------------------- + Any SAL_CALL OFilterControl::queryAggregation( const Type & rType ) throw(RuntimeException) + { + Any aRet = UnoControl::queryAggregation( rType); + if(!aRet.hasValue()) + aRet = OFilterControl_BASE::queryInterface(rType); + + return aRet; + } + + //------------------------------------------------------------------ + ::rtl::OUString OFilterControl::GetComponentServiceName() + { + ::rtl::OUString aServiceName; + switch (m_nControlClass) + { + case FormComponentType::RADIOBUTTON: + aServiceName = ::rtl::OUString::createFromAscii("radiobutton"); + break; + case FormComponentType::CHECKBOX: + aServiceName = ::rtl::OUString::createFromAscii("checkbox"); + break; + case FormComponentType::COMBOBOX: + aServiceName = ::rtl::OUString::createFromAscii("combobox"); + break; + case FormComponentType::LISTBOX: + aServiceName = ::rtl::OUString::createFromAscii("listbox"); + break; + default: + if (m_bMultiLine) + aServiceName = ::rtl::OUString::createFromAscii("MultiLineEdit"); + else + aServiceName = ::rtl::OUString::createFromAscii("Edit"); + } + return aServiceName; + } + + // XComponent + //--------------------------------------------------------------------- + void OFilterControl::dispose() throw( RuntimeException ) + { + EventObject aEvt(*this); + m_aTextListeners.disposeAndClear( aEvt ); + UnoControl::dispose(); + } + + //--------------------------------------------------------------------- + void OFilterControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException) + { + UnoControl::createPeer( rxToolkit, rParentPeer ); + + try + { + Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY_THROW ); + switch ( m_nControlClass ) + { + case FormComponentType::CHECKBOX: + { + // checkboxes always have a tristate-mode + xVclWindow->setProperty( PROPERTY_TRISTATE, makeAny( sal_Bool( sal_True ) ) ); + xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_DONTKNOW ) ) ); + + Reference< XCheckBox > xBox( getPeer(), UNO_QUERY_THROW ); + xBox->addItemListener( this ); + + } + break; + + case FormComponentType::RADIOBUTTON: + { + xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_NOCHECK ) ) ); + + Reference< XRadioButton > xRadio( getPeer(), UNO_QUERY_THROW ); + xRadio->addItemListener( this ); + } + break; + + case FormComponentType::LISTBOX: + { + Reference< XListBox > xListBox( getPeer(), UNO_QUERY_THROW ); + xListBox->addItemListener( this ); + } + // no break + + case FormComponentType::COMBOBOX: + { + xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( sal_Bool( sal_True ) ) ); + } + // no break + + default: + { + Reference< XWindow > xWindow( getPeer(), UNO_QUERY ); + xWindow->addFocusListener( this ); + + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setMaxTextLen(0); + } + break; + } + + OControl::initFormControlPeer( getPeer() ); + + // filter controls are _never_ readonly + // #107013# - 2002-02-03 - fs@openoffice.org + Reference< XPropertySet > xModel( getModel(), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW ); + if ( xModelPSI->hasPropertyByName( PROPERTY_READONLY ) ) + xVclWindow->setProperty( PROPERTY_READONLY, makeAny( sal_Bool( sal_False ) ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if (m_bFilterList) + m_bFilterListFilled = sal_False; + } + + //--------------------------------------------------------------------- + void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr ) + { + if (m_bFilterList) + rDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN; + } + + //--------------------------------------------------------------------- + void OFilterControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal ) + { + // these properties are ignored + if (rPropName == PROPERTY_TEXT || + rPropName == PROPERTY_STATE) + return; + + UnoControl::ImplSetPeerProperty( rPropName, rVal ); + } + + // XEventListener + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::disposing(const EventObject& Source) throw( RuntimeException ) + { + UnoControl::disposing(Source); + } + + // XItemListener + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent ) throw(RuntimeException) + { + ::rtl::OUStringBuffer aText; + switch (m_nControlClass) + { + case FormComponentType::CHECKBOX: + { + if ( ( rEvent.Selected == STATE_CHECK ) || ( rEvent.Selected == STATE_NOCHECK ) ) + { + sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( m_xConnection ).getBooleanComparisonMode(); + + bool bSelected = ( rEvent.Selected == STATE_CHECK ); + + ::rtl::OUString sExpressionMarker( RTL_CONSTASCII_USTRINGPARAM( "$expression$" ) ); + ::dbtools::getBoleanComparisonPredicate( + sExpressionMarker, + bSelected, + nBooleanComparisonMode, + aText + ); + + ::rtl::OUString sText( aText.makeStringAndClear() ); + sal_Int32 nMarkerPos( sText.indexOf( sExpressionMarker ) ); + OSL_ENSURE( nMarkerPos == 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" ); + // If this assertion fails, then getBoleanComparisonPredicate created a predicate which + // does not start with the expression we gave it. The only known case is when + // the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case, + // the expression is rather complex. + // Well, so this is a known issue - the filter controls (and thus the form based filter) + // do not work with boolean MS Access fields. + // To fix this, we would probably have to revert here to always return "1" or "0" as normalized + // filter, and change our client code to properly translate this (which could be some effort). + if ( nMarkerPos == 0 ) + aText.append( sText.copy( sExpressionMarker.getLength() ) ); + else + { + // fallback + aText.appendAscii( bSelected ? "1" : "0" ); + } + } + } + break; + + case FormComponentType::LISTBOX: + { + Sequence< ::rtl::OUString> aValueSelection; + Reference< XPropertySet > aPropertyPointer(getModel(), UNO_QUERY); + aPropertyPointer->getPropertyValue(PROPERTY_VALUE_SEQ) >>= aValueSelection; + if (rEvent.Selected <= aValueSelection.getLength()) + aText.append( aValueSelection[ rEvent.Selected ] ); + } + break; + + case FormComponentType::RADIOBUTTON: + { + if ( rEvent.Selected == STATE_CHECK ) + aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY )->getPropertyValue( PROPERTY_REFVALUE ) ) ); + } + break; + } + + ::rtl::OUString sText( aText.makeStringAndClear() ); + if ( m_aText.compareTo( sText ) ) + { + m_aText = sText; + TextEvent aEvt; + aEvt.Source = *this; + ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners ); + while( aIt.hasMoreElements() ) + ((XTextListener *)aIt.next())->textChanged( aEvt ); + } + } + + //--------------------------------------------------------------------- + void OFilterControl::implInitFilterList() + { + if ( !ensureInitialized( ) ) + // already asserted in ensureInitialized + return; + + // declare here for later disposal + Reference< XResultSet > xListCursor; + Reference< XStatement > xStatement; + + try + { + m_bFilterListFilled = sal_True; + + Reference< XPropertySet > xSet(getModel(), UNO_QUERY); + if (xSet.is() && m_xField.is()) + { + ::rtl::OUString sName; + m_xField->getPropertyValue(PROPERTY_NAME) >>= sName; + + // here we need a table to which the field belongs to + Reference< XChild > xModelAsChild( xSet, UNO_QUERY ); + Reference< XRowSet > xForm( xModelAsChild->getParent(), UNO_QUERY ); + Reference< XPropertySet > xFormAsSet( xForm, UNO_QUERY ); + + // Connection holen + Reference< XConnection > xConnection; + if ( xForm.is() ) + xConnection = ::dbtools::getConnection( xForm ); + Reference< XSQLQueryComposerFactory > xFactory( xConnection, UNO_QUERY ); + OSL_ENSURE( xFactory.is() && xFormAsSet.is(), "OFilterControl::implInitFilterList: invalid form or invalid connection!" ); + if ( !xFactory.is() || !xFormAsSet.is() ) + return; + + // create a query composer + Reference< XSQLQueryComposer > xComposer = xFactory->createQueryComposer(); + OSL_ENSURE( xComposer.is() , "OFilterControl::implInitFilterList: invalid query composer!" ); + if ( !xComposer.is() ) + return; + + // set the statement on the composer, ... + ::rtl::OUString sStatement; + xFormAsSet->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sStatement; + xComposer->setQuery( sStatement ); + + // ... and ask it for the involved tables and queries + Reference< XTablesSupplier > xSuppTables( xComposer, UNO_QUERY ); + Reference< XColumnsSupplier > xSuppColumns( xComposer, UNO_QUERY ); + + Reference< XNameAccess > xFieldNames; + if ( xSuppColumns.is() ) xFieldNames = xSuppColumns->getColumns(); + Reference< XNameAccess > xTablesNames; + if ( xSuppTables.is() ) xTablesNames = xSuppTables->getTables(); + + if ( !xFieldNames.is() || !xTablesNames.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::implInitFilterList: invalid query composer (no fields or no tables supplied)!" ); + return; + } + + // search the field + Reference< XPropertySet > xComposerFieldAsSet; + if ( xFieldNames->hasByName( sName ) ) + xFieldNames->getByName( sName ) >>= xComposerFieldAsSet; + + if ( xComposerFieldAsSet.is() + && ::comphelper::hasProperty( PROPERTY_TABLENAME, xComposerFieldAsSet ) + && ::comphelper::hasProperty( PROPERTY_REALNAME, xComposerFieldAsSet ) + ) + { + ::rtl::OUString sFieldName, sTableName; + xComposerFieldAsSet->getPropertyValue(PROPERTY_REALNAME) >>= sFieldName; + xComposerFieldAsSet->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + + // no possibility to create a select statement + // looking for the complete table name + if (!xTablesNames->hasByName(sTableName)) + return; + + // this is the tablename + Reference< XNamed > xName; + xTablesNames->getByName(sTableName) >>= xName; + OSL_ENSURE(xName.is(),"No XName interface!"); + sTableName = xName->getName(); + + // ein Statement aufbauen und abschicken als query + // Access to the connection + + Reference< XColumn > xDataField; + + Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData(); + ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString(); + ::rtl::OUStringBuffer aStatement; + aStatement.appendAscii( "SELECT DISTINCT " ); + aStatement.append( ::dbtools::quoteName( aQuote, sName ) ); + + if ( sFieldName.getLength() && ( sName != sFieldName ) ) + { + aStatement.appendAscii(" AS "); + aStatement.append( ::dbtools::quoteName(aQuote, sFieldName) ); + } + + aStatement.appendAscii( " FROM " ); + + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( xMeta, sTableName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + aStatement.append( ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) ); + + ::rtl::OUString sSelectStatement( aStatement.makeStringAndClear( ) ); + xStatement = xConnection->createStatement(); + xListCursor = xStatement->executeQuery( sSelectStatement ); + + Reference< XColumnsSupplier > xSupplyCols(xListCursor, UNO_QUERY); + Reference< XIndexAccess > xFields; + if (xSupplyCols.is()) + xFields = Reference< XIndexAccess > (xSupplyCols->getColumns(), UNO_QUERY); + if (xFields.is()) + xFields->getByIndex(0) >>= xDataField; + if (!xDataField.is()) + return; + + + sal_Int16 i = 0; + ::std::vector< ::rtl::OUString> aStringList; + aStringList.reserve(16); + ::rtl::OUString aStr; + + ::com::sun::star::util::Date aNullDate( ::dbtools::DBTypeConversion::getStandardDate() ); + sal_Int32 nFormatKey = 0; + try + { + m_xFormatter->getNumberFormatsSupplier()->getNumberFormatSettings()->getPropertyValue(::rtl::OUString::createFromAscii("NullDate")) + >>= aNullDate; + nFormatKey = ::comphelper::getINT32(m_xField->getPropertyValue(PROPERTY_FORMATKEY)); + } + catch(const Exception&) + { + } + + + sal_Int16 nKeyType = ::comphelper::getNumberFormatType(m_xFormatter->getNumberFormatsSupplier()->getNumberFormats(), nFormatKey); + while ( xListCursor->next() && ( i++ < SHRT_MAX) ) + { + aStr = ::dbtools::DBTypeConversion::getValue(xDataField, m_xFormatter, aNullDate, nFormatKey, nKeyType); + aStringList.push_back(aStr); + } + + Sequence< ::rtl::OUString> aStringSeq(aStringList.size()); + ::rtl::OUString* pustrStrings = aStringSeq.getArray(); + for (i = 0; i < (sal_Int16)aStringList.size(); ++i) + pustrStrings[i] = aStringList[i]; + + Reference< XComboBox > xComboBox( getPeer(), UNO_QUERY); + if ( xComboBox.is() ) + { + xComboBox->addItems(aStringSeq, 0); + // set the drop down line count + sal_Int16 nLineCount = ::std::min( (sal_Int16)10, (sal_Int16)aStringSeq.getLength() ); + xComboBox->setDropDownLineCount( nLineCount ); + } + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + ::comphelper::disposeComponent( xListCursor ); + ::comphelper::disposeComponent( xStatement ); + } + + // XFocusListener + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::focusGained(const FocusEvent& /*e*/) throw( RuntimeException ) + { + // should we fill the combobox? + if (m_bFilterList && !m_bFilterListFilled) + implInitFilterList(); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::focusLost(const FocusEvent& /*e*/) throw( RuntimeException ) + { + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OFilterControl::commit() throw(RuntimeException) + { + if ( !ensureInitialized( ) ) + // already asserted in ensureInitialized + return sal_True; + + ::rtl::OUString aText; + switch (m_nControlClass) + { + case FormComponentType::TEXTFIELD: + case FormComponentType::COMBOBOX: + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + aText = xText->getText(); + } break; + default: + return sal_True; + } + if (m_aText.compareTo(aText)) + { + // check the text with the SQL-Parser + ::rtl::OUString aNewText(aText); + aNewText.trim(); + if ( aNewText.getLength() ) + { + ::dbtools::OPredicateInputController aPredicateInput( m_xORB, m_xConnection, getParseContext() ); + ::rtl::OUString sErrorMessage; + if ( !aPredicateInput.normalizePredicateString( aNewText, m_xField, &sErrorMessage ) ) + { + // display the error and outta here + SQLContext aError; + aError.Message = String( FRM_RES_STRING( RID_STR_SYNTAXERROR ) ); + aError.Details = sErrorMessage; + displayException( aError ); + return sal_False; + } + } + + setText(aNewText); + TextEvent aEvt; + aEvt.Source = *this; + ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners ); + while( aIt.hasMoreElements() ) + static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt ); + } + return sal_True; + } + + // XTextComponent + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::addTextListener(const Reference< XTextListener > & l) throw(RuntimeException) + { + m_aTextListeners.addInterface( l ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::removeTextListener(const Reference< XTextListener > & l) throw(RuntimeException) + { + m_aTextListeners.removeInterface( l ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setText( const ::rtl::OUString& aText ) throw(RuntimeException) + { + if ( !ensureInitialized( ) ) + // already asserted in ensureInitialized + return; + + switch (m_nControlClass) + { + case FormComponentType::CHECKBOX: + { + Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY ); + if (xVclWindow.is()) + { + Any aValue; + if ( aText.equalsAscii( "1" ) + || aText.equalsIgnoreAsciiCaseAscii( "TRUE" ) + || aText.equalsIgnoreAsciiCaseAscii( "IS TRUE" ) + ) + { + aValue <<= (sal_Int32)STATE_CHECK; + } + else if ( aText.equalsAscii( "0" ) + || aText.equalsIgnoreAsciiCaseAscii( "FALSE" ) + ) + { + aValue <<= (sal_Int32)STATE_NOCHECK; + } + else + aValue <<= (sal_Int32)STATE_DONTKNOW; + + m_aText = aText; + xVclWindow->setProperty( PROPERTY_STATE, aValue ); + } + } break; + case FormComponentType::RADIOBUTTON: + { + Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY ); + if (xVclWindow.is()) + { + ::rtl::OUString aRefText = ::comphelper::getString(com::sun::star::uno::Reference< XPropertySet > (getModel(), UNO_QUERY)->getPropertyValue(PROPERTY_REFVALUE)); + Any aValue; + if (aText == aRefText) + aValue <<= (sal_Int32)STATE_CHECK; + else + aValue <<= (sal_Int32)STATE_NOCHECK; + m_aText = aText; + xVclWindow->setProperty(PROPERTY_STATE, aValue); + } + } break; + case FormComponentType::LISTBOX: + { + Reference< XListBox > xListBox( getPeer(), UNO_QUERY ); + if (xListBox.is()) + { + m_aText = aText; + xListBox->selectItem(m_aText, sal_True); + } + } break; + default: + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + { + m_aText = aText; + xText->setText(aText); + } + } + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + { + xText->insertText(rSel, aText); + m_aText = xText->getText(); + } + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getText() throw(RuntimeException) + { + return m_aText; + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getSelectedText( void ) throw(RuntimeException) + { + ::rtl::OUString aSelected; + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + aSelected = xText->getSelectedText(); + + return aSelected; + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setSelection( aSelection ); + } + + //--------------------------------------------------------------------- + ::com::sun::star::awt::Selection SAL_CALL OFilterControl::getSelection( void ) throw(::com::sun::star::uno::RuntimeException) + { + ::com::sun::star::awt::Selection aSel; + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + aSel = xText->getSelection(); + return aSel; + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OFilterControl::isEditable( void ) throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + return xText.is() && xText->isEditable(); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setEditable( sal_Bool bEditable ) throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setEditable(bEditable); + } + + //--------------------------------------------------------------------- + sal_Int16 SAL_CALL OFilterControl::getMaxTextLen() throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + return xText.is() ? xText->getMaxTextLen() : 0; + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setMaxTextLen( sal_Int16 nLength ) throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setMaxTextLen(nLength); + } + + //--------------------------------------------------------------------- + void OFilterControl::displayException( const ::com::sun::star::sdb::SQLContext& _rExcept ) + { + try + { + Sequence< Any > aArgs(2); + aArgs[0] <<= PropertyValue(::rtl::OUString::createFromAscii("SQLException"), 0, makeAny( _rExcept ), PropertyState_DIRECT_VALUE); + aArgs[1] <<= PropertyValue(::rtl::OUString::createFromAscii("ParentWindow"), 0, makeAny( m_xMessageParent ), PropertyState_DIRECT_VALUE); + + static ::rtl::OUString s_sDialogServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.sdb.ErrorMessageDialog" ); + Reference< XExecutableDialog > xErrorDialog( m_xORB->createInstanceWithArguments( s_sDialogServiceName, aArgs ), UNO_QUERY ); + if ( xErrorDialog.is() ) + xErrorDialog->execute(); + else + { + Window* pMessageParent = VCLUnoHelper::GetWindow( m_xMessageParent ); + ShowServiceNotAvailableError( pMessageParent, s_sDialogServiceName, sal_True ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "displayException: could not display the error message!" ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + const Any* pArguments = aArguments.getConstArray(); + const Any* pArgumentsEnd = pArguments + aArguments.getLength(); + + PropertyValue aProp; + NamedValue aValue; + const ::rtl::OUString* pName = NULL; + const Any* pValue = NULL; + + for ( ; pArguments != pArgumentsEnd; ++pArguments ) + { + // we recognize PropertyValues and NamedValues + if ( *pArguments >>= aProp ) + { + pName = &aProp.Name; + pValue = &aProp.Value; + } + else if ( *pArguments >>= aValue ) + { + pName = &aValue.Name; + pValue = &aValue.Value; + } + else + { + DBG_ERROR( "OFilterControl::initialize: unrecognized argument!" ); + continue; + } + + if ( 0 == pName->compareToAscii( "MessageParent" ) ) + { + // the message parent + *pValue >>= m_xMessageParent; + OSL_ENSURE( m_xMessageParent.is(), "OFilterControl::initialize: invalid MessageParent!" ); + } + else if ( 0 == pName->compareToAscii( "NumberFormatter" ) ) + { + // the number format. This argument is optional. + *pValue >>= m_xFormatter; + OSL_ENSURE( m_xFormatter.is(), "OFilterControl::initialize: invalid NumberFormatter!" ); + } + else if ( 0 == pName->compareToAscii( "ControlModel" ) ) + { + // the control model for which we act as filter control + Reference< XPropertySet > xControlModel; + if ( !(*pValue >>= xControlModel ) || !xControlModel.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::initialize: invalid control model argument!" ); + continue; + } + + // some properties which are "derived" from the control model we're working for + // ................................................... + // the field + m_xField.clear(); + OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ), "OFilterControl::initialize: control model needs a bound field property!" ); + xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= m_xField; + + // ................................................... + // filter list and control class + m_bFilterList = ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_FILTERPROPOSAL ) ); + if ( m_bFilterList ) + m_nControlClass = FormComponentType::COMBOBOX; + else + { + sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) ); + switch (nClassId) + { + case FormComponentType::CHECKBOX: + case FormComponentType::RADIOBUTTON: + case FormComponentType::LISTBOX: + case FormComponentType::COMBOBOX: + m_nControlClass = nClassId; + break; + default: + m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) ); + m_nControlClass = FormComponentType::TEXTFIELD; + break; + } + } + + // ................................................... + // the connection meta data for the form which we're working for + Reference< XChild > xModel( xControlModel, UNO_QUERY ); + Reference< XRowSet > xForm; + if ( xModel.is() ) + xForm = xForm.query( xModel->getParent() ); + m_xConnection = ::dbtools::getConnection( xForm ); + OSL_ENSURE( m_xConnection.is(), "OFilterControl::initialize: unable to determine the form's connection!" ); + } + } + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getImplementationName( ) throw (RuntimeException) + { + return getImplementationName_Static(); + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OFilterControl::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSupported.getConstArray(); + for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray ) + if( pArray->equals( ServiceName ) ) + return sal_True; + return sal_False; + } + + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_Static(); + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getImplementationName_Static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.OFilterControl" ) ); + } + + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames_Static() + { + Sequence< ::rtl::OUString > aNames( 2 ); + aNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.FilterControl" ) ); + aNames[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) ); + return aNames; + } + + //--------------------------------------------------------------------- + Reference< XInterface > SAL_CALL OFilterControl::Create( const Reference< XMultiServiceFactory >& _rxFactory ) + { + return static_cast< XServiceInfo* >( new OFilterControl( _rxFactory ) ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/Filter.hxx b/forms/source/component/Filter.hxx new file mode 100644 index 000000000000..84a778e07fd6 --- /dev/null +++ b/forms/source/component/Filter.hxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_COMPONENT_FILTER_HXX +#define FORMS_COMPONENT_FILTER_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/form/XBoundComponent.hpp> +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <toolkit/controls/unocontrol.hxx> + +#ifndef _TOOLKIT_AWT_LISTENERMULTIPLEXER_HXX_ +#include <toolkit/helper/listenermultiplexer.hxx> +#endif +#include <cppuhelper/implbase5.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/implbase4.hxx> +#include <connectivity/sqlparse.hxx> +#include <svx/ParseContext.hxx> + +class Window; + +//......................................................................... +namespace frm +{ +//......................................................................... + + //===================================================================== + // OFilterControl + //===================================================================== + typedef ::cppu::ImplHelper5 < ::com::sun::star::awt::XTextComponent + , ::com::sun::star::awt::XFocusListener + , ::com::sun::star::awt::XItemListener + , ::com::sun::star::form::XBoundComponent + , ::com::sun::star::lang::XInitialization + > OFilterControl_BASE; + + class OFilterControl :public UnoControl + ,public OFilterControl_BASE + ,public ::svxform::OParseContextClient + { + TextListenerMultiplexer m_aTextListeners; + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xORB; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xField; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > m_xFormatter; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xMessageParent; + + ::rtl::OUString m_aText; + ::connectivity::OSQLParser m_aParser; + sal_Int16 m_nControlClass; // which kind of control do we use? + sal_Bool m_bFilterList : 1; + sal_Bool m_bMultiLine : 1; + sal_Bool m_bFilterListFilled : 1; + + private: +// OFilterControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB); + + void implInitFilterList(); + + public: + OFilterControl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ); + + DECLARE_UNO3_AGG_DEFAULTS(OFilterControl,OWeakAggObject); + ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString GetComponentServiceName(); + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > & rxToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > & rParentPeer ) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::lang::XComponent + virtual void SAL_CALL dispose(void) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XTextComponent + virtual void SAL_CALL addTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setText( const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getText() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getSelectedText() throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::awt::Selection SAL_CALL getSelection() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL isEditable() throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setEditable( sal_Bool bEditable ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setMaxTextLen( sal_Int16 nLength ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL getMaxTextLen() throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::form::XBoundComponent + virtual void SAL_CALL addUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & /*l*/) throw( ::com::sun::star::uno::RuntimeException ) {} + virtual void SAL_CALL removeUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & /*l*/) throw( ::com::sun::star::uno::RuntimeException ) {} + virtual sal_Bool SAL_CALL commit() throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XFocusListener + virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XItemListener + virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& rEvent) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::util::XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + virtual void PrepareWindowDescriptor( ::com::sun::star::awt::WindowDescriptor& rDesc ); + virtual void ImplSetPeerProperty( const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rVal ); + + sal_Bool ensureInitialized( ); + + void displayException( const ::com::sun::star::sdb::SQLContext& _rExcept ); + }; +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_COMPONENT_FILTER_HXX diff --git a/forms/source/component/FixedText.cxx b/forms/source/component/FixedText.cxx new file mode 100644 index 000000000000..9396e7aabb59 --- /dev/null +++ b/forms/source/component/FixedText.cxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "FixedText.hxx" +#include "services.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "property.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OFixedTextModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OFixedTextModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OFixedTextModel ) +//------------------------------------------------------------------ +OFixedTextModel::OFixedTextModel( const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel(_rxFactory, VCL_CONTROLMODEL_FIXEDTEXT) + +{ + DBG_CTOR( OFixedTextModel, NULL ); + m_nClassId = FormComponentType::FIXEDTEXT; +} + +//------------------------------------------------------------------ +OFixedTextModel::OFixedTextModel( const OFixedTextModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + +{ + DBG_CTOR( OFixedTextModel, NULL ); +} + +//------------------------------------------------------------------ +OFixedTextModel::~OFixedTextModel( ) +{ + DBG_DTOR( OFixedTextModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OFixedTextModel ) + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OFixedTextModel::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_FIXEDTEXT; + return aSupported; +} + +//------------------------------------------------------------------------------ +void OFixedTextModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OControlModel::describeAggregateProperties( _rAggregateProps ); + RemoveProperty( _rAggregateProps, PROPERTY_TABSTOP ); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFixedTextModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_FIXEDTEXT; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OFixedTextModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + OControlModel::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0002); + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OFixedTextModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + OControlModel::read(_rxInStream); + + // Version + sal_Int16 nVersion = _rxInStream->readShort(); + if (nVersion > 1) + readHelpTextCompatibly(_rxInStream); +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/FixedText.hxx b/forms/source/component/FixedText.hxx new file mode 100644 index 000000000000..5adb15225702 --- /dev/null +++ b/forms/source/component/FixedText.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_FIXEDTEXT_HXX_ +#define _FORMS_FIXEDTEXT_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// OFixedTextModel +//================================================================== +class OFixedTextModel + :public OControlModel +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OFixedTextModel ); + +// XServiceInfo + IMPLEMENTATION_NAME(OFixedTextModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +// XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + DECLARE_XCLONEABLE(); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_FIXEDTEXT_HXX_ + diff --git a/forms/source/component/FormComponent.cxx b/forms/source/component/FormComponent.cxx new file mode 100644 index 000000000000..148e4c9aa298 --- /dev/null +++ b/forms/source/component/FormComponent.cxx @@ -0,0 +1,3116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "componenttools.hxx" +#include "FormComponent.hxx" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "property.hrc" +#include "services.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp> +#include <com/sun/star/sdb/XRowSetSupplier.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/guarding.hxx> +#include <comphelper/listenernotification.hxx> +#include <comphelper/property.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/logfile.hxx> +#include <toolkit/helper/emptyfontdescriptor.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <functional> +#include <algorithm> + +#include <functional> +#include <algorithm> + + +//... namespace frm ....................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + using namespace ::com::sun::star::form::validation; + using namespace ::dbtools; + using namespace ::comphelper; + + //========================================================================= + //= FieldChangeNotifier + //========================================================================= + //------------------------------------------------------------------------- + void ControlModelLock::impl_notifyAll_nothrow() + { + m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() ); + } + + //------------------------------------------------------------------------- + void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue ) + { + sal_Int32 nOldLength = m_aHandles.getLength(); + if ( ( nOldLength != m_aOldValues.getLength() ) + || ( nOldLength != m_aNewValues.getLength() ) + ) + throw RuntimeException( ::rtl::OUString(), m_rModel ); + + m_aHandles.realloc( nOldLength + 1 ); + m_aHandles[ nOldLength ] = _nHandle; + m_aOldValues.realloc( nOldLength + 1 ); + m_aOldValues[ nOldLength ] = _rOldValue; + m_aNewValues.realloc( nOldLength + 1 ); + m_aNewValues[ nOldLength ] = _rNewValue; + } + + //========================================================================= + //= FieldChangeNotifier + //========================================================================= + //------------------------------------------------------------------------- + class FieldChangeNotifier + { + public: + FieldChangeNotifier( ControlModelLock& _rLock ) + :m_rLock( _rLock ) + ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) ) + { + m_xOldField = m_rModel.getField(); + } + + ~FieldChangeNotifier() + { + Reference< XPropertySet > xNewField( m_rModel.getField() ); + if ( m_xOldField != xNewField ) + m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) ); + } + + private: + ControlModelLock& m_rLock; + OBoundControlModel& m_rModel; + Reference< XPropertySet > m_xOldField; + }; + +//============================================================================= +//= base class for form layer controls +//============================================================================= +DBG_NAME(frm_OControl) +//------------------------------------------------------------------------------ +OControl::OControl( const Reference< XMultiServiceFactory >& _rxFactory, const rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator ) + :OComponentHelper(m_aMutex) + ,m_aContext( _rxFactory ) +{ + DBG_CTOR(frm_OControl, NULL); + // VCL-Control aggregieren + // bei Aggregation den Refcount um eins erhoehen da im setDelegator + // das Aggregat selbst den Refcount erhoeht + increment( m_refCount ); + { + m_xAggregate = m_xAggregate.query( _rxFactory->createInstance( _rAggregateService ) ); + m_xControl = m_xControl.query( m_xAggregate ); + } + decrement( m_refCount ); + + if ( _bSetDelegator ) + doSetDelegator(); +} + +//------------------------------------------------------------------------------ +OControl::~OControl() +{ + DBG_DTOR(frm_OControl, NULL); + doResetDelegator(); +} + +//------------------------------------------------------------------------------ +void OControl::doResetDelegator() +{ + if ( m_xAggregate.is() ) + m_xAggregate->setDelegator( NULL ); +} + +//------------------------------------------------------------------------------ +void OControl::doSetDelegator() +{ + increment( m_refCount ); + if ( m_xAggregate.is() ) + { // those brackets are important for some compilers, don't remove! + // (they ensure that the temporary object created in the line below + // is destroyed *before* the refcount-decrement) + m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); + } + decrement( m_refCount ); +} + +// UNO Anbindung +//------------------------------------------------------------------------------ +Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException) +{ + // ask the base class + Any aReturn( OComponentHelper::queryAggregation(_rType) ); + // ask our own interfaces + if (!aReturn.hasValue()) + { + aReturn = OControl_BASE::queryInterface(_rType); + // ask our aggregate + if (!aReturn.hasValue() && m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + + return aReturn; +} + +//------------------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------------------ +Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException) +{ + TypeBag aTypes( _getTypes() ); + + Reference< XTypeProvider > xProv; + if ( query_aggregation( m_xAggregate, xProv ) ) + aTypes.addTypes( xProv->getTypes() ); + + return aTypes.getTypes(); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OControl::_getTypes() +{ + return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes(); +} + +//------------------------------------------------------------------------------ +void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ ) +{ + // nothing to do here +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OControl::disposing() +{ + OComponentHelper::disposing(); + + m_aWindowStateGuard.attach( NULL, NULL ); + + Reference< XComponent > xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->dispose(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::supportsService(const rtl::OUString& _rsServiceName) throw ( RuntimeException) +{ + Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); + const rtl::OUString* pSupported = aSupported.getConstArray(); + for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) + if (pSupported->equals(_rsServiceName)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OControl::getAggregateServiceNames() +{ + Sequence< ::rtl::OUString > aAggServices; + Reference< XServiceInfo > xInfo; + if ( query_aggregation( m_xAggregate, xInfo ) ) + aAggServices = xInfo->getSupportedServiceNames(); + return aAggServices; +} + +//------------------------------------------------------------------------------ +Sequence<rtl::OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException) +{ + return ::comphelper::concatSequences( + getAggregateServiceNames(), + getSupportedServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException ) +{ + // no own supported service names + return Sequence< ::rtl::OUString >(); +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException) +{ + InterfaceRef xAggAsIface; + query_aggregation(m_xAggregate, xAggAsIface); + + // does the disposing come from the aggregate ? + if (xAggAsIface != InterfaceRef(_rEvent.Source, UNO_QUERY)) + { // no -> forward it + Reference<com::sun::star::lang::XEventListener> xListener; + if (query_aggregation(m_xAggregate, xListener)) + xListener->disposing(_rEvent); + } +} + +// XControl +//------------------------------------------------------------------------------ +void SAL_CALL OControl::setContext(const InterfaceRef& Context) throw (RuntimeException) +{ + if (m_xControl.is()) + m_xControl->setContext(Context); +} + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OControl::getContext() throw (RuntimeException) +{ + return m_xControl.is() ? m_xControl->getContext() : InterfaceRef(); +} + +//------------------------------------------------------------------------------ +void OControl::impl_resetStateGuard_nothrow() +{ + Reference< XWindow2 > xWindow; + Reference< XControlModel > xModel; + try + { + xWindow.set( getPeer(), UNO_QUERY ); + xModel.set( getModel(), UNO_QUERY ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_aWindowStateGuard.attach( xWindow, xModel ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException) +{ + if ( m_xControl.is() ) + { + m_xControl->createPeer( _rxToolkit, _rxParent ); + + initFormControlPeer( getPeer() ); + + impl_resetStateGuard_nothrow(); + } +} + +//------------------------------------------------------------------------------ +Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException) +{ + if ( !m_xControl.is() ) + return sal_False; + + sal_Bool bSuccess = m_xControl->setModel( Model ); + impl_resetStateGuard_nothrow(); + return bSuccess; +} + +//------------------------------------------------------------------------------ +Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>(); +} + +//------------------------------------------------------------------------------ +Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->getView() : Reference<XView>(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException) +{ + if (m_xControl.is()) + m_xControl->setDesignMode(bOn); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->isDesignMode() : sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->isTransparent() : sal_True; +} + +//================================================================== +//= OBoundControl +//================================================================== +DBG_NAME(frm_OBoundControl); +//------------------------------------------------------------------ +OBoundControl::OBoundControl( const Reference< XMultiServiceFactory >& _rxFactory, + const ::rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator ) + :OControl( _rxFactory, _rAggregateService, _bSetDelegator ) + ,m_bLocked(sal_False) + ,m_aOriginalFont( EmptyFontDescriptor() ) + ,m_nOriginalTextLineColor( 0 ) +{ + DBG_CTOR(frm_OBoundControl, NULL); +} + +//------------------------------------------------------------------ +OBoundControl::~OBoundControl() +{ + DBG_DTOR(frm_OBoundControl, NULL); +} +// ----------------------------------------------------------------------------- +Sequence< Type> OBoundControl::_getTypes() +{ + return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes(); +} +//------------------------------------------------------------------ +Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn; + + // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types + if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) ) + aReturn = OControl::queryAggregation( _rType ); + + // ask our own interfaces + // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener) + if ( !aReturn.hasValue() ) + aReturn = OBoundControl_BASE::queryInterface( _rType ); + + // ask the base class + if ( !aReturn.hasValue() ) + aReturn = OControl::queryAggregation( _rType ); + + return aReturn; +} + +//------------------------------------------------------------------ +sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException) +{ + return m_bLocked; +} + +//------------------------------------------------------------------ +void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException) +{ + if (m_bLocked == _bLock) + return; + + osl::MutexGuard aGuard(m_aMutex); + _setLock(_bLock); + m_bLocked = _bLock; +} + +//------------------------------------------------------------------ +void OBoundControl::_setLock(sal_Bool _bLock) +{ + // try to set the text component to readonly + Reference< XWindowPeer > xPeer = getPeer(); + Reference< XTextComponent > xText( xPeer, UNO_QUERY ); + + if ( xText.is() ) + xText->setEditable( !_bLock ); + else + { + // disable the window + Reference< XWindow > xComp( xPeer, UNO_QUERY ); + if ( xComp.is() ) + xComp->setEnable( !_bLock ); + } +} + +//-------------------------------------------------------------------- +sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException) +{ + return OControl::setModel( _rxModel ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException) +{ + // just disambiguate + OControl::disposing(Source); +} + +//-------------------------------------------------------------------- +void OBoundControl::disposing() +{ + OControl::disposing(); +} + +//================================================================== +//= OControlModel +//================================================================== +DBG_NAME(OControlModel) +//------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getImplementationId" ); + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getTypes" ); + TypeBag aTypes( _getTypes() ); + + Reference< XTypeProvider > xProv; + if ( query_aggregation( m_xAggregate, xProv ) ) + aTypes.addTypes( xProv->getTypes() ); + + return aTypes.getTypes(); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OControlModel::_getTypes() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::_getTypes" ); + return TypeBag( OComponentHelper::getTypes(), + OPropertySetAggregationHelper::getTypes(), + OControlModel_BASE::getTypes() + ).getTypes(); +} + +//------------------------------------------------------------------ +Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::queryAggregation" ); + // base class 1 + Any aReturn(OComponentHelper::queryAggregation(_rType)); + + // base class 2 + if (!aReturn.hasValue()) + { + aReturn = OControlModel_BASE::queryInterface(_rType); + + // our own interfaces + if (!aReturn.hasValue()) + { + aReturn = OPropertySetAggregationHelper::queryInterface(_rType); + // our aggregate + if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL)))) + aReturn = m_xAggregate->queryAggregation(_rType); + } + } + return aReturn; +} + +//------------------------------------------------------------------------------ +void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::readHelpTextCompatibly" ); + ::rtl::OUString sHelpText; + ::comphelper::operator>>( _rxInStream, sHelpText); + try + { + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText)); + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!"); + } +} + +//------------------------------------------------------------------------------ +void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::writeHelpTextCompatibly" ); + ::rtl::OUString sHelpText; + try + { + if (m_xAggregateSet.is()) + m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText; + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!"); + } + ::comphelper::operator<<( _rxOutStream, sHelpText); +} + +//------------------------------------------------------------------ +OControlModel::OControlModel( + const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _rUnoControlModelTypeName, + const ::rtl::OUString& rDefault, const sal_Bool _bSetDelegator) + :OComponentHelper(m_aMutex) + ,OPropertySetAggregationHelper(OComponentHelper::rBHelper) + ,m_aContext( _rxFactory ) + ,m_lockCount( 0 ) + ,m_aPropertyBagHelper( *this ) + ,m_nTabIndex(FRM_DEFAULT_TABINDEX) + ,m_nClassId(FormComponentType::CONTROL) + ,m_bNativeLook( sal_False ) + // form controls are usually embedded into documents, not dialogs, and in documents + // the native look is ugly .... + // #i37342# / 2004-11-19 / frank.schoenheit@sun.com +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::OControlModel" ); + DBG_CTOR(OControlModel, NULL); + if (_rUnoControlModelTypeName.getLength()) // the is a model we have to aggregate + { + increment(m_refCount); + + { + m_xAggregate = Reference<XAggregation>(_rxFactory->createInstance(_rUnoControlModelTypeName), UNO_QUERY); + setAggregation(m_xAggregate); + + if ( m_xAggregateSet.is() ) + { + try + { + if ( rDefault.getLength() ) + m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlModel::OControlModel: caught an exception!" ); + } + } + } + + if (_bSetDelegator) + doSetDelegator(); + + // Refcount wieder bei NULL + decrement(m_refCount); + } +} + +//------------------------------------------------------------------ +OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator ) + :OComponentHelper( m_aMutex ) + ,OPropertySetAggregationHelper( OComponentHelper::rBHelper ) + ,m_aContext( _rxFactory ) + ,m_lockCount( 0 ) + ,m_aPropertyBagHelper( *this ) + ,m_nTabIndex( FRM_DEFAULT_TABINDEX ) + ,m_nClassId( FormComponentType::CONTROL ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::OControlModel(copy)" ); + DBG_CTOR( OControlModel, NULL ); + DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" ); + + // copy members + m_aName = _pOriginal->m_aName; + m_aTag = _pOriginal->m_aTag; + m_nTabIndex = _pOriginal->m_nTabIndex; + m_nClassId = _pOriginal->m_nClassId; + m_bNativeLook = _pOriginal->m_bNativeLook; + + if ( _bCloneAggregate ) + { + // temporarily increment refcount because of temporary references to ourself in the following + increment( m_refCount ); + + { + // transfer the (only, at the very moment!) ref count + m_xAggregate = createAggregateClone( _pOriginal ); + + // set aggregation (retrieve other direct interfaces of the aggregate) + setAggregation( m_xAggregate ); + } + + // set the delegator, if allowed by our derived class + if ( _bSetDelegator ) + doSetDelegator(); + + // decrement ref count + decrement( m_refCount ); + } +} + +//------------------------------------------------------------------ +OControlModel::~OControlModel() +{ + // release the aggregate + doResetDelegator( ); + + DBG_DTOR(OControlModel, NULL); +} + +//------------------------------------------------------------------ +void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::clonedFrom" ); + // nothing to do in this base class +} + +//------------------------------------------------------------------------------ +void OControlModel::doResetDelegator() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::doResetDelegator" ); + if (m_xAggregate.is()) + m_xAggregate->setDelegator(NULL); +} + +//------------------------------------------------------------------------------ +void OControlModel::doSetDelegator() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::doSetDelegator" ); + increment(m_refCount); + if (m_xAggregate.is()) + { + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); +} + +// XChild +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OControlModel::getParent() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getParent" ); + return m_xParent; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::setParent(const InterfaceRef& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setParent" ); + osl::MutexGuard aGuard(m_aMutex); + + Reference<XComponent> xComp(m_xParent, UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this)); + + m_xParent = _rxParent; + xComp = xComp.query( m_xParent ); + + if ( xComp.is() ) + xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this)); +} + +// XNamed +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OControlModel::getName() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getName" ); + ::rtl::OUString aReturn; + OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn; + return aReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::setName(const ::rtl::OUString& _rName) throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setName" ); + setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName)); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControlModel::supportsService(const rtl::OUString& _rServiceName) throw ( RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::supportsService" ); + Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); + const rtl::OUString* pSupported = aSupported.getConstArray(); + for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) + if (pSupported->equals(_rServiceName)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OControlModel::getAggregateServiceNames() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getAggregateServiceNames" ); + Sequence< ::rtl::OUString > aAggServices; + Reference< XServiceInfo > xInfo; + if ( query_aggregation( m_xAggregate, xInfo ) ) + aAggServices = xInfo->getSupportedServiceNames(); + return aAggServices; +} + +//------------------------------------------------------------------------------ +Sequence<rtl::OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames" ); + return ::comphelper::concatSequences( + getAggregateServiceNames(), + getSupportedServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames_Static" ); + Sequence< ::rtl::OUString > aServiceNames( 2 ); + aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT; + aServiceNames[ 1 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.FormControlModel" ); + return aServiceNames; +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" ); + // release the parent + if (_rSource.Source == m_xParent) + { + osl::MutexGuard aGuard(m_aMutex); + m_xParent = NULL; + } + else + { + Reference<com::sun::star::lang::XEventListener> xEvtLst; + if (query_aggregation(m_xAggregate, xEvtLst)) + { + osl::MutexGuard aGuard(m_aMutex); + xEvtLst->disposing(_rSource); + } + } +} + +// OComponentHelper +//----------------------------------------------------------------------------- +void OControlModel::disposing() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" ); + OPropertySetAggregationHelper::disposing(); + + Reference<com::sun::star::lang::XComponent> xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->dispose(); + + setParent(Reference<XFormComponent>()); + + m_aPropertyBagHelper.dispose(); +} + +//------------------------------------------------------------------------------ +void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::writeAggregate" ); + Reference< XPersistObject > xPersist; + if ( query_aggregation( m_xAggregate, xPersist ) ) + xPersist->write( _rxOutStream ); +} + +//------------------------------------------------------------------------------ +void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::readAggregate" ); + Reference< XPersistObject > xPersist; + if ( query_aggregation( m_xAggregate, xPersist ) ) + xPersist->read( _rxInStream ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) + throw(stario::IOException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::write" ); + osl::MutexGuard aGuard(m_aMutex); + + // 1. Schreiben des UnoControls + Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + if ( !xMark.is() ) + { + throw IOException( + FRM_RES_STRING( RID_STR_INVALIDSTREAM ), + static_cast< ::cppu::OWeakObject* >( this ) + ); + } + + sal_Int32 nMark = xMark->createMark(); + sal_Int32 nLen = 0; + + _rxOutStream->writeLong(nLen); + + writeAggregate( _rxOutStream ); + + // feststellen der Laenge + nLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + + // 2. Schreiben einer VersionsNummer + _rxOutStream->writeShort(0x0003); + + // 3. Schreiben der allgemeinen Properties + ::comphelper::operator<<( _rxOutStream, m_aName); + _rxOutStream->writeShort(m_nTabIndex); + ::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version + + // !!! IMPORTANT NOTE !!! + // don't write any new members here : this wouldn't be compatible with older versions, as OControlModel + // is a base class which is called in derived classes "read" method. So if you increment the version + // and write new stuff, older office versions will read this in the _derived_ classes, which may result + // in anything from data loss to crash. + // !!! EOIN !!! +} + +//------------------------------------------------------------------------------ +void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::read" ); + osl::MutexGuard aGuard(m_aMutex); + + Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY); + if ( !xMark.is() ) + { + throw IOException( + FRM_RES_STRING( RID_STR_INVALIDSTREAM ), + static_cast< ::cppu::OWeakObject* >( this ) + ); + } + + // 1. Lesen des UnoControls + sal_Int32 nLen = InStream->readLong(); + if (nLen) + { + sal_Int32 nMark = xMark->createMark(); + + try + { + readAggregate( InStream ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + xMark->jumpToMark(nMark); + InStream->skipBytes(nLen); + xMark->deleteMark(nMark); + } + + // 2. Lesen des Versionsnummer + UINT16 nVersion = InStream->readShort(); + + // 3. Lesen der allgemeinen Properties + ::comphelper::operator>>( InStream, m_aName); + m_nTabIndex = InStream->readShort(); + + if (nVersion > 0x0002) + ::comphelper::operator>>( InStream, m_aTag); + + // we had a version where we wrote the help text + if (nVersion == 0x0004) + readHelpTextCompatibly(InStream); + + DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !"); + // 4 was the version where we wrote the help text + // later versions shouldn't exist (see write for a detailed comment) +} + +//------------------------------------------------------------------------------ +PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyStateByHandle" ); + // simply compare the current and the default value + Any aCurrentValue = getPropertyDefaultByHandle( _nHandle ); + Any aDefaultValue; getFastPropertyValue( aDefaultValue, _nHandle ); + + sal_Bool bEqual = uno_type_equalData( + const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(), + const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) + ); + return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; +} + +//------------------------------------------------------------------------------ +void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setPropertyToDefaultByHandle" ); + Any aDefault = getPropertyDefaultByHandle( _nHandle ); + + Any aConvertedValue, aOldValue; + if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) ) + { + setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue ); + // TODO: fire the property change + } +} + +//------------------------------------------------------------------------------ +Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyDefaultByHandle" ); + Any aReturn; + switch ( _nHandle ) + { + case PROPERTY_ID_NAME: + case PROPERTY_ID_TAG: + aReturn <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_CLASSID: + aReturn <<= (sal_Int16)FormComponentType::CONTROL; + break; + + case PROPERTY_ID_TABINDEX: + aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX; + break; + + case PROPERTY_ID_NATIVE_LOOK: + aReturn <<= (sal_Bool)sal_True; + break; + + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn ); + else + OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" ); + } + return aReturn; +} + +//------------------------------------------------------------------------------ +void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getFastPropertyValue" ); + switch ( _nHandle ) + { + case PROPERTY_ID_NAME: + _rValue <<= m_aName; + break; + case PROPERTY_ID_TAG: + _rValue <<= m_aTag; + break; + case PROPERTY_ID_CLASSID: + _rValue <<= m_nClassId; + break; + case PROPERTY_ID_TABINDEX: + _rValue <<= m_nTabIndex; + break; + case PROPERTY_ID_NATIVE_LOOK: + _rValue <<= (sal_Bool)m_bNativeLook; + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue ); + else + OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle ); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool OControlModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (com::sun::star::lang::IllegalArgumentException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::convertFastPropertyValue" ); + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_NAME: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName); + break; + case PROPERTY_ID_TAG: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag); + break; + case PROPERTY_ID_TABINDEX: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex); + break; + case PROPERTY_ID_NATIVE_LOOK: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook); + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue ); + else + OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" ); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) + throw (Exception) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setFastPropertyValue_NoBroadcast" ); + switch (_nHandle) + { + case PROPERTY_ID_NAME: + DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL), + "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); + _rValue >>= m_aName; + break; + case PROPERTY_ID_TAG: + DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL), + "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); + _rValue >>= m_aTag; + break; + case PROPERTY_ID_TABINDEX: + DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL), + "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); + _rValue >>= m_nTabIndex; + break; + case PROPERTY_ID_NATIVE_LOOK: + OSL_VERIFY( _rValue >>= m_bNativeLook ); + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue ); + else + OSL_ENSURE( false, "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" ); + break; + } +} + +//------------------------------------------------------------------------------ +void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeFixedProperties" ); + BEGIN_DESCRIBE_BASE_PROPERTIES( 4 ) + DECL_PROP2 (CLASSID, sal_Int16, READONLY, TRANSIENT); + DECL_PROP1 (NAME, ::rtl::OUString, BOUND); + DECL_BOOL_PROP2 (NATIVE_LOOK, BOUND, TRANSIENT); + DECL_PROP1 (TAG, ::rtl::OUString, BOUND); + END_DESCRIBE_PROPERTIES() +} + +//------------------------------------------------------------------------------ +void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeAggregateProperties" ); + if ( m_xAggregateSet.is() ) + { + Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() ); + if ( xPSI.is() ) + _rAggregateProps = xPSI->getProperties(); + } +} + +//------------------------------------------------------------------------------ +::osl::Mutex& OControlModel::getMutex() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getMutex" ); + return m_aMutex; +} + +//------------------------------------------------------------------------------ +void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeFixedAndAggregateProperties" ); + describeFixedProperties( _out_rFixedProperties ); + describeAggregateProperties( _out_rAggregateProperties ); +} + +//------------------------------------------------------------------------------ +Reference< XMultiPropertySet > OControlModel::getPropertiesInterface() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertiesInterface" ); + return Reference< XMultiPropertySet >( *this, UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getInfoHelper" ); + return m_aPropertyBagHelper.getInfoHelper(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OControlModel::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::addProperty" ); + m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OControlModel::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::removeProperty" ); + m_aPropertyBagHelper.removeProperty( _rName ); +} + +//-------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyValues" ); + return m_aPropertyBagHelper.getPropertyValues(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setPropertyValues" ); + m_aPropertyBagHelper.setPropertyValues( _rProps ); +} + +//-------------------------------------------------------------------- +void OControlModel::lockInstance( LockAccess ) +{ + m_aMutex.acquire(); + osl_incrementInterlockedCount( &m_lockCount ); +} + +//-------------------------------------------------------------------- +oslInterlockedCount OControlModel::unlockInstance( LockAccess ) +{ + OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" ); + oslInterlockedCount lockCount = osl_decrementInterlockedCount( &m_lockCount ); + m_aMutex.release(); + return lockCount; +} + +//-------------------------------------------------------------------- +void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues, + const Sequence< Any >& _rNewValues, LockAccess ) +{ + OPropertySetHelper::fire( + const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(), + _rNewValues.getConstArray(), + _rOldValues.getConstArray(), + _rHandles.getLength(), + sal_False + ); +} + +//================================================================== +//= OBoundControlModel +//================================================================== +DBG_NAME(frm_OBoundControlModel); +//------------------------------------------------------------------ +Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn( OControlModel::queryAggregation(_rType) ); + if (!aReturn.hasValue()) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::queryAggregation" ); + aReturn = OBoundControlModel_BASE1::queryInterface(_rType); + + if ( !aReturn.hasValue() && m_bCommitable ) + aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType ); + + if ( !aReturn.hasValue() && m_bSupportsExternalBinding ) + aReturn = OBoundControlModel_BINDING::queryInterface( _rType ); + + if ( !aReturn.hasValue() && m_bSupportsValidation ) + aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType ); + } + + return aReturn; +} + +//------------------------------------------------------------------ +OBoundControlModel::OBoundControlModel( + const Reference< XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault, + const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation ) + :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False ) + ,OPropertyChangeListener( m_aMutex ) + ,m_xField() + ,m_xAmbientForm() + ,m_nValuePropertyAggregateHandle( -1 ) + ,m_nFieldType( DataType::OTHER ) + ,m_bValuePropertyMayBeVoid( false ) + ,m_aResetHelper( *this, m_aMutex ) + ,m_aUpdateListeners(m_aMutex) + ,m_aFormComponentListeners( m_aMutex ) + ,m_bInputRequired( sal_True ) + ,m_pAggPropMultiplexer( NULL ) + ,m_bFormListening( false ) + ,m_bLoaded(sal_False) + ,m_bRequired(sal_False) + ,m_bCommitable(_bCommitable) + ,m_bSupportsExternalBinding( _bSupportExternalBinding ) + ,m_bSupportsValidation( _bSupportsValidation ) + ,m_bForwardValueChanges(sal_True) + ,m_bTransferingValue( sal_False ) + ,m_bIsCurrentValueValid( sal_True ) + ,m_bBindingControlsRO( sal_False ) + ,m_bBindingControlsEnable( sal_False ) + ,m_eControlValueChangeInstigator( eOther ) + ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT) +{ + DBG_CTOR(frm_OBoundControlModel, NULL); + + // start property listening at the aggregate + implInitAggMultiplexer( ); +} + +//------------------------------------------------------------------ +OBoundControlModel::OBoundControlModel( + const OBoundControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory, sal_True, sal_False ) + ,OPropertyChangeListener( m_aMutex ) + ,m_xField() + ,m_xAmbientForm() + ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle ) + ,m_nFieldType( DataType::OTHER ) + ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid ) + ,m_aResetHelper( *this, m_aMutex ) + ,m_aUpdateListeners( m_aMutex ) + ,m_aFormComponentListeners( m_aMutex ) + ,m_xValidator( _pOriginal->m_xValidator ) + ,m_bInputRequired( sal_True ) + ,m_pAggPropMultiplexer( NULL ) + ,m_bFormListening( false ) + ,m_bLoaded( sal_False ) + ,m_bRequired( sal_False ) + ,m_bCommitable( _pOriginal->m_bCommitable ) + ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding ) + ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation ) + ,m_bForwardValueChanges( sal_True ) + ,m_bTransferingValue( sal_False ) + ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid ) + ,m_bBindingControlsRO( sal_False ) + ,m_bBindingControlsEnable( sal_False ) + ,m_eControlValueChangeInstigator( eOther ) +{ + DBG_CTOR(frm_OBoundControlModel, NULL); + + // start property listening at the aggregate + implInitAggMultiplexer( ); + + m_aLabelServiceName = _pOriginal->m_aLabelServiceName; + m_sValuePropertyName = _pOriginal->m_sValuePropertyName; + m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle; + m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid; + m_aValuePropertyType = _pOriginal->m_aValuePropertyType; + m_aControlSource = _pOriginal->m_aControlSource; + m_bInputRequired = _pOriginal->m_bInputRequired; + // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transfered. + // (the former should be clear - a clone of the object we're only referencing does not make sense) + // (the second would violate the restriction for label controls that they're part of the + // same form component hierarchy - we ourself are no part, yet, so we can't have a label control) + + // start listening for changes at the value property + implInitValuePropertyListening( ); +} + +//------------------------------------------------------------------ +OBoundControlModel::~OBoundControlModel() +{ + if ( !OComponentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + doResetDelegator( ); + + OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" ); + if ( m_pAggPropMultiplexer ) + { + m_pAggPropMultiplexer->dispose(); + m_pAggPropMultiplexer->release(); + m_pAggPropMultiplexer = NULL; + } + + DBG_DTOR(frm_OBoundControlModel, NULL); +} + +//------------------------------------------------------------------ +void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal ) +{ + const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal ); + // the value binding can be handled as if somebody called setValueBinding here + // By definition, bindings can be share between bindables + if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() ) + { + try + { + setValueBinding( pBoundOriginal->m_xExternalBinding ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::implInitAggMultiplexer( ) +{ + increment( m_refCount ); + if ( m_xAggregateSet.is() ) + { + m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, sal_False ); + m_pAggPropMultiplexer->acquire(); + } + decrement( m_refCount ); + + doSetDelegator(); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::implInitValuePropertyListening( ) const +{ + // start listening for changes at the value property + // There are three pre-requisites for this to be done: + // 1. We support external value bindings. In this case, the changes in the control value need to + // be propagated to the external binding immediately when they happen + // 2. We support external validation. In this case, we need to listen for changes in the value + // property, since we need to revalidate then. + // 3. We are not committable. In this case, changes in the control value need to be propagated + // to the database column immediately when they happen. + if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable ) + { + OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" ); + if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() ) + m_pAggPropMultiplexer->addProperty( m_sValuePropertyName ); + } +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::initValueProperty( const ::rtl::OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle ) +{ + OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle, + "OBoundControlModel::initValueProperty: already called before!" ); + OSL_ENSURE( _rValuePropertyName.getLength(), "OBoundControlModel::initValueProperty: invalid property name!" ); + OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" ); + + m_sValuePropertyName = _rValuePropertyName; + m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle ); + OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" ); + + if ( m_nValuePropertyAggregateHandle != -1 ) + { + Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW ); + Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName ); + m_aValuePropertyType = aValuePropDesc.Type; + m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0; + } + + // start listening for changes at the value property + implInitValuePropertyListening( ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::suspendValueListening( ) +{ + OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::suspendValueListening: don't have a value property!" ); + OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" ); + + if ( m_pAggPropMultiplexer ) + m_pAggPropMultiplexer->lock(); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::resumeValueListening( ) +{ + OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::resumeValueListening: don't have a value property!" ); + OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" ); + OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" ); + + if ( m_pAggPropMultiplexer ) + m_pAggPropMultiplexer->unlock(); +} + +//----------------------------------------------------------------------------- +Sequence< Type > OBoundControlModel::_getTypes() +{ + TypeBag aTypes( + OControlModel::_getTypes(), + OBoundControlModel_BASE1::getTypes() + ); + + if ( m_bCommitable ) + aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() ); + + if ( m_bSupportsExternalBinding ) + aTypes.addTypes( OBoundControlModel_BINDING::getTypes() ); + + if ( m_bSupportsValidation ) + aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() ); + + return aTypes.getTypes(); +} + +// OComponentHelper +//----------------------------------------------------------------------------- +void OBoundControlModel::disposing() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::_getTypes" ); + OControlModel::disposing(); + + ::osl::ClearableMutexGuard aGuard(m_aMutex); + + if ( m_pAggPropMultiplexer ) + m_pAggPropMultiplexer->dispose(); + + // notify all our listeners + com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) ); + m_aUpdateListeners.disposeAndClear( aEvt ); + m_aResetHelper.disposing(); + + // disconnect from our database column + // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify? + // The only more thing which it does is calling onDisconnectedDbColumn - could this + // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*. + if ( hasField() ) + { + getField()->removePropertyChangeListener( PROPERTY_VALUE, this ); + resetField(); + } + m_xCursor = NULL; + + Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY ); + if ( xComp.is() ) + xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) ); + + // disconnect from our external value binding + if ( hasExternalValueBinding() ) + disconnectExternalValueBinding(); + + // dito for the validator + if ( hasValidator() ) + disconnectValidator( ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException ) +{ + ControlModelLock aLock( *this ); + + OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName, + "OBoundControlModel::_propertyChanged: where did this come from (1)?" ); + OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(), + "OBoundControlModel::_propertyChanged: where did this come from (2)?" ); + + if ( _rEvt.PropertyName == m_sValuePropertyName ) + { // our control value changed + + if ( hasExternalValueBinding() ) + { // the control value changed, while we have an external value binding + // -> forward the value to it + if ( m_eControlValueChangeInstigator != eExternalBinding ) + transferControlValueToExternal( aLock ); + } + else if ( !m_bCommitable && m_xColumnUpdate.is() ) + { // the control value changed, while we are bound to a database column, + // but not committable (which means changes in the control have to be reflected to + // the underlying database column immediately) + // -> forward the value to the database column + if ( m_eControlValueChangeInstigator != eDbColumnBinding ) + commitControlValueToDbColumn( false ); + } + + // validate the new value + if ( m_bSupportsValidation ) + recheckValidity( true ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName ) +{ + OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" ); + OSL_ENSURE( _rPropertyName.getLength(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" ); + + if ( m_pAggPropMultiplexer && _rPropertyName.getLength() ) + { + m_pAggPropMultiplexer->addProperty( _rPropertyName ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::doFormListening( const bool _bStart ) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" ); + + if ( isFormListening() == _bStart ) + return; + + if ( m_xAmbientForm.is() ) + _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this ); + + Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY ); + if ( getParent().is() && !xParentLoadable.is() ) + { + // if our parent does not directly support the XLoadable interface, then it might support the + // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes + // broadcasted by the latter. + Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY ); + if ( xRowSetBroadcaster.is() ) + _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this ); + } + + m_bFormListening = _bStart && m_xAmbientForm.is(); +} + +// XChild +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + if ( getParent() == _rxParent ) + return; + + // disconnect from database column (which is controlled by parent, directly or indirectly) + if ( hasField() ) + impl_disconnectDatabaseColumn_noNotify(); + + // log off old listeners + if ( isFormListening() ) + doFormListening( false ); + + // actually set the new parent + OControlModel::setParent( _rxParent ); + + // a new parent means a new ambient form + impl_determineAmbientForm_nothrow(); + + if ( !hasExternalValueBinding() ) + { + // log on new listeners + doFormListening( true ); + + // re-connect to database column of the new parent + if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) + impl_connectDatabaseColumn_noNotify( false ); + } +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException) +{ + ControlModelLock aLock( *this ); + + if ( _rEvent.Source == getField() ) + { + resetField(); + } + else if ( _rEvent.Source == m_xLabelControl ) + { + Reference<XPropertySet> xOldValue = m_xLabelControl; + m_xLabelControl = NULL; + + // fire a propertyChanged (when we leave aLock's scope) + aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) ); + } + else if ( _rEvent.Source == m_xExternalBinding ) + { // *first* check for the external binding + disconnectExternalValueBinding( ); + } + else if ( _rEvent.Source == m_xValidator ) + { // *then* check for the validator. Reason is that bindings may also act as validator at the same + // time, in this case, the validator is automatically revoked when the binding is revoked + disconnectValidator( ); + } + else + OControlModel::disposing(_rEvent); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" ); + return ::comphelper::concatSequences( + getAggregateServiceNames(), + getSupportedServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > aOwnServiceNames( 1 ); + aOwnServiceNames[ 0 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.DataAwareControlModel" ); + + return ::comphelper::concatSequences( + OControlModel::getSupportedServiceNames_Static(), + aOwnServiceNames + ); +} + +// XPersist +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream ) throw(stario::IOException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames_Static" ); + OControlModel::write(_rxOutStream); + + osl::MutexGuard aGuard(m_aMutex); + + // Version + _rxOutStream->writeShort(0x0002); + + // Controlsource + ::comphelper::operator<<( _rxOutStream, m_aControlSource); + + // !!! IMPORTANT NOTE !!! + // don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel + // is a base class which is called in derived classes "read" method. So if you increment the version + // and write new stuff, older office versions will read this in the _derived_ classes, which may result + // in anything from data loss to crash. + // (use writeCommonProperties instead, this is called in derived classes write-method) + // !!! EOIN !!! + // FS - 68876 - 28.09.1999 +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::defaultCommonProperties() +{ + Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + m_xLabelControl = NULL; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream) +{ + sal_Int32 nLen = _rxInStream->readLong(); + + Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // read the reference to the label control + Reference<stario::XPersistObject> xPersist; + sal_Int32 nUsedFlag; + nUsedFlag = _rxInStream->readLong(); + if (nUsedFlag) + xPersist = _rxInStream->readObject(); + m_xLabelControl = m_xLabelControl.query( xPersist ); + Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY ); + if (xComp.is()) + xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + + // read any other new common properties here + + // skip the remaining bytes + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nLen); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream) +{ + Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // a placeholder where we will write the overall length (later in this method) + sal_Int32 nLen = 0; + _rxOutStream->writeLong(nLen); + + // write the reference to the label control + Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY); + sal_Int32 nUsedFlag = 0; + if (xPersist.is()) + nUsedFlag = 1; + _rxOutStream->writeLong(nUsedFlag); + if (xPersist.is()) + _rxOutStream->writeObject(xPersist); + + // write any other new common properties here + + // write the correct length at the beginning of the block + nLen = xMark->offsetToMark(nMark) - sizeof(nLen); + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream ) throw(stario::IOException, RuntimeException) +{ + OControlModel::read(_rxInStream); + + osl::MutexGuard aGuard(m_aMutex); + UINT16 nVersion = _rxInStream->readShort(); (void)nVersion; + ::comphelper::operator>>( _rxInStream, m_aControlSource); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OBoundControlModel::getFastPropertyValue" ); + switch (nHandle) + { + case PROPERTY_ID_INPUT_REQUIRED: + rValue <<= m_bInputRequired; + break; + case PROPERTY_ID_CONTROLSOURCEPROPERTY: + rValue <<= m_sValuePropertyName; + break; + case PROPERTY_ID_CONTROLSOURCE: + rValue <<= m_aControlSource; + break; + case PROPERTY_ID_BOUNDFIELD: + rValue <<= getField(); + break; + case PROPERTY_ID_CONTROLLABEL: + if (!m_xLabelControl.is()) + rValue.clear(); + else + rValue <<= m_xLabelControl; + break; + default: + OControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OBoundControlModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, + const Any& _rValue) + throw (com::sun::star::lang::IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_INPUT_REQUIRED: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired ); + break; + case PROPERTY_ID_CONTROLSOURCE: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource); + break; + case PROPERTY_ID_BOUNDFIELD: + DBG_ERROR( "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" ); + throw com::sun::star::lang::IllegalArgumentException(); + case PROPERTY_ID_CONTROLLABEL: + if (!_rValue.hasValue()) + { // property set to void + _rConvertedValue = Any(); + getFastPropertyValue(_rOldValue, _nHandle); + bModified = m_xLabelControl.is(); + } + else + { + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl); + if (!m_xLabelControl.is()) + // an empty interface is interpreted as VOID + _rOldValue.clear(); + } + break; + default: + bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + } + return bModified; +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::convertFastPropertyValue" ); + Any aDefault; + switch ( _nHandle ) + { + case PROPERTY_ID_INPUT_REQUIRED: + aDefault <<= sal_Bool( sal_True ); + break; + + case PROPERTY_ID_CONTROLSOURCE: + aDefault <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_CONTROLLABEL: + aDefault <<= Reference< XPropertySet >(); + break; + } + return aDefault; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_INPUT_REQUIRED: + OSL_VERIFY( rValue >>= m_bInputRequired ); + break; + case PROPERTY_ID_CONTROLSOURCE: + OSL_VERIFY( rValue >>= m_aControlSource ); + break; + case PROPERTY_ID_BOUNDFIELD: + DBG_ERROR("OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !"); + throw com::sun::star::lang::IllegalArgumentException(); + case PROPERTY_ID_CONTROLLABEL: + { + DBG_ASSERT(!rValue.hasValue() || (rValue.getValueType().getTypeClass() == TypeClass_INTERFACE), + "OBoundControlModel::setFastPropertyValue_NoBroadcast : invalid argument !"); + if (!rValue.hasValue()) + { // set property to "void" + Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + m_xLabelControl = NULL; + break; + } + + InterfaceRef xNewValue; + rValue >>= xNewValue; + + Reference<XControlModel> xAsModel(xNewValue, UNO_QUERY); + Reference<com::sun::star::lang::XServiceInfo> xAsServiceInfo(xNewValue, UNO_QUERY); + Reference<XPropertySet> xAsPropSet(xNewValue, UNO_QUERY); + Reference<XChild> xAsChild(xNewValue, UNO_QUERY); + if (!xAsModel.is() || !xAsServiceInfo.is() || !xAsPropSet.is() || !xAsChild.is()) + { + throw com::sun::star::lang::IllegalArgumentException(); + } + + if (!xAsServiceInfo->supportsService(m_aLabelServiceName)) + { + throw com::sun::star::lang::IllegalArgumentException(); + } + + // check if weself and the given model have a common anchestor (up to the forms collection) + Reference<XChild> xCont; + query_interface(static_cast<XWeak*>(this), xCont); + InterfaceRef xMyTopLevel = xCont->getParent(); + while (xMyTopLevel.is()) + { + Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY); + if (!xAsForm.is()) + // found my root + break; + + Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY); + xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : InterfaceRef(); + } + InterfaceRef xNewTopLevel = xAsChild->getParent(); + while (xNewTopLevel.is()) + { + Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY); + if (!xAsForm.is()) + break; + + Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY); + xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : InterfaceRef(); + } + if (xNewTopLevel != xMyTopLevel) + { + // the both objects don't belong to the same forms collection -> not acceptable + throw com::sun::star::lang::IllegalArgumentException(); + } + + m_xLabelControl = xAsPropSet; + Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); + if (xComp.is()) + xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + } + break; + default: + OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue ); + } +} + +// XPropertyChangeListener +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException) +{ + // if the DBColumn value changed, transfer it to the control + if ( evt.PropertyName.equals( PROPERTY_VALUE ) ) + { + OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database colum?" ); + osl::MutexGuard aGuard(m_aMutex); + if ( m_bForwardValueChanges && m_xColumn.is() ) + transferDbValueToControl(); + } + else + { + OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" ); + + // our binding has properties which can control properties of ourself + ::rtl::OUString sBindingControlledProperty; + bool bForwardToLabelControl = false; + if ( evt.PropertyName.equals( PROPERTY_READONLY ) ) + { + sBindingControlledProperty = PROPERTY_READONLY; + } + else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) ) + { + sBindingControlledProperty = PROPERTY_ENABLED; + bForwardToLabelControl = true; + } + else + return; + + try + { + setPropertyValue( sBindingControlledProperty, evt.NewValue ); + if ( bForwardToLabelControl && m_xLabelControl.is() ) + m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!" ); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + // disconnect from database column (which is controlled by parent, directly or indirectly) + if ( hasField() ) + impl_disconnectDatabaseColumn_noNotify(); + + // log off old listeners + if ( isFormListening() ) + doFormListening( false ); + + // determine the new ambient form + impl_determineAmbientForm_nothrow(); + + // log on new listeners + doFormListening( true ); + + // re-connect to database column if needed and possible + if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) + impl_connectDatabaseColumn_noNotify( false ); +} + +// XBoundComponent +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException) +{ + m_aUpdateListeners.addInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException) +{ + m_aUpdateListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + + OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " ); + if ( hasExternalValueBinding() ) + { + // in most cases, no action is required: For most derivees, we know the value property of + // our control (see initValueProperty), and when an external binding is active, we + // instantly forward all changes in this property to the external binding. + if ( !m_sValuePropertyName.getLength() ) + // but for those derivees which did not use this feature, we need an + // explicit transfer + transferControlValueToExternal( aLock ); + return sal_True; + } + + OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" ); + // we reach this only if we're not working with an external binding + + if ( !hasField() ) + return sal_True; + + ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners ); + EventObject aEvent; + aEvent.Source = static_cast< XWeak* >( this ); + sal_Bool bSuccess = sal_True; + + aLock.release(); + // >>>>>>>> ----- UNSAFE ----- >>>>>>>> + while (aIter.hasMoreElements() && bSuccess) + bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent ); + // <<<<<<<< ----- UNSAFE ----- <<<<<<<< + aLock.acquire(); + + if ( bSuccess ) + { + try + { + if ( m_xColumnUpdate.is() ) + bSuccess = commitControlValueToDbColumn( sal_False ); + } + catch(Exception&) + { + bSuccess = sal_False; + } + } + + if ( bSuccess ) + { + aLock.release(); + m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent ); + } + + return bSuccess; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::resetField() +{ + m_xColumnUpdate.clear(); + m_xColumn.clear(); + m_xField.clear(); + m_nFieldType = DataType::OTHER; +} + +//------------------------------------------------------------------------------ +sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" ); + + // wenn eine Verbindung zur Datenbank existiert + if (rForm.is() && getConnection(rForm).is()) + { + // Feld bestimmen und PropertyChangeListener + m_xCursor = rForm; + Reference<XPropertySet> xFieldCandidate; + + if (m_xCursor.is()) + { + Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY); + DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !"); + if (xColumnsSupplier.is()) + { + Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY); + if (xColumns.is() && xColumns->hasByName(m_aControlSource)) + { + OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate ); + } + } + } + + try + { + sal_Int32 nFieldType = DataType::OTHER; + if ( xFieldCandidate.is() ) + { + xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType; + if ( approveDbColumnType( nFieldType ) ) + impl_setField_noNotify( xFieldCandidate ); + } + else + impl_setField_noNotify( NULL ); + + if ( m_xField.is() ) + { + if( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) ) + { + m_nFieldType = nFieldType; + + // an wertaenderungen horchen + m_xField->addPropertyChangeListener( PROPERTY_VALUE, this ); + m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY ); + m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY ); + + INT32 nNullableFlag = ColumnValue::NO_NULLS; + m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag; + m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag); + // we're optimistic : in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability .... + } + else + { + OSL_ENSURE(sal_False, "OBoundControlModel::connectToField: property NAME not supported!"); + impl_setField_noNotify( NULL ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + resetField(); + } + } + return hasField(); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet ) +{ + // but only if the rowset if posisitioned on a valid record + if ( hasField() && _rxRowSet.is() ) + { + if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() ) + transferDbValueToControl(); + else + // reset the field if the row set is empty + // #i30661# / 2004-12-16 / frank.schoenheit@sun.com + resetNoBroadcast(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" ); + + if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY) + || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER) + || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT) + || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY) + || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/ + || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL)) + return sal_False; + + return sal_True; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::impl_determineAmbientForm_nothrow() +{ + Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() ); + + m_xAmbientForm.set( xParent, UNO_QUERY ); + if ( !m_xAmbientForm.is() ) + { + Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY ); + if ( xSupRowSet.is() ) + m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload ) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" ); + + // consistency checks + DBG_ASSERT( !( hasField() && !_bFromReload ), + "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" ); + (void)_bFromReload; + + Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY ); + OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" ); + if ( !xRowSet.is() ) + return; + + if ( !hasField() ) + { + // connect to the column + connectToField( xRowSet ); + } + + // now that we're connected (more or less, even if we did not find a column), + // we definately want to forward any potentially occuring value changes + m_bForwardValueChanges = sal_True; + + // let derived classes react on this new connection + m_bLoaded = sal_True; + onConnectedDbColumn( xRowSet ); + + // initially transfer the db column value to the control, if we successfully connected to a database column + if ( hasField() ) + initFromField( xRowSet ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify() +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" ); + + // let derived classes react on this + onDisconnectedDbColumn(); + + if ( hasField() ) + { + getField()->removePropertyChangeListener( PROPERTY_VALUE, this ); + resetField(); + } + + m_xCursor = NULL; + m_bLoaded = sal_False; +} + +//============================================================================== +// XLoadListener +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" ); + (void)_rEvent; + + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + impl_connectDatabaseColumn_noNotify( false ); +} + + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + osl::MutexGuard aGuard(m_aMutex); + m_bForwardValueChanges = sal_False; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + impl_disconnectDatabaseColumn_noNotify(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" ); + (void)_rEvent; + + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + impl_connectDatabaseColumn_noNotify( true ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator ) +{ + m_eControlValueChangeInstigator = _eInstigator; + doSetControlValue( _rValue ); + m_eControlValueChangeInstigator = eOther; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::doSetControlValue( const Any& _rValue ) +{ + OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(), + "OBoundControlModel::doSetControlValue: invalid aggregate !" ); + OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ), + "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" ); + + try + { + // release our mutex once (it's acquired in one of the the calling methods), as setting aggregate properties + // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with + // our own mutex locked + // #72451# / 2000-01-31 / frank.schoenheit@sun.com + MutexRelease aRelease( m_aMutex ); + if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() ) + { + m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue ); + } + else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() ) + { + m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::doSetControlValue: caught an exception!" ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onConnectedValidator( ) +{ + try + { + // if we have an external validator, we do not want the control to force invalid + // inputs to the default value. Instead, invalid inputs should be translated + // to NaN (not a number) + Reference< XPropertySetInfo > xAggregatePropertyInfo; + if ( m_xAggregateSet.is() ) + xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo(); + if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) ) + m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" ); + } + recheckValidity( false ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onDisconnectedValidator( ) +{ + try + { + Reference< XPropertySetInfo > xAggregatePropertyInfo; + if ( m_xAggregateSet.is() ) + xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo(); + if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) ) + m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" ); + } + recheckValidity( false ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onConnectedExternalValue( ) +{ + calculateExternalValueType(); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onDisconnectedExternalValue( ) +{ +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ ) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onDisconnectedDbColumn() +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" ); +} + +// XReset +//----------------------------------------------------------------------------- +Any OBoundControlModel::getDefaultForReset() const +{ + return Any(); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::resetNoBroadcast() +{ + setControlValue( getDefaultForReset(), eOther ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException) +{ + m_aResetHelper.addResetListener( l ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException) +{ + m_aResetHelper.removeResetListener( l ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::reset() throw (RuntimeException) +{ + if ( !m_aResetHelper.approveReset() ) + return; + + ControlModelLock aLock( *this ); + + // on a new record? + sal_Bool bIsNewRecord = sal_False; + Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY ); + if ( xSet.is() ) + { + try + { + xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // cursor on an invalid row? + sal_Bool bInvalidCursorPosition = sal_True; + try + { + bInvalidCursorPosition = m_xCursor.is() + && ( m_xCursor->isAfterLast() + || m_xCursor->isBeforeFirst() + ) + && !bIsNewRecord; + } + catch( const SQLException& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::reset: caught an SQL exception!" ); + } + // don't count the insert row as "invalid" + // @since #i24495# + // @date 2004-05-14 + // @author fs@openoffice.org + + sal_Bool bSimpleReset = + ( !m_xColumn.is() // no connection to a database column + || ( m_xCursor.is() // OR we have an improperly positioned cursor + && bInvalidCursorPosition + ) + || hasExternalValueBinding() // OR we have an external value binding + ); + + if ( !bSimpleReset ) + { + // The default values will be set if and only if the current value of the field which we're bound + // to is NULL. + // Else, the current field value should be refreshed + // This behaviour is not completely ... "matured": What should happen if the field as well as the + // control have a default value? + + sal_Bool bIsNull = sal_True; + // we have to access the field content at least once to get a reliable result by XColumn::wasNull + try + { + // normally, we'd do a getString here. However, this is extremely expensive in the case + // of binary fields. Unfortunately, getString is the only method which is guaranteed + // to *always* succeed, all other getXXX methods may fail if the column is asked for a + // non-convertible type + sal_Int32 nFieldType = DataType::OBJECT; + getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType; + if ( ( nFieldType == DataType::BINARY ) + || ( nFieldType == DataType::VARBINARY ) + || ( nFieldType == DataType::LONGVARBINARY ) + || ( nFieldType == DataType::OBJECT ) + /*|| ( nFieldType == DataType::CLOB )*/ + ) + m_xColumn->getBinaryStream(); + else if ( nFieldType == DataType::BLOB ) + m_xColumn->getBlob(); + else + m_xColumn->getString(); + + bIsNull = m_xColumn->wasNull(); + } + catch(Exception&) + { + DBG_ERROR("OBoundControlModel::reset: this should have succeeded in all cases!"); + } + + sal_Bool bNeedValueTransfer = sal_True; + + if ( bIsNull ) + { + if ( bIsNewRecord ) + { + // reset the control to it's default + resetNoBroadcast(); + // and immediately commit the changes to the DB column, to keep consistency + commitControlValueToDbColumn( sal_True ); + + bNeedValueTransfer = sal_False; + } + } + + if ( bNeedValueTransfer ) + transferDbValueToControl(); + } + else + { + resetNoBroadcast(); + + // transfer to the external binding, if necessary + if ( hasExternalValueBinding() ) + transferControlValueToExternal( aLock ); + } + + // revalidate, if necessary + if ( hasValidator() ) + recheckValidity( true ); + + aLock.release(); + + m_aResetHelper.notifyResetted(); +} + +// ----------------------------------------------------------------------------- +void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField ) +{ + DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" ); + m_xField = _rxField; +} + +//-------------------------------------------------------------------- +sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding ) +{ + if ( !_rxBinding.is() ) + return sal_False; + + Sequence< Type > aTypeCandidates; + { + // SYNCHRONIZED --> + ::osl::MutexGuard aGuard( m_aMutex ); + aTypeCandidates = getSupportedBindingTypes(); + // <-- SYNCHRONIZED + } + + for ( const Type* pType = aTypeCandidates.getConstArray(); + pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength(); + ++pType + ) + { + if ( _rxBinding->supportsType( *pType ) ) + return sal_True; + } + + return sal_False; +} + +//-------------------------------------------------------------------- +void OBoundControlModel::connectExternalValueBinding( + const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock ) +{ + OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" ); + OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" ); + + // if we're connected to a database column, suspend this + if ( hasField() ) + impl_disconnectDatabaseColumn_noNotify(); + + // suspend listening for load-related events at out ambient form. + // This is because an external value binding overrules a possible database binding. + if ( isFormListening() ) + doFormListening( false ); + + // remember this new binding + m_xExternalBinding = _rxBinding; + + // tell the derivee + onConnectedExternalValue(); + + try + { + // add as value listener so we get notified when the value changes + Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY ); + if ( xModifiable.is() ) + xModifiable->addModifyListener( this ); + + // add as property change listener for some (possibly present) properties we're + // interested in + Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY ); + Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() ); + if ( xBindingPropsInfo.is() ) + { + if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) ) + { + xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this ); + m_bBindingControlsRO = sal_True; + } + if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) ) + { + xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this ); + m_bBindingControlsEnable = sal_True; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // propagate our new value + transferExternalValueToControl( _rInstanceLock ); + + // if the binding is also a validator, use it, too. This is a constraint of the + // com.sun.star.form.binding.ValidatableBindableFormComponent service + if ( m_bSupportsValidation ) + { + try + { + Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY ); + if ( xAsValidator.is() ) + setValidator( xAsValidator ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//-------------------------------------------------------------------- +void OBoundControlModel::disconnectExternalValueBinding( ) +{ + try + { + // not listening at the binding anymore + Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY ); + if ( xModifiable.is() ) + xModifiable->removeModifyListener( this ); + + // remove as property change listener + Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY ); + if ( m_bBindingControlsRO ) + xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this ); + if ( m_bBindingControlsEnable ) + xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::disconnectExternalValueBinding: caught an exception!" ); + } + + // if the binding also acts as our validator, disconnect the validator, too + if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() ) + disconnectValidator( ); + + // no binding anymore + m_xExternalBinding.clear(); + + // be a load listener at our form, again. This was suspended while we had + // an external value binding in place. + doFormListening( true ); + + // re-connect to database column of the new parent + if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) + impl_connectDatabaseColumn_noNotify( false ); + + // tell the derivee + onDisconnectedExternalValue(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException) +{ + OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support binding to external data + + if ( !impl_approveValueBinding_nolock( _rxBinding ) ) + { + throw IncompatibleTypesException( + FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ), + *this + ); + } + + ControlModelLock aLock( *this ); + + // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding + // might trigger a change in our BoundField. + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + // disconnect from the old binding + if ( hasExternalValueBinding() ) + disconnectExternalValueBinding( ); + + // connect to the new binding + if ( _rxBinding.is() ) + connectExternalValueBinding( _rxBinding, aLock ); +} + +//-------------------------------------------------------------------- +Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support binding to external data + + return m_xExternalBinding; +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException ) +{ + ControlModelLock aLock( *this ); + + OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" ); + if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() ) + { + transferExternalValueToControl( aLock ); + } +} + +//-------------------------------------------------------------------- +void OBoundControlModel::transferDbValueToControl( ) +{ + try + { + setControlValue( translateDbColumnToControlValue(), eDbColumnBinding ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock ) +{ + Reference< XValueBinding > xExternalBinding( m_xExternalBinding ); + Type aValueExchangeType( getExternalValueType() ); + + _rInstanceLock.release(); + // >>>>>>>> ----- UNSAFE ----- >>>>>>>> + Any aExternalValue; + try + { + aExternalValue = xExternalBinding->getValue( aValueExchangeType ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + // <<<<<<<< ----- UNSAFE ----- <<<<<<<< + _rInstanceLock.acquire(); + + setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock ) +{ + OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(), + "OBoundControlModel::transferControlValueToExternal: precondition not met!" ); + + if ( m_xExternalBinding.is() ) + { + Any aExternalValue( translateControlValueToExternalValue() ); + m_bTransferingValue = sal_True; + + _rInstanceLock.release(); + // >>>>>>>> ----- UNSAFE ----- >>>>>>>> + try + { + m_xExternalBinding->setValue( aExternalValue ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + // <<<<<<<< ----- UNSAFE ----- <<<<<<<< + _rInstanceLock.acquire(); + + m_bTransferingValue = sal_False; + } +} + +// ----------------------------------------------------------------------------- +Sequence< Type > OBoundControlModel::getSupportedBindingTypes() +{ + return Sequence< Type >( &m_aValuePropertyType, 1 ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::calculateExternalValueType() +{ + m_aExternalValueType = Type(); + if ( !m_xExternalBinding.is() ) + return; + + Sequence< Type > aTypeCandidates( getSupportedBindingTypes() ); + for ( const Type* pTypeCandidate = aTypeCandidates.getConstArray(); + pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength(); + ++pTypeCandidate + ) + { + if ( m_xExternalBinding->supportsType( *pTypeCandidate ) ) + { + m_aExternalValueType = *pTypeCandidate; + break; + } + } +} + +//----------------------------------------------------------------------------- +Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(), + "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" ); + + Any aControlValue( _rExternalValue ); + + // if the external value is VOID, and our value property is not allowed to be VOID, + // then default-construct a value + if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid ) + aControlValue.setValue( NULL, m_aValuePropertyType ); + + // outta here + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::translateControlValueToExternalValue( ) const +{ + return getControlValue( ); +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::translateControlValueToValidatableValue( ) const +{ + OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" ); + if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() ) + return translateControlValueToExternalValue(); + return getControlValue(); +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::getControlValue( ) const +{ + OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(), + "OBoundControlModel::getControlValue: invalid aggregate !" ); + OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ), + "OBoundControlModel::getControlValue: please override if you have own value property handling!" ); + + // determine the current control value + Any aControlValue; + if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() ) + { + aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle ); + } + else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() ) + { + aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName ); + } + + return aControlValue; +} + +//-------------------------------------------------------------------- +void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator ) +{ + OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" ); + OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" ); + + m_xValidator = _rxValidator; + + // add as value listener so we get notified when the value changes + if ( m_xValidator.is() ) + { + try + { + m_xValidator->addValidityConstraintListener( this ); + } + catch( const RuntimeException& ) + { + } + } + + onConnectedValidator( ); +} + +//-------------------------------------------------------------------- +void OBoundControlModel::disconnectValidator( ) +{ + OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" ); + + // add as value listener so we get notified when the value changes + if ( m_xValidator.is() ) + { + try + { + m_xValidator->removeValidityConstraintListener( this ); + } + catch( const RuntimeException& ) + { + } + } + + m_xValidator.clear(); + + onDisconnectedValidator( ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support validation + + // early out if the validator does not change + if( _rxValidator == m_xValidator ) + return; + + if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) ) + throw VetoException( + FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ), + *this + ); + + // disconnect from the old validator + if ( hasValidator() ) + disconnectValidator( ); + + // connect to the new validator + if ( _rxValidator.is() ) + connectValidator( _rxValidator ); +} + +//-------------------------------------------------------------------- +Reference< XValidator > SAL_CALL OBoundControlModel::getValidator( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support validation + + return m_xValidator; +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ ) throw (RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support validation + + recheckValidity( false ); +} + +//-------------------------------------------------------------------- +sal_Bool SAL_CALL OBoundControlModel::isValid( ) throw (RuntimeException) +{ + return m_bIsCurrentValueValid; +} + +//-------------------------------------------------------------------- +::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const +{ + if ( hasValidator() ) + return translateControlValueToValidatableValue(); + return getControlValue(); +} + +//-------------------------------------------------------------------- +Any SAL_CALL OBoundControlModel::getCurrentValue( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return getCurrentFormComponentValue(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException) +{ + if ( Listener.is() ) + m_aFormComponentListeners.addInterface( Listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException) +{ + if ( Listener.is() ) + m_aFormComponentListeners.removeInterface( Listener ); +} + +//-------------------------------------------------------------------- +void OBoundControlModel::recheckValidity( bool _bForceNotification ) +{ + try + { + sal_Bool bIsCurrentlyValid = sal_True; + if ( hasValidator() ) + bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() ); + + if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification ) + { + m_bIsCurrentValueValid = bIsCurrentlyValid; + + // release our mutex for the notifications + MutexRelease aRelease( m_aMutex ); + m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::recheckValidity: caught an exception!" ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel ) + DECL_PROP1 ( CONTROLSOURCE, ::rtl::OUString, BOUND ); + DECL_IFACE_PROP3( BOUNDFIELD, XPropertySet, BOUND, READONLY, TRANSIENT ); + DECL_IFACE_PROP2( CONTROLLABEL, XPropertySet, BOUND, MAYBEVOID ); + DECL_PROP2 ( CONTROLSOURCEPROPERTY, ::rtl::OUString, READONLY, TRANSIENT ); + DECL_BOOL_PROP1 ( INPUT_REQUIRED, BOUND ); + END_DESCRIBE_PROPERTIES() +} + +// ----------------------------------------------------------------------------- + +//......................................................................... +} +//... namespace frm ....................................................... + diff --git a/forms/source/component/FormattedField.cxx b/forms/source/component/FormattedField.cxx new file mode 100644 index 000000000000..6e11fa7c9dbb --- /dev/null +++ b/forms/source/component/FormattedField.cxx @@ -0,0 +1,1257 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "FormattedField.hxx" +#include "services.hxx" +#include "property.hrc" +#include "property.hxx" +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "propertybaghelper.hxx" +#include <comphelper/sequence.hxx> +#include <comphelper/numbers.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbconversion.hxx> +#include <svl/zforlist.hxx> +#include <svl/numuno.hxx> +#include <vcl/svapp.hxx> +#include <tools/debug.hxx> +#include <vcl/wintypes.hxx> +#include <i18npool/mslangid.hxx> +#include <rtl/textenc.h> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/awt/MouseEvent.hpp> +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XKeyListener.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <vos/mutex.hxx> + // needed as long as we use the SolarMutex +#include <comphelper/streamsection.hxx> +#include <cppuhelper/weakref.hxx> +#include <unotools/desktopterminationobserver.hxx> + +#include <list> +#include <algorithm> + +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +namespace +{ + typedef com::sun::star::util::Date UNODate; + typedef com::sun::star::util::Time UNOTime; + typedef com::sun::star::util::DateTime UNODateTime; +} + +//......................................................................... +namespace frm +{ + +/*************************************************************************/ + +class StandardFormatsSupplier : protected SvNumberFormatsSupplierObj, public ::utl::ITerminationListener +{ +protected: + SvNumberFormatter* m_pMyPrivateFormatter; + static WeakReference< XNumberFormatsSupplier > s_xDefaultFormatsSupplier; + +public: + static Reference< XNumberFormatsSupplier > get( const Reference< XMultiServiceFactory >& _rxORB ); + + using SvNumberFormatsSupplierObj::operator new; + using SvNumberFormatsSupplierObj::operator delete; + +protected: + StandardFormatsSupplier(const Reference<XMultiServiceFactory>& _rxFactory,LanguageType _eSysLanguage); + ~StandardFormatsSupplier(); + +protected: + virtual bool queryTermination() const; + virtual void notifyTermination(); +}; + +//------------------------------------------------------------------ +WeakReference< XNumberFormatsSupplier > StandardFormatsSupplier::s_xDefaultFormatsSupplier; + +//------------------------------------------------------------------ +StandardFormatsSupplier::StandardFormatsSupplier(const Reference< XMultiServiceFactory > & _rxFactory,LanguageType _eSysLanguage) + :SvNumberFormatsSupplierObj() + ,m_pMyPrivateFormatter(new SvNumberFormatter(_rxFactory, _eSysLanguage)) +{ + SetNumberFormatter(m_pMyPrivateFormatter); + + // #i29147# - 2004-06-18 - fs@openoffice.org + ::utl::DesktopTerminationObserver::registerTerminationListener( this ); +} + +//------------------------------------------------------------------ +StandardFormatsSupplier::~StandardFormatsSupplier() +{ + ::utl::DesktopTerminationObserver::revokeTerminationListener( this ); + + DELETEZ( m_pMyPrivateFormatter ); +} + +//------------------------------------------------------------------ +Reference< XNumberFormatsSupplier > StandardFormatsSupplier::get( const Reference< XMultiServiceFactory >& _rxORB ) +{ + LanguageType eSysLanguage = LANGUAGE_SYSTEM; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier; + if ( xSupplier.is() ) + return xSupplier; + + // get the Office's locale + const Locale& rSysLocale = SvtSysLocale().GetLocaleData().getLocale(); + // translate + eSysLanguage = MsLangId::convertLocaleToLanguage( rSysLocale ); + } + + StandardFormatsSupplier* pSupplier = new StandardFormatsSupplier( _rxORB, eSysLanguage ); + Reference< XNumberFormatsSupplier > xNewlyCreatedSupplier( pSupplier ); + + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier; + if ( xSupplier.is() ) + // somebody used the small time frame where the mutex was not locked to create and set + // the supplier + return xSupplier; + + s_xDefaultFormatsSupplier = xNewlyCreatedSupplier; + } + + return xNewlyCreatedSupplier; +} + +//------------------------------------------------------------------ +bool StandardFormatsSupplier::queryTermination() const +{ + return true; +} + +//------------------------------------------------------------------ +void StandardFormatsSupplier::notifyTermination() +{ + Reference< XNumberFormatsSupplier > xKeepAlive = this; + // when the application is terminating, release our static reference so that we are cleared/destructed + // earlier than upon unloading the library + // #i29147# - 2004-06-18 - fs@openoffice.org + s_xDefaultFormatsSupplier = WeakReference< XNumberFormatsSupplier >( ); + + SetNumberFormatter( NULL ); + DELETEZ( m_pMyPrivateFormatter ); +} + +/*************************************************************************/ +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormattedControl(_rxFactory)); +} + +//------------------------------------------------------------------ +Sequence<Type> OFormattedControl::_getTypes() +{ + return ::comphelper::concatSequences( + OFormattedControl_BASE::getTypes(), + OBoundControl::_getTypes() + ); +} + +//------------------------------------------------------------------ +Any SAL_CALL OFormattedControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OFormattedControl_BASE::queryInterface(_rType); + return aReturn; +} + + +DBG_NAME(OFormattedControl); +//------------------------------------------------------------------------------ +OFormattedControl::OFormattedControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_FORMATTEDFIELD) + ,m_nKeyEvent(0) +{ + DBG_CTOR(OFormattedControl,NULL); + + increment(m_refCount); + { + Reference<XWindow> xComp; + if (query_aggregation(m_xAggregate, xComp)) + { + xComp->addKeyListener(this); + } + } + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +OFormattedControl::~OFormattedControl() +{ + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OFormattedControl,NULL); +} + +// XKeyListener +//------------------------------------------------------------------------------ +void OFormattedControl::disposing(const EventObject& _rSource) throw(RuntimeException) +{ + OBoundControl::disposing(_rSource); +} + +//------------------------------------------------------------------------------ +void OFormattedControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 ) + return; + + // Steht das Control in einem Formular mit einer Submit-URL? + Reference<com::sun::star::beans::XPropertySet> xSet(getModel(), UNO_QUERY); + if( !xSet.is() ) + return; + + Reference<XFormComponent> xFComp(xSet, UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + if( !xParent.is() ) + return; + + Reference<com::sun::star::beans::XPropertySet> xFormSet(xParent, UNO_QUERY); + if( !xFormSet.is() ) + return; + + Any aTmp(xFormSet->getPropertyValue( PROPERTY_TARGET_URL )); + if (!isA(aTmp, static_cast< ::rtl::OUString* >(NULL)) || + !getString(aTmp).getLength() ) + return; + + Reference<XIndexAccess> xElements(xParent, UNO_QUERY); + sal_Int32 nCount = xElements->getCount(); + if( nCount > 1 ) + { + + Reference<com::sun::star::beans::XPropertySet> xFCSet; + for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ ) + { + // Any aElement(xElements->getByIndex(nIndex)); + xElements->getByIndex(nIndex) >>= xFCSet; + + if (hasProperty(PROPERTY_CLASSID, xFCSet) && + getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD) + { + // Noch ein weiteres Edit gefunden ==> dann nicht submitten + if (xFCSet != xSet) + return; + } + } + } + + // Da wir noch im Haender stehen, submit asynchron ausloesen + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + m_nKeyEvent = Application::PostUserEvent( LINK(this, OFormattedControl, + OnKeyPressed) ); +} + +//------------------------------------------------------------------------------ +void OFormattedControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +IMPL_LINK(OFormattedControl, OnKeyPressed, void*, /*EMPTYARG*/) +{ + m_nKeyEvent = 0; + + Reference<XFormComponent> xFComp(getModel(), UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + Reference<XSubmit> xSubmit(xParent, UNO_QUERY); + if (xSubmit.is()) + xSubmit->submit( Reference<XControl> (), ::com::sun::star::awt::MouseEvent() ); + return 0L; +} + +//------------------------------------------------------------------------------ +StringSequence OFormattedControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_FORMATTEDFIELD; + return aSupported; +} + +//------------------------------------------------------------------------------ +void OFormattedControl::setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException) +{ + OBoundControl::setDesignMode(bOn); +} + +/*************************************************************************/ +DBG_NAME(OFormattedModel) +//------------------------------------------------------------------ +void OFormattedModel::implConstruct() +{ + // members + m_bOriginalNumeric = sal_False; + m_bNumeric = sal_False; + m_xOriginalFormatter = NULL; + m_nKeyType = NumberFormat::UNDEFINED; + m_aNullDate = DBTypeConversion::getStandardDate(); + m_nFieldType = DataType::OTHER; + + // default our formats supplier + increment(m_refCount); + setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER); + decrement(m_refCount); + + startAggregatePropertyListening( PROPERTY_FORMATKEY ); + startAggregatePropertyListening( PROPERTY_FORMATSSUPPLIER ); +} + +//------------------------------------------------------------------ +OFormattedModel::OFormattedModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel(_rxFactory, VCL_CONTROLMODEL_FORMATTEDFIELD, FRM_SUN_CONTROL_FORMATTEDFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OErrorBroadcaster( OComponentHelper::rBHelper ) +{ + DBG_CTOR(OFormattedModel, NULL); + + implConstruct(); + + m_nClassId = FormComponentType::TEXTFIELD; + initValueProperty( PROPERTY_EFFECTIVE_VALUE, PROPERTY_ID_EFFECTIVE_VALUE ); +} + +//------------------------------------------------------------------ +OFormattedModel::OFormattedModel( const OFormattedModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) +{ + DBG_CTOR(OFormattedModel, NULL); + + implConstruct(); +} + +//------------------------------------------------------------------------------ +OFormattedModel::~OFormattedModel() +{ + DBG_DTOR(OFormattedModel, NULL); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OFormattedModel ) + +//------------------------------------------------------------------------------ +void SAL_CALL OFormattedModel::disposing() +{ + OErrorBroadcaster::disposing(); + OEditBaseModel::disposing(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OFormattedModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OEditBaseModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_FORMATTEDFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD; + *pStoreTo++ = BINDABLE_DATABASE_FORMATTED_FIELD; + + return aSupported; +} + +// XAggregation +//------------------------------------------------------------------------------ +Any SAL_CALL OFormattedModel::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = OEditBaseModel::queryAggregation( _rType ); + return aReturn.hasValue() ? aReturn : OErrorBroadcaster::queryInterface( _rType ); +} + +// XTypeProvider +//------------------------------------------------------------------------------ +Sequence< Type > OFormattedModel::_getTypes() +{ + return ::comphelper::concatSequences( + OEditBaseModel::_getTypes(), + OErrorBroadcaster::getTypes() + ); +} + +// XPersistObject +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormattedModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString(FRM_COMPONENT_EDIT); +} + +// XPropertySet +//------------------------------------------------------------------------------ +void OFormattedModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 3, OEditBaseModel ) + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_BOOL_PROP2(FILTERPROPOSAL, BOUND, MAYBEDEFAULT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OEditBaseModel::describeAggregateProperties( _rAggregateProps ); + + // TreatAsNumeric nicht transient : wir wollen es an der UI anbinden (ist noetig, um dem EffectiveDefault + // - der kann Text oder Zahl sein - einen Sinn zu geben) + ModifyPropertyAttributes(_rAggregateProps, PROPERTY_TREATASNUMERIC, 0, PropertyAttribute::TRANSIENT); + // same for FormatKey + // (though the paragraph above for the TreatAsNumeric does not hold anymore - we do not have an UI for this. + // But we have for the format key ...) + // 25.06.2001 - 87862 - frank.schoenheit@sun.com + ModifyPropertyAttributes(_rAggregateProps, PROPERTY_FORMATKEY, 0, PropertyAttribute::TRANSIENT); + + RemoveProperty(_rAggregateProps, PROPERTY_STRICTFORMAT); + // no strict format property for formatted fields: it does not make sense, 'cause + // there is no general way to decide which characters/sub strings are allowed during the input of an + // arbitraryly formatted control + // 81441 - 12/07/00 - FS +} + +//------------------------------------------------------------------------------ +void OFormattedModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + OEditBaseModel::getFastPropertyValue(rValue, nHandle); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception) +{ + OEditBaseModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); +} + +//------------------------------------------------------------------------------ +sal_Bool OFormattedModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) +{ + return OEditBaseModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::setPropertyToDefaultByHandle(sal_Int32 nHandle) +{ + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + { + Reference<XNumberFormatsSupplier> xSupplier = calcDefaultFormatsSupplier(); + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::setPropertyToDefaultByHandle(FORMATSSUPPLIER) : have no aggregate !"); + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier)); + } + else + OEditBaseModel::setPropertyToDefaultByHandle(nHandle); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException ) +{ + OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName( aPropertyName ); + + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER); + else + OEditBaseModel::setPropertyToDefault(aPropertyName); +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + { + Reference<XNumberFormatsSupplier> xSupplier = calcDefaultFormatsSupplier(); + return makeAny(xSupplier); + } + else + return OEditBaseModel::getPropertyDefaultByHandle(nHandle); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OFormattedModel::getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException ) +{ + OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName( aPropertyName ); + + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + return getPropertyDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER); + else + return OEditBaseModel::getPropertyDefault(aPropertyName); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::_propertyChanged( const com::sun::star::beans::PropertyChangeEvent& evt ) throw(RuntimeException) +{ + // TODO: check how this works with external bindings + + OSL_ENSURE( evt.Source == m_xAggregateSet, "OFormattedModel::_propertyChanged: where did this come from?" ); + if ( evt.Source == m_xAggregateSet ) + { + Reference< XPropertySet > xSourceSet( evt.Source, UNO_QUERY ); + if ( evt.PropertyName.equals( PROPERTY_FORMATKEY ) ) + { + if ( evt.NewValue.getValueType().getTypeClass() == TypeClass_LONG ) + { + try + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Reference<XNumberFormatsSupplier> xSupplier( calcFormatsSupplier() ); + m_nKeyType = getNumberFormatType(xSupplier->getNumberFormats(), getINT32( evt.NewValue ) ); + + // as m_aSaveValue (which is used by commitControlValueToDbColumn) is format dependent we have + // to recalc it, which is done by translateDbColumnToControlValue + if ( m_xColumn.is() && m_xAggregateFastSet.is() && !m_xCursor->isBeforeFirst() && !m_xCursor->isAfterLast()) + { + setControlValue( translateDbColumnToControlValue(), eOther ); + } + + // if we're connected to an external value binding, then re-calculate the type + // used to exchange the value - it depends on the format, too + if ( hasExternalValueBinding() ) + { + calculateExternalValueType(); + } + } + catch(Exception&) + { + } + } + return; + } + + if ( evt.PropertyName.equals( PROPERTY_FORMATSSUPPLIER ) ) + { + updateFormatterNullDate(); + return; + } + + OBoundControlModel::_propertyChanged( evt ); + } +} + +//------------------------------------------------------------------------------ +void OFormattedModel::updateFormatterNullDate() +{ + // calc the current NULL date + Reference< XNumberFormatsSupplier > xSupplier( calcFormatsSupplier() ); + if ( xSupplier.is() ) + xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ) ) ) >>= m_aNullDate; +} + +//------------------------------------------------------------------------------ +Reference< XNumberFormatsSupplier > OFormattedModel::calcFormatsSupplier() const +{ + Reference<XNumberFormatsSupplier> xSupplier; + + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::calcFormatsSupplier : have no aggregate !"); + // hat mein aggregiertes Model einen FormatSupplier ? + if( m_xAggregateSet.is() ) + m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xSupplier; + + if (!xSupplier.is()) + // check if my parent form has a supplier + xSupplier = calcFormFormatsSupplier(); + + if (!xSupplier.is()) + xSupplier = calcDefaultFormatsSupplier(); + + DBG_ASSERT(xSupplier.is(), "OFormattedModel::calcFormatsSupplier : no supplier !"); + // jetzt sollte aber einer da sein + return xSupplier; +} + +//------------------------------------------------------------------------------ +Reference<XNumberFormatsSupplier> OFormattedModel::calcFormFormatsSupplier() const +{ + Reference<XChild> xMe; + query_interface(static_cast<XWeak*>(const_cast<OFormattedModel*>(this)), xMe); + // damit stellen wir sicher, dass wir auch fuer den Fall der Aggregation das richtige + // Objekt bekommen + DBG_ASSERT(xMe.is(), "OFormattedModel::calcFormFormatsSupplier : I should have a content interface !"); + + // jetzt durchhangeln nach oben, bis wir auf eine starform treffen (angefangen mit meinem eigenen Parent) + Reference<XChild> xParent(xMe->getParent(), UNO_QUERY); + Reference<XForm> xNextParentForm(xParent, UNO_QUERY); + while (!xNextParentForm.is() && xParent.is()) + { + xParent = xParent.query( xParent->getParent() ); + xNextParentForm = xNextParentForm.query( xParent ); + } + + if (!xNextParentForm.is()) + { + DBG_ERROR("OFormattedModel::calcFormFormatsSupplier : have no ancestor which is a form !"); + return NULL; + } + + // den FormatSupplier von meinem Vorfahren (falls der einen hat) + Reference< XRowSet > xRowSet( xNextParentForm, UNO_QUERY ); + Reference< XNumberFormatsSupplier > xSupplier; + if (xRowSet.is()) + xSupplier = getNumberFormats( getConnection(xRowSet), sal_True, getContext().getLegacyServiceFactory() ); + return xSupplier; +} + +//------------------------------------------------------------------------------ +Reference< XNumberFormatsSupplier > OFormattedModel::calcDefaultFormatsSupplier() const +{ + return StandardFormatsSupplier::get( getContext().getLegacyServiceFactory() ); +} + +// XBoundComponent +//------------------------------------------------------------------------------ +void OFormattedModel::loaded(const EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException) +{ + // HACK : our onConnectedDbColumn accesses our NumberFormatter which locks the solar mutex (as it doesn't have + // an own one). To prevent deadlocks with other threads which may request a property from us in an + // UI-triggered action (e.g. an tooltip) we lock the solar mutex _here_ before our base class locks + // it's own muext (which is used for property requests) + // alternative a): we use two mutexes, one which is passed to the OPropertysetHelper and used for + // property requests and one for our own code. This would need a lot of code rewriting + // alternative b): The NumberFormatter has to be really threadsafe (with an own mutex), which is + // the only "clean" solution for me. + // FS - 69603 - 02.11.99 + + ::vos::OGuard aGuard(Application::GetSolarMutex()); + OEditBaseModel::loaded(rEvent); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + m_xOriginalFormatter = NULL; + + // get some properties of the field + m_nFieldType = DataType::OTHER; + Reference<XPropertySet> xField = getField(); + if ( xField.is() ) + xField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= m_nFieldType; + + sal_Int32 nFormatKey = 0; + + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::onConnectedDbColumn : have no aggregate !"); + if (m_xAggregateSet.is()) + { // all the following doesn't make any sense if we have no aggregate ... + Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER); + DBG_ASSERT( aSupplier.hasValue(), "OFormattedModel::onConnectedDbColumn : invalid property value !" ); + // das sollte im Constructor oder im read auf was richtiges gesetzt worden sein + + Any aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY); + if ( !(aFmtKey >>= nFormatKey ) ) + { // nobody gave us a format to use. So we examine the field we're bound to for a + // format key, and use it ourself, too + sal_Int32 nType = DataType::VARCHAR; + if (xField.is()) + { + aFmtKey = xField->getPropertyValue(PROPERTY_FORMATKEY); + xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType ; + } + + Reference<XNumberFormatsSupplier> xSupplier = calcFormFormatsSupplier(); + DBG_ASSERT(xSupplier.is(), "OFormattedModel::onConnectedDbColumn : bound to a field but no parent with a formatter ? how this ?"); + if (xSupplier.is()) + { + m_bOriginalNumeric = getBOOL(getPropertyValue(PROPERTY_TREATASNUMERIC)); + + if (!aFmtKey.hasValue()) + { // we aren't bound to a field (or this field's format is invalid) + // -> determine the standard text (or numeric) format of the supplier + Reference<XNumberFormatTypes> xTypes(xSupplier->getNumberFormats(), UNO_QUERY); + if (xTypes.is()) + { + Locale aApplicationLocale = Application::GetSettings().GetUILocale(); + + if (m_bOriginalNumeric) + aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::NUMBER, aApplicationLocale); + else + aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::TEXT, aApplicationLocale); + } + } + + aSupplier >>= m_xOriginalFormatter; + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier)); + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, aFmtKey); + + // das Numeric-Flag an mein gebundenes Feld anpassen + if (xField.is()) + { + m_bNumeric = sal_False; + switch (nType) + { + case DataType::BIT: + case DataType::BOOLEAN: + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + case DataType::BIGINT: + case DataType::FLOAT: + case DataType::REAL: + case DataType::DOUBLE: + case DataType::NUMERIC: + case DataType::DECIMAL: + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + m_bNumeric = sal_True; + break; + } + } + else + m_bNumeric = m_bOriginalNumeric; + + setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bNumeric)); + + OSL_VERIFY( aFmtKey >>= nFormatKey ); + } + } + } + + Reference<XNumberFormatsSupplier> xSupplier = calcFormatsSupplier(); + m_bNumeric = getBOOL( getPropertyValue( PROPERTY_TREATASNUMERIC ) ); + m_nKeyType = getNumberFormatType( xSupplier->getNumberFormats(), nFormatKey ); + xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString::createFromAscii("NullDate") ) >>= m_aNullDate; + + OEditBaseModel::onConnectedDbColumn( _rxForm ); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::onDisconnectedDbColumn() +{ + OEditBaseModel::onDisconnectedDbColumn(); + if (m_xOriginalFormatter.is()) + { // unser aggregiertes Model hatte keinerlei Format-Informationen + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(m_xOriginalFormatter)); + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, Any()); + setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bOriginalNumeric)); + m_xOriginalFormatter = NULL; + } + + m_nFieldType = DataType::OTHER; + m_nKeyType = NumberFormat::UNDEFINED; + m_aNullDate = DBTypeConversion::getStandardDate(); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OEditBaseModel::write(_rxOutStream); + _rxOutStream->writeShort(0x0003); + + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::write : have no aggregate !"); + + // mein Format (evtl. void) in ein persistentes Format bringen (der Supplier zusammen mit dem Key ist es zwar auch, + // aber deswegen muessen wir ja nicht gleich den ganzen Supplier speichern, das waere ein klein wenig Overhead ;) + + Reference<XNumberFormatsSupplier> xSupplier; + Any aFmtKey; + sal_Bool bVoidKey = sal_True; + if (m_xAggregateSet.is()) + { + Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER); + if (aSupplier.getValueType().getTypeClass() != TypeClass_VOID) + { + OSL_VERIFY( aSupplier >>= xSupplier ); + } + + aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY); + bVoidKey = (!xSupplier.is() || !aFmtKey.hasValue()) || (isLoaded() && m_xOriginalFormatter.is()); + // (kein Fomatter und/oder Key) oder (loaded und faked Formatter) + } + + _rxOutStream->writeBoolean(!bVoidKey); + if (!bVoidKey) + { + // aus dem FormatKey und dem Formatter persistente Angaben basteln + + Any aKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY); + sal_Int32 nKey = aKey.hasValue() ? getINT32(aKey) : 0; + + Reference<XNumberFormats> xFormats = xSupplier->getNumberFormats(); + + ::rtl::OUString sFormatDescription; + LanguageType eFormatLanguage = LANGUAGE_DONTKNOW; + + static const ::rtl::OUString s_aLocaleProp = ::rtl::OUString::createFromAscii("Locale"); + Reference<com::sun::star::beans::XPropertySet> xFormat = xFormats->getByKey(nKey); + if (hasProperty(s_aLocaleProp, xFormat)) + { + Any aLocale = xFormat->getPropertyValue(s_aLocaleProp); + DBG_ASSERT(isA(aLocale, static_cast<Locale*>(NULL)), "OFormattedModel::write : invalid language property !"); + if (isA(aLocale, static_cast<Locale*>(NULL))) + { + Locale* pLocale = (Locale*)aLocale.getValue(); + eFormatLanguage = MsLangId::convertLocaleToLanguage( *pLocale ); + } + } + + static const ::rtl::OUString s_aFormatStringProp = ::rtl::OUString::createFromAscii("FormatString"); + if (hasProperty(s_aFormatStringProp, xFormat)) + xFormat->getPropertyValue(s_aFormatStringProp) >>= sFormatDescription; + + _rxOutStream->writeUTF(sFormatDescription); + _rxOutStream->writeLong((sal_Int32)eFormatLanguage); + } + + // version 2 : write the properties common to all OEditBaseModels + writeCommonEditProperties(_rxOutStream); + + // version 3 : write the effective value property of the aggregate + // Due to a bug within the UnoControlFormattedFieldModel implementation (our default aggregate) this props value isn't correctly read + // and this can't be corrected without being incompatible. + // so we have our own handling. + + // and to be a little bit more compatible we make the following section skippable + { + Reference< XDataOutputStream > xOut(_rxOutStream, UNO_QUERY); + OStreamSection aDownCompat(xOut); + + // a sub version within the skippable block + _rxOutStream->writeShort(0x0000); + + // version 0: the effective value of the aggregate + Any aEffectiveValue; + if (m_xAggregateSet.is()) + { + try { aEffectiveValue = m_xAggregateSet->getPropertyValue(PROPERTY_EFFECTIVE_VALUE); } catch(Exception&) { } + } + + { + OStreamSection aDownCompat2(xOut); + switch (aEffectiveValue.getValueType().getTypeClass()) + { + case TypeClass_STRING: + _rxOutStream->writeShort(0x0000); + _rxOutStream->writeUTF(::comphelper::getString(aEffectiveValue)); + break; + case TypeClass_DOUBLE: + _rxOutStream->writeShort(0x0001); + _rxOutStream->writeDouble(::comphelper::getDouble(aEffectiveValue)); + break; + default: // void and all unknown states + DBG_ASSERT(!aEffectiveValue.hasValue(), "FmXFormattedModel::write : unknown property value type !"); + _rxOutStream->writeShort(0x0002); + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void OFormattedModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OEditBaseModel::read(_rxInStream); + sal_uInt16 nVersion = _rxInStream->readShort(); + + Reference<XNumberFormatsSupplier> xSupplier; + sal_Int32 nKey = -1; + switch (nVersion) + { + case 0x0001 : + case 0x0002 : + case 0x0003 : + { + sal_Bool bNonVoidKey = _rxInStream->readBoolean(); + if (bNonVoidKey) + { + // den String und die Language lesen .... + ::rtl::OUString sFormatDescription = _rxInStream->readUTF(); + LanguageType eDescriptionLanguage = (LanguageType)_rxInStream->readLong(); + + // und daraus von einem Formatter zu einem Key zusammenwuerfeln lassen ... + xSupplier = calcFormatsSupplier(); + // calcFormatsSupplier nimmt erst den vom Model, dann einen von der starform, dann einen ganz neuen .... + Reference<XNumberFormats> xFormats = xSupplier->getNumberFormats(); + + if (xFormats.is()) + { + Locale aDescriptionLanguage( MsLangId::convertLanguageToLocale(eDescriptionLanguage)); + + nKey = xFormats->queryKey(sFormatDescription, aDescriptionLanguage, sal_False); + if (nKey == (sal_Int32)-1) + { // noch nicht vorhanden in meinem Formatter ... + nKey = xFormats->addNew(sFormatDescription, aDescriptionLanguage); + } + } + } + if ((nVersion == 0x0002) || (nVersion == 0x0003)) + readCommonEditProperties(_rxInStream); + + if (nVersion == 0x0003) + { // since version 3 there is a "skippable" block at this position + Reference< XDataInputStream > xIn(_rxInStream, UNO_QUERY); + OStreamSection aDownCompat(xIn); + + sal_Int16 nSubVersion = _rxInStream->readShort(); + (void)nSubVersion; + + // version 0 and higher : the "effective value" property + Any aEffectiveValue; + { + OStreamSection aDownCompat2(xIn); + switch (_rxInStream->readShort()) + { + case 0: // String + aEffectiveValue <<= _rxInStream->readUTF(); + break; + case 1: // double + aEffectiveValue <<= (double)_rxInStream->readDouble(); + break; + case 2: + break; + case 3: + DBG_ERROR("FmXFormattedModel::read : unknown effective value type !"); + } + } + + // this property is only to be set if we have no control source : in all other cases the base class did a + // reset after it's read and this set the effective value to a default value + if ( m_xAggregateSet.is() && ( getControlSource().getLength() == 0 ) ) + { + try + { + m_xAggregateSet->setPropertyValue(PROPERTY_EFFECTIVE_VALUE, aEffectiveValue); + } + catch(Exception&) + { + } + } + } + } + break; + default : + DBG_ERROR("OFormattedModel::read : unknown version !"); + // dann bleibt das Format des aggregierten Sets, wie es bei der Erzeugung ist : void + defaultCommonEditProperties(); + break; + } + + if ((nKey != -1) && m_xAggregateSet.is()) + { + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier)); + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, makeAny((sal_Int32)nKey)); + } + else + { + setPropertyToDefault(PROPERTY_FORMATSSUPPLIER); + setPropertyToDefault(PROPERTY_FORMATKEY); + } +} + +//------------------------------------------------------------------------------ +sal_uInt16 OFormattedModel::getPersistenceFlags() const +{ + return (OEditBaseModel::getPersistenceFlags() & ~PF_HANDLE_COMMON_PROPS); + // a) we do our own call to writeCommonEditProperties +} + +//------------------------------------------------------------------------------ +sal_Bool OFormattedModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( aControlValue != m_aSaveValue ) + { + // Leerstring + EmptyIsNull = void + if ( !aControlValue.hasValue() + || ( ( aControlValue.getValueType().getTypeClass() == TypeClass_STRING ) + && ( getString( aControlValue ).getLength() == 0 ) + && m_bEmptyIsNull + ) + ) + m_xColumnUpdate->updateNull(); + else + { + // als Value koennen nur double, string oder void auftreten + try + { + if ( aControlValue.getValueType().getTypeClass() == TypeClass_DOUBLE ) + { + DBTypeConversion::setValue( m_xColumnUpdate, m_aNullDate, getDouble( aControlValue ), m_nKeyType ); + } + else + { + DBG_ASSERT( aControlValue.getValueType().getTypeClass() == TypeClass_STRING, "OFormattedModel::commitControlValueToDbColumn: invalud value type !" ); + m_xColumnUpdate->updateString( getString( aControlValue ) ); + } + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +void OFormattedModel::onConnectedExternalValue( ) +{ + OEditBaseModel::onConnectedExternalValue(); + updateFormatterNullDate(); +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue; + switch( _rExternalValue.getValueTypeClass() ) + { + case TypeClass_VOID: + break; + + case TypeClass_STRING: + aControlValue = _rExternalValue; + break; + + case TypeClass_BOOLEAN: + { + sal_Bool bExternalValue = sal_False; + _rExternalValue >>= bExternalValue; + aControlValue <<= (double)( bExternalValue ? 1 : 0 ); + } + break; + + default: + { + if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) ) + { + UNODate aDate; + _rExternalValue >>= aDate; + aControlValue <<= DBTypeConversion::toDouble( aDate, m_aNullDate ); + } + else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) ) + { + UNOTime aTime; + _rExternalValue >>= aTime; + aControlValue <<= DBTypeConversion::toDouble( aTime ); + } + else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) ) + { + UNODateTime aDateTime; + _rExternalValue >>= aDateTime; + aControlValue <<= DBTypeConversion::toDouble( aDateTime, m_aNullDate ); + } + else + { + OSL_ENSURE( _rExternalValue.getValueTypeClass() == TypeClass_DOUBLE, + "OFormattedModel::translateExternalValueToControlValue: don't know how to translate this type!" ); + double fValue = 0; + OSL_VERIFY( _rExternalValue >>= fValue ); + aControlValue <<= fValue; + } + } + } + + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::translateControlValueToExternalValue( ) const +{ + OSL_PRECOND( hasExternalValueBinding(), + "OFormattedModel::translateControlValueToExternalValue: precondition not met!" ); + + Any aControlValue( getControlValue() ); + if ( !aControlValue.hasValue() ) + return aControlValue; + + Any aExternalValue; + + // translate into the the external value type + Type aExternalValueType( getExternalValueType() ); + switch ( aExternalValueType.getTypeClass() ) + { + case TypeClass_STRING: + { + ::rtl::OUString sString; + if ( aControlValue >>= sString ) + { + aExternalValue <<= sString; + break; + } + } + // NO break here! + + case TypeClass_BOOLEAN: + { + double fValue = 0; + OSL_VERIFY( aControlValue >>= fValue ); + // if this asserts ... well, the somebody set the TreatAsNumeric property to false, + // and the control value is a string. This implies some weird misconfiguration + // of the FormattedModel, so we won't care for it for the moment. + aExternalValue <<= (sal_Bool)( fValue ? sal_True : sal_False ); + } + break; + + default: + { + double fValue = 0; + OSL_VERIFY( aControlValue >>= fValue ); + // if this asserts ... well, the somebody set the TreatAsNumeric property to false, + // and the control value is a string. This implies some weird misconfiguration + // of the FormattedModel, so we won't care for it for the moment. + + if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) ) + { + aExternalValue <<= DBTypeConversion::toDate( fValue, m_aNullDate ); + } + else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) ) + { + aExternalValue <<= DBTypeConversion::toTime( fValue ); + } + else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) ) + { + aExternalValue <<= DBTypeConversion::toDateTime( fValue, m_aNullDate ); + } + else + { + OSL_ENSURE( aExternalValueType.equals( ::getCppuType( static_cast< double* >( NULL ) ) ), + "OFormattedModel::translateControlValueToExternalValue: don't know how to translate this type!" ); + aExternalValue <<= fValue; + } + } + break; + } + return aExternalValue; +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::translateDbColumnToControlValue() +{ + if ( m_bNumeric ) + m_aSaveValue <<= DBTypeConversion::getValue( m_xColumn, m_aNullDate, m_nKeyType ); // #100056# OJ + else + m_aSaveValue <<= m_xColumn->getString(); + + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + + return m_aSaveValue; +} + +// ----------------------------------------------------------------------------- +Sequence< Type > OFormattedModel::getSupportedBindingTypes() +{ + ::std::list< Type > aTypes; + aTypes.push_back( ::getCppuType( static_cast< double* >( NULL ) ) ); + + switch ( m_nKeyType & ~NumberFormat::DEFINED ) + { + case NumberFormat::DATE: + aTypes.push_front(::getCppuType( static_cast< UNODate* >( NULL ) ) ); + break; + case NumberFormat::TIME: + aTypes.push_front(::getCppuType( static_cast< UNOTime* >( NULL ) ) ); + break; + case NumberFormat::DATETIME: + aTypes.push_front(::getCppuType( static_cast< UNODateTime* >( NULL ) ) ); + break; + case NumberFormat::TEXT: + aTypes.push_front(::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ) ); + break; + case NumberFormat::LOGICAL: + aTypes.push_front(::getCppuType( static_cast< sal_Bool* >( NULL ) ) ); + break; + } + + Sequence< Type > aTypesRet( aTypes.size() ); + ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() ); + return aTypesRet; +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::getDefaultForReset() const +{ + return m_xAggregateSet->getPropertyValue( PROPERTY_EFFECTIVE_DEFAULT ); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//......................................................................... +} +//......................................................................... diff --git a/forms/source/component/FormattedField.hxx b/forms/source/component/FormattedField.hxx new file mode 100644 index 000000000000..42c7a5b1bf2a --- /dev/null +++ b/forms/source/component/FormattedField.hxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_FORMATTEDFIELD_HXX_ +#define _FORMS_FORMATTEDFIELD_HXX_ + +#include "EditBase.hxx" +#include <comphelper/propmultiplex.hxx> +#include <cppuhelper/implbase1.hxx> +#include "errorbroadcaster.hxx" + +//......................................................................... +namespace frm +{ + + //================================================================== + //= OFormattedModel + //================================================================== + + class OFormattedModel + :public OEditBaseModel + ,public OErrorBroadcaster + { + // das Original, falls ich die Format-Properties meines aggregierten Models gefaket, d.h. von dem Feld, an das + // ich gebunden bin, weitergereicht habe (nur gueltig wenn loaded) + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> m_xOriginalFormatter; + ::com::sun::star::util::Date m_aNullDate; + ::com::sun::star::uno::Any m_aSaveValue; + + sal_Int32 m_nFieldType; + sal_Int16 m_nKeyType; + sal_Bool m_bOriginalNumeric : 1, + m_bNumeric : 1; // analog fuer TreatAsNumeric-Property + + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> calcDefaultFormatsSupplier() const; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> calcFormFormatsSupplier() const; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> calcFormatsSupplier() const; + + DECLARE_DEFAULT_LEAF_XTOR( OFormattedModel ); + + friend class OFormattedFieldWrapper; + + protected: + // XInterface + DECLARE_UNO3_AGG_DEFAULTS( OFormattedModel, OEditBaseModel ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + // XAggregation + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XServiceInfo + IMPLEMENTATION_NAME(OFormattedModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // XPersistObject + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + // XLoadListener + virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException); + + // XPropertyState + void setPropertyToDefaultByHandle(sal_Int32 nHandle); + ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const; + + void SAL_CALL setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XPropertyChangeListener + virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OEditBaseModel::disposing; + using OEditBaseModel::getFastPropertyValue; + + protected: + virtual sal_uInt16 getPersistenceFlags() const; + // as we have an own version handling for persistence + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual void onConnectedExternalValue( ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + private: + DECLARE_XCLONEABLE(); + + void implConstruct(); + + void updateFormatterNullDate(); + }; + + //================================================================== + //= OFormattedControl + //================================================================== + typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XKeyListener> OFormattedControl_BASE; + class OFormattedControl : public OBoundControl + ,public OFormattedControl_BASE + { + sal_uInt32 m_nKeyEvent; + + public: + OFormattedControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OFormattedControl(); + + DECLARE_UNO3_AGG_DEFAULTS(OFormattedControl, OBoundControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OFormattedControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::awt::XKeyListener + virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::awt::XControl + virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException); + + // disambiguation + using OBoundControl::disposing; + + private: + DECL_LINK( OnKeyPressed, void* ); + }; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_FORMATTEDFIELD_HXX_ + diff --git a/forms/source/component/FormattedFieldWrapper.cxx b/forms/source/component/FormattedFieldWrapper.cxx new file mode 100644 index 000000000000..cf9a04074cfc --- /dev/null +++ b/forms/source/component/FormattedFieldWrapper.cxx @@ -0,0 +1,398 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "FormattedFieldWrapper.hxx" +#include "Edit.hxx" +#include "FormattedField.hxx" +#include <tools/debug.hxx> +#include "EditBase.hxx" +#include "services.hxx" +#include <connectivity/dbtools.hxx> +#include <vcl/svapp.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +// OFormattedFieldWrapper +//================================================================== +DBG_NAME(OFormattedFieldWrapper) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormattedFieldWrapper(_rxFactory, sal_True)); +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormattedFieldWrapper(_rxFactory, sal_False)); +} + +//------------------------------------------------------------------ +OFormattedFieldWrapper::OFormattedFieldWrapper(const Reference<XMultiServiceFactory>& _rxFactory, sal_Bool _bActAsFormatted) + :m_xServiceFactory(_rxFactory) + ,m_pEditPart(NULL) +{ + DBG_CTOR(OFormattedFieldWrapper, NULL); + + if (_bActAsFormatted) + { + increment(m_refCount); + { + // instantiate an FormattedModel + InterfaceRef xFormattedModel; + // (instantiate it directly ..., as the OFormattedModel isn't registered for any service names anymore) + OFormattedModel* pModel = new OFormattedModel(m_xServiceFactory); + query_interface(static_cast<XWeak*>(pModel), xFormattedModel); + + m_xAggregate = Reference<XAggregation> (xFormattedModel, UNO_QUERY); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : the OFormattedModel didn't have an XAggregation interface !"); + + // _before_ setting the delegator, give it to the member references + query_interface(xFormattedModel, m_xFormattedPart); + m_pEditPart = new OEditModel(m_xServiceFactory); + m_pEditPart->acquire(); + } + if (m_xAggregate.is()) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); + } +} + +//------------------------------------------------------------------ +OFormattedFieldWrapper::OFormattedFieldWrapper( const OFormattedFieldWrapper* _pCloneSource ) + :m_xServiceFactory( _pCloneSource->m_xServiceFactory ) + ,m_pEditPart( NULL ) +{ + Reference< XCloneable > xCloneAccess; + query_aggregation( _pCloneSource->m_xAggregate, xCloneAccess ); + + // clone the aggregate + if ( xCloneAccess.is() ) + { + increment( m_refCount ); + { + Reference< XCloneable > xClone = xCloneAccess->createClone(); + m_xAggregate = Reference< XAggregation >( xClone, UNO_QUERY ); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : invalid aggregate clone!"); + + query_interface( Reference< XInterface >( xClone.get() ), m_xFormattedPart ); + + if ( _pCloneSource->m_pEditPart ) + { + m_pEditPart = new OEditModel( _pCloneSource->m_pEditPart, _pCloneSource->m_xServiceFactory ); + m_pEditPart->acquire(); + } + } + if ( m_xAggregate.is() ) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); + } + decrement( m_refCount ); + } + else + { // the clone source does not yet have an aggregate -> we don't yet need one, too + } +} + +//------------------------------------------------------------------ +OFormattedFieldWrapper::~OFormattedFieldWrapper() +{ + // release the aggregated object (if any) + if (m_xAggregate.is()) + m_xAggregate->setDelegator(InterfaceRef ()); + + if (m_pEditPart) + m_pEditPart->release(); + + DBG_DTOR(OFormattedFieldWrapper, NULL); +} + +//------------------------------------------------------------------ +Any SAL_CALL OFormattedFieldWrapper::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn; + + if (_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >(NULL) ) ) ) + { // a XTypeProvider interface needs a working aggregate - we don't want to give the type provider + // of our base class (OFormattedFieldWrapper_Base) to the caller as it supplies nearly nothing + ensureAggregate(); + if (m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + + if (!aReturn.hasValue()) + { + aReturn = OFormattedFieldWrapper_Base::queryAggregation(_rType); + + if ((_rType.equals( ::getCppuType( static_cast< Reference< XServiceInfo >* >(NULL) ) ) ) && aReturn.hasValue()) + { // somebody requested an XServiceInfo interface and our base class provided it + // check our aggregate if it has one, too + ensureAggregate(); + } + + if (!aReturn.hasValue()) + { + aReturn = ::cppu::queryInterface( _rType, + static_cast< XPersistObject* >( this ), + static_cast< XCloneable* >( this ) + ); + + if (!aReturn.hasValue()) + { + // somebody requests an interface other than the basics (XInterface) and other than + // the two we can supply without an aggregate. So ensure + // the aggregate exists. + ensureAggregate(); + if (m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + } + } + + return aReturn; +} + +//------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormattedFieldWrapper::getServiceName() throw(RuntimeException) +{ + // return the old compatibility name for an EditModel + return FRM_COMPONENT_EDIT; +} + +//------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormattedFieldWrapper::getImplementationName( ) throw (RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.OFormattedFieldWrapper"); +} + +//------------------------------------------------------------------ +sal_Bool SAL_CALL OFormattedFieldWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::supportsService: should never have made it 'til here without an aggregate!"); + Reference< XServiceInfo > xSI; + m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI; + return xSI->supportsService(_rServiceName); +} + +//------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OFormattedFieldWrapper::getSupportedServiceNames( ) throw (RuntimeException) +{ + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::getSupportedServiceNames: should never have made it 'til here without an aggregate!"); + Reference< XServiceInfo > xSI; + m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI; + return xSI->getSupportedServiceNames(); +} + +//------------------------------------------------------------------ +void SAL_CALL OFormattedFieldWrapper::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException ) +{ + // can't write myself + ensureAggregate(); + + // if we act as real edit field, we can simple forward this write request + if (!m_xFormattedPart.is()) + { + Reference<XPersistObject> xAggregatePersistence; + query_aggregation(m_xAggregate, xAggregatePersistence); + DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::write : don't know how to handle this : can't write !"); + // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ... + if (xAggregatePersistence.is()) + xAggregatePersistence->write(_rxOutStream); + return; + } + + // else we have to write an edit part first + DBG_ASSERT(m_pEditPart, "OFormattedFieldWrapper::write : formatted part without edit part ?"); + if ( !m_pEditPart ) + throw RuntimeException( ::rtl::OUString(), *this ); + + // for this we transfer the current props of the formatted part to the edit part + Reference<XPropertySet> xFormatProps(m_xFormattedPart, UNO_QUERY); + Reference<XPropertySet> xEditProps; + query_interface(static_cast<XWeak*>(m_pEditPart), xEditProps); + + Locale aAppLanguage = Application::GetSettings().GetUILocale(); + dbtools::TransferFormComponentProperties(xFormatProps, xEditProps, aAppLanguage); + + // then write the edit part, after switching to "fake mode" + m_pEditPart->enableFormattedWriteFake(); + m_pEditPart->write(_rxOutStream); + m_pEditPart->disableFormattedWriteFake(); + + // and finally write the formatted part we're really interested in + m_xFormattedPart->write(_rxOutStream); +} + +//------------------------------------------------------------------ +void SAL_CALL OFormattedFieldWrapper::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException ) +{ + if (m_xAggregate.is()) + { // we alread did a decision if we're an EditModel or a FormattedModel + + // if we act as formatted, we have to read the edit part first + if (m_xFormattedPart.is()) + { + // two possible cases: + // a) the stuff was written by a version which didn't work with an Edit header (all intermediate + // versions >5.1 && <=568) + // b) it was written by a version using edit headers + // as we can distinguish a) from b) only after we have read the edit part, we need to remember the + // position + Reference<XMarkableStream> xInMarkable(_rxInStream, UNO_QUERY); + DBG_ASSERT(xInMarkable.is(), "OFormattedFieldWrapper::read : can only work with markable streams !"); + sal_Int32 nBeforeEditPart = xInMarkable->createMark(); + + m_pEditPart->read(_rxInStream); + // this only works because an edit model can read the stuff written by a formatted model (maybe with + // some assertions) , but not vice versa + if (!m_pEditPart->lastReadWasFormattedFake()) + { // case a), written with a version without the edit part fake, so seek to the start position, again + xInMarkable->jumpToMark(nBeforeEditPart); + } + xInMarkable->deleteMark(nBeforeEditPart); + } + + Reference<XPersistObject> xAggregatePersistence; + query_aggregation(m_xAggregate, xAggregatePersistence); + DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::read : don't know how to handle this : can't read !"); + // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ... + + if (xAggregatePersistence.is()) + xAggregatePersistence->read(_rxInStream); + return; + } + + // we have to decide from the data within the stream whether we should be an EditModel or a FormattedModel + OEditBaseModel* pNewAggregate = NULL; + + // let an OEditModel do the reading + OEditModel* pBasicReader = new OEditModel(m_xServiceFactory); + Reference< XInterface > xHoldBasicReaderAlive( *pBasicReader ); + pBasicReader->read(_rxInStream); + + // was it really an edit model ? + if (!pBasicReader->lastReadWasFormattedFake()) + // yes -> all fine + pNewAggregate = pBasicReader; + else + { // no -> substitute it with a formatted model + + // let the formmatted model do the reading + OFormattedModel* pFormattedReader = new OFormattedModel(m_xServiceFactory); + Reference< XInterface > xHoldAliveWhileRead( *pFormattedReader ); + pFormattedReader->read(_rxInStream); + + // for the next write (if any) : the FormattedModel and the EditModel parts + query_interface(static_cast<XWeak*>(pFormattedReader), m_xFormattedPart); + m_pEditPart = pBasicReader; + m_pEditPart->acquire(); + + // aggregate the formatted part below + pNewAggregate = pFormattedReader; + } + + // do the aggregation + increment(m_refCount); + { + query_interface(static_cast<XWeak*>(pNewAggregate), m_xAggregate); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::read : the OEditModel didn't have an XAggregation interface !"); + } + if (m_xAggregate.is()) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); +} + +//------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OFormattedFieldWrapper::createClone( ) throw (RuntimeException) +{ + ensureAggregate(); + + return new OFormattedFieldWrapper( this ); +} + +//------------------------------------------------------------------ +void OFormattedFieldWrapper::ensureAggregate() +{ + if (m_xAggregate.is()) + return; + + increment(m_refCount); + { + // instantiate an EditModel (the only place where we are allowed to decide that we're an FormattedModel + // is in ::read) + InterfaceRef xEditModel = m_xServiceFactory->createInstance(FRM_SUN_COMPONENT_TEXTFIELD); + if (!xEditModel.is()) + { + // arghhh ... instantiate it directly ... it's dirty, but we really need this aggregate + OEditModel* pModel = new OEditModel(m_xServiceFactory); + query_interface(static_cast<XWeak*>(pModel), xEditModel); + } + + m_xAggregate = Reference<XAggregation> (xEditModel, UNO_QUERY); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::ensureAggregate : the OEditModel didn't have an XAggregation interface !"); + + { + Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY); + if (!xSI.is()) + { + DBG_ERROR("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!"); + m_xAggregate.clear(); + } + } + } + if (m_xAggregate.is()) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); +} + +//......................................................................... +} +//......................................................................... + + diff --git a/forms/source/component/FormattedFieldWrapper.hxx b/forms/source/component/FormattedFieldWrapper.hxx new file mode 100644 index 000000000000..a3cfcaab50d0 --- /dev/null +++ b/forms/source/component/FormattedFieldWrapper.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_FORMATTED_FIELD_WRAPPER_HXX_ +#define _FRM_FORMATTED_FIELD_WRAPPER_HXX_ + +#include "FormComponent.hxx" +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +//......................................................................... +namespace frm +{ + +class OEditModel; +//================================================================== +//= OFormattedFieldWrapper +//================================================================== +typedef ::cppu::WeakAggImplHelper3 < ::com::sun::star::io::XPersistObject + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::util::XCloneable + > OFormattedFieldWrapper_Base; + +class OFormattedFieldWrapper : public OFormattedFieldWrapper_Base +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory> m_xServiceFactory; + +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; + + OEditModel* m_pEditPart; + // if we act as formatted this is used to write the EditModel part + ::com::sun::star::uno::Reference< ::com::sun::star::io::XPersistObject> m_xFormattedPart; + // if we act as formatted, this is the PersistObject interface of our aggregate, used + // to read and write the FormattedModel part + + OFormattedFieldWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, sal_Bool _bActAsFormatted); + // if _bActAsFormatted is sal_False, the state is undetermined until somebody calls ::read or does + // anything which requires a living aggregate + OFormattedFieldWrapper( const OFormattedFieldWrapper* _pCloneSource ); + virtual ~OFormattedFieldWrapper(); + + friend InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + friend InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + +public: + // UNO + DECLARE_UNO3_AGG_DEFAULTS(OFormattedFieldWrapper, OWeakAggObject); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + +protected: + /// ensure we're in a defined state, which means a FormattedModel _OR_ an EditModel + void ensureAggregate(); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FRM_FORMATTED_FIELD_WRAPPER_HXX_ + diff --git a/forms/source/component/FormsCollection.cxx b/forms/source/component/FormsCollection.cxx new file mode 100644 index 000000000000..2664a74546e8 --- /dev/null +++ b/forms/source/component/FormsCollection.cxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "FormsCollection.hxx" +#include "services.hxx" +#include <comphelper/sequence.hxx> +#include <tools/debug.hxx> +#include <com/sun/star/form/XForm.hpp> +#include <rtl/logfile.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------ +DBG_NAME(OFormsCollection) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormsCollection_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormsCollection(_rxFactory)); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormsCollection::getServiceName() throw(RuntimeException) +{ + return FRM_SUN_FORMS_COLLECTION; +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > SAL_CALL OFormsCollection::getImplementationId( ) throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------------------ +Sequence<Type> SAL_CALL OFormsCollection::getTypes() throw(RuntimeException) +{ + return concatSequences(OInterfaceContainer::getTypes(), FormsCollectionComponentBase::getTypes(), OFormsCollection_BASE::getTypes()); +} + +//------------------------------------------------------------------ +OFormsCollection::OFormsCollection(const Reference<XMultiServiceFactory>& _rxFactory) + :FormsCollectionComponentBase( m_aMutex ) + ,OInterfaceContainer( _rxFactory, m_aMutex, XForm::static_type() ) + ,OFormsCollection_BASE() +{ + DBG_CTOR(OFormsCollection, NULL); +} + +//------------------------------------------------------------------------------ +OFormsCollection::OFormsCollection( const OFormsCollection& _cloneSource ) + :FormsCollectionComponentBase( m_aMutex ) + ,OInterfaceContainer( m_aMutex, _cloneSource ) + ,OFormsCollection_BASE() +{ + DBG_CTOR( OFormsCollection, NULL ); +} + +//------------------------------------------------------------------------------ +OFormsCollection::~OFormsCollection() +{ + DBG_DTOR(OFormsCollection, NULL); + if (!FormsCollectionComponentBase::rBHelper.bDisposed) + { + acquire(); + dispose(); + } +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OFormsCollection::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = OFormsCollection_BASE::queryInterface(_rType); + if (!aReturn.hasValue()) + { + aReturn = OInterfaceContainer::queryInterface(_rType); + + if (!aReturn.hasValue()) + aReturn = FormsCollectionComponentBase::queryAggregation(_rType); + } + + return aReturn; +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormsCollection::getImplementationName() throw(RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.OFormsCollection"); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OFormsCollection::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) +{ + Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); + const rtl::OUString* pSupported = aSupported.getConstArray(); + for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) + if (pSupported->equals(_rServiceName)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OFormsCollection::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aReturn(2); + + aReturn.getArray()[0] = FRM_SUN_FORMS_COLLECTION; + aReturn.getArray()[1] = ::rtl::OUString::createFromAscii("com.sun.star.form.FormComponents"); + + return aReturn; +} + +// XCloneable +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OFormsCollection::createClone( ) throw (RuntimeException) +{ + OFormsCollection* pClone = new OFormsCollection( *this ); + osl_incrementInterlockedCount( &pClone->m_refCount ); + pClone->clonedFrom( *this ); + osl_decrementInterlockedCount( &pClone->m_refCount ); + return pClone; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OFormsCollection::disposing() +{ + { + RTL_LOGFILE_CONTEXT( aLogger, "forms::OFormsCollection::disposing" ); + OInterfaceContainer::disposing(); + } + FormsCollectionComponentBase::disposing(); + m_xParent = NULL; +} + +//XChild +//------------------------------------------------------------------------------ +void OFormsCollection::setParent(const InterfaceRef& Parent) throw( NoSupportException, RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_xParent = Parent; +} + +//------------------------------------------------------------------------------ +InterfaceRef OFormsCollection::getParent() throw( RuntimeException ) +{ + return m_xParent; +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/FormsCollection.hxx b/forms/source/component/FormsCollection.hxx new file mode 100644 index 000000000000..705ac89b211a --- /dev/null +++ b/forms/source/component/FormsCollection.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "InterfaceContainer.hxx" +#include "ids.hxx" +#include <cppuhelper/component.hxx> +#include <cppuhelper/implbase2.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OFormsCollection +// Implementiert den UNO-Container fuer Formulare +// enthaelt alle zugeordneten Forms +// dieses Container kann selbst den Context fuer Formulare darstellen +// oder aussen einen Context uebergeben bekommen +//================================================================== +typedef ::cppu::OComponentHelper FormsCollectionComponentBase; +typedef ::cppu::ImplHelper2< ::com::sun::star::container::XChild + ,::com::sun::star::lang::XServiceInfo > OFormsCollection_BASE; + + // else MSVC kills itself on some statements +class OFormsCollection + :public FormsCollectionComponentBase + ,public OInterfaceContainer + ,public OFormsCollection_BASE +{ + ::osl::Mutex m_aMutex; + OImplementationIdsRef m_aHoldIdHelper; + ::comphelper::InterfaceRef m_xParent; // Parent + +public: + OFormsCollection(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + OFormsCollection( const OFormsCollection& _cloneSource ); + virtual ~OFormsCollection(); + +public: + DECLARE_UNO3_AGG_DEFAULTS(OFormsCollection, FormsCollectionComponentBase); + + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // ::com::sun::star::container::XChild + virtual ::comphelper::InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent(const ::comphelper::InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OInterfaceContainer::disposing; +}; + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Grid.cxx b/forms/source/component/Grid.cxx new file mode 100644 index 000000000000..c7b65906dc30 --- /dev/null +++ b/forms/source/component/Grid.cxx @@ -0,0 +1,1163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Columns.hxx" +#include "findpos.hxx" +#include "Grid.hxx" +#include "property.hrc" +#include "property.hxx" +#include "services.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/container.hxx> +#include <comphelper/extract.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star::uno; + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::view; + +namespace WritingMode2 = ::com::sun::star::text::WritingMode2; + +const sal_uInt16 ROWHEIGHT = 0x0001; +const sal_uInt16 FONTTYPE = 0x0002; +const sal_uInt16 FONTSIZE = 0x0004; +const sal_uInt16 FONTATTRIBS = 0x0008; +const sal_uInt16 TABSTOP = 0x0010; +const sal_uInt16 TEXTCOLOR = 0x0020; +const sal_uInt16 FONTDESCRIPTOR = 0x0040; +const sal_uInt16 RECORDMARKER = 0x0080; +const sal_uInt16 BACKGROUNDCOLOR = 0x0100; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OGridControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OGridControlModel(_rxFactory)); +} + +DBG_NAME(OGridControlModel); +//------------------------------------------------------------------ +OGridControlModel::OGridControlModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, ::rtl::OUString()) + ,OInterfaceContainer(_rxFactory, m_aMutex, ::getCppuType(static_cast<Reference<XPropertySet>*>(NULL))) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,FontControlModel( false ) + ,m_aSelectListeners(m_aMutex) + ,m_aResetListeners(m_aMutex) + ,m_aRowSetChangeListeners(m_aMutex) + ,m_aDefaultControl( FRM_SUN_CONTROL_GRIDCONTROL ) + ,m_nBorder(1) + ,m_nWritingMode( WritingMode2::CONTEXT ) + ,m_nContextWritingMode( WritingMode2::CONTEXT ) + ,m_bEnableVisible(sal_True) + ,m_bEnable(sal_True) + ,m_bNavigation(sal_True) + ,m_bRecordMarker(sal_True) + ,m_bPrintable(sal_True) + ,m_bAlwaysShowCursor(sal_False) + ,m_bDisplaySynchron(sal_True) +{ + DBG_CTOR(OGridControlModel,NULL); + + m_nClassId = FormComponentType::GRIDCONTROL; +} + +//------------------------------------------------------------------ +OGridControlModel::OGridControlModel( const OGridControlModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,OInterfaceContainer( _rxFactory, m_aMutex, ::getCppuType( static_cast<Reference<XPropertySet>*>( NULL ) ) ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,FontControlModel( _pOriginal ) + ,m_aSelectListeners( m_aMutex ) + ,m_aResetListeners( m_aMutex ) + ,m_aRowSetChangeListeners( m_aMutex ) +{ + DBG_CTOR(OGridControlModel,NULL); + + m_aDefaultControl = _pOriginal->m_aDefaultControl; + m_bEnable = _pOriginal->m_bEnable; + m_bEnableVisible = _pOriginal->m_bEnableVisible; + m_bNavigation = _pOriginal->m_bNavigation; + m_nBorder = _pOriginal->m_nBorder; + m_nWritingMode = _pOriginal->m_nWritingMode; + m_nContextWritingMode = _pOriginal->m_nContextWritingMode; + m_bRecordMarker = _pOriginal->m_bRecordMarker; + m_bPrintable = _pOriginal->m_bPrintable; + m_bAlwaysShowCursor = _pOriginal->m_bAlwaysShowCursor; + m_bDisplaySynchron = _pOriginal->m_bDisplaySynchron; + + // clone the columns + cloneColumns( _pOriginal ); + + // TODO: clone the events? +} + +//------------------------------------------------------------------ +OGridControlModel::~OGridControlModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OGridControlModel,NULL); +} + +// XCloneable +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OGridControlModel::createClone( ) throw (RuntimeException) +{ + OGridControlModel* pClone = new OGridControlModel( this, getContext().getLegacyServiceFactory() ); + osl_incrementInterlockedCount( &pClone->m_refCount ); + pClone->OControlModel::clonedFrom( this ); + // do not call OInterfaceContainer::clonedFrom, it would clone the elements aka columns, which is + // already done in the ctor + //pClone->OInterfaceContainer::clonedFrom( *this ); + osl_decrementInterlockedCount( &pClone->m_refCount ); + return static_cast< XCloneable* >( static_cast< OControlModel* >( pClone ) ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::cloneColumns( const OGridControlModel* _pOriginalContainer ) +{ + try + { + Reference< XCloneable > xColCloneable; + + const OInterfaceArray::const_iterator pColumnStart = _pOriginalContainer->m_aItems.begin(); + const OInterfaceArray::const_iterator pColumnEnd = _pOriginalContainer->m_aItems.end(); + for ( OInterfaceArray::const_iterator pColumn = pColumnStart; pColumn != pColumnEnd; ++pColumn ) + { + // ask the col for a factory for the clone + xColCloneable = xColCloneable.query( *pColumn ); + DBG_ASSERT( xColCloneable.is(), "OGridControlModel::cloneColumns: column is not cloneable!" ); + + if ( xColCloneable.is() ) + { + // create a clone of the column + Reference< XCloneable > xColClone( xColCloneable->createClone() ); + DBG_ASSERT( xColClone.is(), "OGridControlModel::cloneColumns: invalid column clone!" ); + + if ( xColClone.is() ) + { + // insert this clone into our own container + insertByIndex( pColumn - pColumnStart, xColClone->queryInterface( m_aElementType ) ); + } + + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "OGridControlModel::cloneColumns: caught an exception while cloning the columns!" ); + } +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OGridControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 2); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-2] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlModel")); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_GRIDCONTROL; + return aSupported; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OGridControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn = OGridControlModel_BASE::queryInterface(_rType); + + if ( !aReturn.hasValue() ) + { + aReturn = OControlModel::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + { + aReturn = OInterfaceContainer::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OErrorBroadcaster::queryInterface( _rType ); + } + } + return aReturn; +} + +// XSQLErrorListener +//------------------------------------------------------------------------------ +void SAL_CALL OGridControlModel::errorOccured( const SQLErrorEvent& _rEvent ) throw (RuntimeException) +{ + // forward the errors which happened to my columns to my own listeners + onError( _rEvent ); +} + +// XRowSetSupplier +//------------------------------------------------------------------------------ +Reference< XRowSet > SAL_CALL OGridControlModel::getRowSet( ) throw (RuntimeException) +{ + return Reference< XRowSet >( getParent(), UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGridControlModel::setRowSet( const Reference< XRowSet >& /*_rxDataSource*/ ) throw (RuntimeException) +{ + OSL_ENSURE( false, "OGridControlModel::setRowSet: not supported!" ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OGridControlModel::addRowSetChangeListener( const Reference< XRowSetChangeListener >& i_Listener ) throw (RuntimeException) +{ + if ( i_Listener.is() ) + m_aRowSetChangeListeners.addInterface( i_Listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OGridControlModel::removeRowSetChangeListener( const Reference< XRowSetChangeListener >& i_Listener ) throw (RuntimeException) +{ + m_aRowSetChangeListeners.removeInterface( i_Listener ); +} + +// XChild +//------------------------------------------------------------------------------ +void SAL_CALL OGridControlModel::setParent( const InterfaceRef& i_Parent ) throw(NoSupportException, RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( i_Parent == getParent() ) + return; + + OControlModel::setParent( i_Parent ); + + EventObject aEvent( *this ); + aGuard.clear(); + m_aRowSetChangeListeners.notifyEach( &XRowSetChangeListener::onRowSetChanged, aEvent ); +} + +//------------------------------------------------------------------------------ +Sequence< Type > SAL_CALL OGridControlModel::getTypes( ) throw(RuntimeException) +{ + return concatSequences( + concatSequences( + OControlModel::getTypes(), + OInterfaceContainer::getTypes(), + OErrorBroadcaster::getTypes() + ), + OGridControlModel_BASE::getTypes() + ); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OGridControlModel::disposing() +{ + OControlModel::disposing(); + OErrorBroadcaster::disposing(); + OInterfaceContainer::disposing(); + + setParent(NULL); + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aSelectListeners.disposeAndClear(aEvt); + m_aResetListeners.disposeAndClear(aEvt); + m_aRowSetChangeListeners.disposeAndClear(aEvt); +} + +// XEventListener +//------------------------------------------------------------------------------ +void OGridControlModel::disposing(const EventObject& _rEvent) throw( RuntimeException ) +{ + OControlModel::disposing( _rEvent ); + OInterfaceContainer::disposing( _rEvent ); +} + +// XSelectionSupplier +//----------------------------------------------------------------------------- +sal_Bool SAL_CALL OGridControlModel::select(const Any& rElement) throw(IllegalArgumentException, RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + Reference<XPropertySet> xSel; + if (rElement.hasValue() && !::cppu::extractInterface(xSel, rElement)) + { + throw IllegalArgumentException(); + } + InterfaceRef xMe = static_cast<XWeak*>(this); + + if (xSel.is()) + { + Reference<XChild> xAsChild(xSel, UNO_QUERY); + if (!xAsChild.is() || (xAsChild->getParent() != xMe)) + { + throw IllegalArgumentException(); + } + } + + if ( xSel != m_xSelection ) + { + m_xSelection = xSel; + aGuard.clear(); + m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, EventObject( *this ) ); + return sal_True; + } + return sal_False; +} + +//----------------------------------------------------------------------------- +Any SAL_CALL OGridControlModel::getSelection() throw(RuntimeException) +{ + return makeAny(m_xSelection); +} + +//----------------------------------------------------------------------------- +void OGridControlModel::addSelectionChangeListener(const Reference< XSelectionChangeListener >& _rxListener) throw( RuntimeException ) +{ + m_aSelectListeners.addInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void OGridControlModel::removeSelectionChangeListener(const Reference< XSelectionChangeListener >& _rxListener) throw( RuntimeException ) +{ + m_aSelectListeners.removeInterface(_rxListener); +} + +// XGridColumnFactory +//------------------------------------------------------------------------------ +Reference<XPropertySet> SAL_CALL OGridControlModel::createColumn(const ::rtl::OUString& ColumnType) throw ( :: com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + const Sequence< ::rtl::OUString >& rColumnTypes = frm::getColumnTypes(); + return createColumn( detail::findPos( ColumnType, rColumnTypes ) ); +} + +//------------------------------------------------------------------------------ +Reference<XPropertySet> OGridControlModel::createColumn(sal_Int32 nTypeId) const +{ + Reference<XPropertySet> xReturn; + switch (nTypeId) + { + case TYPE_CHECKBOX: xReturn = new CheckBoxColumn( getContext() ); break; + case TYPE_COMBOBOX: xReturn = new ComboBoxColumn( getContext() ); break; + case TYPE_CURRENCYFIELD: xReturn = new CurrencyFieldColumn( getContext() ); break; + case TYPE_DATEFIELD: xReturn = new DateFieldColumn( getContext() ); break; + case TYPE_LISTBOX: xReturn = new ListBoxColumn( getContext() ); break; + case TYPE_NUMERICFIELD: xReturn = new NumericFieldColumn( getContext() ); break; + case TYPE_PATTERNFIELD: xReturn = new PatternFieldColumn( getContext() ); break; + case TYPE_TEXTFIELD: xReturn = new TextFieldColumn( getContext() ); break; + case TYPE_TIMEFIELD: xReturn = new TimeFieldColumn( getContext() ); break; + case TYPE_FORMATTEDFIELD: xReturn = new FormattedFieldColumn( getContext() ); break; + default: + DBG_ERROR("OGridControlModel::createColumn: Unknown Column"); + break; + } + return xReturn; +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OGridControlModel::getColumnTypes() throw ( ::com::sun::star::uno::RuntimeException) +{ + return frm::getColumnTypes(); +} + +// XReset +//----------------------------------------------------------------------------- +void SAL_CALL OGridControlModel::reset() throw ( ::com::sun::star::uno::RuntimeException) +{ + ::cppu::OInterfaceIteratorHelper aIter(m_aResetListeners); + EventObject aEvt(static_cast<XWeak*>(this)); + sal_Bool bContinue = sal_True; + while (aIter.hasMoreElements() && bContinue) + bContinue =((XResetListener*)aIter.next())->approveReset(aEvt); + + if (bContinue) + { + _reset(); + m_aResetListeners.notifyEach( &XResetListener::resetted, aEvt ); + } +} + +//----------------------------------------------------------------------------- +void SAL_CALL OGridControlModel::addResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.addInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void SAL_CALL OGridControlModel::removeResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.removeInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void OGridControlModel::_reset() +{ + Reference<XReset> xReset; + sal_Int32 nCount = getCount(); + for (sal_Int32 nIndex=0; nIndex < nCount; nIndex++) + { + getByIndex( nIndex ) >>= xReset; + if (xReset.is()) + xReset->reset(); + } +} + +// XPropertySet +//------------------------------------------------------------------------------ +void OGridControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_BASE_PROPERTIES( 37 ) + DECL_PROP1(NAME, ::rtl::OUString, BOUND); + DECL_PROP2(CLASSID, sal_Int16, READONLY, TRANSIENT); + DECL_PROP1(TAG, ::rtl::OUString, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP3(TABSTOP, sal_Bool, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP2(HASNAVIGATION, sal_Bool, BOUND, MAYBEDEFAULT); + DECL_PROP1(ENABLED, sal_Bool, BOUND); + DECL_PROP2(ENABLEVISIBLE, sal_Bool, BOUND, MAYBEDEFAULT); + DECL_PROP1(BORDER, sal_Int16, BOUND); + DECL_PROP2(BORDERCOLOR, sal_Int16, BOUND, MAYBEVOID); + DECL_PROP1(DEFAULTCONTROL, ::rtl::OUString, BOUND); + DECL_PROP3(TEXTCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP3(BACKGROUNDCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP2(FONT, FontDescriptor, BOUND, MAYBEDEFAULT); + DECL_PROP3(ROWHEIGHT, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(HELPTEXT, ::rtl::OUString, BOUND); + DECL_PROP1(FONT_NAME, ::rtl::OUString, MAYBEDEFAULT); + DECL_PROP1(FONT_STYLENAME, ::rtl::OUString, MAYBEDEFAULT); + DECL_PROP1(FONT_FAMILY, sal_Int16, MAYBEDEFAULT); + DECL_PROP1(FONT_CHARSET, sal_Int16, MAYBEDEFAULT); + DECL_PROP1(FONT_HEIGHT, float, MAYBEDEFAULT); + DECL_PROP1(FONT_WEIGHT, float, MAYBEDEFAULT); + DECL_PROP1(FONT_SLANT, sal_Int16, MAYBEDEFAULT); + DECL_PROP1(FONT_UNDERLINE, sal_Int16, MAYBEDEFAULT); + DECL_BOOL_PROP1(FONT_WORDLINEMODE, MAYBEDEFAULT); + DECL_PROP3(TEXTLINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP2(FONTEMPHASISMARK, sal_Int16, BOUND, MAYBEDEFAULT); + DECL_PROP2(FONTRELIEF, sal_Int16, BOUND, MAYBEDEFAULT); + DECL_PROP1(FONT_STRIKEOUT, sal_Int16, MAYBEDEFAULT); + DECL_PROP2(RECORDMARKER, sal_Bool, BOUND, MAYBEDEFAULT ); + DECL_PROP2(PRINTABLE, sal_Bool, BOUND, MAYBEDEFAULT ); + DECL_PROP4(CURSORCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID , TRANSIENT); + DECL_PROP3(ALWAYSSHOWCURSOR, sal_Bool, BOUND, MAYBEDEFAULT, TRANSIENT); + DECL_PROP3(DISPLAYSYNCHRON, sal_Bool, BOUND, MAYBEDEFAULT, TRANSIENT); + DECL_PROP2(HELPURL, ::rtl::OUString, BOUND, MAYBEDEFAULT); + DECL_PROP2(WRITING_MODE, sal_Int16, BOUND, MAYBEDEFAULT); + DECL_PROP3(CONTEXT_WRITING_MODE,sal_Int16, BOUND, MAYBEDEFAULT, TRANSIENT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + rValue <<= m_nContextWritingMode; + break; + case PROPERTY_ID_WRITING_MODE: + rValue <<= m_nWritingMode; + break; + case PROPERTY_ID_HELPTEXT: + rValue <<= m_sHelpText; + break; + case PROPERTY_ID_HELPURL: + rValue <<= m_sHelpURL; + break; + case PROPERTY_ID_DISPLAYSYNCHRON: + setBOOL(rValue, m_bDisplaySynchron); + break; + case PROPERTY_ID_ALWAYSSHOWCURSOR: + setBOOL(rValue, m_bAlwaysShowCursor); + break; + case PROPERTY_ID_CURSORCOLOR: + rValue = m_aCursorColor; + break; + case PROPERTY_ID_PRINTABLE: + setBOOL(rValue, m_bPrintable); + break; + case PROPERTY_ID_TABSTOP: + rValue = m_aTabStop; + break; + case PROPERTY_ID_HASNAVIGATION: + setBOOL(rValue, m_bNavigation); + break; + case PROPERTY_ID_RECORDMARKER: + setBOOL(rValue, m_bRecordMarker); + break; + case PROPERTY_ID_ENABLED: + setBOOL(rValue, m_bEnable); + break; + case PROPERTY_ID_ENABLEVISIBLE: + setBOOL(rValue, m_bEnableVisible); + break; + case PROPERTY_ID_BORDER: + rValue <<= (sal_Int16)m_nBorder; + break; + case PROPERTY_ID_BORDERCOLOR: + rValue <<= m_aBorderColor; + break; + case PROPERTY_ID_DEFAULTCONTROL: + rValue <<= m_aDefaultControl; + break; + case PROPERTY_ID_BACKGROUNDCOLOR: + rValue = m_aBackgroundColor; + break; + case PROPERTY_ID_ROWHEIGHT: + rValue = m_aRowHeight; + break; + + default: + if ( isFontRelatedProperty( nHandle ) ) + FontControlModel::getFastPropertyValue( rValue, nHandle ); + else + OControlModel::getFastPropertyValue( rValue, nHandle ); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OGridControlModel::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue )throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_nContextWritingMode ); + break; + case PROPERTY_ID_WRITING_MODE: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_nWritingMode ); + break; + case PROPERTY_ID_HELPTEXT: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sHelpText); + break; + case PROPERTY_ID_HELPURL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sHelpURL); + break; + case PROPERTY_ID_DISPLAYSYNCHRON: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDisplaySynchron); + break; + case PROPERTY_ID_ALWAYSSHOWCURSOR: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAlwaysShowCursor); + break; + case PROPERTY_ID_CURSORCOLOR: + if (!rValue.hasValue() || !m_aCursorColor.hasValue()) + { + if (rValue.hasValue() && (TypeClass_LONG != rValue.getValueType().getTypeClass())) + { + throw IllegalArgumentException(); + } + rOldValue = m_aCursorColor; + rConvertedValue = rValue; + bModified = (rOldValue.getValue() != rConvertedValue.getValue()); + } + else + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, getINT32(m_aCursorColor)); + break; + case PROPERTY_ID_PRINTABLE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bPrintable); + break; + case PROPERTY_ID_TABSTOP: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTabStop, ::getBooleanCppuType()); + break; + case PROPERTY_ID_HASNAVIGATION: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bNavigation); + break; + case PROPERTY_ID_RECORDMARKER: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bRecordMarker); + break; + case PROPERTY_ID_ENABLED: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEnable); + break; + case PROPERTY_ID_ENABLEVISIBLE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEnableVisible); + break; + case PROPERTY_ID_BORDER: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_nBorder); + break; + case PROPERTY_ID_BORDERCOLOR: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aBorderColor, ::getCppuType((const sal_Int32*)NULL)); + break; + case PROPERTY_ID_DEFAULTCONTROL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefaultControl); + break; + case PROPERTY_ID_BACKGROUNDCOLOR: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aBackgroundColor, ::getCppuType((const sal_Int32*)NULL)); + break; + case PROPERTY_ID_ROWHEIGHT: + { + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aRowHeight, ::getCppuType((const sal_Int32*)NULL)); + + sal_Int32 nNewVal( 0 ); + if ( ( rConvertedValue >>= nNewVal ) && ( nNewVal <= 0 ) ) + { + rConvertedValue.clear(); + bModified = m_aRowHeight.hasValue(); + } + } + break; + default: + if ( isFontRelatedProperty( nHandle ) ) + bModified = FontControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + else + bModified = OControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue); + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OGridControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + rValue >>= m_nContextWritingMode; + break; + case PROPERTY_ID_WRITING_MODE: + rValue >>= m_nWritingMode; + break; + case PROPERTY_ID_HELPTEXT: + rValue >>= m_sHelpText; + break; + case PROPERTY_ID_HELPURL: + rValue >>= m_sHelpURL; + break; + case PROPERTY_ID_DISPLAYSYNCHRON: + m_bDisplaySynchron = getBOOL(rValue); + break; + case PROPERTY_ID_ALWAYSSHOWCURSOR: + m_bAlwaysShowCursor = getBOOL(rValue); + break; + case PROPERTY_ID_CURSORCOLOR: + m_aCursorColor = rValue; + break; + case PROPERTY_ID_PRINTABLE: + m_bPrintable = getBOOL(rValue); + break; + case PROPERTY_ID_TABSTOP: + m_aTabStop = rValue; + break; + case PROPERTY_ID_HASNAVIGATION: + m_bNavigation = getBOOL(rValue); + break; + case PROPERTY_ID_ENABLED: + m_bEnable = getBOOL(rValue); + break; + case PROPERTY_ID_ENABLEVISIBLE: + m_bEnableVisible = getBOOL(rValue); + break; + case PROPERTY_ID_RECORDMARKER: + m_bRecordMarker = getBOOL(rValue); + break; + case PROPERTY_ID_BORDER: + rValue >>= m_nBorder; + break; + case PROPERTY_ID_BORDERCOLOR: + m_aBorderColor = rValue; + break; + case PROPERTY_ID_DEFAULTCONTROL: + rValue >>= m_aDefaultControl; + break; + case PROPERTY_ID_BACKGROUNDCOLOR: + m_aBackgroundColor = rValue; + break; + case PROPERTY_ID_ROWHEIGHT: + m_aRowHeight = rValue; + break; + + default: + if ( isFontRelatedProperty( nHandle ) ) + { + FontDescriptor aOldFont( getFont() ); + + FontControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + + if ( isFontAggregateProperty( nHandle ) ) + firePropertyChange( PROPERTY_ID_FONT, makeAny( getFont() ), makeAny( aOldFont ) ); + } + else + OControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } + +} + +//XPropertyState + +//------------------------------------------------------------------------------ +Any OGridControlModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + Any aReturn; + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + case PROPERTY_ID_WRITING_MODE: + aReturn <<= WritingMode2::CONTEXT; + break; + + case PROPERTY_ID_DEFAULTCONTROL: + aReturn <<= ::rtl::OUString( STARDIV_ONE_FORM_CONTROL_GRID ); + break; + + case PROPERTY_ID_PRINTABLE: + case PROPERTY_ID_HASNAVIGATION: + case PROPERTY_ID_RECORDMARKER: + case PROPERTY_ID_DISPLAYSYNCHRON: + case PROPERTY_ID_ENABLED: + case PROPERTY_ID_ENABLEVISIBLE: + aReturn = makeBoolAny(sal_True); + break; + + case PROPERTY_ID_ALWAYSSHOWCURSOR: + aReturn = makeBoolAny(sal_False); + break; + + case PROPERTY_ID_HELPURL: + case PROPERTY_ID_HELPTEXT: + aReturn <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_BORDER: + aReturn <<= (sal_Int16)1; + break; + + case PROPERTY_ID_BORDERCOLOR: + case PROPERTY_ID_TABSTOP: + case PROPERTY_ID_BACKGROUNDCOLOR: + case PROPERTY_ID_ROWHEIGHT: + case PROPERTY_ID_CURSORCOLOR: + // void + break; + + default: + if ( isFontRelatedProperty( nHandle ) ) + aReturn = FontControlModel::getPropertyDefaultByHandle( nHandle ); + else + aReturn = OControlModel::getPropertyDefaultByHandle(nHandle); + } + return aReturn; +} + +//------------------------------------------------------------------------------ +OGridColumn* OGridControlModel::getColumnImplementation(const InterfaceRef& _rxIFace) const +{ + OGridColumn* pImplementation = NULL; + Reference< XUnoTunnel > xUnoTunnel( _rxIFace, UNO_QUERY ); + if ( xUnoTunnel.is() ) + pImplementation = reinterpret_cast<OGridColumn*>(xUnoTunnel->getSomething(OGridColumn::getUnoTunnelImplementationId())); + + return pImplementation; +} + +//------------------------------------------------------------------------------ +void OGridControlModel::gotColumn( const Reference< XInterface >& _rxColumn ) +{ + Reference< XSQLErrorBroadcaster > xBroadcaster( _rxColumn, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->addSQLErrorListener( this ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::lostColumn(const Reference< XInterface >& _rxColumn) +{ + if ( m_xSelection == _rxColumn ) + { // the currently selected element was replaced + m_xSelection.clear(); + EventObject aEvt( static_cast< XWeak* >( this ) ); + m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvt ); + } + + Reference< XSQLErrorBroadcaster > xBroadcaster( _rxColumn, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->removeSQLErrorListener( this ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::implRemoved(const InterfaceRef& _rxObject) +{ + OInterfaceContainer::implRemoved(_rxObject); + lostColumn(_rxObject); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::implInserted( const ElementDescription* _pElement ) +{ + OInterfaceContainer::implInserted( _pElement ); + gotColumn( _pElement->xInterface ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::impl_replacedElement( const ContainerEvent& _rEvent, ::osl::ClearableMutexGuard& _rInstanceLock ) +{ + Reference< XInterface > xOldColumn( _rEvent.ReplacedElement, UNO_QUERY ); + Reference< XInterface > xNewColumn( _rEvent.Element, UNO_QUERY ); + + bool bNewSelection = ( xOldColumn == m_xSelection ); + + lostColumn( xOldColumn ); + gotColumn( xNewColumn ); + + if ( bNewSelection ) + m_xSelection.set( xNewColumn, UNO_QUERY ); + + OInterfaceContainer::impl_replacedElement( _rEvent, _rInstanceLock ); + // <<---- SYNCHRONIZED + + if ( bNewSelection ) + { + m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, EventObject( *this ) ); + } +} + +//------------------------------------------------------------------------------ +ElementDescription* OGridControlModel::createElementMetaData( ) +{ + return new ColumnDescription; +} + +//------------------------------------------------------------------------------ +void OGridControlModel::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement ) +{ + OGridColumn* pCol = getColumnImplementation( _rxObject ); + if ( !pCol ) + throw IllegalArgumentException(); + + OInterfaceContainer::approveNewElement( _rxObject, _pElement ); + + // if we're here, the object passed all tests + if ( _pElement ) + static_cast< ColumnDescription* >( _pElement )->pColumn = pCol; +} + +// XPersistObject +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OGridControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_GRID; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OGridControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::write(_rxOutStream); + + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + + // 1. Version + _rxOutStream->writeShort(0x0008); + + // 2. Columns + sal_Int32 nLen = getCount(); + _rxOutStream->writeLong(nLen); + OGridColumn* pCol; + for (sal_Int32 i = 0; i < nLen; i++) + { + // zuerst den Servicenamen fuer das darunterliegende Model + pCol = getColumnImplementation(m_aItems[i]); + DBG_ASSERT(pCol != NULL, "OGridControlModel::write : such items should never reach it into my container !"); + + _rxOutStream << pCol->getModelName(); + + // dann das Object selbst + sal_Int32 nMark = xMark->createMark(); + sal_Int32 nObjLen = 0; + _rxOutStream->writeLong(nObjLen); + + // schreiben der Col + pCol->write(_rxOutStream); + + // feststellen der Laenge + nObjLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nObjLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + } + + // 3. Events + writeEvents(_rxOutStream); + + // 4. Attribute + // Maskierung fuer alle any Typen + sal_uInt16 nAnyMask = 0; + if (m_aRowHeight.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= ROWHEIGHT; + if ( getFont() != getDefaultFont() ) + nAnyMask |= FONTATTRIBS | FONTSIZE | FONTTYPE | FONTDESCRIPTOR; + if (m_aTabStop.getValueType().getTypeClass() == TypeClass_BOOLEAN) + nAnyMask |= TABSTOP; + if ( hasTextColor() ) + nAnyMask |= TEXTCOLOR; + if (m_aBackgroundColor.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= BACKGROUNDCOLOR; + if (!m_bRecordMarker) + nAnyMask |= RECORDMARKER; + + _rxOutStream->writeShort(nAnyMask); + + if (nAnyMask & ROWHEIGHT) + _rxOutStream->writeLong(getINT32(m_aRowHeight)); + + // old structures + const FontDescriptor& aFont = getFont(); + if ( nAnyMask & FONTDESCRIPTOR ) + { + // Attrib + _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( VCLUnoHelper::ConvertFontWeight( aFont.Weight ) ) ); + _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( aFont.Slant ) ); + _rxOutStream->writeShort( aFont.Underline ); + _rxOutStream->writeShort( aFont.Strikeout ); + _rxOutStream->writeShort( sal_Int16(aFont.Orientation * 10) ); + _rxOutStream->writeBoolean( aFont.Kerning ); + _rxOutStream->writeBoolean( aFont.WordLineMode ); + + // Size + _rxOutStream->writeLong( aFont.Width ); + _rxOutStream->writeLong( aFont.Height ); + _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( VCLUnoHelper::ConvertFontWidth( aFont.CharacterWidth ) ) ); + + // Type + _rxOutStream->writeUTF( aFont.Name ); + _rxOutStream->writeUTF( aFont.StyleName ); + _rxOutStream->writeShort( aFont.Family ); + _rxOutStream->writeShort( aFont.CharSet ); + _rxOutStream->writeShort( aFont.Pitch ); + } + + _rxOutStream << m_aDefaultControl; + + _rxOutStream->writeShort(m_nBorder); + _rxOutStream->writeBoolean(m_bEnable); + + if (nAnyMask & TABSTOP) + _rxOutStream->writeBoolean(getBOOL(m_aTabStop)); + + _rxOutStream->writeBoolean(m_bNavigation); + + if (nAnyMask & TEXTCOLOR) + _rxOutStream->writeLong( getTextColor() ); + + // neu ab Version 6 + _rxOutStream << m_sHelpText; + + if (nAnyMask & FONTDESCRIPTOR) + _rxOutStream << getFont(); + + if (nAnyMask & RECORDMARKER) + _rxOutStream->writeBoolean(m_bRecordMarker); + + // neu ab Version 7 + _rxOutStream->writeBoolean(m_bPrintable); + + // new since 8 + if (nAnyMask & BACKGROUNDCOLOR) + _rxOutStream->writeLong(getINT32(m_aBackgroundColor)); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::read(_rxInStream); + + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + + // 1. Version + sal_Int16 nVersion = _rxInStream->readShort(); + + // 2. Einlesen der Spalten + sal_Int32 nLen = _rxInStream->readLong(); + if (nLen) + { + for (sal_Int32 i = 0; i < nLen; i++) + { + // Lesen des Modelnamen + + ::rtl::OUString sModelName; + _rxInStream >> sModelName; + + Reference<XPropertySet> xCol(createColumn(getColumnTypeByModelName(sModelName))); + DBG_ASSERT(xCol.is(), "OGridControlModel::read : unknown column type !"); + sal_Int32 nObjLen = _rxInStream->readLong(); + if (nObjLen) + { + sal_Int32 nMark = xMark->createMark(); + if (xCol.is()) + { + OGridColumn* pCol = getColumnImplementation(xCol); + pCol->read(_rxInStream); + } + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nObjLen); + xMark->deleteMark(nMark); + } + + if ( xCol.is() ) + implInsert( i, xCol, sal_False, NULL, sal_False ); + } + } + + // In der Basisimplementierung werden die Events nur gelesen, Elemente im Container existieren + // da aber vor TF_ONE fuer das GridControl immer Events geschrieben wurden, muessen sie auch immer + // mit gelesen werden + sal_Int32 nObjLen = _rxInStream->readLong(); + if (nObjLen) + { + sal_Int32 nMark = xMark->createMark(); + Reference<XPersistObject> xObj(m_xEventAttacher, UNO_QUERY); + if (xObj.is()) + xObj->read(_rxInStream); + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nObjLen); + xMark->deleteMark(nMark); + } + + // Attachement lesen + for (sal_Int32 i = 0; i < nLen; i++) + { + InterfaceRef xIfc(m_aItems[i], UNO_QUERY); + Reference<XPropertySet> xSet(xIfc, UNO_QUERY); + Any aHelper; + aHelper <<= xSet; + m_xEventAttacher->attach( i, xIfc, aHelper ); + } + + // 4. Einlesen der Attribute + if (nVersion == 1) + return; + + // Maskierung fuer any + sal_uInt16 nAnyMask = _rxInStream->readShort(); + + if (nAnyMask & ROWHEIGHT) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aRowHeight <<= (sal_Int32)nValue; + } + + FontDescriptor aFont( getFont() ); + if ( nAnyMask & FONTATTRIBS ) + { + aFont.Weight = (float)VCLUnoHelper::ConvertFontWeight( _rxInStream->readShort() ); + + aFont.Slant = (FontSlant)_rxInStream->readShort(); + aFont.Underline = _rxInStream->readShort(); + aFont.Strikeout = _rxInStream->readShort(); + aFont.Orientation = ( (float)_rxInStream->readShort() ) / 10; + aFont.Kerning = _rxInStream->readBoolean(); + aFont.WordLineMode = _rxInStream->readBoolean(); + } + if ( nAnyMask & FONTSIZE ) + { + aFont.Width = (sal_Int16)_rxInStream->readLong(); + aFont.Height = (sal_Int16)_rxInStream->readLong(); + aFont.CharacterWidth = (float)VCLUnoHelper::ConvertFontWidth( _rxInStream->readShort() ); + } + if ( nAnyMask & FONTTYPE ) + { + aFont.Name = _rxInStream->readUTF(); + aFont.StyleName = _rxInStream->readUTF(); + aFont.Family = _rxInStream->readShort(); + aFont.CharSet = _rxInStream->readShort(); + aFont.Pitch = _rxInStream->readShort(); + } + + if ( nAnyMask & ( FONTATTRIBS | FONTSIZE | FONTTYPE ) ) + setFont( aFont ); + + // Name + _rxInStream >> m_aDefaultControl; + m_nBorder = _rxInStream->readShort(); + m_bEnable = _rxInStream->readBoolean(); + + if (nAnyMask & TABSTOP) + { + m_aTabStop = makeBoolAny(_rxInStream->readBoolean()); + } + + if (nVersion > 3) + m_bNavigation = _rxInStream->readBoolean(); + + if (nAnyMask & TEXTCOLOR) + { + sal_Int32 nValue = _rxInStream->readLong(); + setTextColor( (sal_Int32)nValue ); + } + + // neu ab Version 6 + if (nVersion > 5) + _rxInStream >> m_sHelpText; + + if (nAnyMask & FONTDESCRIPTOR) + { + FontDescriptor aUNOFont; + _rxInStream >> aUNOFont; + setFont( aFont ); + } + + if (nAnyMask & RECORDMARKER) + m_bRecordMarker = _rxInStream->readBoolean(); + + // neu ab Version 7 + if (nVersion > 6) + m_bPrintable = _rxInStream->readBoolean(); + + if (nAnyMask & BACKGROUNDCOLOR) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aBackgroundColor <<= (sal_Int32)nValue; + } +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Grid.hxx b/forms/source/component/Grid.hxx new file mode 100644 index 000000000000..6cd0e9787ef1 --- /dev/null +++ b/forms/source/component/Grid.hxx @@ -0,0 +1,219 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "errorbroadcaster.hxx" +#include "FormComponent.hxx" +#include "formcontrolfont.hxx" +#include "InterfaceContainer.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/form/XGridColumnFactory.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/sdb/XRowSetSupplier.hpp> +#include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +/** === end UNO includes === **/ + +#include <comphelper/proparrhlp.hxx> +#include <cppuhelper/implbase7.hxx> +#include <tools/link.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + +class OGridColumn; + +//================================================================== +// ColumnDescription +//================================================================== + + struct ColumnDescription : public ElementDescription + { + public: + OGridColumn* pColumn; // not owned by this instance! only to prevent duplicate XUnoTunnel usage + }; + +//================================================================== +// OGridControlModel +//================================================================== +typedef ::cppu::ImplHelper7 < ::com::sun::star::awt::XControlModel + , ::com::sun::star::form::XGridColumnFactory + , ::com::sun::star::form::XReset + , ::com::sun::star::view::XSelectionSupplier + , ::com::sun::star::sdb::XSQLErrorListener + , ::com::sun::star::sdb::XRowSetSupplier + , ::com::sun::star::sdb::XRowSetChangeBroadcaster + > OGridControlModel_BASE; + +class OGridControlModel :public OControlModel + ,public OInterfaceContainer + ,public OErrorBroadcaster + ,public FontControlModel + ,public OGridControlModel_BASE +{ + ::cppu::OInterfaceContainerHelper m_aSelectListeners, + m_aResetListeners, + m_aRowSetChangeListeners; + +// [properties] + ::com::sun::star::uno::Any m_aRowHeight; // Zeilenhoehe + ::com::sun::star::uno::Any m_aTabStop; + ::com::sun::star::uno::Any m_aBackgroundColor; + ::com::sun::star::uno::Any m_aCursorColor; // transient + ::com::sun::star::uno::Any m_aBorderColor; + ::rtl::OUString m_aDefaultControl; + ::rtl::OUString m_sHelpText; +// [properties] + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xSelection; + +// [properties] + ::rtl::OUString m_sHelpURL; // URL + sal_Int16 m_nBorder; + sal_Int16 m_nWritingMode; + sal_Int16 m_nContextWritingMode; + sal_Bool m_bEnableVisible : 1; + sal_Bool m_bEnable : 1; + sal_Bool m_bNavigation : 1; + sal_Bool m_bRecordMarker : 1; + sal_Bool m_bPrintable : 1; + sal_Bool m_bAlwaysShowCursor : 1; // transient + sal_Bool m_bDisplaySynchron : 1; // transient +// [properties] + +protected: + void _reset(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OGridControlModel ); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OGridControlModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // XChild + virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OGridControlModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XReset + virtual void SAL_CALL reset() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + + // XSelectionSupplier + virtual sal_Bool SAL_CALL select(const ::com::sun::star::uno::Any& aElement) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getSelection() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSelectionChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionChangeListener >& xListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSelectionChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionChangeListener >& xListener) throw(::com::sun::star::uno::RuntimeException); + + // XGridColumnFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> SAL_CALL createColumn(const ::rtl::OUString& ColumnType) throw ( :: com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getColumnTypes() throw ( ::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // XSQLErrorListener + virtual void SAL_CALL errorOccured( const ::com::sun::star::sdb::SQLErrorEvent& _rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XRowSetSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > SAL_CALL getRowSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRowSet( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet >& xDataSource ) throw (::com::sun::star::uno::RuntimeException); + + // XRowSetChangeBroadcaster + virtual void SAL_CALL addRowSetChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetChangeListener >& i_Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetChangeListener >& i_Listener ) throw (::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + +protected: + DECLARE_XCLONEABLE(); + +protected: + virtual void approveNewElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject, + ElementDescription* _pElement + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> createColumn(sal_Int32 nTypeId) const; + + OGridColumn* getColumnImplementation(const InterfaceRef& _rxIFace) const; + + virtual ElementDescription* createElementMetaData( ); + +protected: + virtual void implRemoved(const InterfaceRef& _rxObject); + virtual void implInserted( const ElementDescription* _pElement ); + virtual void impl_replacedElement( + const ::com::sun::star::container::ContainerEvent& _rEvent, + ::osl::ClearableMutexGuard& _rInstanceLock + ); + + void gotColumn(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxColumn); + void lostColumn(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxColumn); + + void cloneColumns( const OGridControlModel* _pOriginalContainer ); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + + diff --git a/forms/source/component/GroupBox.cxx b/forms/source/component/GroupBox.cxx new file mode 100644 index 000000000000..adf055955f3a --- /dev/null +++ b/forms/source/component/GroupBox.cxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "GroupBox.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +// OGroupBoxModel +//================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OGroupBoxModel_CreateInstance(const Reference<starlang::XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OGroupBoxModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OGroupBoxModel ) +//------------------------------------------------------------------ +OGroupBoxModel::OGroupBoxModel(const Reference<starlang::XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, VCL_CONTROLMODEL_GROUPBOX, VCL_CONTROL_GROUPBOX) +{ + DBG_CTOR( OGroupBoxModel, NULL ); + m_nClassId = FormComponentType::GROUPBOX; +} + +//------------------------------------------------------------------ +OGroupBoxModel::OGroupBoxModel( const OGroupBoxModel* _pOriginal, const Reference<starlang::XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OGroupBoxModel, NULL ); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OGroupBoxModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_GROUPBOX; + return aSupported; +} + +//------------------------------------------------------------------ +OGroupBoxModel::~OGroupBoxModel() +{ + DBG_DTOR( OGroupBoxModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OGroupBoxModel ) + +//------------------------------------------------------------------------------ +void OGroupBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OControlModel::describeAggregateProperties( _rAggregateProps ); + // don't want to have the TabStop property + RemoveProperty(_rAggregateProps, PROPERTY_TABSTOP); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OGroupBoxModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_GROUPBOX; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGroupBoxModel::write(const Reference< XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + OControlModel::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0002); + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGroupBoxModel::read(const Reference< XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + OControlModel::read( _rxInStream ); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + DBG_ASSERT(nVersion > 0, "OGroupBoxModel::read : version 0 ? this should never have been written !"); + // ups, ist das Englisch richtig ? ;) + + if (nVersion == 2) + readHelpTextCompatibly(_rxInStream); + + if (nVersion > 0x0002) + { + DBG_ERROR("OGroupBoxModel::read : unknown version !"); + } +}; + +//================================================================== +// OGroupBoxControl +//================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OGroupBoxControl_CreateInstance(const Reference<starlang::XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OGroupBoxControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +OGroupBoxControl::OGroupBoxControl(const Reference<starlang::XMultiServiceFactory>& _rxFactory) + :OControl(_rxFactory, VCL_CONTROL_GROUPBOX) +{ +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OGroupBoxControl::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_GROUPBOX; + return aSupported; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/GroupBox.hxx b/forms/source/component/GroupBox.hxx new file mode 100644 index 000000000000..902c60ced488 --- /dev/null +++ b/forms/source/component/GroupBox.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_GROUPBOX_HXX_ +#define _FORMS_GROUPBOX_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// OGroupBoxModel +//================================================================== +class OGroupBoxModel + :public OControlModel +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OGroupBoxModel ); + + // XServiceInfo + IMPLEMENTATION_NAME(OGroupBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +// OGroupBoxControl (nur aus Kompatibilitaet zur 5.0) +//================================================================== +class OGroupBoxControl : public OControl +{ +public: + OGroupBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OGroupBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_GROUPBOX_HXX_ + diff --git a/forms/source/component/GroupManager.cxx b/forms/source/component/GroupManager.cxx new file mode 100644 index 000000000000..fde6aa1a23ca --- /dev/null +++ b/forms/source/component/GroupManager.cxx @@ -0,0 +1,501 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "GroupManager.hxx" +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <comphelper/property.hxx> +#include <comphelper/uno3.hxx> +#include <tools/solar.h> +#include <tools/debug.hxx> + +#include "property.hrc" + +#include <algorithm> + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::form; + +namespace +{ + bool isRadioButton( const Reference< XPropertySet >& _rxComponent ) + { + bool bIs = false; + if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) ) + { + sal_Int16 nClassId = FormComponentType::CONTROL; + _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId; + if ( nClassId == FormComponentType::RADIOBUTTON ) + bIs = true; + } + return bIs; + } +} + +//======================================================================== +// class OGroupCompAcc +//======================================================================== +//------------------------------------------------------------------ +OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp ) + :m_xComponent( rxElement ) + ,m_aGroupComp( _rGroupComp ) +{ +} + +//------------------------------------------------------------------ +sal_Bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const +{ + return (m_xComponent == rCompAcc.GetComponent()); +} + +//------------------------------------------------------------------ +class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool> +{ +public: + sal_Bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const + { + return + reinterpret_cast<sal_Int64>(lhs.m_xComponent.get()) + < reinterpret_cast<sal_Int64>(rhs.m_xComponent.get()); + } +}; + +//======================================================================== +// class OGroupComp +//======================================================================== + +//------------------------------------------------------------------ +OGroupComp::OGroupComp() + :m_nPos( -1 ) + ,m_nTabIndex( 0 ) +{ +} + +//------------------------------------------------------------------ +OGroupComp::OGroupComp(const OGroupComp& _rSource) + :m_aName( _rSource.m_aName ) + ,m_xComponent( _rSource.m_xComponent ) + ,m_xControlModel(_rSource.m_xControlModel) + ,m_nPos( _rSource.m_nPos ) + ,m_nTabIndex( _rSource.m_nTabIndex ) +{ +} + +//------------------------------------------------------------------ +OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos ) + :m_xComponent( rxSet ) + ,m_xControlModel(rxSet,UNO_QUERY) + ,m_nPos( nInsertPos ) + ,m_nTabIndex(0) +{ + if (m_xComponent.is()) + { + if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) ) + // Indices kleiner 0 werden wie 0 behandelt + m_nTabIndex = Max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0)); + + m_xComponent->getPropertyValue( PROPERTY_NAME ) >>= m_aName; + } +} + +//------------------------------------------------------------------ +sal_Bool OGroupComp::operator==( const OGroupComp& rComp ) const +{ + return m_nTabIndex == rComp.GetTabIndex() && m_nPos == rComp.GetPos(); +} + +//------------------------------------------------------------------ +class OGroupCompLess : public ::std::binary_function<OGroupComp, OGroupComp, sal_Bool> +{ +public: + sal_Bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const + { + sal_Bool bResult; + // TabIndex von 0 wird hinten einsortiert + if (lhs.m_nTabIndex == rhs.GetTabIndex()) + bResult = lhs.m_nPos < rhs.GetPos(); + else if (lhs.m_nTabIndex && rhs.GetTabIndex()) + bResult = lhs.m_nTabIndex < rhs.GetTabIndex(); + else + bResult = lhs.m_nTabIndex != 0; + return bResult; + } +}; + +//======================================================================== +// class OGroup +//======================================================================== + +DBG_NAME(OGroup) +//------------------------------------------------------------------ +OGroup::OGroup( const ::rtl::OUString& rGroupName ) + :m_aGroupName( rGroupName ) + ,m_nInsertPos(0) +{ + DBG_CTOR(OGroup,NULL); +} + +#ifdef DBG_UTIL +//------------------------------------------------------------------ +OGroup::OGroup( const OGroup& _rSource ) +:m_aCompArray(_rSource.m_aCompArray) + ,m_aCompAccArray(_rSource.m_aCompAccArray) + ,m_aGroupName(_rSource.m_aGroupName) + ,m_nInsertPos(_rSource.m_nInsertPos) +{ + DBG_CTOR(OGroup,NULL); +} +#endif + +//------------------------------------------------------------------ +OGroup::~OGroup() +{ + DBG_DTOR(OGroup,NULL); +} + +//------------------------------------------------------------------ +void OGroup::InsertComponent( const Reference<XPropertySet>& xSet ) +{ + OGroupComp aNewGroupComp( xSet, m_nInsertPos ); + sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess()); + + OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] ); + insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess()); + m_nInsertPos++; +} + +//------------------------------------------------------------------ +void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement ) +{ + sal_Int32 nGroupCompAccPos; + OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() ); + if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) ) + { + OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos]; + const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent(); + + sal_Int32 nGroupCompPos; + if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) ) + { + m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos ); + m_aCompArray.erase( m_aCompArray.begin() + nGroupCompPos ); + + /*============================================================ + Durch das Entfernen der GroupComp ist die Einfuegeposition + ungueltig geworden. Sie braucht hier aber nicht angepasst werden, + da sie fortlaufend vergeben wird und damit immer + aufsteigend eindeutig ist. + ============================================================*/ + } + else + { + DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" ); + } + } + else + { + DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" ); + } +} + +//------------------------------------------------------------------ +sal_Bool OGroup::operator==( const OGroup& rGroup ) const +{ + return m_aGroupName.equals(rGroup.GetGroupName()); +} + +//------------------------------------------------------------------ +class OGroupLess : public ::std::binary_function<OGroup, OGroup, sal_Bool> +{ +public: + sal_Bool operator() (const OGroup& lhs, const OGroup& rhs) const + { + return lhs.m_aGroupName < rhs.m_aGroupName; + } +}; + +//------------------------------------------------------------------ +Sequence< Reference<XControlModel> > OGroup::GetControlModels() const +{ + sal_Int32 nLen = m_aCompArray.size(); + Sequence<Reference<XControlModel> > aControlModelSeq( nLen ); + Reference<XControlModel>* pModels = aControlModelSeq.getArray(); + + ConstOGroupCompArrIterator aGroupComps = m_aCompArray.begin(); + for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps) + { + *pModels = aGroupComps->GetControlModel(); + } + return aControlModelSeq; +} + +DBG_NAME(OGroupManager); +//------------------------------------------------------------------ +OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer) + :m_pCompGroup( new OGroup( ::rtl::OUString::createFromAscii( "AllComponentGroup" ) ) ) + ,m_xContainer(_rxContainer) +{ + DBG_CTOR(OGroupManager,NULL); + + increment(m_refCount); + { + _rxContainer->addContainerListener(this); + } + decrement(m_refCount); +} + +//------------------------------------------------------------------ +OGroupManager::~OGroupManager() +{ + DBG_DTOR(OGroupManager,NULL); + // Alle Components und CompGroup loeschen + delete m_pCompGroup; +} + +// XPropertyChangeListener +//------------------------------------------------------------------ +void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException ) +{ + Reference<XContainer> xContainer(evt.Source, UNO_QUERY); + if (xContainer.get() == m_xContainer.get()) + { + DELETEZ(m_pCompGroup); + + //////////////////////////////////////////////////////////////// + // Gruppen loeschen + m_aGroupArr.clear(); + m_xContainer.clear(); + } +} +// ----------------------------------------------------------------------------- +void OGroupManager::removeFromGroupMap(const ::rtl::OUString& _sGroupName,const Reference<XPropertySet>& _xSet) +{ + // Component aus CompGroup entfernen + m_pCompGroup->RemoveComponent( _xSet ); + + OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName); + + if ( aFind != m_aGroupArr.end() ) + { + // Gruppe vorhanden + aFind->second.RemoveComponent( _xSet ); + + // Wenn Anzahl der Gruppenelemente == 1 ist, Gruppe deaktivieren + if ( aFind->second.Count() == 1 ) + { + OActiveGroups::iterator aActiveFind = ::std::find( + m_aActiveGroupMap.begin(), + m_aActiveGroupMap.end(), + aFind + ); + if ( aActiveFind != m_aActiveGroupMap.end() ) + { + // the group is active. Deactivate it if the remaining component + // is *no* radio button + if ( !isRadioButton( aFind->second.GetObject( 0 ) ) ) + m_aActiveGroupMap.erase( aActiveFind ); + } + } + } + + + // Bei Component als PropertyChangeListener abmelden + _xSet->removePropertyChangeListener( PROPERTY_NAME, this ); + if (hasProperty(PROPERTY_TABINDEX, _xSet)) + _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this ); +} +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xSet(evt.Source, UNO_QUERY); + + // Component aus Gruppe entfernen + ::rtl::OUString sGroupName; + if (evt.PropertyName == PROPERTY_NAME) + evt.OldValue >>= sGroupName; + else + xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; + + removeFromGroupMap(sGroupName,xSet); + + // Component neu einordnen + InsertElement( xSet ); +} + +// XContainerListener +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference< XPropertySet > xProps; + Event.Element >>= xProps; + if ( xProps.is() ) + InsertElement( xProps ); +} + +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xProps; + Event.Element >>= xProps; + if ( xProps.is() ) + RemoveElement( xProps ); +} + +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::elementReplaced(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xProps; + Event.ReplacedElement >>= xProps; + if ( xProps.is() ) + RemoveElement( xProps ); + + xProps.clear(); + Event.Element >>= xProps; + if ( xProps.is() ) + InsertElement( xProps ); +} + +// Other functions +//------------------------------------------------------------------ +Sequence<Reference<XControlModel> > OGroupManager::getControlModels() +{ + return m_pCompGroup->GetControlModels(); +} + +//------------------------------------------------------------------ +sal_Int32 OGroupManager::getGroupCount() +{ + return m_aActiveGroupMap.size(); +} + +//------------------------------------------------------------------ +void OGroupManager::getGroup(sal_Int32 nGroup, Sequence< Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName) +{ + OSL_ENSURE(nGroup >= 0 && (size_t)nGroup < m_aActiveGroupMap.size(),"OGroupManager::getGroup: Invalid group index!"); + OGroupArr::iterator aGroupPos = m_aActiveGroupMap[nGroup]; + _rName = aGroupPos->second.GetGroupName(); + _rGroup = aGroupPos->second.GetControlModels(); +} + +//------------------------------------------------------------------ +void OGroupManager::getGroupByName(const ::rtl::OUString& _rName, Sequence< Reference<XControlModel> >& _rGroup) +{ + OGroupArr::iterator aFind = m_aGroupArr.find(_rName); + if ( aFind != m_aGroupArr.end() ) + _rGroup = aFind->second.GetControlModels(); +} + +//------------------------------------------------------------------ +void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet ) +{ + // Nur ControlModels + Reference<XControlModel> xControl(xSet, UNO_QUERY); + if (!xControl.is() ) + return; + + // Component in CompGroup aufnehmen + m_pCompGroup->InsertComponent( xSet ); + + // Component in Gruppe aufnehmen + ::rtl::OUString sGroupName; + xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; + + OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName); + + if ( aFind == m_aGroupArr.end() ) + { + aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first; + } + + aFind->second.InsertComponent( xSet ); + + // if we have at least 2 elements in the group, then this is an "active group" + bool bActivateGroup = aFind->second.Count() == 2; + + // Additionally, if the component is a radio button, then it's group becomes active, + // too. With this, we ensure that in a container with n radio buttons which all are + // in different groups the selection still works reliably (means that all radios can be + // clicked independently) + if ( aFind->second.Count() == 1 ) + { + if ( isRadioButton( xSet ) ) + bActivateGroup = true; + } + + if ( bActivateGroup ) + { + OActiveGroups::iterator aAlreadyExistent = ::std::find( + m_aActiveGroupMap.begin(), + m_aActiveGroupMap.end(), + aFind + ); + if ( aAlreadyExistent == m_aActiveGroupMap.end() ) + m_aActiveGroupMap.push_back( aFind ); + } + + + // Bei Component als PropertyChangeListener anmelden + xSet->addPropertyChangeListener( PROPERTY_NAME, this ); + + // Tabindex muss nicht jeder unterstuetzen + if (hasProperty(PROPERTY_TABINDEX, xSet)) + xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this ); + +} + +//------------------------------------------------------------------ +void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet ) +{ + // Nur ControlModels + Reference<XControlModel> xControl(xSet, UNO_QUERY); + if (!xControl.is() ) + return; + + // Component aus Gruppe entfernen + ::rtl::OUString sGroupName; + xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; + + removeFromGroupMap(sGroupName,xSet); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/GroupManager.hxx b/forms/source/component/GroupManager.hxx new file mode 100644 index 000000000000..fc9d8ce82c61 --- /dev/null +++ b/forms/source/component/GroupManager.hxx @@ -0,0 +1,228 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_GROUPMANAGER_HXX_ +#define _FRM_GROUPMANAGER_HXX_ + +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <comphelper/stl_types.hxx> +#include <cppuhelper/implbase2.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/types.hxx> +using namespace comphelper; + +/*======================================================================== +Funktionsweise GroupManager: + +Der GroupManager horcht an der starform, ob FormComponents eingefuegt oder entfernt +werden. Zusaetzlich horcht er bei den FormComponents an den Properties +"Name" und "TabIndex". Mit diesen Infos aktualisiert er seine Gruppen. + +Der GroupManager verwaltet eine Gruppe, in der alle Controls nach TabIndex +geordnet sind, und ein Array von Gruppen, in dem jede FormComponent noch +einmal einer Gruppe dem Namen nach zugeordnet wird. +Die einzelnen Gruppen werden ueber eine Map aktiviert, wenn sie mehr als +ein Element besitzen. + +Die Gruppen verwalten intern die FormComponents in zwei Arrays. In dem +GroupCompArray werden die Components nach TabIndex und Einfuegepostion +sortiert. Da auf dieses Array ueber die FormComponent zugegriffen +wird, gibt es noch das GroupCompAccessArray, in dem die FormComponents +nach ihrer Speicheradresse sortiert sind. Jedes Element des +GroupCompAccessArrays ist mit einem Element des GroupCompArrays verpointert. + +========================================================================*/ + +//......................................................................... +namespace frm +{ +//......................................................................... + +//======================================================================== + template <class ELEMENT, class LESS_COMPARE> + sal_Int32 insert_sorted(::std::vector<ELEMENT>& _rArray, const ELEMENT& _rNewElement, const LESS_COMPARE& _rCompareOp) + { + typename ::std::vector<ELEMENT>::iterator aInsertPos = lower_bound( + _rArray.begin(), + _rArray.end(), + _rNewElement, + _rCompareOp + ); + aInsertPos = _rArray.insert(aInsertPos, _rNewElement); + return aInsertPos - _rArray.begin(); + } + + template <class ELEMENT, class LESS_COMPARE> + sal_Bool seek_entry(const ::std::vector<ELEMENT>& _rArray, const ELEMENT& _rNewElement, sal_Int32& nPos, const LESS_COMPARE& _rCompareOp) + { + typename ::std::vector<ELEMENT>::const_iterator aExistentPos = lower_bound( + _rArray.begin(), + _rArray.end(), + _rNewElement, + _rCompareOp + ); + if ((aExistentPos != _rArray.end()) && (*aExistentPos == _rNewElement)) + { // we have a valid "lower or equal" element and it's really "equal" + nPos = aExistentPos - _rArray.begin(); + return sal_True; + } + nPos = -1; + return sal_False; + } + +//======================================================================== +class OGroupComp +{ + ::rtl::OUString m_aName; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> m_xComponent; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> m_xControlModel; + sal_Int32 m_nPos; + sal_Int16 m_nTabIndex; + + friend class OGroupCompLess; + +public: + OGroupComp(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement, sal_Int32 nInsertPos ); + OGroupComp(const OGroupComp& _rSource); + OGroupComp(); + + sal_Bool operator==( const OGroupComp& rComp ) const; + + inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& GetComponent() const { return m_xComponent; } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel>& GetControlModel() const { return m_xControlModel; } + + sal_Int32 GetPos() const { return m_nPos; } + sal_Int16 GetTabIndex() const { return m_nTabIndex; } + ::rtl::OUString GetName() const { return m_aName; } +}; + +DECLARE_STL_VECTOR(OGroupComp, OGroupCompArr); + +//======================================================================== +class OGroupComp; +class OGroupCompAcc +{ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> m_xComponent; + + OGroupComp m_aGroupComp; + + friend class OGroupCompAccLess; + +public: + OGroupCompAcc(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement, const OGroupComp& _rGroupComp ); + + sal_Bool operator==( const OGroupCompAcc& rCompAcc ) const; + + inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& GetComponent() const { return m_xComponent; } + const OGroupComp& GetGroupComponent() const { return m_aGroupComp; } +}; + +DECLARE_STL_VECTOR(OGroupCompAcc, OGroupCompAccArr); + +//======================================================================== +class OGroup +{ + OGroupCompArr m_aCompArray; + OGroupCompAccArr m_aCompAccArray; + + ::rtl::OUString m_aGroupName; + sal_uInt16 m_nInsertPos; // Die Einfugeposition der GroupComps wird von der Gruppe bestimmt. + + friend class OGroupLess; + +public: + OGroup( const ::rtl::OUString& rGroupName ); +#ifdef DBG_UTIL + OGroup( const OGroup& _rSource ); // just to ensure the DBG_CTOR call +#endif + virtual ~OGroup(); + + sal_Bool operator==( const OGroup& rGroup ) const; + + ::rtl::OUString GetGroupName() const { return m_aGroupName; } + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> > GetControlModels() const; + + void InsertComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + void RemoveComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + sal_uInt16 Count() const { return sal::static_int_cast< sal_uInt16 >(m_aCompArray.size()); } + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& GetObject( sal_uInt16 nP ) const + { return m_aCompArray[nP].GetComponent(); } +}; + +DECLARE_STL_USTRINGACCESS_MAP(OGroup, OGroupArr); +DECLARE_STL_VECTOR(OGroupArr::iterator, OActiveGroups); + +//======================================================================== +class OGroupManager : public ::cppu::WeakImplHelper2< ::com::sun::star::beans::XPropertyChangeListener, ::com::sun::star::container::XContainerListener> +{ + OGroup* m_pCompGroup; // Alle Components nach TabIndizes sortiert + OGroupArr m_aGroupArr; // Alle Components nach Gruppen sortiert + OActiveGroups m_aActiveGroupMap; // In dieser Map werden die Indizes aller Gruppen gehalten, + // die mehr als 1 Element haben + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > + m_xContainer; + + // Helper functions + void InsertElement( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + void RemoveElement( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + void removeFromGroupMap(const ::rtl::OUString& _sGroupName,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xSet); + +public: + OGroupManager(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer >& _rxContainer); + virtual ~OGroupManager(); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XContainerListener + virtual void SAL_CALL elementInserted(const ::com::sun::star::container::ContainerEvent& _rEvent) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved(const ::com::sun::star::container::ContainerEvent& _rEvent) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced(const ::com::sun::star::container::ContainerEvent& _rEvent) throw ( ::com::sun::star::uno::RuntimeException); + +// Other functions + sal_Int32 getGroupCount(); + void getGroup(sal_Int32 nGroup, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> >& _rGroup, ::rtl::OUString& Name); + void getGroupByName(const ::rtl::OUString& Name, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> >& _rGroup); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> > getControlModels(); +}; + + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_GROUPMANAGER_HXX_ + diff --git a/forms/source/component/Hidden.cxx b/forms/source/component/Hidden.cxx new file mode 100644 index 000000000000..9c20de263d80 --- /dev/null +++ b/forms/source/component/Hidden.cxx @@ -0,0 +1,190 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Hidden.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/basicio.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OHiddenModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OHiddenModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OHiddenModel ) +//------------------------------------------------------------------ +OHiddenModel::OHiddenModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, ::rtl::OUString()) +{ + DBG_CTOR( OHiddenModel, NULL ); + m_nClassId = FormComponentType::HIDDENCONTROL; +} + +//------------------------------------------------------------------ +OHiddenModel::OHiddenModel( const OHiddenModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OHiddenModel, NULL ); + m_sHiddenValue = _pOriginal->m_sHiddenValue; +} + +//------------------------------------------------------------------------------ +OHiddenModel::~OHiddenModel( ) +{ + DBG_CTOR( OHiddenModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OHiddenModel ) + +//------------------------------------------------------------------------------ +void OHiddenModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + switch (_nHandle) + { + case PROPERTY_ID_HIDDEN_VALUE : _rValue <<= m_sHiddenValue; break; + default: + OControlModel::getFastPropertyValue(_rValue, _nHandle); + } +} + +//------------------------------------------------------------------------------ +void OHiddenModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception) +{ + switch (_nHandle) + { + case PROPERTY_ID_HIDDEN_VALUE : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING, "OHiddenModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_sHiddenValue; + break; + default: + OControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OHiddenModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_HIDDEN_VALUE : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_sHiddenValue); + break; + default: + bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OHiddenModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_BASE_PROPERTIES(4) + DECL_PROP2(CLASSID, sal_Int16, READONLY, TRANSIENT); + DECL_PROP1(HIDDEN_VALUE, ::rtl::OUString, BOUND); + DECL_PROP1(NAME, ::rtl::OUString, BOUND); + DECL_PROP1(TAG, ::rtl::OUString, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OHiddenModel::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported( 2 ); + aSupported[ 0 ] = FRM_SUN_COMPONENT_HIDDENCONTROL; + aSupported[ 1 ] = FRM_SUN_FORMCOMPONENT; + return aSupported; +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OHiddenModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_HIDDEN; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OHiddenModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + // Version + _rxOutStream->writeShort(0x0002); + + // Wert + _rxOutStream << m_sHiddenValue; + + OControlModel::write(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OHiddenModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + // Version + UINT16 nVersion = _rxInStream->readShort(); + + // Name + DBG_ASSERT(nVersion != 1, "OHiddenModel::read : this version is obsolete !"); + switch (nVersion) + { + case 1 : { ::rtl::OUString sDummy; _rxInStream >> sDummy; _rxInStream >> m_sHiddenValue; } break; + case 2 : _rxInStream >> m_sHiddenValue; break; + default : DBG_ERROR("OHiddenModel::read : unknown version !"); m_sHiddenValue = ::rtl::OUString(); + } + OControlModel::read(_rxInStream); +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/Hidden.hxx b/forms/source/component/Hidden.hxx new file mode 100644 index 000000000000..9052417c3f2c --- /dev/null +++ b/forms/source/component/Hidden.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_HIDDEN_HXX_ +#define _FORMS_HIDDEN_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// OHiddenModel +//================================================================== +class OHiddenModel + :public OControlModel +{ + ::rtl::OUString m_sHiddenValue; + +public: + DECLARE_DEFAULT_LEAF_XTOR( OHiddenModel ); + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + + // XServiceInfo + IMPLEMENTATION_NAME(OHiddenModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::getFastPropertyValue; + +protected: + DECLARE_XCLONEABLE( ); +}; + +#endif // _FORMS_HIDDEN_HXX_ + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/ImageButton.cxx b/forms/source/component/ImageButton.cxx new file mode 100644 index 000000000000..e026f5380bc1 --- /dev/null +++ b/forms/source/component/ImageButton.cxx @@ -0,0 +1,273 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "ImageButton.hxx" +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <comphelper/basicio.hxx> +#include <com/sun/star/awt/MouseButton.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +//= OImageButtonModel +//================================================================== +DBG_NAME(OImageButtonModel) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageButtonModel(_rxFactory)); +} + +//------------------------------------------------------------------ +OImageButtonModel::OImageButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseModel( _rxFactory, VCL_CONTROLMODEL_IMAGEBUTTON, FRM_SUN_CONTROL_IMAGEBUTTON ) + // use the old control name for compytibility reasons +{ + DBG_CTOR(OImageButtonModel, NULL); + m_nClassId = FormComponentType::IMAGEBUTTON; +} + +//------------------------------------------------------------------ +OImageButtonModel::OImageButtonModel( const OImageButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR(OImageButtonModel, NULL); + implInitializeImageURL(); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OImageButtonModel ) + +//------------------------------------------------------------------------------ +OImageButtonModel::~OImageButtonModel() +{ + DBG_DTOR(OImageButtonModel, NULL); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OImageButtonModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_IMAGEBUTTON; + return aSupported; +} + +//------------------------------------------------------------------------------ +void OImageButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 5, OClickableImageBaseModel ) + DECL_PROP1(BUTTONTYPE, FormButtonType, BOUND); + DECL_PROP1(DISPATCHURLINTERNAL, sal_Bool, BOUND); + DECL_PROP1(TARGET_URL, ::rtl::OUString, BOUND); + DECL_PROP1(TARGET_FRAME, ::rtl::OUString, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OImageButtonModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_IMAGEBUTTON; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OImageButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0003); + _rxOutStream->writeShort((sal_uInt16)m_eButtonType); + + ::rtl::OUString sTmp(INetURLObject::decode( m_sTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS)); + _rxOutStream << sTmp; + _rxOutStream << m_sTargetFrame; + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void OImageButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::read(_rxInStream); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + + switch (nVersion) + { + case 0x0001: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + } + break; + case 0x0002: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + } + break; + case 0x0003: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + readHelpTextCompatibly(_rxInStream); + } + break; + + default : + DBG_ERROR("OImageButtonModel::read : unknown version !"); + m_eButtonType = FormButtonType_PUSH; + m_sTargetURL = ::rtl::OUString(); + m_sTargetFrame = ::rtl::OUString(); + break; + } +} + +//================================================================== +// OImageButtonControl +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageButtonControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OImageButtonControl::_getTypes() +{ + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + aTypes = concatSequences(OClickableImageBaseControl::_getTypes(), OImageButtonControl_BASE::getTypes()); + return aTypes; +} + +//------------------------------------------------------------------------------ +StringSequence OImageButtonControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_IMAGEBUTTON; + return aSupported; +} + +//------------------------------------------------------------------------------ +OImageButtonControl::OImageButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseControl(_rxFactory, VCL_CONTROL_IMAGEBUTTON) +{ + increment(m_refCount); + { + // als MouseListener anmelden + Reference< awt::XWindow > xComp; + query_aggregation( m_xAggregate, xComp); + if (xComp.is()) + xComp->addMouseListener( static_cast< awt::XMouseListener* >( this ) ); + } + decrement(m_refCount); +} + +// UNO Anbindung +//------------------------------------------------------------------------------ +Any SAL_CALL OImageButtonControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OClickableImageBaseControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OImageButtonControl_BASE::queryInterface(_rType); + + return aReturn; +} + +//------------------------------------------------------------------------------ +void OImageButtonControl::mousePressed(const awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + if (e.Buttons != awt::MouseButton::LEFT) + return; + + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if( m_aApproveActionListeners.getLength() ) + { + // if there are listeners, start the action in an own thread, to not allow + // them to block us here (we're in the application's main thread) + getImageProducerThread()->OComponentEventThread::addEvent( &e ); + } + else + { + // Sonst nicht. Dann darf man aber auf keinen Fal die Listener + // benachrichtigen, auch dann nicht, wenn er spaeter hinzukommt. + aGuard.clear(); + actionPerformed_Impl( sal_False, e ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageButtonControl::mouseReleased(const awt::MouseEvent& /*e*/) throw ( RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageButtonControl::mouseEntered(const awt::MouseEvent& /*e*/) throw ( RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageButtonControl::mouseExited(const awt::MouseEvent& /*e*/) throw ( RuntimeException) +{ +} + + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/ImageButton.hxx b/forms/source/component/ImageButton.hxx new file mode 100644 index 000000000000..188ee8558e70 --- /dev/null +++ b/forms/source/component/ImageButton.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_IMAGE_BUTTON_HXX_ +#define _FRM_IMAGE_BUTTON_HXX_ + +#include "clickableimage.hxx" +#include <com/sun/star/awt/XMouseListener.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OImageButtonModel +//================================================================== +class OImageButtonModel + :public OClickableImageBaseModel +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OImageButtonModel ); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OImageButtonModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + +// ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +// OImageButtonControl +//================================================================== +typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XMouseListener> OImageButtonControl_BASE; +class OImageButtonControl : public OClickableImageBaseControl, + public OImageButtonControl_BASE +{ +protected: + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OImageButtonControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OImageButtonControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OImageButtonControl, OClickableImageBaseControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException) + { OControl::disposing(_rSource); } + + // XMouseListener + virtual void SAL_CALL mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseReleased(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseEntered(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseExited(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OClickableImageBaseControl::disposing; +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_IMAGE_BUTTON_HXX_ + diff --git a/forms/source/component/ImageControl.cxx b/forms/source/component/ImageControl.cxx new file mode 100644 index 000000000000..72d22d3f30a5 --- /dev/null +++ b/forms/source/component/ImageControl.cxx @@ -0,0 +1,949 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "ImageControl.hxx" + +#include "property.hrc" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "services.hxx" +#include "componenttools.hxx" + +#include <svtools/imageresourceaccess.hxx> +#include <unotools/ucblockbytes.hxx> +#include <sfx2/filedlghelper.hxx> +#include <com/sun/star/awt/XPopupMenu.hpp> +#include <com/sun/star/awt/PopupMenuDirection.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XDialog.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/GraphicObject.hpp> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> +#include <unotools/streamhelper.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/guarding.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svl/urihelper.hxx> + +#include <memory> + +#define ID_OPEN_GRAPHICS 1 +#define ID_CLEAR_GRAPHICS 2 + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::frame; + +//============================================================================== +//= OImageControlModel +//============================================================================== +namespace +{ + enum ImageStoreType + { + ImageStoreBinary, + ImageStoreLink, + + ImageStoreInvalid + }; + + ImageStoreType lcl_getImageStoreType( const sal_Int32 _nFieldType ) + { + // binary/longvarchar types could be used to store images in binary representation + if ( ( _nFieldType == DataType::BINARY ) + || ( _nFieldType == DataType::VARBINARY ) + || ( _nFieldType == DataType::LONGVARBINARY ) + || ( _nFieldType == DataType::OTHER ) + || ( _nFieldType == DataType::OBJECT ) + || ( _nFieldType == DataType::BLOB ) + || ( _nFieldType == DataType::LONGVARCHAR ) + || ( _nFieldType == DataType::CLOB ) + ) + return ImageStoreBinary; + + // char types could be used to store links to images + if ( ( _nFieldType == DataType::CHAR ) + || ( _nFieldType == DataType::VARCHAR ) + ) + return ImageStoreLink; + + return ImageStoreInvalid; + } +} + +//============================================================================== +// OImageControlModel +//============================================================================== + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageControlModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OImageControlModel::_getTypes() +{ + return concatSequences( + OBoundControlModel::_getTypes(), + OImageControlModel_Base::getTypes() + ); +} + +DBG_NAME(OImageControlModel) +//------------------------------------------------------------------ +OImageControlModel::OImageControlModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_IMAGECONTROL, FRM_SUN_CONTROL_IMAGECONTROL, sal_False, sal_False, sal_False ) + // use the old control name for compytibility reasons + ,m_pImageProducer( NULL ) + ,m_bReadOnly( sal_False ) +{ + DBG_CTOR( OImageControlModel, NULL ); + m_nClassId = FormComponentType::IMAGECONTROL; + initValueProperty( PROPERTY_IMAGE_URL, PROPERTY_ID_IMAGE_URL); + + implConstruct(); +} + +//------------------------------------------------------------------ +OImageControlModel::OImageControlModel( const OImageControlModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + // use the old control name for compytibility reasons + ,m_pImageProducer( NULL ) +{ + DBG_CTOR( OImageControlModel, NULL ); + implConstruct(); + m_bReadOnly = _pOriginal->m_bReadOnly; + + osl_incrementInterlockedCount( &m_refCount ); + { + // simulate a propertyChanged event for the ImageURL + // 2003-05-15 - #109591# - fs@openoffice.org + Any aImageURL; + getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL ); + ::rtl::OUString sImageURL; + aImageURL >>= sImageURL; + + ::osl::MutexGuard aGuard( m_aMutex ); + impl_handleNewImageURL_lck( sImageURL, eOther ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//------------------------------------------------------------------ +void OImageControlModel::implConstruct() +{ + m_pImageProducer = new ImageProducer; + m_xImageProducer = m_pImageProducer; +} + +//------------------------------------------------------------------ +OImageControlModel::~OImageControlModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OImageControlModel,NULL); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OImageControlModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OImageControlModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_IMAGECONTROL; + return aSupported; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OImageControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + // oder matters: we want to "override" the XImageProducer interface of the aggreate with out + // own XImageProducer interface, thus we need to query OImageControlModel_Base first + Any aReturn = OImageControlModel_Base::queryInterface( _rType ); + + // BUT: _don't_ let it feel responsible for the XTypeProvider interface + // (as this is implemented by our base class in the proper way) + if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) + || !aReturn.hasValue() + ) + aReturn = OBoundControlModel::queryAggregation( _rType ); + + return aReturn; +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::approveDbColumnType( sal_Int32 _nColumnType ) +{ + return ImageStoreInvalid != lcl_getImageStoreType( _nColumnType ); +} + + +//------------------------------------------------------------------------------ +void OImageControlModel::_propertyChanged( const PropertyChangeEvent& _rEvent ) + throw( RuntimeException ) +{ + if ( m_xColumnUpdate.is() ) + { + OBoundControlModel::_propertyChanged( _rEvent ); + } + else + { // we're not bound. In this case, we have to manually care for updating the + // image producer, since the base class will not do this + ::rtl::OUString sImageURL; + _rEvent.NewValue >>= sImageURL; + + ::osl::MutexGuard aGuard( m_aMutex ); + impl_handleNewImageURL_lck( sImageURL, eOther ); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + switch (nHandle) + { + case PROPERTY_ID_READONLY : rValue <<= (sal_Bool)m_bReadOnly; break; + default: + OBoundControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_READONLY : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OImageControlModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + m_bReadOnly = getBOOL(rValue); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) +{ + switch (nHandle) + { + case PROPERTY_ID_READONLY : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bReadOnly); + + default: + return OBoundControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OBoundControlModel ) + DECL_BOOL_PROP1 ( READONLY, BOUND ); + DECL_PROP1 ( TABINDEX, sal_Int16, BOUND ); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OImageControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_IMAGECONTROL; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OImageControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + // Basisklasse + OBoundControlModel::write(_rxOutStream); + // Version + _rxOutStream->writeShort(0x0003); + // Name + _rxOutStream->writeBoolean(m_bReadOnly); + writeHelpTextCompatibly(_rxOutStream); + // from version 0x0003 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void OImageControlModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OBoundControlModel::read(_rxInStream); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + switch (nVersion) + { + case 0x0001: + m_bReadOnly = _rxInStream->readBoolean(); + break; + case 0x0002: + m_bReadOnly = _rxInStream->readBoolean(); + readHelpTextCompatibly(_rxInStream); + break; + case 0x0003: + m_bReadOnly = _rxInStream->readBoolean(); + readHelpTextCompatibly(_rxInStream); + readCommonProperties(_rxInStream); + break; + default : + DBG_ERROR("OImageControlModel::read : unknown version !"); + m_bReadOnly = sal_False; + defaultCommonProperties(); + break; + } + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + { // (not if we don't have a control source - the "State" property acts like it is persistent, then + ::osl::MutexGuard aGuard(m_aMutex); // resetNoBroadcast expects this mutex guarding + resetNoBroadcast(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::impl_updateStreamForURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ) +{ + // create a stream for the image specified by the URL + ::std::auto_ptr< SvStream > pImageStream; + Reference< XInputStream > xImageStream; + + if ( ::svt::GraphicAccess::isSupportedURL( _rURL ) ) + { + xImageStream = ::svt::GraphicAccess::getImageXStream( getContext().getLegacyServiceFactory(), _rURL ); + } + else + { + pImageStream.reset( ::utl::UcbStreamHelper::CreateStream( _rURL, STREAM_READ ) ); + sal_Bool bSetNull = ( pImageStream.get() == NULL ) || ( ERRCODE_NONE != pImageStream->GetErrorCode() ); + + if ( !bSetNull ) + { + // get the size of the stream + pImageStream->Seek(STREAM_SEEK_TO_END); + sal_Int32 nSize = (sal_Int32)pImageStream->Tell(); + if (pImageStream->GetBufferSize() < 8192) + pImageStream->SetBufferSize(8192); + pImageStream->Seek(STREAM_SEEK_TO_BEGIN); + + xImageStream = new ::utl::OInputStreamHelper( new SvLockBytes( pImageStream.get(), sal_False ), nSize ); + } + } + + if ( xImageStream.is() ) + { + if ( m_xColumnUpdate.is() ) + m_xColumnUpdate->updateBinaryStream( xImageStream, xImageStream->available() ); + else + setControlValue( makeAny( xImageStream ), _eInstigator ); + xImageStream->closeInput(); + return sal_True; + } + + return sal_False; +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::impl_handleNewImageURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ) +{ + switch ( lcl_getImageStoreType( getFieldType() ) ) + { + case ImageStoreBinary: + if ( impl_updateStreamForURL_lck( _rURL, _eInstigator ) ) + return sal_True; + break; + + case ImageStoreLink: + { + ::rtl::OUString sCommitURL( _rURL ); + if ( m_sDocumentURL.getLength() ) + sCommitURL = URIHelper::simpleNormalizedMakeRelative( m_sDocumentURL, sCommitURL ); + OSL_ENSURE( m_xColumnUpdate.is(), "OImageControlModel::impl_handleNewImageURL_lck: no bound field, but ImageStoreLink?!" ); + if ( m_xColumnUpdate.is() ) + { + m_xColumnUpdate->updateString( sCommitURL ); + return sal_True; + } + } + break; + + case ImageStoreInvalid: + OSL_ENSURE( false, "OImageControlModel::impl_handleNewImageURL_lck: invalid current field type!" ); + break; + } + + // if we're here, then the above code was unable to update our field/control from the given URL + // => fall back to NULL/VOID + if ( m_xColumnUpdate.is() ) + m_xColumnUpdate->updateNull(); + else + setControlValue( Any(), _eInstigator ); + + return sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::commitControlValueToDbColumn( bool _bPostReset ) +{ + if ( _bPostReset ) + { + // since this is a "commit after reset", we can simply update the column + // with null - this is our "default" which we were just reset to + if ( m_xColumnUpdate.is() ) + m_xColumnUpdate->updateNull(); + } + else + { + ::osl::MutexGuard aGuard(m_aMutex); + + ::rtl::OUString sImageURL; + m_xAggregateSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sImageURL; + return impl_handleNewImageURL_lck( sImageURL, eDbColumnBinding ); + } + + return sal_True; +} + +//------------------------------------------------------------------------------ +namespace +{ + bool lcl_isValidDocumentURL( const ::rtl::OUString& _rDocURL ) + { + return ( _rDocURL.getLength() && !_rDocURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:object" ) ) ); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OBoundControlModel::onConnectedDbColumn( _rxForm ); + + try + { + Reference< XModel > xDocument( getXModel( *this ) ); + if ( xDocument.is() ) + { + m_sDocumentURL = xDocument->getURL(); + if ( !lcl_isValidDocumentURL( m_sDocumentURL ) ) + { + Reference< XChild > xAsChild( xDocument, UNO_QUERY ); + while ( xAsChild.is() && !lcl_isValidDocumentURL( m_sDocumentURL ) ) + { + xDocument.set( xAsChild->getParent(), UNO_QUERY ); + if ( xDocument.is() ) + m_sDocumentURL = xDocument->getURL(); + xAsChild.set( xDocument, UNO_QUERY ); + } + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::onDisconnectedDbColumn() +{ + OBoundControlModel::onDisconnectedDbColumn(); + + m_sDocumentURL = ::rtl::OUString(); +} + +//------------------------------------------------------------------------------ +Any OImageControlModel::translateDbColumnToControlValue() +{ + switch ( lcl_getImageStoreType( getFieldType() ) ) + { + case ImageStoreBinary: return makeAny( m_xColumn->getBinaryStream() ); + case ImageStoreLink: + { + ::rtl::OUString sImageLink( m_xColumn->getString() ); + if ( m_sDocumentURL.getLength() ) + sImageLink = INetURLObject::GetAbsURL( m_sDocumentURL, sImageLink ); + return makeAny( sImageLink ); + } + case ImageStoreInvalid: + OSL_ENSURE( false, "OImageControlModel::translateDbColumnToControlValue: invalid field type!" ); + break; + } + return Any(); +} + +//------------------------------------------------------------------------------ +void OImageControlModel::doSetControlValue( const Any& _rValue ) +{ + DBG_ASSERT( GetImageProducer() && m_xImageProducer.is(), "OImageControlModel::doSetControlValue: no image producer!" ); + if ( !GetImageProducer() || !m_xImageProducer.is() ) + return; + + bool bStartProduction = false; + switch ( lcl_getImageStoreType( getFieldType() ) ) + { + case ImageStoreBinary: + { + // give the image producer the stream + Reference< XInputStream > xInStream; + _rValue >>= xInStream; + GetImageProducer()->setImage( xInStream ); + bStartProduction = true; + } + break; + + case ImageStoreLink: + { + ::rtl::OUString sImageURL; + _rValue >>= sImageURL; + GetImageProducer()->SetImage( sImageURL ); + bStartProduction = true; + } + break; + + case ImageStoreInvalid: + OSL_ENSURE( false, "OImageControlModel::doSetControlValue: invalid field type!" ); + break; + + } // switch ( lcl_getImageStoreType( getFieldType() ) ) + + if ( bStartProduction ) + { + // start production + Reference< XImageProducer > xProducer = m_xImageProducer; + { + // release our mutex once (it's acquired in the calling method!), as starting the image production may + // result in the locking of the solar mutex (unfortunally the default implementation of our aggregate, + // VCLXImageControl, does this locking) + // FS - 74438 - 30.03.00 + MutexRelease aRelease(m_aMutex); + xProducer->startProduction(); + } + } +} + +// OComponentHelper +//------------------------------------------------------------------ +void SAL_CALL OImageControlModel::disposing() +{ + OBoundControlModel::disposing(); + + { + ::osl::MutexGuard aGuard( m_aMutex ); // setControlValue expects this + setControlValue( Any(), eOther ); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::resetNoBroadcast() +{ + if ( hasField() ) // only reset when we are connected to a column + OBoundControlModel::resetNoBroadcast( ); +} + +//-------------------------------------------------------------------- +Reference< XImageProducer > SAL_CALL OImageControlModel::getImageProducer() throw ( RuntimeException) +{ + return this; +} + +//-------------------------------------------------------------------- +void SAL_CALL OImageControlModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) +{ + GetImageProducer()->addConsumer( _rxConsumer ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OImageControlModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) +{ + GetImageProducer()->removeConsumer( _rxConsumer ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OImageControlModel::startProduction( ) throw (RuntimeException) +{ + GetImageProducer()->startProduction(); +} + + +//================================================================== +// OImageControlControl +//================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageControlControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageControlControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OImageControlControl::_getTypes() +{ + return concatSequences( + OBoundControl::_getTypes(), + OImageControlControl_Base::getTypes() + ); +} + +//------------------------------------------------------------------------------ +OImageControlControl::OImageControlControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_IMAGECONTROL) + ,m_aModifyListeners( m_aMutex ) +{ + increment(m_refCount); + { + // als Focus- und MouseListener anmelden + Reference< XWindow > xComp; + query_aggregation( m_xAggregate, xComp ); + if ( xComp.is() ) + xComp->addMouseListener( this ); + } + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OImageControlControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControl::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + aReturn = ::cppu::queryInterface( + _rType, + static_cast< XMouseListener* >( this ), + static_cast< XModifyBroadcaster* >( this ) + ); + + return aReturn; +} + +//------------------------------------------------------------------------------ +StringSequence OImageControlControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_IMAGECONTROL; + return aSupported; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::addModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException) +{ + m_aModifyListeners.addInterface( _Listener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::removeModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException) +{ + m_aModifyListeners.removeInterface( _Listener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::disposing() +{ + EventObject aEvent( *this ); + m_aModifyListeners.disposeAndClear( aEvent ); + + OBoundControl::disposing(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::disposing( const EventObject& _Event ) throw(RuntimeException) +{ + OBoundControl::disposing( _Event ); +} + +//------------------------------------------------------------------------------ +void OImageControlControl::implClearGraphics( sal_Bool _bForce ) +{ + Reference< XPropertySet > xSet( getModel(), UNO_QUERY ); + if ( xSet.is() ) + { + if ( _bForce ) + { + ::rtl::OUString sOldImageURL; + xSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sOldImageURL; + + if ( !sOldImageURL.getLength() ) + // the ImageURL is already empty, so simply setting a new empty one would not suffice + // (since it would be ignored) + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:emptyImage" ) ) ) ); + // (the concrete URL we're passing here doens't matter. It's important that + // the model cannot resolve it to a a valid resource describing an image stream + } + + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString() ) ); + } +} + +//------------------------------------------------------------------------------ +bool OImageControlControl::implInsertGraphics() +{ + Reference< XPropertySet > xSet( getModel(), UNO_QUERY ); + if ( !xSet.is() ) + return false; + + ::rtl::OUString sTitle = FRM_RES_STRING(RID_STR_IMPORT_GRAPHIC); + // build some arguments for the upcoming dialog + try + { + ::sfx2::FileDialogHelper aDialog( TemplateDescription::FILEOPEN_LINK_PREVIEW, SFXWB_GRAPHIC ); + aDialog.SetTitle( sTitle ); + + Reference< XFilePickerControlAccess > xController( aDialog.GetFilePicker(), UNO_QUERY_THROW ); + xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, ::cppu::bool2any(sal_True)); + + Reference<XPropertySet> xBoundField; + if ( hasProperty( PROPERTY_BOUNDFIELD, xSet ) ) + xSet->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xBoundField; + sal_Bool bHasField = xBoundField.is(); + + // if the control is bound to a DB field, then it's not possible to decide whether or not to link + xController->enableControl(ExtendedFilePickerElementIds::CHECKBOX_LINK, !bHasField ); + + // if the control is bound to a DB field, then linking of the image depends on the type of the field + sal_Bool bImageIsLinked = sal_True; + if ( bHasField ) + { + sal_Int32 nFieldType = DataType::OTHER; + OSL_VERIFY( xBoundField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType ); + bImageIsLinked = ( lcl_getImageStoreType( nFieldType ) == ImageStoreLink ); + } + xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, makeAny( bImageIsLinked ) ); + + if ( ERRCODE_NONE == aDialog.Execute() ) + { + // reset the url property in case it already has the value we're about to set - in this case + // our propertyChanged would not get called without this. + implClearGraphics( sal_False ); + sal_Bool bIsLink = sal_False; + xController->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bIsLink; + if ( !bIsLink ) + { + Graphic aGraphic; + aDialog.GetGraphic( aGraphic ); + + Reference< graphic::XGraphicObject > xGrfObj = graphic::GraphicObject::create( m_aContext.getUNOContext() ); + xGrfObj->setGraphic( aGraphic.GetXGraphic() ); + rtl::OUString sObjectID( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) ); + sObjectID = sObjectID + xGrfObj->getUniqueID(); + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( sObjectID ) ) ); + } + else + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( aDialog.GetPath() ) ) ); + + return true; + } + } + catch(Exception&) + { + DBG_ERROR("OImageControlControl::implInsertGraphics: caught an exception while attempting to execute the FilePicker!"); + } + return false; +} + +//------------------------------------------------------------------------------ +bool OImageControlControl::impl_isEmptyGraphics_nothrow() const +{ + bool bIsEmpty = true; + + try + { + Reference< XPropertySet > xModelProps( const_cast< OImageControlControl* >( this )->getModel(), UNO_QUERY_THROW ); + Reference< XGraphic > xGraphic; + OSL_VERIFY( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ) ) ) >>= xGraphic ); + bIsEmpty = !xGraphic.is(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return bIsEmpty; +} + +// MouseListener +//------------------------------------------------------------------------------ +void OImageControlControl::mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if (e.Buttons != MouseButton::LEFT) + return; + + bool bModified = false; + // is this a request for a context menu? + if ( e.PopupTrigger ) + { + Reference< XPopupMenu > xMenu( m_aContext.createComponent( "com.sun.star.awt.PopupMenu" ), UNO_QUERY ); + DBG_ASSERT( xMenu.is(), "OImageControlControl::mousePressed: could not create a popup menu!" ); + + Reference< XWindowPeer > xWindowPeer = getPeer(); + DBG_ASSERT( xWindowPeer.is(), "OImageControlControl::mousePressed: no window!" ); + + if ( xMenu.is() && xWindowPeer.is() ) + { + xMenu->insertItem( ID_OPEN_GRAPHICS, FRM_RES_STRING( RID_STR_OPEN_GRAPHICS ), 0, 0 ); + xMenu->insertItem( ID_CLEAR_GRAPHICS, FRM_RES_STRING( RID_STR_CLEAR_GRAPHICS ), 0, 1 ); + + // check if the ImageURL is empty + if ( impl_isEmptyGraphics_nothrow() ) + xMenu->enableItem( ID_CLEAR_GRAPHICS, sal_False ); + + awt::Rectangle aRect( e.X, e.Y, 0, 0 ); + if ( ( e.X < 0 ) || ( e.Y < 0 ) ) + { // context menu triggered by keyboard + // position it in the center of the control + // 102205 - 16.08.2002 - fs@openoffice.org + Reference< XWindow > xWindow( static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY ); + OSL_ENSURE( xWindow.is(), "OImageControlControl::mousePressed: me not a window? How this?" ); + if ( xWindow.is() ) + { + awt::Rectangle aPosSize = xWindow->getPosSize(); + aRect.X = aPosSize.Width / 2; + aRect.Y = aPosSize.Height / 2; + } + } + + const sal_Int16 nResult = xMenu->execute( xWindowPeer, aRect, PopupMenuDirection::EXECUTE_DEFAULT ); + + switch ( nResult ) + { + case ID_OPEN_GRAPHICS: + implInsertGraphics(); + bModified = true; + break; + + case ID_CLEAR_GRAPHICS: + implClearGraphics( sal_True ); + bModified = true; + break; + } + } + } + else + { + ////////////////////////////////////////////////////////////////////// + // Doppelclick + if (e.ClickCount == 2) + { + + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (!xSet.is()) + return; + + // wenn Control nicht gebunden ist, kein Dialog (da die zu schickende URL hinterher sowieso + // versanden wuerde) + // FS - #64946# - 19.04.99 + Reference<XPropertySet> xBoundField; + if (hasProperty(PROPERTY_BOUNDFIELD, xSet)) + ::cppu::extractInterface(xBoundField, xSet->getPropertyValue(PROPERTY_BOUNDFIELD)); + if (!xBoundField.is()) + { + // but only if our IMAGE_URL property is handled as if it is transient, which is equivalent to + // an empty control source + if (!hasProperty(PROPERTY_CONTROLSOURCE, xSet) || (::comphelper::getString(xSet->getPropertyValue(PROPERTY_CONTROLSOURCE)).getLength() != 0)) + return; + } + + sal_Bool bReadOnly = false; + xSet->getPropertyValue(PROPERTY_READONLY) >>= bReadOnly; + if (bReadOnly) + return; + + if ( implInsertGraphics() ) + bModified = true; + } + } + + if ( bModified ) + { + EventObject aEvent( *this ); + m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::mouseReleased(const awt::MouseEvent& /*e*/) throw ( RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::mouseEntered(const awt::MouseEvent& /*e*/) throw ( RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::mouseExited(const awt::MouseEvent& /*e*/) throw ( RuntimeException ) +{ +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/ImageControl.hxx b/forms/source/component/ImageControl.hxx new file mode 100644 index 000000000000..eb0e15660ca6 --- /dev/null +++ b/forms/source/component/ImageControl.hxx @@ -0,0 +1,201 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_IMAGE_CONTROL_HXX_ +#define _FRM_IMAGE_CONTROL_HXX_ + +#include "FormComponent.hxx" +#include "imgprod.hxx" +#include <com/sun/star/form/XImageProducerSupplier.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <comphelper/propmultiplex.hxx> +#include <comphelper/implementationreference.hxx> +#include <cppuhelper/implbase2.hxx> + +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OImageControlModel +//================================================================== +typedef ::cppu::ImplHelper2 < ::com::sun::star::form::XImageProducerSupplier + , ::com::sun::star::awt::XImageProducer + > OImageControlModel_Base; + +class OImageControlModel + :public OImageControlModel_Base + ,public OBoundControlModel +{ + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> m_xImageProducer; + ImageProducer* m_pImageProducer; + sal_Bool m_bReadOnly; + ::rtl::OUString m_sDocumentURL; + +protected: + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + inline ImageProducer* GetImageProducer() { return m_pImageProducer; } + +public: + DECLARE_DEFAULT_LEAF_XTOR( OImageControlModel ); + + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OImageControlModel, OBoundControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OImageControlModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // OPropertyChangeListener + virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& ) throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XImageProducerSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> SAL_CALL getImageProducer() throw ( ::com::sun::star::uno::RuntimeException); + + // XImageProducer + virtual void SAL_CALL addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startProduction( ) throw (::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OBoundControlModel::disposing; + using OBoundControlModel::getFastPropertyValue; + +protected: + // OBoundControlModel overridables + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual void doSetControlValue( const ::com::sun::star::uno::Any& _rValue ); + + virtual sal_Bool approveDbColumnType(sal_Int32 _nColumnType); + + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); + + void implConstruct(); + + /** displays the image described by the given URL + @precond + our own mutex is locked + */ + sal_Bool impl_handleNewImageURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ); + + /** updates the binary stream, created from loading the file which the given URL points to, into our + bound field, or the control itself if there is no bound field + */ + sal_Bool impl_updateStreamForURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ); +}; + +//================================================================== +//= OImageControlControl +//================================================================== +typedef ::cppu::ImplHelper2 < ::com::sun::star::awt::XMouseListener + , ::com::sun::star::util::XModifyBroadcaster + > OImageControlControl_Base; +class OImageControlControl : public OBoundControl + , public OImageControlControl_Base +{ +private: + ::cppu::OInterfaceContainerHelper m_aModifyListeners; + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OImageControlControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS( OImageControlControl, OBoundControl ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OImageControlControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // XMouseListener + virtual void SAL_CALL mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseReleased(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseEntered(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseExited(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + +private: + void implClearGraphics( sal_Bool _bForce ); + bool implInsertGraphics(); + + /** determines whether the control does currently have an empty grahic set + */ + bool impl_isEmptyGraphics_nothrow() const; +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_IMAGE_CONTROL_HXX_ + diff --git a/forms/source/component/ListBox.cxx b/forms/source/component/ListBox.cxx new file mode 100644 index 000000000000..0aa90d9919cf --- /dev/null +++ b/forms/source/component/ListBox.cxx @@ -0,0 +1,1844 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "ListBox.hxx" +#include "property.hxx" +#include "property.hrc" +#include "services.hxx" +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "BaseListBox.hxx" +#include "listenercontainers.hxx" +#include "componenttools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/container.hxx> +#include <comphelper/numbers.hxx> +#include <comphelper/listenernotification.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/formattedcolumnvalue.hxx> +#include <connectivity/dbconversion.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/logfile.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> +#include <vcl/svapp.hxx> + +#include <algorithm> +#include <functional> + + +//......................................................................... +namespace frm +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + using namespace ::dbtools; + + using ::connectivity::ORowSetValue; + + //============================================================================== + //= helper + //============================================================================== + namespace + { + //-------------------------------------------------------------------------- + struct RowSetValueToString : public ::std::unary_function< ORowSetValue, ::rtl::OUString > + { + ::rtl::OUString operator()( const ORowSetValue& _value ) const + { + return _value.getString(); + } + }; + + //-------------------------------------------------------------------------- + struct AppendRowSetValueString : public ::std::unary_function< ::rtl::OUString, void > + { + AppendRowSetValueString( ::rtl::OUString& _string ) + :m_string( _string ) + { + } + + void operator()( const ::rtl::OUString _append ) + { + m_string += _append; + } + + private: + ::rtl::OUString& m_string; + }; + + //-------------------------------------------------------------------------- + Sequence< ::rtl::OUString > lcl_convertToStringSequence( const ValueList& _values ) + { + Sequence< ::rtl::OUString > aStrings( _values.size() ); + ::std::transform( + _values.begin(), + _values.end(), + aStrings.getArray(), + RowSetValueToString() + ); + return aStrings; + } + } + + //============================================================================== + //= ItemEventDescription + //============================================================================== + typedef ::comphelper::EventHolder< ItemEvent > ItemEventDescription; + + //============================================================================== + //= OListBoxModel + //============================================================================== + //------------------------------------------------------------------ + InterfaceRef SAL_CALL OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) + { + return *(new OListBoxModel(_rxFactory)); + } + + //------------------------------------------------------------------------------ + Sequence< Type> OListBoxModel::_getTypes() + { + return TypeBag( + OBoundControlModel::_getTypes(), + OEntryListHelper::getTypes(), + OErrorBroadcaster::getTypes() + ).getTypes(); + } + + + DBG_NAME(OListBoxModel); + //------------------------------------------------------------------ + OListBoxModel::OListBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, sal_True, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OEntryListHelper( (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_nNULLPos(-1) + ,m_bBoundComponent(sal_False) + { + DBG_CTOR(OListBoxModel,NULL); + + m_nClassId = FormComponentType::LISTBOX; + m_eListSourceType = ListSourceType_VALUELIST; + m_aBoundColumn <<= (sal_Int16)1; + initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ); + } + + //------------------------------------------------------------------ + OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + ,OEntryListHelper( *_pOriginal, (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_eListSourceType( _pOriginal->m_eListSourceType ) + ,m_aBoundColumn( _pOriginal->m_aBoundColumn ) + ,m_aListSourceValues( _pOriginal->m_aListSourceValues ) + ,m_aBoundValues( _pOriginal->m_aBoundValues ) + ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq ) + ,m_nNULLPos(-1) + ,m_bBoundComponent(sal_False) + { + DBG_CTOR(OListBoxModel,NULL); + } + + //------------------------------------------------------------------ + OListBoxModel::~OListBoxModel() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OListBoxModel,NULL); + } + + // XCloneable + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( OListBoxModel ) + + // XServiceInfo + //------------------------------------------------------------------------------ + StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException) + { + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX; + *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX; + + return aSupported; + } + + //------------------------------------------------------------------------------ + Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException) + { + Any aReturn = OBoundControlModel::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OEntryListHelper::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OErrorBroadcaster::queryInterface( _rType ); + return aReturn; + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OListBoxModel::disposing() + { + OBoundControlModel::disposing(); + OEntryListHelper::disposing(); + OErrorBroadcaster::disposing(); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const + { + switch (_nHandle) + { + case PROPERTY_ID_BOUNDCOLUMN: + _rValue <<= m_aBoundColumn; + break; + + case PROPERTY_ID_LISTSOURCETYPE: + _rValue <<= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE: + _rValue <<= lcl_convertToStringSequence( m_aListSourceValues ); + break; + + case PROPERTY_ID_VALUE_SEQ: + _rValue <<= lcl_convertToStringSequence( m_aBoundValues ); + break; + + case PROPERTY_ID_DEFAULT_SELECT_SEQ: + _rValue <<= m_aDefaultSelectSeq; + break; + + case PROPERTY_ID_STRINGITEMLIST: + _rValue <<= getStringItemList(); + break; + + default: + OBoundControlModel::getFastPropertyValue(_rValue, _nHandle); + } + } + + //------------------------------------------------------------------------------ + void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception) + { + switch (_nHandle) + { + case PROPERTY_ID_BOUNDCOLUMN : + DBG_ASSERT((_rValue.getValueType().getTypeClass() == TypeClass_SHORT) || (_rValue.getValueType().getTypeClass() == TypeClass_VOID), + "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + m_aBoundColumn = _rValue; + break; + + case PROPERTY_ID_LISTSOURCETYPE : + DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType*>(NULL))), + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE: + { + // extract + Sequence< ::rtl::OUString > aListSource; + OSL_VERIFY( _rValue >>= aListSource ); + + // copy to member + ValueList().swap(m_aListSourceValues); + ::std::copy( + aListSource.getConstArray(), + aListSource.getConstArray() + aListSource.getLength(), + ::std::insert_iterator< ValueList >( m_aListSourceValues, m_aListSourceValues.end() ) + ); + + // propagate + if ( m_eListSourceType == ListSourceType_VALUELIST ) + { + m_aBoundValues = m_aListSourceValues; + } + else + { + if ( m_xCursor.is() && !hasField() && !hasExternalListSource() ) + // listbox is already connected to a database, and no external list source + // data source changed -> refresh + loadData( false ); + } + } + break; + + case PROPERTY_ID_VALUE_SEQ : + OSL_ENSURE( false, "ValueItemList is read-only!" ); + throw PropertyVetoException(); + + case PROPERTY_ID_DEFAULT_SELECT_SEQ : + DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast< Sequence<sal_Int16>*>(NULL))), + "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_aDefaultSelectSeq; + + DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !"); + if ( m_xAggregateFastSet.is() ) + setControlValue( _rValue, eOther ); + break; + + case PROPERTY_ID_STRINGITEMLIST: + { + ControlModelLock aLock( *this ); + setNewStringItemList( _rValue, aLock ); + // TODO: this is bogus. setNewStringItemList expects a guard which has the *only* + // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with + // a lock - so we effectively has two locks here, of which setNewStringItemList can + // only control one. + } + resetNoBroadcast(); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OListBoxModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (IllegalArgumentException) + { + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_BOUNDCOLUMN : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::getCppuType(reinterpret_cast<sal_Int16*>(NULL))); + break; + + case PROPERTY_ID_LISTSOURCETYPE: + bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType); + break; + + case PROPERTY_ID_LISTSOURCE: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) ); + break; + + case PROPERTY_ID_VALUE_SEQ : + OSL_ENSURE( false, "ValueItemList is read-only!" ); + throw PropertyVetoException(); + + case PROPERTY_ID_DEFAULT_SELECT_SEQ : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq); + break; + + case PROPERTY_ID_STRINGITEMLIST: + bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue ); + break; + + default: + return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + } + return bModified; + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< ::rtl::OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) + { + // if both SelectedItems and StringItemList are set, care for this + // #i27024# / 2004-04-05 / fs@openoffice.org + const Any* pSelectSequenceValue = NULL; + + const ::rtl::OUString* pStartPos = _rPropertyNames.getConstArray(); + const ::rtl::OUString* pEndPos = _rPropertyNames.getConstArray() + _rPropertyNames.getLength(); + const ::rtl::OUString* pSelectedItemsPos = ::std::find_if( + pStartPos, pEndPos, + ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_SELECT_SEQ ) + ); + const ::rtl::OUString* pStringItemListPos = ::std::find_if( + pStartPos, pEndPos, + ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_STRINGITEMLIST ) + ); + if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) ) + { + // both properties are present + // -> remember the value for the select sequence + pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos ); + } + + OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues ); + + if ( pSelectSequenceValue ) + { + setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue ); + // Note that this is the only reliable way, since one of the properties is implemented + // by ourself, and one is implemented by the aggregate, we cannot rely on any particular + // results when setting them both - too many undocumented behavior in all the involved + // classes + } + } + + //------------------------------------------------------------------------------ + void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 7, OBoundControlModel ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP2(BOUNDCOLUMN, sal_Int16, BOUND, MAYBEVOID); + DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND); + DECL_PROP1(LISTSOURCE, StringSequence, BOUND); + DECL_PROP3(VALUE_SEQ, StringSequence, BOUND, READONLY, TRANSIENT); + DECL_PROP1(DEFAULT_SELECT_SEQ, Sequence<sal_Int16>, BOUND); + DECL_PROP1(STRINGITEMLIST, Sequence< ::rtl::OUString >, BOUND); + END_DESCRIBE_PROPERTIES(); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const + { + OBoundControlModel::describeAggregateProperties( _rAggregateProps ); + + // superseded properties: + RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST ); + } + + //------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException) + { + return FRM_COMPONENT_LISTBOX; // old (non-sun) name for compatibility ! + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) + { + OBoundControlModel::write(_rxOutStream); + + // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird + Sequence<sal_Int16> aDummySeq; + + // Version + // Version 0x0002: ListSource wird StringSeq + _rxOutStream->writeShort(0x0004); + + // Maskierung fuer any + sal_uInt16 nAnyMask = 0; + if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID) + nAnyMask |= BOUNDCOLUMN; + + _rxOutStream << nAnyMask; + + _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues ); + _rxOutStream << (sal_Int16)m_eListSourceType; + _rxOutStream << aDummySeq; + _rxOutStream << m_aDefaultSelectSeq; + + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nBoundColumn = 0; + m_aBoundColumn >>= nBoundColumn; + _rxOutStream << nBoundColumn; + } + writeHelpTextCompatibly(_rxOutStream); + + // from version 0x0004 : common properties + writeCommonProperties(_rxOutStream); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) + { + // Bei manchen Variblen muessen Abhaengigkeiten beruecksichtigt werden. + // Deshalb muessen sie explizit ueber setPropertyValue() gesetzt werden. + + OBoundControlModel::read(_rxInStream); + ControlModelLock aLock( *this ); + + // since we are "overwriting" the StringItemList of our aggregate (means we have + // an own place to store the value, instead of relying on our aggregate storing it), + // we need to respect what the aggregate just read for the StringItemList property. + try + { + if ( m_xAggregateSet.is() ) + setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" ); + } + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !"); + + if (nVersion > 0x0004) + { + DBG_ERROR("OListBoxModel::read : invalid (means unknown) version !"); + ValueList().swap(m_aListSourceValues); + m_aBoundColumn <<= (sal_Int16)0; + ValueList().swap(m_aBoundValues); + m_eListSourceType = ListSourceType_VALUELIST; + m_aDefaultSelectSeq.realloc(0); + defaultCommonProperties(); + return; + } + + // Maskierung fuer any + sal_uInt16 nAnyMask; + _rxInStream >> nAnyMask; + + // ListSourceSeq + StringSequence aListSourceSeq; + if (nVersion == 0x0001) + { + // ListSourceSeq aus String zusammenstellen; + ::rtl::OUString sListSource; + _rxInStream >> sListSource; + + sal_Int32 nTokens = 1; + const sal_Unicode* pStr = sListSource.getStr(); + while ( *pStr ) + { + if ( *pStr == ';' ) + nTokens++; + pStr++; + } + aListSourceSeq.realloc( nTokens ); + for (sal_uInt16 i=0; i<nTokens; ++i) + { + sal_Int32 nTmp = 0; + aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp); + } + } + else + _rxInStream >> aListSourceSeq; + + sal_Int16 nListSourceType; + _rxInStream >> nListSourceType; + m_eListSourceType = (ListSourceType)nListSourceType; + Any aListSourceSeqAny; + aListSourceSeqAny <<= aListSourceSeq; + + setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny ); + + // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird + Sequence<sal_Int16> aDummySeq; + _rxInStream >> aDummySeq; + + // DefaultSelectSeq + Sequence<sal_Int16> aDefaultSelectSeq; + _rxInStream >> aDefaultSelectSeq; + Any aDefaultSelectSeqAny; + aDefaultSelectSeqAny <<= aDefaultSelectSeq; + setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny); + + // BoundColumn + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nValue; + _rxInStream >> nValue; + m_aBoundColumn <<= nValue; + } + + if (nVersion > 2) + readHelpTextCompatibly(_rxInStream); + + // if our string list is not filled from the value list, we must empty it + // this can be the case when somebody saves in alive mode + if ( ( m_eListSourceType != ListSourceType_VALUELIST ) + && !hasExternalListSource() + ) + { + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); + } + + if (nVersion > 3) + readCommonProperties(_rxInStream); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::loadData( bool _bForce ) + { + RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData" ); + DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" ); + DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" ); + + m_nNULLPos = -1; + m_bBoundComponent = sal_False; + + // pre-requisites: + // PRE1: connection + Reference< XConnection > xConnection; + // is the active connection of our form + Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY ); + if ( xFormProps.is() ) + xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection; + + // PRE2: list source + ::rtl::OUString sListSource; + // if our list source type is no value list, we need to concatenate + // the single list source elements + ::std::for_each( + m_aListSourceValues.begin(), + m_aListSourceValues.end(), + AppendRowSetValueString( sListSource ) + ); + + // outta here if we don't have all pre-requisites + if ( !xConnection.is() || !sListSource.getLength() ) + { + ValueList().swap(m_aBoundValues); + return; + } + + sal_Int16 nBoundColumn = 0; + if (m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT) + m_aBoundColumn >>= nBoundColumn; + + ::utl::SharedUNOComponent< XResultSet > xListCursor; + try + { + m_aListRowSet.setConnection( xConnection ); + + sal_Bool bExecute = sal_False; + switch (m_eListSourceType) + { + case ListSourceType_TABLEFIELDS: + // don't work with a statement here, the fields will be collected below + break; + + case ListSourceType_TABLE: + { + Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource); + Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY); + + // do we have a bound column if yes we have to select it + // and the displayed column is the first column othwhise we act as a combobox + ::rtl::OUString aFieldName; + ::rtl::OUString aBoundFieldName; + + if ((nBoundColumn > 0) && xFieldsByIndex.is()) + { + if (xFieldsByIndex->getCount() <= nBoundColumn) + break; + + Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex(nBoundColumn),UNO_QUERY); + xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName; + nBoundColumn = 1; + + xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY); + xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName; + } + else if (xFieldsByName.is()) + { + if ( xFieldsByName->hasByName( getControlSource() ) ) + aFieldName = getControlSource(); + else + { + // otherwise look for the alias + Reference<XSQLQueryComposerFactory> xFactory(xConnection, UNO_QUERY); + if (!xFactory.is()) + break; + + Reference<XSQLQueryComposer> xComposer = xFactory->createQueryComposer(); + try + { + ::rtl::OUString aStatement; + xFormProps->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= aStatement; + xComposer->setQuery( aStatement ); + } + catch(Exception&) + { + disposeComponent(xComposer); + break; + } + + // search the field + Reference<XColumnsSupplier> xSupplyFields(xComposer, UNO_QUERY); + DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !"); + + Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns(); + if ( xFieldNames->hasByName( getControlSource() ) ) + { + Reference<XPropertySet> xComposerFieldAsSet; + xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet; + if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet)) + xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName; + } + disposeComponent(xComposer); + } + } + if (!aFieldName.getLength()) + break; + + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString(); + ::rtl::OUString aStatement = ::rtl::OUString::createFromAscii("SELECT "); + if (!aBoundFieldName.getLength()) // act like a combobox + aStatement += ::rtl::OUString::createFromAscii("DISTINCT "); + + aStatement += quoteName(aQuote,aFieldName); + if (aBoundFieldName.getLength()) + { + aStatement += ::rtl::OUString::createFromAscii(", "); + aStatement += quoteName(aQuote, aBoundFieldName); + } + aStatement += ::rtl::OUString::createFromAscii(" FROM "); + + ::rtl::OUString sCatalog, sSchema, sTable; + qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation ); + aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ); + + m_aListRowSet.setEscapeProcessing( sal_False ); + m_aListRowSet.setCommand( aStatement ); + bExecute = sal_True; + } + break; + + case ListSourceType_QUERY: + m_aListRowSet.setCommandFromQuery( sListSource ); + bExecute = sal_True; + break; + + default: + m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType ); + m_aListRowSet.setCommand( sListSource ); + bExecute = sal_True; + break; + } + + if (bExecute) + { + if ( !_bForce && !m_aListRowSet.isDirty() ) + { + // if none of the settings of the row set changed, compared to the last + // invocation of loadData, then don't re-fill the list. Instead, assume + // the list entries are the same. + return; + } + xListCursor.reset( m_aListRowSet.execute() ); + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch(const Exception& eUnknown) + { + (void)eUnknown; + return; + } + + // Anzeige- und Werteliste fuellen + ValueList aDisplayList, aValueList; + sal_Bool bUseNULL = hasField() && !isRequired(); + + try + { + OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ), + "OListBoxModel::loadData: logic error!" ); + if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) ) + return; + + switch (m_eListSourceType) + { + case ListSourceType_SQL: + case ListSourceType_SQLPASSTHROUGH: + case ListSourceType_TABLE: + case ListSourceType_QUERY: + { + // Feld der 1. Column des ResultSets holen + Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY); + DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!"); + Reference<XIndexAccess> xColumns; + if (xSupplyCols.is()) + { + xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY); + DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !"); + } + + Reference< XPropertySet > xDataField; + if ( xColumns.is() ) + xColumns->getByIndex(0) >>= xDataField; + if ( !xDataField.is() ) + return; + + ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField ); + + // Feld der BoundColumn des ResultSets holen + sal_Int32 nBoundColumnType = DataType::SQLNULL; + if ( ( nBoundColumn > 0 ) && m_xColumn.is() ) + { // don't look for a bound column if we're not connected to a field + try + { + Reference< XPropertySet > xBoundField( xColumns->getByIndex( nBoundColumn ), UNO_QUERY_THROW ); + OSL_VERIFY( xBoundField->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) >>= nBoundColumnType ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + m_bBoundComponent = ( nBoundColumnType != DataType::SQLNULL ); + + // Ist die LB an ein Feld gebunden und sind Leereintraege zulaessig + // dann wird die Position fuer einen Leereintrag gemerkt + + RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData: string collection" ); + ::rtl::OUString aStr; + sal_Int16 entryPos = 0; + ORowSetValue aBoundValue; + Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW ); + while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries + { + aStr = aValueFormatter.getFormattedValue(); + aDisplayList.push_back( aStr ); + + if ( m_bBoundComponent ) + { + aBoundValue.fill( nBoundColumn + 1, nBoundColumnType, xCursorRow ); + aValueList.push_back( aBoundValue ); + } + + if ( bUseNULL && ( m_nNULLPos == -1 ) && !aStr.getLength() ) + m_nNULLPos = sal_Int16( aDisplayList.size() - 1 ); + } + } + break; + + case ListSourceType_TABLEFIELDS: + { + Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource); + if (xFieldNames.is()) + { + StringSequence seqNames = xFieldNames->getElementNames(); + ::std::copy( + seqNames.getConstArray(), + seqNames.getConstArray() + seqNames.getLength(), + ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() ) + ); + } + } + break; + default: + OSL_ENSURE( false, "OListBoxModel::loadData: unreachable!" ); + break; + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + + // Value-Sequence erzeugen + // NULL eintrag hinzufuegen + if (bUseNULL && m_nNULLPos == -1) + { + if ( m_bBoundComponent ) + aValueList.insert( aValueList.begin(), ORowSetValue() ); + + aDisplayList.insert( aDisplayList.begin(), ORowSetValue( ::rtl::OUString() ) ); + m_nNULLPos = 0; + } + + m_aBoundValues = aValueList; + + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) ); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ ) + { + // list boxes which are bound to a db column don't have multi selection + // - this would be unable to reflect in the db column + if ( hasField() ) + { + setFastPropertyValue( PROPERTY_ID_MULTISELECTION, ::cppu::bool2any( ( sal_False ) ) ); + } + + if ( !hasExternalListSource() ) + impl_refreshDbEntryList( false ); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::onDisconnectedDbColumn() + { + if ( m_eListSourceType != ListSourceType_VALUELIST ) + { + ValueList().swap(m_aBoundValues); + m_nNULLPos = -1; + m_bBoundComponent = sal_False; + + if ( !hasExternalListSource() ) + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); + + m_aListRowSet.dispose(); + } + } + + //------------------------------------------------------------------------------ + ValueList OListBoxModel::impl_getValues() const + { + if ( !m_aBoundValues.empty() ) + return m_aBoundValues; + + Sequence< ::rtl::OUString > aStringItems( getStringItemList() ); + ValueList aValues( aStringItems.getLength() ); + ::std::copy( + aStringItems.getConstArray(), + aStringItems.getConstArray() + aStringItems.getLength(), + aValues.begin() + ); + + return aValues; + } + //------------------------------------------------------------------------------ + ORowSetValue OListBoxModel::getFirstSelectedValue() const + { + static const ORowSetValue s_aEmptyVaue; + + DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" ); + if ( !m_xAggregateFastSet.is() ) + return s_aEmptyVaue; + + Sequence< sal_Int16 > aSelectedIndices; + OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices ); + if ( !aSelectedIndices.getLength() ) + // nothing selected at all + return s_aEmptyVaue; + + if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) ) + // the dedicated "NULL" entry is selected + return s_aEmptyVaue; + + ValueList aValues( impl_getValues() ); + + size_t selectedValue = aSelectedIndices[0]; + if ( selectedValue >= aValues.size() ) + { + OSL_ENSURE( false, "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" ); + return s_aEmptyVaue; + } + + return aValues[ selectedValue ]; + } + + //------------------------------------------------------------------------------ + sal_Bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) + { + // current selektion list + const ORowSetValue aCurrentValue( getFirstSelectedValue() ); + if ( aCurrentValue != m_aSaveValue ) + { + if ( aCurrentValue.isNull() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + m_xColumnUpdate->updateObject( aCurrentValue.makeAny() ); + } + catch ( const Exception& ) + { + return sal_False; + } + } + m_aSaveValue = aCurrentValue; + } + return sal_True; + } + + // XPropertiesChangeListener + //------------------------------------------------------------------------------ + Any OListBoxModel::translateDbColumnToControlValue() + { + Reference< XPropertySet > xBoundField( getField() ); + if ( !xBoundField.is() ) + { + OSL_ENSURE( false, "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" ); + return Any(); + } + + Sequence< sal_Int16 > aSelectionIndicies; + + ORowSetValue aCurrentValue; + aCurrentValue.fill( getFieldType(), m_xColumn ); + + // reset selection for NULL values + if ( aCurrentValue.isNull() ) + { + if ( m_nNULLPos != -1 ) + { + aSelectionIndicies.realloc(1); + aSelectionIndicies[0] = m_nNULLPos; + } + } + else + { + ValueList aValues( impl_getValues() ); + ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), aCurrentValue ); + if ( curValuePos != aValues.end() ) + { + aSelectionIndicies.realloc( 1 ); + aSelectionIndicies[0] = curValuePos - aValues.begin(); + } + } + + m_aSaveValue = aCurrentValue; + + return makeAny( aSelectionIndicies ); + } + + // XReset + //------------------------------------------------------------------------------ + Any OListBoxModel::getDefaultForReset() const + { + Any aValue; + if (m_aDefaultSelectSeq.getLength()) + aValue <<= m_aDefaultSelectSeq; + else if (m_nNULLPos != -1) // gebundene Listbox + { + Sequence<sal_Int16> aSeq(1); + aSeq.getArray()[0] = m_nNULLPos; + aValue <<= aSeq; + } + else + { + Sequence<sal_Int16> aSeq; + aValue <<= aSeq; + } + + return aValue; + } + + //-------------------------------------------------------------------- + void OListBoxModel::resetNoBroadcast() + { + OBoundControlModel::resetNoBroadcast(); + m_aSaveValue.setNull(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException ) + { + if ( !OEntryListHelper::handleDisposing( _rSource ) ) + OBoundControlModel::disposing( _rSource ); + } + + //-------------------------------------------------------------------- + namespace + { + /** type how we should transfer our selection to external value bindings + */ + enum ExchangeType + { + eIndexList, /// as list of indexes of selected entries + eIndex, /// as index of the selected entry + eEntryList, /// as list of string representations of selected entries + eEntry /// as string representation of the selected entry + }; + + //-------------------------------------------------------------------- + ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType ) + { + switch ( _rExchangeType.getTypeClass() ) + { + case TypeClass_STRING: + return eEntry; + case TypeClass_LONG: + return eIndex; + case TypeClass_SEQUENCE: + { + Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType ); + switch ( aElementType.getTypeClass() ) + { + case TypeClass_STRING: + return eEntryList; + case TypeClass_LONG: + return eIndexList; + default: + break; + } + } + default: + break; + } + OSL_ENSURE( false, "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" ); + return eEntry; + } + } + + //-------------------------------------------------------------------- + Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + Sequence< sal_Int16 > aSelectIndexes; + + switch ( lcl_getCurrentExchangeType( getExternalValueType() ) ) + { + case eIndexList: + { + // unfortunately, our select sequence is a sequence<short>, while the external binding + // supplies sequence<int> only -> transform this + Sequence< sal_Int32 > aSelectIndexesPure; + OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure ); + aSelectIndexes.realloc( aSelectIndexesPure.getLength() ); + ::std::copy( + aSelectIndexesPure.getConstArray(), + aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(), + aSelectIndexes.getArray() + ); + } + break; + + case eIndex: + { + sal_Int32 nSelectIndex = -1; + OSL_VERIFY( _rExternalValue >>= nSelectIndex ); + if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) ) + { + aSelectIndexes.realloc( 1 ); + aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex ); + } + } + break; + + case eEntryList: + { + // we can retrieve a string list from the binding for multiple selection + Sequence< ::rtl::OUString > aSelectEntries; + OSL_VERIFY( _rExternalValue >>= aSelectEntries ); + + ::std::set< sal_Int16 > aSelectionSet; + + // find the selection entries in our item list + const ::rtl::OUString* pSelectEntries = aSelectEntries.getArray(); + const ::rtl::OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength(); + while ( pSelectEntries != pSelectEntriesEnd ) + { + // the indexes where the current string appears in our string items + Sequence< sal_Int16 > aThisEntryIndexes; + aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, sal_False ); + + // insert all the indexes of this entry into our set + ::std::copy( + aThisEntryIndexes.getConstArray(), + aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(), + ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() ) + ); + } + + // copy the indexes to the sequence + aSelectIndexes.realloc( aSelectionSet.size() ); + ::std::copy( + aSelectionSet.begin(), + aSelectionSet.end(), + aSelectIndexes.getArray() + ); + } + break; + + case eEntry: + { + ::rtl::OUString sStringToSelect; + OSL_VERIFY( _rExternalValue >>= sStringToSelect ); + + aSelectIndexes = findValue( getStringItemList(), sStringToSelect, sal_False ); + } + break; + } + + return makeAny( aSelectIndexes ); + } + + //-------------------------------------------------------------------- + namespace + { + //................................................................ + struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, ::rtl::OUString > + { + protected: + const Sequence< ::rtl::OUString >& m_rList; + + public: + ExtractStringFromSequence_Safe( const Sequence< ::rtl::OUString >& _rList ) : m_rList( _rList ) { } + + ::rtl::OUString operator ()( sal_Int16 _nIndex ) + { + OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" ); + if ( _nIndex < m_rList.getLength() ) + return m_rList[ _nIndex ]; + return ::rtl::OUString(); + } + }; + + //................................................................ + Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList ) + { + Any aReturn; + + // by definition, multiple selected entries are transfered as NULL if the + // binding does not support string lists + if ( _rSelectSequence.getLength() <= 1 ) + { + ::rtl::OUString sSelectedEntry; + + if ( _rSelectSequence.getLength() == 1 ) + sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] ); + + aReturn <<= sSelectedEntry; + } + + return aReturn; + } + + //................................................................ + Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList ) + { + Sequence< ::rtl::OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() ); + ::std::transform( + _rSelectSequence.getConstArray(), + _rSelectSequence.getConstArray() + _rSelectSequence.getLength(), + aSelectedEntriesTexts.getArray(), + ExtractStringFromSequence_Safe( _rStringList ) + ); + return makeAny( aSelectedEntriesTexts ); + } + } + + //-------------------------------------------------------------------- + Any OListBoxModel::translateControlValueToExternalValue( ) const + { + OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" ); + + Sequence< sal_Int16 > aSelectSequence; + const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence; + + Any aReturn; + switch ( lcl_getCurrentExchangeType( getExternalValueType() ) ) + { + case eIndexList: + { + // unfortunately, the select sequence is a sequence<short>, but our binding + // expects int's + Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() ); + ::std::copy( + aSelectSequence.getConstArray(), + aSelectSequence.getConstArray() + aSelectSequence.getLength(), + aTransformed.getArray() + ); + aReturn <<= aTransformed; + } + break; + + case eIndex: + if ( aSelectSequence.getLength() <= 1 ) + { + sal_Int32 nIndex = -1; + + if ( aSelectSequence.getLength() == 1 ) + nIndex = aSelectSequence[0]; + + aReturn <<= nIndex; + } + break; + + case eEntryList: + aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() ); + break; + + case eEntry: + aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() ); + break; + } + + return aReturn; + } + + //-------------------------------------------------------------------- + Any OListBoxModel::getCurrentFormComponentValue() const + { + if ( hasValidator() ) + return OBoundControlModel::getCurrentFormComponentValue(); + + Any aCurretnValue; + + try + { + Sequence< sal_Int16 > aSelectSequence; + OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence ); + + sal_Bool bMultiSelection( sal_False ); + OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection ); + + if ( bMultiSelection ) + aCurretnValue = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() ); + else + aCurretnValue = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return aCurretnValue; + } + + //-------------------------------------------------------------------- + Sequence< Type > OListBoxModel::getSupportedBindingTypes() + { + Sequence< Type > aTypes(4); + aTypes[0] = ::getCppuType( static_cast< Sequence< sal_Int32 >* >( NULL ) ); + aTypes[1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); + aTypes[2] = ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) ); + aTypes[3] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); + return aTypes; + } + + //-------------------------------------------------------------------- + void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock ) + { + if ( !m_xAggregateSet.is() ) + return; + + suspendValueListening(); + try + { + m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + resumeValueListening(); + + // update the selection here + if ( hasExternalValueBinding( ) ) + transferExternalValueToControl( _rInstanceLock ); + else + { + if ( hasField() ) + { + // TODO: update the selection in case we're bound to a database column + } + else + { + if ( m_aDefaultSelectSeq.getLength() ) + setControlValue( makeAny( m_aDefaultSelectSeq ), eOther ); + } + } + } + + //-------------------------------------------------------------------- + void OListBoxModel::connectedExternalListSource( ) + { + // TODO? + } + + //-------------------------------------------------------------------- + void OListBoxModel::disconnectedExternalListSource( ) + { + // TODO: in case we're part of an already loaded form, we should probably simulate + // an onConnectedDbColumn, so our list get's filled with the data as indicated + // by our SQL-binding related properties + } + + //-------------------------------------------------------------------- + void OListBoxModel::impl_refreshDbEntryList( bool _bForce ) + { + DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" ); + + if ( !hasExternalListSource( ) + && ( m_eListSourceType != ListSourceType_VALUELIST ) + && ( m_xCursor.is() ) + ) + { + loadData( _bForce ); + } + } + + //-------------------------------------------------------------------- + void OListBoxModel::refreshInternalEntryList() + { + impl_refreshDbEntryList( true ); + if ( hasField() && m_xCursor.is() ) + initFromField( m_xCursor ); + } + + //================================================================== + // OListBoxControl + //================================================================== + + //------------------------------------------------------------------ + InterfaceRef SAL_CALL OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) + { + return *(new OListBoxControl(_rxFactory)); + } + + //------------------------------------------------------------------------------ + Sequence< Type> OListBoxControl::_getTypes() + { + return TypeBag( + OBoundControl::_getTypes(), + OListBoxControl_BASE::getTypes() + ).getTypes(); + } + + //------------------------------------------------------------------ + Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException) + { + Any aReturn = OListBoxControl_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() + || _rType.equals( XTypeProvider::static_type() ) + ) + aReturn = OBoundControl::queryAggregation( _rType ); + + return aReturn; + } + + DBG_NAME(OListBoxControl); + //------------------------------------------------------------------------------ + OListBoxControl::OListBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, sal_False ) + ,m_aChangeListeners( m_aMutex ) + ,m_aItemListeners( m_aMutex ) + ,m_pItemBroadcaster( NULL ) + { + DBG_CTOR(OListBoxControl,NULL); + + increment(m_refCount); + { + // als FocusListener anmelden + Reference<XWindow> xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->addFocusListener(this); + + // als ItemListener anmelden + if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) ) + m_xAggregateListBox->addItemListener(this); + } + // Refcount bei 2 fuer angemeldete Listener + decrement(m_refCount); + + doSetDelegator(); + + m_aChangeTimer.SetTimeout(500); + m_aChangeTimer.SetTimeoutHdl(LINK(this,OListBoxControl,OnTimeout)); + } + + //------------------------------------------------------------------------------ + OListBoxControl::~OListBoxControl() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + doResetDelegator(); + m_xAggregateListBox.clear(); + + DBG_DTOR(OListBoxControl,NULL); + } + + //------------------------------------------------------------------------------ + StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException) + { + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_LISTBOX; + return aSupported; + } + + + // XFocusListener + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException) + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( m_aChangeListeners.getLength() ) // only if there are listeners + { + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + { + // memorize the current selection for posting the change event + m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); + } + } + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException) + { + m_aCurrentSelection.clear(); + } + + // XItemListener + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException) + { + // forward this to our listeners + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_aItemListeners.getLength() ) + { + if ( !m_pItemBroadcaster.is() ) + { + m_pItemBroadcaster.set( new ::comphelper::AsyncEventNotifier ); + m_pItemBroadcaster->create(); + } + m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this ); + } + } + + // and do the handling for the ChangeListeners + ::osl::ClearableMutexGuard aGuard(m_aMutex); + if ( m_aChangeTimer.IsActive() ) + { + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); + + m_aChangeTimer.Stop(); + m_aChangeTimer.Start(); + } + else + { + if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() ) + { + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + { + // Has the selection been changed? + sal_Bool bModified(sal_False); + Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); + + Sequence<sal_Int16>& rSelection = *(Sequence<sal_Int16> *)aValue.getValue(); + Sequence<sal_Int16>& rOldSelection = *(Sequence<sal_Int16> *)m_aCurrentSelection.getValue(); + sal_Int32 nLen = rSelection.getLength(); + if (nLen != rOldSelection.getLength()) + bModified = sal_True; + else + { + const sal_Int16* pVal = rSelection.getConstArray(); + const sal_Int16* pCompVal = rOldSelection.getConstArray(); + + while (nLen-- && !bModified) + bModified = pVal[nLen] != pCompVal[nLen]; + } + + if (bModified) + { + m_aCurrentSelection = aValue; + m_aChangeTimer.Start(); + } + } + } + else if (m_aCurrentSelection.hasValue()) + m_aCurrentSelection.clear(); + } + } + + // XEventListener + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException) + { + OBoundControl::disposing(_rSource); + } + + // XChangeBroadcaster + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException) + { + m_aChangeListeners.addInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException) + { + m_aChangeListeners.removeInterface( _rxListener ); + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OListBoxControl::disposing() + { + if (m_aChangeTimer.IsActive()) + m_aChangeTimer.Stop(); + + EventObject aEvent( *this ); + m_aChangeListeners.disposeAndClear( aEvent ); + m_aItemListeners.disposeAndClear( aEvent ); + + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_pItemBroadcaster.is() ) + { + m_pItemBroadcaster->removeEventsForProcessor( this ); + m_pItemBroadcaster->terminate(); + m_pItemBroadcaster = NULL; + } + } + + OBoundControl::disposing(); + } + + //------------------------------------------------------------------------------ + void OListBoxControl::processEvent( const AnyEvent& _rEvent ) + { + Reference< XListBox > xKeepAlive( this ); + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( OComponentHelper::rBHelper.bDisposed ) + return; + } + const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent ); + m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() ); + } + + //------------------------------------------------------------------------------ + IMPL_LINK(OListBoxControl, OnTimeout, void*, /*EMPTYTAG*/) + { + m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) ); + return 0L; + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException) + { + m_aItemListeners.addInterface( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException) + { + m_aItemListeners.removeInterface( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->addActionListener( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->removeActionListener( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->addItem( aItem, nPos ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addItems( const Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->addItems( aItems, nPos ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->removeItems( nPos, nCount ); + } + + //-------------------------------------------------------------------- + ::sal_Int16 SAL_CALL OListBoxControl::getItemCount( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getItemCount(); + return 0; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getItem( nPos ); + return ::rtl::OUString( ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getItems( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getItems(); + return Sequence< ::rtl::OUString >( ); + } + + //-------------------------------------------------------------------- + ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItemPos(); + return 0; + } + + //-------------------------------------------------------------------- + Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItemsPos(); + return Sequence< ::sal_Int16 >( ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OListBoxControl::getSelectedItem( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItem(); + return ::rtl::OUString( ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getSelectedItems( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItems(); + return Sequence< ::rtl::OUString >( ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->selectItemPos( nPos, bSelect ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->selectItemsPos( aPositions, bSelect ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->selectItem( aItem, bSelect ); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL OListBoxControl::isMutipleMode( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->isMutipleMode(); + return sal_False; + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::setMultipleMode( ::sal_Bool bMulti ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->setMultipleMode( bMulti ); + } + + //-------------------------------------------------------------------- + ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getDropDownLineCount(); + return 0; + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->setDropDownLineCount( nLines ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->makeVisible( nEntry ); + } + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/ListBox.hxx b/forms/source/component/ListBox.hxx new file mode 100644 index 000000000000..d2af81c1c52c --- /dev/null +++ b/forms/source/component/ListBox.hxx @@ -0,0 +1,280 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_LISTBOX_HXX_ +#define _FORMS_LISTBOX_HXX_ + +#include "FormComponent.hxx" +#include "cachedrowset.hxx" +#include "errorbroadcaster.hxx" +#include "entrylisthelper.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/awt/XItemListener.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XListBox.hpp> +#include <com/sun/star/form/XChangeBroadcaster.hpp> +/** === end UNO includes === **/ + +#include <comphelper/asyncnotification.hxx> +#include <connectivity/FValue.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/implbase1.hxx> +#include <vcl/timer.hxx> + +#include <vector> + +namespace dbtools +{ + class FormattedColumnValue; +} + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OListBoxModel +//================================================================== +typedef ::std::vector< ::connectivity::ORowSetValue > ValueList; + +class OListBoxModel :public OBoundControlModel + ,public OEntryListHelper + ,public OErrorBroadcaster +{ + + CachedRowSet m_aListRowSet; // the row set to fill the list + ::connectivity::ORowSetValue m_aSaveValue; + + // <properties> + ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source + ::com::sun::star::uno::Any m_aBoundColumn; + ValueList m_aListSourceValues; + ValueList m_aBoundValues; + ::com::sun::star::uno::Sequence<sal_Int16> m_aDefaultSelectSeq; // DefaultSelected + // </properties> + + sal_Int16 m_nNULLPos; // position of the NULL value in our list + sal_Bool m_bBoundComponent : 1; + +private: + ::connectivity::ORowSetValue getFirstSelectedValue() const; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OListBoxModel ); + +// XServiceInfo + IMPLEMENTATION_NAME(OListBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +// UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OListBoxModel, OBoundControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + +protected: + // XMultiPropertySet + virtual void SAL_CALL setPropertyValues(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Values) throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OBoundControlModel::getFastPropertyValue; + using OBoundControlModel::setPropertyValues; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + + virtual ::com::sun::star::uno::Any + getCurrentFormComponentValue() const; + + // OEntryListHelper overriables + virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ); + virtual void connectedExternalListSource( ); + virtual void disconnectedExternalListSource( ); + virtual void refreshInternalEntryList(); + +protected: + DECLARE_XCLONEABLE(); + +private: + void loadData( bool _bForce ); + + /** refreshes the list boxes list data + @precond we don't actually have an external list source + */ + void impl_refreshDbEntryList( bool _bForce ); + + ValueList impl_getValues() const; +}; + +//================================================================== +//= OListBoxControl +//================================================================== +typedef ::cppu::ImplHelper4 < ::com::sun::star::awt::XFocusListener + , ::com::sun::star::awt::XItemListener + , ::com::sun::star::awt::XListBox + , ::com::sun::star::form::XChangeBroadcaster + > OListBoxControl_BASE; + +class ChangeListeners; + +class OListBoxControl :public OBoundControl + ,public OListBoxControl_BASE + ,public IEventProcessor +{ +private: + ::cppu::OInterfaceContainerHelper m_aChangeListeners; + ::cppu::OInterfaceContainerHelper m_aItemListeners; + + ::com::sun::star::uno::Any m_aCurrentSelection; + Timer m_aChangeTimer; + + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox > + m_xAggregateListBox; + + ::rtl::Reference< ::comphelper::AsyncEventNotifier > + m_pItemBroadcaster; + +protected: + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OListBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OListBoxControl(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OListBoxControl, OBoundControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + +// XServiceInfo + IMPLEMENTATION_NAME(OListBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +// XChangeBroadcaster + virtual void SAL_CALL addChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + +// XFocusListener + virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException); + +// XItemListener + virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException); + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// XListBox + virtual void SAL_CALL addItemListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XItemListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeItemListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XItemListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addActionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeActionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addItems( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getItemCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getItem( ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getItems( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getSelectedItemPos( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int16 > SAL_CALL getSelectedItemsPos( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSelectedItem( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedItems( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectItemsPos( const ::com::sun::star::uno::Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isMutipleMode( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setMultipleMode( ::sal_Bool bMulti ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getDropDownLineCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDropDownLineCount( ::sal_Int16 nLines ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL makeVisible( ::sal_Int16 nEntry ) throw (::com::sun::star::uno::RuntimeException); + +protected: + // IEventProcessor + virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ); + +private: + DECL_LINK( OnTimeout, void* ); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_LISTBOX_HXX_ + diff --git a/forms/source/component/Numeric.cxx b/forms/source/component/Numeric.cxx new file mode 100644 index 000000000000..0d60fd2f62fb --- /dev/null +++ b/forms/source/component/Numeric.cxx @@ -0,0 +1,222 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Numeric.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//================================================================== +// ONumericControl +//================================================================== + +//------------------------------------------------------------------ +ONumericControl::ONumericControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_NUMERICFIELD) +{ +} + +//------------------------------------------------------------------------------ +StringSequence ONumericControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_NUMERICFIELD; + return aSupported; +} + + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ONumericControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ONumericControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ONumericControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//================================================================== +// ONumericModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ONumericModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ONumericModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ONumericModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( ONumericModel ) +//------------------------------------------------------------------ +ONumericModel::ONumericModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_NUMERICFIELD, FRM_SUN_CONTROL_NUMERICFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( ONumericModel, NULL ); + + m_nClassId = FormComponentType::NUMERICFIELD; + initValueProperty( PROPERTY_VALUE, PROPERTY_ID_VALUE ); +} + +//------------------------------------------------------------------ +ONumericModel::ONumericModel( const ONumericModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( ONumericModel, NULL ); +} + +//------------------------------------------------------------------ +ONumericModel::~ONumericModel() +{ + DBG_DTOR( ONumericModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( ONumericModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence ONumericModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_NUMERICFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_NUMERICFIELD; + *pStoreTo++ = BINDABLE_DATABASE_NUMERIC_FIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void ONumericModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OEditBaseModel ) + DECL_PROP3(DEFAULT_VALUE, double, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ONumericModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_NUMERICFIELD; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +sal_Bool ONumericModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( !aControlValue.hasValue() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + m_xColumnUpdate->updateDouble( getDouble( aControlValue ) ); + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +Any ONumericModel::translateDbColumnToControlValue() +{ + m_aSaveValue <<= (double)m_xColumn->getDouble(); + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + + return m_aSaveValue; +} + +//------------------------------------------------------------------------------ +Any ONumericModel::getDefaultForReset() const +{ + Any aValue; + if (m_aDefault.getValueType().getTypeClass() == TypeClass_DOUBLE) + aValue = m_aDefault; + + return aValue; +} + +//------------------------------------------------------------------------------ +void ONumericModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Numeric.hxx b/forms/source/component/Numeric.hxx new file mode 100644 index 000000000000..1159ad98c3f0 --- /dev/null +++ b/forms/source/component/Numeric.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_NUMERIC_HXX_ +#define _FORMS_NUMERIC_HXX_ + +#include "EditBase.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= ONumericModel +//================================================================== +class ONumericModel + :public OEditBaseModel +{ +private: + ::com::sun::star::uno::Any m_aSaveValue; +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( ONumericModel ); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(ONumericModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +//= ONumericControl +//================================================================== +class ONumericControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + ONumericControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(ONumericControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_NUMERIC_HXX_ + diff --git a/forms/source/component/Pattern.cxx b/forms/source/component/Pattern.cxx new file mode 100644 index 000000000000..e7b6c695d0cf --- /dev/null +++ b/forms/source/component/Pattern.cxx @@ -0,0 +1,262 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Pattern.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//......................................................................... +namespace frm +{ +//......................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::beans::Property; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::sdbc::XRowSet; + using ::com::sun::star::uno::UNO_QUERY; + /** === end UNO using === **/ + namespace FormComponentType = ::com::sun::star::form::FormComponentType; + +//================================================================== +// OPatternControl +//================================================================== +//------------------------------------------------------------------ +OPatternControl::OPatternControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_PATTERNFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OPatternControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OPatternControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OPatternControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence OPatternControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_PATTERNFIELD; + return aSupported; +} + +//================================================================== +// OPatternModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OPatternModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OPatternModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OPatternModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( OPatternModel ) +//------------------------------------------------------------------ +OPatternModel::OPatternModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_PATTERNFIELD, FRM_SUN_CONTROL_PATTERNFIELD, sal_False, sal_False ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( OPatternModel, NULL ); + + m_nClassId = FormComponentType::PATTERNFIELD; + initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT ); +} + +//------------------------------------------------------------------ +OPatternModel::OPatternModel( const OPatternModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OPatternModel, NULL ); +} + +//------------------------------------------------------------------ +OPatternModel::~OPatternModel() +{ + DBG_DTOR( OPatternModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OPatternModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OPatternModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 2); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-2] = FRM_SUN_COMPONENT_DATABASE_PATTERNFIELD; + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_PATTERNFIELD; + return aSupported; +} + + +//------------------------------------------------------------------------------ +void OPatternModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 4, OEditBaseModel ) + DECL_PROP2(DEFAULT_TEXT, ::rtl::OUString, BOUND, MAYBEDEFAULT); + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP2(FILTERPROPOSAL, sal_Bool, BOUND, MAYBEDEFAULT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OPatternModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_PATTERNFIELD; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +sal_Bool OPatternModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + + if ( aNewValue != m_aLastKnownValue ) + { + ::rtl::OUString sNewValue; + aNewValue >>= sNewValue; + + if ( !aNewValue.hasValue() + || ( !sNewValue.getLength() // an empty string + && m_bEmptyIsNull // which should be interpreted as NULL + ) + ) + { + m_xColumnUpdate->updateNull(); + } + else + { + OSL_ENSURE( m_pFormattedValue.get(), "OPatternModel::commitControlValueToDbColumn: no value helper!" ); + if ( !m_pFormattedValue.get() ) + return sal_False; + + if ( !m_pFormattedValue->setFormattedValue( sNewValue ) ) + return sal_False; + } + + m_aLastKnownValue = aNewValue; + } + + return sal_True; +} + +//------------------------------------------------------------------------------ +void OPatternModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OEditBaseModel::onConnectedDbColumn( _rxForm ); + + Reference< XPropertySet > xField( getField() ); + if ( !xField.is() ) + return; + + m_pFormattedValue.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) ); +} + +//------------------------------------------------------------------------------ +void OPatternModel::onDisconnectedDbColumn() +{ + OEditBaseModel::onDisconnectedDbColumn(); + m_pFormattedValue.reset(); +} + +// XPropertyChangeListener +//------------------------------------------------------------------------------ +Any OPatternModel::translateDbColumnToControlValue() +{ + OSL_PRECOND( m_pFormattedValue.get(), "OPatternModel::translateDbColumnToControlValue: no value helper!" ); + + if ( m_pFormattedValue.get() ) + { + ::rtl::OUString sValue( m_pFormattedValue->getFormattedValue() ); + if ( !sValue.getLength() + && m_pFormattedValue->getColumn().is() + && m_pFormattedValue->getColumn()->wasNull() + ) + { + m_aLastKnownValue.clear(); + } + else + { + m_aLastKnownValue <<= sValue; + } + } + else + m_aLastKnownValue.clear(); + + return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( ::rtl::OUString() ); + // (m_aLastKnownValue is alllowed to be VOID, the control value isn't) +} + +// XReset +//------------------------------------------------------------------------------ +Any OPatternModel::getDefaultForReset() const +{ + return makeAny( m_aDefaultText ); +} + +//------------------------------------------------------------------------------ +void OPatternModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aLastKnownValue.clear(); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Pattern.hxx b/forms/source/component/Pattern.hxx new file mode 100644 index 000000000000..9a96a39820ff --- /dev/null +++ b/forms/source/component/Pattern.hxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_PATTERN_HXX_ +#define _FORMS_PATTERN_HXX_ + +#include "EditBase.hxx" + +#include <connectivity/formattedcolumnvalue.hxx> + +#include <memory> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= OPatternModel +//================================================================== +class OPatternModel + :public OEditBaseModel +{ +private: + ::com::sun::star::uno::Any m_aLastKnownValue; + ::std::auto_ptr< ::dbtools::FormattedColumnValue > + m_pFormattedValue; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OPatternModel ); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OPatternModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +//= OPatternControl +//================================================================== +class OPatternControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OPatternControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OPatternControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_PATTERN_HXX_ + diff --git a/forms/source/component/RadioButton.cxx b/forms/source/component/RadioButton.cxx new file mode 100644 index 000000000000..c4a1216ad76c --- /dev/null +++ b/forms/source/component/RadioButton.cxx @@ -0,0 +1,411 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "RadioButton.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/basicio.hxx> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//================================================================== +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL ORadioButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new ORadioButtonControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ORadioButtonControl::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_RADIOBUTTON; + return aSupported; +} + + +//------------------------------------------------------------------ +ORadioButtonControl::ORadioButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_RADIOBUTTON) +{ +} + +//------------------------------------------------------------------ +void SAL_CALL ORadioButtonControl::createPeer(const Reference<starawt::XToolkit>& _rxToolkit, const Reference<starawt::XWindowPeer>& _rxParent) throw (RuntimeException) +{ + OBoundControl::createPeer(_rxToolkit, _rxParent); + + // switch off the auto-toggle, we do this ourself .... + // (formerly this switch-off was done in the toolkit - but the correct place is here ...) +// Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY ); +// if (xVclWindowPeer.is()) +// xVclWindowPeer->setProperty(::rtl::OUString::createFromAscii("AutoToggle"), ::cppu::bool2any(sal_False)); + // new order: do _not_ switch off the auto toggle because: + // * today, it is not necessary anymore to handle the toggling ourself (everything works fine without it) + // * without auto toggle, the AccessibleEvents as fired by the radio buttons are + // a. newly checked button: "unchecked"->"checked" + // b. previously checked button: "checked"->"unchecked" + // This is deadly for AT-tools, which then get the "unchecked" event _immediately_ after the "checked" event, + // and only read the latter. This makes radio buttons pretty unusable in form documents. + // So we switched AutoToggle _on_, again, because then VCL can handle the notifications, and will send + // them in the proper order. +} + +//================================================================== +InterfaceRef SAL_CALL ORadioButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new ORadioButtonModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( ORadioButtonModel ) +//------------------------------------------------------------------ +ORadioButtonModel::ORadioButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OReferenceValueComponent( _rxFactory, VCL_CONTROLMODEL_RADIOBUTTON, FRM_SUN_CONTROL_RADIOBUTTON,sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( ORadioButtonModel, NULL ); + + m_nClassId = FormComponentType::RADIOBUTTON; + m_aLabelServiceName = FRM_SUN_COMPONENT_GROUPBOX; + initValueProperty( PROPERTY_STATE, PROPERTY_ID_STATE ); +} + +//------------------------------------------------------------------ +ORadioButtonModel::ORadioButtonModel( const ORadioButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OReferenceValueComponent( _pOriginal, _rxFactory ) +{ + DBG_CTOR( ORadioButtonModel, NULL ); +} + +//------------------------------------------------------------------------------ +ORadioButtonModel::~ORadioButtonModel() +{ + DBG_DTOR( ORadioButtonModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( ORadioButtonModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ORadioButtonModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OReferenceValueComponent::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_RADIOBUTTON; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_RADIOBUTTON; + *pStoreTo++ = BINDABLE_DATABASE_RADIO_BUTTON; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::SetSiblingPropsTo(const ::rtl::OUString& rPropName, const Any& rValue) +{ + // mein Name + ::rtl::OUString sMyName(m_aName); + + // meine Siblings durchiterieren + Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY); + if (xIndexAccess.is()) + { + Reference<XPropertySet> xMyProps; + query_interface(static_cast<XWeak*>(this), xMyProps); + ::rtl::OUString sCurrentName; + for (sal_Int32 i=0; i<xIndexAccess->getCount(); ++i) + { + Reference<XPropertySet> xSiblingProperties(*(InterfaceRef*)xIndexAccess->getByIndex(i).getValue(), UNO_QUERY); + if (!xSiblingProperties.is()) + continue; + if (xMyProps == xSiblingProperties) + continue; // mich selber nicht umsetzen + + // nur wenn es ein Radio-Button ist + if (!hasProperty(PROPERTY_CLASSID, xSiblingProperties)) + continue; + sal_Int16 nType = 0; + xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType; + if (nType != FormComponentType::RADIOBUTTON) + continue; + + // das 'zur selben Gruppe gehoeren' wird am Namen festgemacht + xSiblingProperties->getPropertyValue(PROPERTY_NAME) >>= sCurrentName; + if (sCurrentName == sMyName) + xSiblingProperties->setPropertyValue(rPropName, rValue); + } + } +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw (Exception) +{ + OReferenceValueComponent::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + + // if the label control changed ... + if (nHandle == PROPERTY_ID_CONTROLLABEL) + { // ... forward this to our siblings + SetSiblingPropsTo(PROPERTY_CONTROLLABEL, rValue); + } + + // wenn sich die ControlSource-Eigenschaft geaendert hat ... + if (nHandle == PROPERTY_ID_CONTROLSOURCE) + { // ... muss ich allen meinen Siblings, die in der selben RadioButton-Gruppe sind wie ich, auch die + // neue ControlSource mitgeben + SetSiblingPropsTo(PROPERTY_CONTROLSOURCE, rValue); + } + + // die andere Richtung : wenn sich mein Name aendert ... + if (nHandle == PROPERTY_ID_NAME) + { + // ... muss ich testen, ob ich Siblings mit dem selben Namen habe, damit ich deren ControlSource uebernehmen kann + Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY); + if (xIndexAccess.is()) + { + ::rtl::OUString sName; + ::rtl::OUString sControlSource; + + Reference<XPropertySet> xMyProps; + query_interface(static_cast<XWeak*>(this), xMyProps); + for (sal_Int32 i=0; i<xIndexAccess->getCount(); ++i) + { + Reference<XPropertySet> xSiblingProperties(*(InterfaceRef*)xIndexAccess->getByIndex(i).getValue(), UNO_QUERY); + if (!xSiblingProperties.is()) + continue; + + if (xMyProps == xSiblingProperties) + // nur wenn ich nicht mich selber gefunden habe + continue; + + sal_Int16 nType = 0; + xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType; + if (nType != FormComponentType::RADIOBUTTON) + // nur Radio-Buttons + continue; + + xSiblingProperties->getPropertyValue(PROPERTY_NAME) >>= sName; + // Control, das zur gleichen Gruppe gehoert ? + if (rValue == sName) + { + setPropertyValue(PROPERTY_CONTROLSOURCE, xSiblingProperties->getPropertyValue(PROPERTY_CONTROLSOURCE)); + break; + } + } + } + } + + if (nHandle == PROPERTY_ID_DEFAULT_STATE) + { + sal_Int16 nValue; + rValue >>= nValue; + if (1 == nValue) + { // bei allen Radios der selben Gruppe das 'default checked' ruecksetzen, denn wie schon der highlander wusste : + // es kann nur einen geben. + Any aZero; + nValue = 0; + aZero <<= nValue; + SetSiblingPropsTo(PROPERTY_DEFAULT_STATE, aZero); + } + } +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 1, OReferenceValueComponent ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ORadioButtonModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_RADIOBUTTON; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL ORadioButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + OReferenceValueComponent::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0003); + + // Properties + _rxOutStream << getReferenceValue(); + _rxOutStream << (sal_Int16)getDefaultChecked(); + writeHelpTextCompatibly(_rxOutStream); + + // from version 0x0003 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ORadioButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + OReferenceValueComponent::read(_rxInStream); + ::osl::MutexGuard aGuard(m_aMutex); + + // Version + UINT16 nVersion = _rxInStream->readShort(); + + ::rtl::OUString sReferenceValue; + sal_Int16 nDefaultChecked( 0 ); + switch (nVersion) + { + case 0x0001 : + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + break; + case 0x0002 : + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly(_rxInStream); + break; + case 0x0003 : + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly(_rxInStream); + readCommonProperties(_rxInStream); + break; + default : + DBG_ERROR("ORadioButtonModel::read : unknown version !"); + defaultCommonProperties(); + break; + } + + setReferenceValue( sReferenceValue ); + setDefaultChecked( (ToggleState)nDefaultChecked ); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::_propertyChanged(const PropertyChangeEvent& _rEvent) throw(RuntimeException) +{ + if ( _rEvent.PropertyName.equals( PROPERTY_STATE ) ) + { + if ( _rEvent.NewValue == (sal_Int16)1 ) + { + // wenn sich mein Status auf 'checked' geaendert hat, muss ich alle meine Siblings, die in der selben Gruppe + // sind wie ich, entsprechend zuruecksetzen + Any aZero; + aZero <<= (sal_Int16)0; + SetSiblingPropsTo( PROPERTY_STATE, aZero ); + } + } + + OReferenceValueComponent::_propertyChanged( _rEvent ); +} + +//------------------------------------------------------------------------------ +Any ORadioButtonModel::translateDbColumnToControlValue() +{ + return makeAny( (sal_Int16) + ( ( m_xColumn->getString() == getReferenceValue() ) ? STATE_CHECK : STATE_NOCHECK ) + ); +} + +//------------------------------------------------------------------------------ +Any ORadioButtonModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue = OReferenceValueComponent::translateExternalValueToControlValue( _rExternalValue ); + sal_Int16 nState = STATE_NOCHECK; + if ( ( aControlValue >>= nState ) && ( nState == STATE_DONTKNOW ) ) + // radio buttons do not have the DONTKNOW state + aControlValue <<= (sal_Int16)STATE_NOCHECK; + return aControlValue; +} + +//----------------------------------------------------------------------------- +sal_Bool ORadioButtonModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Reference< XPropertySet > xField( getField() ); + OSL_PRECOND( xField.is(), "ORadioButtonModel::commitControlValueToDbColumn: not bound!" ); + if ( xField.is() ) + { + try + { + sal_Int16 nValue = 0; + m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) >>= nValue; + if ( nValue == 1 ) + xField->setPropertyValue( PROPERTY_VALUE, makeAny( getReferenceValue() ) ); + } + catch(Exception&) + { + DBG_ERROR("ORadioButtonModel::commitControlValueToDbColumn: could not commit !"); + } + } + return sal_True; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/RadioButton.hxx b/forms/source/component/RadioButton.hxx new file mode 100644 index 000000000000..3f122fe7b27c --- /dev/null +++ b/forms/source/component/RadioButton.hxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_RADIOBUTTON_HXX_ +#define _FORMS_RADIOBUTTON_HXX_ + +#include "refvaluecomponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// ORadioButtonModel +//================================================================== +class ORadioButtonModel :public OReferenceValueComponent +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( ORadioButtonModel ); + + // XServiceInfo + IMPLEMENTATION_NAME(ORadioButtonModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // OPropertyChangeListener + virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + +protected: + void SetSiblingPropsTo(const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rValue); + + DECLARE_XCLONEABLE( ); + +private: + /** sets the given value as new State at the aggregate + @precond + our mutex is aquired exactly once + */ + void setNewAggregateState( const ::com::sun::star::uno::Any& _rValue ); +}; + +//================================================================== +// ORadioButtonControl +//================================================================== +class ORadioButtonControl: public OBoundControl +{ +public: + ORadioButtonControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(ORadioButtonControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +protected: + // XControl + virtual void SAL_CALL createPeer(const ::com::sun::star::uno::Reference<starawt::XToolkit>& Toolkit, const ::com::sun::star::uno::Reference<starawt::XWindowPeer>& Parent) throw (::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_RADIOBUTTON_HXX_ + diff --git a/forms/source/component/Time.cxx b/forms/source/component/Time.cxx new file mode 100644 index 000000000000..49b07adf84e4 --- /dev/null +++ b/forms/source/component/Time.cxx @@ -0,0 +1,365 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Time.hxx" +#include <tools/debug.hxx> +#include <tools/time.hxx> +#include <connectivity/dbconversion.hxx> +#include <com/sun/star/sdbc/DataType.hpp> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; + +//================================================================== +//= +//================================================================== + +//================================================================== +//= OTimeControl +//================================================================== +//------------------------------------------------------------------ +OTimeControl::OTimeControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_TIMEFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OTimeControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OTimeControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OTimeControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OTimeControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_TIMEFIELD; + return aSupported; +} + +//================================================================== +//= OTimeModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OTimeModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OTimeModel(_rxFactory)); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OTimeModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_TIMEFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_TIMEFIELD; + *pStoreTo++ = BINDABLE_DATABASE_TIME_FIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +Sequence<Type> OTimeModel::_getTypes() +{ + return OBoundControlModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( OTimeModel ) +//------------------------------------------------------------------ +OTimeModel::OTimeModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_TIMEFIELD, FRM_SUN_CONTROL_TIMEFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OLimitedFormats(_rxFactory, FormComponentType::TIMEFIELD) +{ + DBG_CTOR( OTimeModel, NULL ); + + m_nClassId = FormComponentType::TIMEFIELD; + initValueProperty( PROPERTY_TIME, PROPERTY_ID_TIME ); + + setAggregateSet(m_xAggregateFastSet, getOriginalHandle(PROPERTY_ID_TIMEFORMAT)); +} + +//------------------------------------------------------------------------------ +OTimeModel::OTimeModel( const OTimeModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,OLimitedFormats( _rxFactory, FormComponentType::TIMEFIELD ) +{ + DBG_CTOR( OTimeModel, NULL ); + + setAggregateSet( m_xAggregateFastSet, getOriginalHandle( PROPERTY_ID_TIMEFORMAT ) ); +} + +//------------------------------------------------------------------------------ +OTimeModel::~OTimeModel( ) +{ + setAggregateSet(Reference< XFastPropertySet >(), -1); + DBG_DTOR( OTimeModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OTimeModel ) + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OTimeModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_TIMEFIELD; // old (non-sun) name for compatibility ! +} + +// XPropertySet +//------------------------------------------------------------------------------ +void OTimeModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 4, OEditBaseModel ) + DECL_PROP3(DEFAULT_TIME, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP1(FORMATKEY, sal_Int32, TRANSIENT); + DECL_IFACE_PROP2(FORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OTimeModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle ) const +{ + switch (_nHandle) + { + case PROPERTY_ID_FORMATKEY: + getFormatKeyPropertyValue(_rValue); + break; + case PROPERTY_ID_FORMATSSUPPLIER: + _rValue <<= getFormatsSupplier(); + break; + default: + OEditBaseModel::getFastPropertyValue(_rValue, _nHandle); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OTimeModel::convertFastPropertyValue(Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + return convertFormatKeyPropertyValue(_rConvertedValue, _rOldValue, _rValue); + else + return OEditBaseModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OTimeModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw ( ::com::sun::star::uno::Exception) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + setFormatKeyPropertyValue(_rValue); + else + OEditBaseModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); +} + +// XLoadListener +//------------------------------------------------------------------------------ +void OTimeModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OBoundControlModel::onConnectedDbColumn( _rxForm ); + Reference<XPropertySet> xField = getField(); + if (xField.is()) + { + m_bDateTimeField = sal_False; + try + { + sal_Int32 nFieldType = 0; + xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nFieldType; + m_bDateTimeField = (nFieldType == DataType::TIMESTAMP); + } + catch(Exception&) + { + } + } +} + +//------------------------------------------------------------------------------ +sal_Bool OTimeModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( !aControlValue.hasValue() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + util::Time aTime; + if ( !( aControlValue >>= aTime ) ) + { + sal_Int32 nAsInt(0); + aControlValue >>= nAsInt; + aTime = DBTypeConversion::toTime(nAsInt); + } + + if (!m_bDateTimeField) + m_xColumnUpdate->updateTime(aTime); + else + { + util::DateTime aDateTime = m_xColumn->getTimestamp(); + aDateTime.HundredthSeconds = aTime.HundredthSeconds; + aDateTime.Seconds = aTime.Seconds; + aDateTime.Minutes = aTime.Minutes; + aDateTime.Hours = aTime.Hours; + m_xColumnUpdate->updateTimestamp(aDateTime); + } + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +void OTimeModel::impl_translateControlValueToUNOTime( Any& _rUNOValue ) const +{ + _rUNOValue = getControlValue(); + if ( _rUNOValue.hasValue() ) + { + sal_Int32 nTime = 0; + OSL_VERIFY( _rUNOValue >>= nTime ); + if ( nTime == ::Time( 99, 99, 99 ).GetTime() ) + // "invalid time" in VCL is different from "invalid time" in UNO + _rUNOValue.clear(); + else + _rUNOValue <<= DBTypeConversion::toTime( nTime ); + } +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateControlValueToExternalValue( ) const +{ + Any aExternalValue; + impl_translateControlValueToUNOTime( aExternalValue ); + return aExternalValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue; + if ( _rExternalValue.hasValue() ) + { + util::Time aTime; + OSL_VERIFY( _rExternalValue >>= aTime ); + aControlValue <<= DBTypeConversion::toINT32( aTime ); + } + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateControlValueToValidatableValue( ) const +{ + Any aValidatableValue; + impl_translateControlValueToUNOTime( aValidatableValue ); + return aValidatableValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateDbColumnToControlValue() +{ + util::Time aTime = m_xColumn->getTime(); + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + else + // the aggregated set expects an Int32 as value ... + m_aSaveValue <<= DBTypeConversion::toINT32( aTime ); + + return m_aSaveValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::getDefaultForReset() const +{ + return m_aDefault; +} + +//------------------------------------------------------------------------------ +void OTimeModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//------------------------------------------------------------------------------ +Sequence< Type > OTimeModel::getSupportedBindingTypes() +{ + return Sequence< Type >( &::getCppuType( static_cast< util::Time* >( NULL ) ), 1 ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Time.hxx b/forms/source/component/Time.hxx new file mode 100644 index 000000000000..a9ac1b4adfd0 --- /dev/null +++ b/forms/source/component/Time.hxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_TIME_HXX_ +#define _FORMS_TIME_HXX_ + +#include "EditBase.hxx" +#include "limitedformats.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= OTimeModel +//================================================================== +class OTimeModel + :public OEditBaseModel + ,public OLimitedFormats +{ +private: + ::com::sun::star::uno::Any m_aSaveValue; + sal_Bool m_bDateTimeField; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OTimeModel ); + + // stario::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::beans::XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OTimeModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OBoundControlModel::getFastPropertyValue; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + +protected: + DECLARE_XCLONEABLE(); + +private: + /** translates the control value (the VCL-internal integer representation of a date) into + a UNO-Date. + */ + void impl_translateControlValueToUNOTime( + ::com::sun::star::uno::Any& _rUNOValue ) const; +}; + +//================================================================== +//= OTimeControl +//================================================================== +class OTimeControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OTimeControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + DECLARE_UNO3_AGG_DEFAULTS(OTimeControl, OBoundControl); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OTimeControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_TIME_HXX_ + diff --git a/forms/source/component/cachedrowset.cxx b/forms/source/component/cachedrowset.cxx new file mode 100644 index 000000000000..2c9cd82e9fee --- /dev/null +++ b/forms/source/component/cachedrowset.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "cachedrowset.hxx" +#include "services.hxx" +#include "frm_strings.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::sdb::XQueriesSupplier; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::sdbc::XResultSet; + using ::com::sun::star::sdbc::XStatement; + /** === end UNO using === **/ + namespace ResultSetType = ::com::sun::star::sdbc::ResultSetType; + + //==================================================================== + //= CachedRowSet_Data + //==================================================================== + struct CachedRowSet_Data + { + ::comphelper::ComponentContext aContext; + ::rtl::OUString sCommand; + sal_Bool bEscapeProcessing; + Reference< XConnection > xConnection; + + bool bStatementDirty; + + CachedRowSet_Data( const ::comphelper::ComponentContext& _rContext ) + :aContext( _rContext ) + ,sCommand() + ,bEscapeProcessing( sal_False ) + ,xConnection() + ,bStatementDirty( true ) + { + } + }; + + //==================================================================== + //= CachedRowSet + //==================================================================== + //-------------------------------------------------------------------- + CachedRowSet::CachedRowSet( const ::comphelper::ComponentContext& _rContext ) + :m_pData( new CachedRowSet_Data( _rContext ) ) + { + } + + //-------------------------------------------------------------------- + CachedRowSet::~CachedRowSet() + { + dispose(); + } + + //-------------------------------------------------------------------- + void CachedRowSet::setCommand( const ::rtl::OUString& _rCommand ) + { + if ( m_pData->sCommand == _rCommand ) + return; + + m_pData->sCommand = _rCommand; + m_pData->bStatementDirty = true; + } + + //-------------------------------------------------------------------- + void CachedRowSet::setCommandFromQuery( const ::rtl::OUString& _rQueryName ) + { + Reference< XQueriesSupplier > xSupplyQueries( m_pData->xConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xQueries ( xSupplyQueries->getQueries(), UNO_QUERY_THROW ); + Reference< XPropertySet > xQuery ( xQueries->getByName( _rQueryName ), UNO_QUERY_THROW ); + + sal_Bool bEscapeProcessing( sal_False ); + OSL_VERIFY( xQuery->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing ); + setEscapeProcessing( bEscapeProcessing ); + + ::rtl::OUString sCommand; + OSL_VERIFY( xQuery->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand ); + setCommand( sCommand ); + } + + //-------------------------------------------------------------------- + void CachedRowSet::setEscapeProcessing ( const sal_Bool _bEscapeProcessing ) + { + if ( m_pData->bEscapeProcessing == _bEscapeProcessing ) + return; + + m_pData->bEscapeProcessing = _bEscapeProcessing; + m_pData->bStatementDirty = true; + } + + //-------------------------------------------------------------------- + void CachedRowSet::setConnection( const Reference< XConnection >& _rxConnection ) + { + if ( m_pData->xConnection == _rxConnection ) + return; + + m_pData->xConnection = _rxConnection; + m_pData->bStatementDirty = true; + } + + //-------------------------------------------------------------------- + Reference< XResultSet > CachedRowSet::execute() + { + Reference< XResultSet > xResult; + try + { + OSL_PRECOND( m_pData->xConnection.is(), "CachedRowSet::execute: how am I expected to do this without a connection?" ); + if ( !m_pData->xConnection.is() ) + return xResult; + + Reference< XStatement > xStatement( m_pData->xConnection->createStatement(), UNO_SET_THROW ); + Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW ); + xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( m_pData->bEscapeProcessing ) ); + xStatementProps->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( ResultSetType::FORWARD_ONLY ) ); + + xResult.set( xStatement->executeQuery( m_pData->sCommand ), UNO_SET_THROW ); + m_pData->bStatementDirty = false; + } + catch( const SQLException& ) + { + throw; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xResult; + } + + //-------------------------------------------------------------------- + bool CachedRowSet::isDirty() const + { + return m_pData->bStatementDirty; + } + + //-------------------------------------------------------------------- + void CachedRowSet::dispose() + { + try + { + m_pData.reset( new CachedRowSet_Data( m_pData->aContext ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/component/cachedrowset.hxx b/forms/source/component/cachedrowset.hxx new file mode 100644 index 000000000000..d2310bf8fc8c --- /dev/null +++ b/forms/source/component/cachedrowset.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef CACHEDROWSET_HXX +#define CACHEDROWSET_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <unotools/sharedunocomponent.hxx> + +#include <memory> + +//........................................................................ +namespace frm +{ +//........................................................................ + + struct CachedRowSet_Data; + //==================================================================== + //= CachedRowSet + //==================================================================== + /** caches a result set obtained from a SQL statement + */ + class CachedRowSet + { + public: + CachedRowSet( const ::comphelper::ComponentContext& _rContext ); + ~CachedRowSet(); + + public: + /** executes the statement + + @return + the result set produced by the statement. The caller takes ownership of the + given object. + + @throws ::com::sun::star::sdbc::SQLException + if such an exception is thrown when executing the statement + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > + execute(); + + /// determines whether the row set properties are dirty, i.e. have changed since the last call to execute + bool isDirty() const; + + /// disposes the instance and frees all associated resources + void dispose(); + + /** sets the command of a query as command to be executed + + A connection must have been set before. + + @throws Exception + */ + void setCommandFromQuery ( const ::rtl::OUString& _rQueryName ); + + void setCommand ( const ::rtl::OUString& _rCommand ); + void setEscapeProcessing ( const sal_Bool _bEscapeProcessing ); + void setConnection ( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection ); + + private: + ::std::auto_ptr< CachedRowSet_Data > m_pData; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // CACHEDROWSET_HXX diff --git a/forms/source/component/clickableimage.cxx b/forms/source/component/clickableimage.cxx new file mode 100644 index 000000000000..7818cb5d66d3 --- /dev/null +++ b/forms/source/component/clickableimage.cxx @@ -0,0 +1,935 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "clickableimage.hxx" +#include "controlfeatureinterception.hxx" +#include "urltransformer.hxx" +#include "componenttools.hxx" +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/awt/SystemPointer.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/awt/ActionEvent.hpp> +#include <com/sun/star/awt/XActionListener.hpp> +#include <tools/urlobj.hxx> +#include <tools/debug.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/objsh.hxx> +#include <vos/mutex.hxx> +#include "services.hxx" +#include <comphelper/container.hxx> +#include <comphelper/listenernotification.hxx> +#include <svtools/imageresourceaccess.hxx> +#define LOCAL_URL_PREFIX '#' + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::form::submission; + using ::com::sun::star::awt::MouseEvent; + using ::com::sun::star::task::XInteractionHandler; + + //================================================================== + // OClickableImageBaseControl + //================================================================== + //------------------------------------------------------------------------------ + Sequence<Type> OClickableImageBaseControl::_getTypes() + { + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes()); + return aTypes; + } + + //------------------------------------------------------------------------------ + OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _aService) + :OControl(_rxFactory, _aService) + ,m_pThread(NULL) + ,m_aSubmissionVetoListeners( m_aMutex ) + ,m_aApproveActionListeners( m_aMutex ) + ,m_aActionListeners( m_aMutex ) + { + m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) ); + } + + //------------------------------------------------------------------------------ + OClickableImageBaseControl::~OClickableImageBaseControl() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + } + + // UNO Anbindung + //------------------------------------------------------------------------------ + Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) throw (RuntimeException) + { + Any aReturn = OControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType); + return aReturn; + } + + // XApproveActionBroadcaster + //------------------------------------------------------------------------------ + void OClickableImageBaseControl::addApproveActionListener( + const Reference<XApproveActionListener>& l) throw( RuntimeException ) + { + m_aApproveActionListeners.addInterface(l); + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseControl::removeApproveActionListener( + const Reference<XApproveActionListener>& l) throw( RuntimeException ) + { + m_aApproveActionListeners.removeInterface(l); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor ); + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OClickableImageBaseControl::disposing() + { + EventObject aEvent( static_cast< XWeak* >( this ) ); + m_aApproveActionListeners.disposeAndClear( aEvent ); + m_aActionListeners.disposeAndClear( aEvent ); + m_aSubmissionVetoListeners.disposeAndClear( aEvent ); + m_pFeatureInterception->dispose(); + + { + ::osl::MutexGuard aGuard( m_aMutex ); + if( m_pThread ) + { + m_pThread->release(); + m_pThread = NULL; + } + } + + OControl::disposing(); + } + + //------------------------------------------------------------------------------ + OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread() + { + if ( !m_pThread ) + { + m_pThread = new OImageProducerThread_Impl( this ); + m_pThread->acquire(); + m_pThread->create(); + } + return m_pThread; + } + + //------------------------------------------------------------------------------ + bool OClickableImageBaseControl::approveAction( ) + { + sal_Bool bCancelled = sal_False; + EventObject aEvent( static_cast< XWeak* >( this ) ); + + ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners ); + while( !bCancelled && aIter.hasMoreElements() ) + { + // Jede approveAction-Methode muss thread-safe sein!!! + if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) ) + bCancelled = sal_True; + } + + return !bCancelled; + } + + //------------------------------------------------------------------------------ + // Diese Methode wird auch aus einem Thread gerufen und muss deshalb + // thread-safe sein. + void OClickableImageBaseControl::actionPerformed_Impl(sal_Bool bNotifyListener, const MouseEvent& rEvt) + { + if( bNotifyListener ) + { + if ( !approveAction() ) + return; + } + + // Ob der Rest des Codes Thread-Safe ist weiss man nicht genau. Deshalb + // wird das meiste bei gelocktem Solar-Mutex erledigen. + Reference<XPropertySet> xSet; + Reference< XInterface > xModelsParent; + FormButtonType eButtonType = FormButtonType_PUSH; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Parent holen + Reference<XFormComponent> xComp(getModel(), UNO_QUERY); + if (!xComp.is()) + return; + + xModelsParent = xComp->getParent(); + if (!xModelsParent.is()) + return; + + // which button type? + xSet = xSet.query( xComp ); + if ( !xSet.is() ) + return; + xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType; + } + + switch (eButtonType) + { + case FormButtonType_RESET: + { + // reset-Methoden muessen thread-safe sein! + Reference<XReset> xReset(xModelsParent, UNO_QUERY); + if (!xReset.is()) + return; + + xReset->reset(); + } + break; + + case FormButtonType_SUBMIT: + { + // if some outer component can provide an interaction handler, use it + Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY ); + try + { + implSubmit( rEvt, xHandler ); + } + catch( const Exception& ) + { + // ignore + } + } + break; + + case FormButtonType_URL: + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + Reference< XModel > xModel = getXModel(xModelsParent); + if (!xModel.is()) + return; + + /////////////////////////////////////////////////////////////////////// + // Jetzt URL ausfuehren + Reference< XController > xController = xModel->getCurrentController(); + if (!xController.is()) + return; + + Reference< XFrame > xFrame = xController->getFrame(); + if( !xFrame.is() ) + return; + + URL aURL; + aURL.Complete = + getString(xSet->getPropertyValue(PROPERTY_TARGET_URL)); + + if (aURL.Complete.getLength() && (LOCAL_URL_PREFIX == aURL.Complete.getStr()[0])) + { // the URL contains a local URL only. Since the URLTransformer does not handle this case correctly + // (it can't: it does not know the document URL), we have to take care for this ourself. + // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all + // URLs have to be absolute), but for compatibility reasons this is no option. + // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it + // could be "#mark" as well. + // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete + // solutiuon would be: + // * recognize URLs consisting of a mark only while _reading_ the document + // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to + // transform such mark-only URLs into correct absolute URLs + // * at the UI, show only the mark + // * !!!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems + // rather impossible !!! + // 89752 - 23.07.2001 - frank.schoenheit@sun.com + aURL.Mark = aURL.Complete; + aURL.Complete = xModel->getURL(); + aURL.Complete += aURL.Mark; + } + + sal_Bool bDispatchUrlInternal = sal_False; + xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal; + if ( bDispatchUrlInternal ) + { + m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME ); + + ::rtl::OUString aTargetFrame; + xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame; + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE ); + + Sequence<PropertyValue> aArgs(1); + PropertyValue& rProp = aArgs.getArray()[0]; + rProp.Name = ::rtl::OUString::createFromAscii("Referer"); + rProp.Value <<= xModel->getURL(); + + if (xDisp.is()) + xDisp->dispatch( aURL, aArgs ); + } + else + { + URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" ); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, ::rtl::OUString() , 0); + + if ( xDisp.is() ) + { + Sequence<PropertyValue> aProps(3); + aProps[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL")); + aProps[0].Value <<= aURL.Complete; + + aProps[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FrameName")); + aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME); + + aProps[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); + aProps[2].Value <<= xModel->getURL(); + + xDisp->dispatch( aHyperLink, aProps ); + } + } + } break; + default: + { + // notify the action listeners for a push button + ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); + m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt ); + } + } + } + + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException) + { + m_aSubmissionVetoListeners.addInterface( listener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException) + { + m_aSubmissionVetoListeners.removeInterface( listener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException) + { + implSubmit( MouseEvent(), _rxHandler ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException) + { + implSubmit( MouseEvent(), NULL ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupported = OControl::getSupportedServiceNames(); + aSupported.realloc( aSupported.getLength() + 1 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON; + + return aSupported; + } + + //-------------------------------------------------------------------- + void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler ) SAL_THROW((VetoException, WrappedTargetException, RuntimeException)) + { + try + { + // allow the veto listeners to join the game + m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) ); + + // see whether there's an "submit interceptor" set at our model + Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY ); + Reference< XSubmission > xSubmission; + if ( xSubmissionSupp.is() ) + xSubmission = xSubmissionSupp->getSubmission(); + + if ( xSubmission.is() ) + { + if ( !_rxHandler.is() ) + xSubmission->submit(); + else + xSubmission->submitWithInteraction( _rxHandler ); + } + else + { + // no "interceptor" -> ordinary (old-way) submission + Reference< XChild > xChild( getModel(), UNO_QUERY ); + Reference< XSubmit > xParentSubmission; + if ( xChild.is() ) + xParentSubmission = xParentSubmission.query( xChild->getParent() ); + if ( xParentSubmission.is() ) + xParentSubmission->submit( this, _rEvent ); + } + } + catch( const VetoException& ) + { + // allowed to leave + throw; + } + catch( const RuntimeException& ) + { + // allowed to leave + throw; + } + catch( const WrappedTargetException& e ) + { + // allowed to leave + throw; + } + catch( const Exception& e ) + { + OSL_ENSURE( sal_False, "OClickableImageBaseControl::implSubmit: caught an unknown exception!" ); + throw WrappedTargetException( ::rtl::OUString(), *this, makeAny( e ) ); + } + } + + //================================================================== + // OClickableImageBaseModel + //================================================================== + //------------------------------------------------------------------------------ + Sequence<Type> OClickableImageBaseModel::_getTypes() + { + return concatSequences( + OControlModel::_getTypes(), + OClickableImageBaseModel_Base::getTypes() + ); + } + + //------------------------------------------------------------------ + DBG_NAME( OClickableImageBaseModel ) + //------------------------------------------------------------------ + OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName, + const ::rtl::OUString& rDefault ) + :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault ) + ,OPropertyChangeListener(m_aMutex) + ,m_pMedium(NULL) + ,m_pProducer( NULL ) + ,m_bDispatchUrlInternal(sal_False) + ,m_bDownloading(sal_False) + ,m_bProdStarted(sal_False) + { + DBG_CTOR( OClickableImageBaseModel, NULL ); + implConstruct(); + m_eButtonType = FormButtonType_PUSH; + } + + //------------------------------------------------------------------ + OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,OPropertyChangeListener( m_aMutex ) + ,m_pMedium( NULL ) + ,m_pProducer( NULL ) + ,m_bDispatchUrlInternal(sal_False) + ,m_bDownloading( sal_False ) + ,m_bProdStarted( sal_False ) + { + DBG_CTOR( OClickableImageBaseModel, NULL ); + implConstruct(); + + // copy properties + m_eButtonType = _pOriginal->m_eButtonType; + m_sTargetURL = _pOriginal->m_sTargetURL; + m_sTargetFrame = _pOriginal->m_sTargetFrame; + m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal; + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::implInitializeImageURL( ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // simulate a propertyChanged event for the ImageURL + // 2003-05-15 - #109591# - fs@openoffice.org + Any aImageURL; + getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL ); + _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::implConstruct() + { + m_pProducer = new ImageProducer; + increment( m_refCount ); + { + m_xProducer = m_pProducer; + + if ( m_xAggregateSet.is() ) + { + OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet ); + pMultiplexer->addProperty( PROPERTY_IMAGE_URL ); + } + } + decrement(m_refCount); + } + + //------------------------------------------------------------------------------ + OClickableImageBaseModel::~OClickableImageBaseModel() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ..."); + // spaetestens im dispose sollte das aufgeraeumt worden sein + + DBG_DTOR( OClickableImageBaseModel, NULL ); + } + + // XImageProducer + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) + { + ImageModelMethodGuard aGuard( *this ); + GetImageProducer()->addConsumer( _rxConsumer ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) + { + ImageModelMethodGuard aGuard( *this ); + GetImageProducer()->removeConsumer( _rxConsumer ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException) + { + ImageModelMethodGuard aGuard( *this ); + GetImageProducer()->startProduction(); + } + + //-------------------------------------------------------------------- + Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException) + { + return m_xSubmissionDelegate; + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) throw (RuntimeException) + { + m_xSubmissionDelegate = _submission; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc( aSupported.getLength() + 1 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON; + + return aSupported; + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::disposing() + { + OControlModel::disposing(); + if (m_pMedium) + { + delete m_pMedium; + m_pMedium = NULL; + } + + m_xProducer = NULL; + m_pProducer = NULL; + } + + //------------------------------------------------------------------------------ + Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) throw (RuntimeException) + { + // order matters: + // we definately want to "overload" the XImageProducer interface of our aggregate, + // thus check OClickableImageBaseModel_Base (which provides this) first + Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType ); + + // BUT: _don't_ let it feel responsible for the XTypeProvider interface + // (as this is implemented by our base class in the proper way) + if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) + || !aReturn.hasValue() + ) + aReturn = OControlModel::queryAggregation( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break; + case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break; + case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break; + case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break; + default: + OControlModel::getFastPropertyValue(rValue, nHandle); + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( Exception) + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : + DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_eButtonType; + break; + + case PROPERTY_ID_TARGET_URL : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_sTargetURL; + break; + + case PROPERTY_ID_TARGET_FRAME : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_sTargetFrame; + break; + + case PROPERTY_ID_DISPATCHURLINTERNAL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_bDispatchUrlInternal; + break; + + default: + OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : + return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType ); + + case PROPERTY_ID_TARGET_URL : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL); + + case PROPERTY_ID_TARGET_FRAME : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame); + + case PROPERTY_ID_DISPATCHURLINTERNAL : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal); + + default: + return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::StartProduction() + { + ImageProducer *pImgProd = GetImageProducer(); + // grab the ImageURL + rtl::OUString sURL; + getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ImageURL") ) ) >>= sURL; + if (!m_pMedium) + { + if ( ::svt::GraphicAccess::isSupportedURL( sURL ) ) + pImgProd->SetImage( sURL ); + else + // caution: the medium may be NULL if somebody gave us a invalid URL to work with + // 11/24/2000 - 79667 - FS + pImgProd->SetImage(String()); + m_bDownloading = sal_False; + return; + } + if (m_pMedium->GetErrorCode()==0) + { + SvStream* pStream = m_pMedium->GetInStream(); + + pImgProd->SetImage(*pStream); + pImgProd->startProduction(); + m_bProdStarted = sal_True; + } + else + { + pImgProd->SetImage(String()); + delete m_pMedium; + m_pMedium = 0; + m_bDownloading = sal_False; + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::SetURL( const ::rtl::OUString& rURL ) + { + if (m_pMedium || !rURL.getLength()) + { + // Den Stream am Producer freigeben, bevor das Medium geloscht wird. + GetImageProducer()->SetImage(String()); + delete m_pMedium; + m_pMedium = NULL; + } + + // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first + // 23.01.2001 - 81927 - FS + INetURLObject aUrl(rURL); + if (INET_PROT_NOT_VALID == aUrl.GetProtocol()) + // we treat an invalid URL like we would treat no URL + return; + + if (rURL.getLength() && !::svt::GraphicAccess::isSupportedURL( rURL ) ) + { + if (m_pMedium) + delete m_pMedium; + + m_pMedium = new SfxMedium(rURL, STREAM_STD_READ, sal_False); + m_pMedium->SetDataAvailableLink( + STATIC_LINK(this, OClickableImageBaseModel, DataAvailableLink)); + + // Das XModel suchen, um an die Object-Shell oder zumindest den + // Referer zu gelangen. + // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten + // und dann, wenn die URL in einem bereits geladenen Dokument + // geaendert wird. Waehrend des Ladens kommt man nicht an das + // Model ran. + Reference< XModel > xModel; + InterfaceRef xIfc( *this ); + while( !xModel.is() && xIfc.is() ) + { + Reference<XChild> xChild( xIfc, UNO_QUERY ); + xIfc = xChild->getParent(); + query_interface(xIfc, xModel); + } + + // Die Object-Shell suchen, indem wir + // ueber alle Object-Shells iterieren und deren XModel mit dem + // eigenen vergleichen. Als Optimierung probieren wir aber erstmal + // die aktuelle Object-Shell. + // wir unser XModel mit dem aller Object + SfxObjectShell *pObjSh = 0; + + if( xModel.is() ) + { + SfxObjectShell *pTestObjSh = SfxObjectShell::Current(); + if( pTestObjSh ) + { + Reference< XModel > xTestModel = pTestObjSh->GetModel(); + if( xTestModel == xModel ) + pObjSh = pTestObjSh; + } + if( !pObjSh ) + { + pTestObjSh = SfxObjectShell::GetFirst(); + while( !pObjSh && pTestObjSh ) + { + Reference< XModel > xTestModel = pTestObjSh->GetModel(); + if( xTestModel == xModel ) + pObjSh = pTestObjSh; + else + pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh ); + } + } + } + + #ifdef USE_REGISTER_TRANSFER + if( pObjSh ) + { + // Medium registrieren, damit abgebrochen werden kann + pObjSh->RegisterTransfer( *m_pMedium ); + + // Target-Frame uebertragen, damit auch javascript:-URLs + // "geladen" werden koennen. + const SfxMedium *pShMedium = pObjSh->GetMedium(); + if( pShMedium ) + m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); + } + else + { + // Keine Object-Shell, aber ein Medium? Dann uebernehmen wir + // zumindest den Referer. + if( xModel.is() ) + { + ::rtl::OUString sReferer( xModel->getURL() ); + if( sReferer.getLength() ) + m_pMedium->SetReferer( OUStringToString(sReferer, CHARSET_SYSTEM) ); + } + + // Keinen Eintrag im Roter Button Menu + m_pMedium->SetDontCreateCancellable(); + } + #else + if( pObjSh ) + { + // Target-Frame uebertragen, damit auch javascript:-URLs + // "geladen" werden koennen. + const SfxMedium *pShMedium = pObjSh->GetMedium(); + if( pShMedium ) + m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); + } + + if( xModel.is() ) + { + ::rtl::OUString sReferer( xModel->getURL() ); + if( sReferer.getLength() ) + m_pMedium->SetReferer( sReferer ); + } + + // Keinen Eintrag im Roter Button Menu + m_pMedium->SetDontCreateCancellable(); + #endif + + // Downloading-Flag auf sal_True setzen. Es werden dann auch + // Data-Available-Links, wenn wir in den Pending-Staus gelangen. + m_bDownloading = sal_True; + m_bProdStarted = sal_False; + + // Download anstossen (Achtung: Kann auch synchron sein). + m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink)); + } + else + { + if ( ::svt::GraphicAccess::isSupportedURL( rURL ) ) + GetImageProducer()->SetImage( rURL ); + GetImageProducer()->startProduction(); + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::DataAvailable() + { + if (!m_bProdStarted) + StartProduction(); + + GetImageProducer()->NewDataAvailable(); + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::DownloadDone() + { + DataAvailable(); + m_bDownloading = sal_False; + } + + //------------------------------------------------------------------------------ + IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG ) + { + ::osl::MutexGuard aGuard( pThis->m_aMutex ); + pThis->DownloadDone(); + return 0; + } + + //------------------------------------------------------------------------------ + IMPL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void*, EMPTYARG ) + { + ::osl::MutexGuard aGuard( pThis->m_aMutex ); + pThis->DataAvailable(); + return 0; + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt ) + throw( RuntimeException ) + { + // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer + // weitergereicht werden. + ::osl::MutexGuard aGuard(m_aMutex); + SetURL( getString(rEvt.NewValue) ); + } + + // ----------------------------------------------------------------------------- + Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH ); + case PROPERTY_ID_TARGET_URL : + case PROPERTY_ID_TARGET_FRAME : return makeAny( ::rtl::OUString() ); + case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False ); + default: + return OControlModel::getPropertyDefaultByHandle(nHandle); + } + } + + //================================================================== + // OImageProducerThread_Impl + //================================================================== + //------------------------------------------------------------------ + EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const + { + return new EventObject( *_pEvt ); + } + + //------------------------------------------------------------------ + void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl, + const EventObject* pEvt, + const Reference<XControl>&, + sal_Bool ) + { + ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt ); + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/clickableimage.hxx b/forms/source/component/clickableimage.hxx new file mode 100644 index 000000000000..f888aa4e3309 --- /dev/null +++ b/forms/source/component/clickableimage.hxx @@ -0,0 +1,295 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_CLICKABLEIMAGE_HXX +#define FORMS_SOURCE_CLICKABLEIMAGE_HXX + +#include "FormComponent.hxx" +#include "EventThread.hxx" +#include "imgprod.hxx" +#include <tools/link.hxx> +#include <comphelper/propmultiplex.hxx> +#include <com/sun/star/form/XImageProducerSupplier.hpp> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/form/XApproveActionListener.hpp> +#include <com/sun/star/form/XApproveActionBroadcaster.hpp> +#include <com/sun/star/form/submission/XSubmissionSupplier.hpp> +#include <com/sun/star/form/submission/XSubmission.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include <cppuhelper/implbase3.hxx> + + +class SfxMedium; + +//......................................................................... +namespace frm +{ +//......................................................................... + + class OImageProducerThread_Impl; + class ControlFeatureInterception; + //================================================================== + // OClickableImageBaseModel + //================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::form::XImageProducerSupplier + , ::com::sun::star::awt::XImageProducer + , ::com::sun::star::form::submission::XSubmissionSupplier + > OClickableImageBaseModel_Base; + + class OClickableImageBaseModel :public OClickableImageBaseModel_Base + ,public OControlModel + ,public OPropertyChangeListener + { + protected: + ::com::sun::star::form::FormButtonType m_eButtonType; // Art des Buttons (push,submit,reset) + ::rtl::OUString m_sTargetURL; // URL fuer den URL-Button + ::rtl::OUString m_sTargetFrame; // TargetFrame zum Oeffnen + + // ImageProducer stuff + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> m_xProducer; + SfxMedium* m_pMedium; // Download-Medium + ImageProducer* m_pProducer; + sal_Bool m_bDispatchUrlInternal; // property: is not allowed to set : 1 + sal_Bool m_bDownloading : 1; // laeuft ein Download? + sal_Bool m_bProdStarted : 1; + + // XSubmission stuff + ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmission > + m_xSubmissionDelegate; + + + DECL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void* ); + DECL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void* ); + + inline ImageProducer* GetImageProducer() { return m_pProducer; } + + void StartProduction(); + void SetURL(const ::rtl::OUString& rURL); + void DataAvailable(); + void DownloadDone(); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + inline sal_Bool isDispatchUrlInternal() const { return m_bDispatchUrlInternal; } + inline void setDispatchUrlInternal(sal_Bool _bDispatch) { m_bDispatchUrlInternal = _bDispatch; } + + public: + DECLARE_DEFAULT_XTOR( OClickableImageBaseModel ); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OClickableImageBaseModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + protected: + // OComponentHelper + virtual void SAL_CALL disposing(); + + // ::com::sun::star::form::XImageProducerSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> SAL_CALL getImageProducer() throw (::com::sun::star::uno::RuntimeException) { return m_xProducer; } + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + + using ::cppu::OPropertySetHelper::getFastPropertyValue; + + // OPropertyChangeListener + virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent&) throw(::com::sun::star::uno::RuntimeException); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // XImageProducer + virtual void SAL_CALL addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startProduction( ) throw (::com::sun::star::uno::RuntimeException); + + // XSubmissionSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmission > SAL_CALL getSubmission() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setSubmission( const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmission >& _submission ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + using OControlModel::disposing; + + public: + struct GuardAccess { friend class ImageModelMethodGuard; private: GuardAccess() { } }; + ::osl::Mutex& getMutex( GuardAccess ) { return m_aMutex; } + ImageProducer* getImageProducer( GuardAccess ) { return m_pProducer; } + + protected: + using OControlModel::getMutex; + + void implConstruct(); + + // to be called from within the cloning-ctor of your derived class + void implInitializeImageURL( ); + }; + + //================================================================== + // ImageModelMethodGuard + //================================================================== + class ImageModelMethodGuard : public ::osl::MutexGuard + { + private: + typedef ::osl::MutexGuard GuardBase; + + public: + ImageModelMethodGuard( OClickableImageBaseModel& _rModel ) + :GuardBase( _rModel.getMutex( OClickableImageBaseModel::GuardAccess() ) ) + { + if ( NULL == _rModel.getImageProducer( OClickableImageBaseModel::GuardAccess() ) ) + throw ::com::sun::star::lang::DisposedException( + ::rtl::OUString(), + static_cast< ::com::sun::star::form::XImageProducerSupplier* >( &_rModel ) + ); + } + }; + + //================================================================== + // OClickableImageBaseControl + //================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::form::XApproveActionBroadcaster + , ::com::sun::star::form::submission::XSubmission + , ::com::sun::star::frame::XDispatchProviderInterception + > OClickableImageBaseControl_BASE; + + class OClickableImageBaseControl :public OClickableImageBaseControl_BASE + ,public OControl + { + friend class OImageProducerThread_Impl; + + private: + OImageProducerThread_Impl* m_pThread; + ::cppu::OInterfaceContainerHelper m_aSubmissionVetoListeners; + ::std::auto_ptr< ControlFeatureInterception > + m_pFeatureInterception; + + protected: + ::cppu::OInterfaceContainerHelper m_aApproveActionListeners; + ::cppu::OInterfaceContainerHelper m_aActionListeners; + ::rtl::OUString m_aActionCommand; + + // XSubmission + virtual void SAL_CALL submit( ) throw (::com::sun::star::util::VetoException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL submitWithInteraction( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler ) throw (::com::sun::star::util::VetoException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSubmissionVetoListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSubmissionVetoListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + using OControl::disposing; + + public: + OClickableImageBaseControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _aService); + virtual ~OClickableImageBaseControl(); + + protected: + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OClickableImageBaseControl, OControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // ::com::sun::star::form::XApproveActionBroadcaster + virtual void SAL_CALL addApproveActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XApproveActionListener>& _rxListener) + throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeApproveActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XApproveActionListener>& _rxListener) + throw(::com::sun::star::uno::RuntimeException); + + // XDispatchProviderInterception + virtual void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + + protected: + virtual void actionPerformed_Impl( sal_Bool bNotifyListener, const ::com::sun::star::awt::MouseEvent& rEvt ); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > _getTypes(); + + /** approves the action by calling the approve listeners + @return <TRUE/> if and only if the action has <em>not</em> been cancelled by a listener + */ + bool approveAction( ); + + /** retrieves (and if necessary creates) the image producer thread. + + Must be called with our mutex locked + */ + OImageProducerThread_Impl* getImageProducerThread(); + + private: + void implSubmit( + const ::com::sun::star::awt::MouseEvent& _rEvent, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler + ) SAL_THROW((com::sun::star::util::VetoException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)); + }; + + //================================================================== + // OImageProducerThread_Impl + //================================================================== + class OImageProducerThread_Impl: public OComponentEventThread + { + protected: + + // Die folgende Methode wrrd gerufen um das Event unter Beruecksichtigung + // seines Typs zu duplizieren + virtual ::com::sun::star::lang::EventObject* cloneEvent( const ::com::sun::star::lang::EventObject* _pEvt ) const; + + // Ein Event bearbeiten. Der Mutex ist dabei nicht gelockt, pCompImpl + // bleibt aber in jedem Fall gueltig. + virtual void processEvent( ::cppu::OComponentHelper *pCompImpl, + const ::com::sun::star::lang::EventObject*, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>&, + sal_Bool ); + + public: + OImageProducerThread_Impl( OClickableImageBaseControl *pControl ) : + OComponentEventThread( pControl ) + {} + + void addEvent() { ::com::sun::star::lang::EventObject aEvt; OComponentEventThread::addEvent( &aEvt ); } + + protected: + using OComponentEventThread::addEvent; + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_SOURCE_CLICKABLEIMAGE_HXX + diff --git a/forms/source/component/cloneable.cxx b/forms/source/component/cloneable.cxx new file mode 100644 index 000000000000..5392dbee3e7f --- /dev/null +++ b/forms/source/component/cloneable.cxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "cloneable.hxx" +#include <com/sun/star/util/XCloneable.hpp> +#include <comphelper/uno3.hxx> +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::comphelper; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + + //==================================================================== + //= OCloneableAggregation + //==================================================================== + //------------------------------------------------------------------ + Reference< XAggregation > OCloneableAggregation::createAggregateClone( const OCloneableAggregation* _pOriginal ) + { + Reference< XCloneable > xAggregateCloneable; // will be the aggregate's XCloneable + Reference< XAggregation > xAggregateClone; // will be the aggregate's clone + + if ( query_aggregation( _pOriginal->m_xAggregate, xAggregateCloneable ) ) + { + xAggregateClone = xAggregateClone.query( xAggregateCloneable->createClone() ); + DBG_ASSERT( xAggregateClone.is(), "OCloneableAggregation::createAggregateClone: invalid clone returned by the aggregate!" ); + } + else { + DBG_ASSERT( !_pOriginal->m_xAggregate.is(), "OCloneableAggregation::createAggregateClone: aggregate is not cloneable!" ); + } + + return xAggregateClone; + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/entrylisthelper.cxx b/forms/source/component/entrylisthelper.cxx new file mode 100644 index 000000000000..065bd4ca6896 --- /dev/null +++ b/forms/source/component/entrylisthelper.cxx @@ -0,0 +1,321 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "entrylisthelper.hxx" +#include "FormComponent.hxx" + +#include <osl/diagnose.h> +#include <comphelper/sequence.hxx> +#include <comphelper/property.hxx> +#include <algorithm> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + + //===================================================================== + //= OEntryListHelper + //===================================================================== + //--------------------------------------------------------------------- + OEntryListHelper::OEntryListHelper( OControlModel& _rControlModel ) + :m_rControlModel( _rControlModel ) + ,m_aRefreshListeners( _rControlModel.getInstanceMutex() ) + { + } + + //--------------------------------------------------------------------- + OEntryListHelper::OEntryListHelper( const OEntryListHelper& _rSource, OControlModel& _rControlModel ) + :m_rControlModel( _rControlModel ) + ,m_xListSource ( _rSource.m_xListSource ) + ,m_aStringItems( _rSource.m_aStringItems ) + ,m_aRefreshListeners( _rControlModel.getInstanceMutex() ) + { + } + + //--------------------------------------------------------------------- + OEntryListHelper::~OEntryListHelper( ) + { + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::setListEntrySource( const Reference< XListEntrySource >& _rxSource ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + // disconnect from the current external list source + disconnectExternalListSource(); + + // and connect to the new one + if ( _rxSource.is() ) + connectExternalListSource( _rxSource, aLock ); + } + + //--------------------------------------------------------------------- + Reference< XListEntrySource > SAL_CALL OEntryListHelper::getListEntrySource( ) throw (RuntimeException) + { + return m_xListSource; + } + + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::entryChanged( const ListEntryEvent& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::entryChanged: where did this come from?" ); + OSL_ENSURE( ( _rEvent.Position >= 0 ) && ( _rEvent.Position < m_aStringItems.getLength() ), + "OEntryListHelper::entryChanged: invalid index!" ); + OSL_ENSURE( _rEvent.Entries.getLength() == 1, + "OEntryListHelper::entryChanged: invalid string list!" ); + + if ( ( _rEvent.Position >= 0 ) + && ( _rEvent.Position < m_aStringItems.getLength() ) + && ( _rEvent.Entries.getLength() > 0 ) + ) + { + m_aStringItems[ _rEvent.Position ] = _rEvent.Entries[ 0 ]; + stringItemListChanged( aLock ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::entryRangeInserted( const ListEntryEvent& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::entryRangeInserted: where did this come from?" ); + OSL_ENSURE( ( _rEvent.Position > 0 ) && ( _rEvent.Position < m_aStringItems.getLength() ) && ( _rEvent.Entries.getLength() > 0 ), + "OEntryListHelper::entryRangeRemoved: invalid count and/or position!" ); + + if ( ( _rEvent.Position > 0 ) + && ( _rEvent.Position < m_aStringItems.getLength() ) + && ( _rEvent.Entries.getLength() > 0 ) + ) + { + // the entries *before* the insertion pos + Sequence< ::rtl::OUString > aKeepEntries( + m_aStringItems.getConstArray(), + _rEvent.Position + ); + // the entries *behind* the insertion pos + Sequence< ::rtl::OUString > aMovedEntries( + m_aStringItems.getConstArray() + _rEvent.Position, + m_aStringItems.getLength() - _rEvent.Position + ); + + // concat all three parts + m_aStringItems = ::comphelper::concatSequences( + aKeepEntries, + _rEvent.Entries, + aMovedEntries + ); + + stringItemListChanged( aLock ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::entryRangeRemoved( const ListEntryEvent& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::entryRangeRemoved: where did this come from?" ); + OSL_ENSURE( ( _rEvent.Position > 0 ) && ( _rEvent.Count > 0 ) && ( _rEvent.Position + _rEvent.Count <= m_aStringItems.getLength() ), + "OEntryListHelper::entryRangeRemoved: invalid count and/or position!" ); + + if ( ( _rEvent.Position > 0 ) + && ( _rEvent.Count > 0 ) + && ( _rEvent.Position + _rEvent.Count <= m_aStringItems.getLength() ) + ) + { + // copy all items after the removed ones + ::std::copy( + m_aStringItems.getConstArray() + _rEvent.Position + _rEvent.Count, + m_aStringItems.getConstArray() + m_aStringItems.getLength(), + m_aStringItems.getArray( ) + _rEvent.Position + ); + // shrink the array + m_aStringItems.realloc( m_aStringItems.getLength() - _rEvent.Count ); + + stringItemListChanged( aLock ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::allEntriesChanged( const EventObject& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::allEntriesChanged: where did this come from?" ); + + Reference< XListEntrySource > xSource( _rEvent.Source, UNO_QUERY ); + if ( _rEvent.Source == m_xListSource ) + { + impl_lock_refreshList( aLock ); + } + } + + // XRefreshable + //------------------------------------------------------------------------------ + void SAL_CALL OEntryListHelper::addRefreshListener(const Reference<XRefreshListener>& _rxListener) throw(RuntimeException) + { + if ( _rxListener.is() ) + m_aRefreshListeners.addInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OEntryListHelper::removeRefreshListener(const Reference<XRefreshListener>& _rxListener) throw(RuntimeException) + { + if ( _rxListener.is() ) + m_aRefreshListeners.removeInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OEntryListHelper::refresh() throw(RuntimeException) + { + { + ControlModelLock aLock( m_rControlModel ); + impl_lock_refreshList( aLock ); + } + + EventObject aEvt( static_cast< XRefreshable* >( this ) ); + m_aRefreshListeners.notifyEach( &XRefreshListener::refreshed, aEvt ); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::impl_lock_refreshList( ControlModelLock& _rInstanceLock ) + { + if ( hasExternalListSource() ) + { + m_aStringItems = m_xListSource->getAllListEntries( ); + stringItemListChanged( _rInstanceLock ); + } + else + refreshInternalEntryList(); + } + + //--------------------------------------------------------------------- + bool OEntryListHelper::handleDisposing( const EventObject& _rEvent ) + { + if ( m_xListSource .is() && ( _rEvent.Source == m_xListSource ) ) + { + disconnectExternalListSource( ); + return true; + } + return false; + } + + //--------------------------------------------------------------------- + void OEntryListHelper::disposing( ) + { + EventObject aEvt( static_cast< XRefreshable* >( this ) ); + m_aRefreshListeners.disposeAndClear(aEvt); + + if ( hasExternalListSource( ) ) + disconnectExternalListSource( ); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::disconnectExternalListSource( ) + { + if ( m_xListSource.is() ) + m_xListSource->removeListEntryListener( this ); + + m_xListSource.clear(); + + disconnectedExternalListSource(); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::connectedExternalListSource( ) + { + // nothing to do here + } + + //--------------------------------------------------------------------- + void OEntryListHelper::disconnectedExternalListSource( ) + { + // nothing to do here + } + + //--------------------------------------------------------------------- + void OEntryListHelper::connectExternalListSource( const Reference< XListEntrySource >& _rxSource, ControlModelLock& _rInstanceLock ) + { + OSL_ENSURE( !hasExternalListSource(), "OEntryListHelper::connectExternalListSource: only to be called if no external source is active!" ); + OSL_ENSURE( _rxSource.is(), "OEntryListHelper::connectExternalListSource: invalid list source!" ); + + // remember it + m_xListSource = _rxSource; + + // initially fill our item list + if ( m_xListSource.is() ) + { + // be notified when the list changes ... + m_xListSource->addListEntryListener( this ); + + m_aStringItems = m_xListSource->getAllListEntries( ); + stringItemListChanged( _rInstanceLock ); + + // let derivees react on the new list source + connectedExternalListSource(); + } + } + + //--------------------------------------------------------------------- + sal_Bool OEntryListHelper::convertNewListSourceProperty( Any& _rConvertedValue, + Any& _rOldValue, const Any& _rValue ) SAL_THROW( ( IllegalArgumentException ) ) + { + if ( hasExternalListSource() ) + throw IllegalArgumentException( ); + // TODO: error message + + return ::comphelper::tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aStringItems ); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::setNewStringItemList( const ::com::sun::star::uno::Any& _rValue, ControlModelLock& _rInstanceLock ) + { + OSL_PRECOND( !hasExternalListSource(), "OEntryListHelper::setNewStringItemList: this should never have survived convertNewListSourceProperty!" ); + OSL_VERIFY( _rValue >>= m_aStringItems ); + stringItemListChanged( _rInstanceLock ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/entrylisthelper.hxx b/forms/source/component/entrylisthelper.hxx new file mode 100644 index 000000000000..64778e9abdc3 --- /dev/null +++ b/forms/source/component/entrylisthelper.hxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_ENTRYLISTHELPER_HXX +#define FORMS_ENTRYLISTHELPER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/form/binding/XListEntryListener.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + + class OControlModel; + class ControlModelLock; + + //===================================================================== + //= OEntryListHelper + //===================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::form::binding::XListEntrySink + , ::com::sun::star::form::binding::XListEntryListener + , ::com::sun::star::util::XRefreshable + > OEntryListHelper_BASE; + + class OEntryListHelper : public OEntryListHelper_BASE + { + private: + OControlModel& m_rControlModel; + + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > + m_xListSource; /// our external list source + ::com::sun::star::uno::Sequence< ::rtl::OUString > + m_aStringItems; /// "overridden" StringItemList property value + ::cppu::OInterfaceContainerHelper + m_aRefreshListeners; + + + protected: + OEntryListHelper( OControlModel& _rControlModel ); + OEntryListHelper( const OEntryListHelper& _rSource, OControlModel& _rControlModel ); + virtual ~OEntryListHelper( ); + + /// returns the current string item list + inline const ::com::sun::star::uno::Sequence< ::rtl::OUString >& + getStringItemList() const { return m_aStringItems; } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& + getExternalListEntrySource() const { return m_xListSource; } + + /// determines whether we actually have an external list source + inline bool hasExternalListSource( ) const { return m_xListSource.is(); } + + /** handling the XEventListener::disposing call for the case where + our list source is being disposed + @return + <TRUE/> if and only if the disposed object was our list source, and so the + event was handled + */ + bool handleDisposing( const ::com::sun::star::lang::EventObject& _rEvent ); + + /** to be called by derived classes' instances when they're being disposed + */ + void disposing( ); + + // prevent method hiding + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) = 0; + + /** helper for implementing convertFastPropertyValue( StringItemList ) + + <p>The signature of this method and the return type have the same semantics + as convertFastPropertyValue.</p> + */ + sal_Bool convertNewListSourceProperty( + ::com::sun::star::uno::Any& _rConvertedValue, + ::com::sun::star::uno::Any& _rOldValue, + const ::com::sun::star::uno::Any& _rValue + ) + SAL_THROW( ( ::com::sun::star::lang::IllegalArgumentException ) ); + + /** helper for implementing setFastPropertyValueNoBroadcast + + <p>Will internally call stringItemListChanged after the new item list + has been set.</p> + + @precond + not to be called when we have an external list source + @see hasExternalListSource + */ + void setNewStringItemList( const ::com::sun::star::uno::Any& _rValue, ControlModelLock& _rInstanceLock ); + + /** announces that the list of entries has changed. + + <p>Derived classes have to override this. Most probably, they'll set the new + as model property.</p> + + @pure + @see getStringItemList + */ + virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ) = 0; + + /** called whenever a connection to a new external list source has been established + */ + virtual void connectedExternalListSource( ); + + /** called whenever a connection to a new external list source has been revoked + */ + virtual void disconnectedExternalListSource( ); + + /** called when XRefreshable::refresh has been called, and we do *not* have an external + list source + */ + virtual void refreshInternalEntryList() = 0; + + private: + // XListEntrySink + virtual void SAL_CALL setListEntrySource( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > SAL_CALL getListEntrySource( ) throw (::com::sun::star::uno::RuntimeException); + + // XListEntryListener + virtual void SAL_CALL entryChanged( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL entryRangeInserted( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL entryRangeRemoved( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL allEntriesChanged( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + + // XRefreshable + virtual void SAL_CALL refresh() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRefreshListener(const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRefreshListener(const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + private: + /** disconnects from the active external list source, if present + @see connectExternalListSource + */ + void disconnectExternalListSource( ); + + /** connects to a new external list source + @param _rxSource + the new list source. Must not be <NULL/> + @see disconnectExternalListSource + */ + void connectExternalListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource, + ControlModelLock& _rInstanceLock + ); + + /** refreshes our list entries + + In case we have an external list source, its used to obtain the new entries, and then + stringItemListChanged is called to give the derived class the possibility to + react on this. + + In case we do not have an external list source, refreshInternalEntryList is called. + */ + void impl_lock_refreshList( ControlModelLock& _rInstanceLock ); + + private: + OEntryListHelper(); // never implemented + OEntryListHelper( const OEntryListHelper& ); // never implemented + OEntryListHelper& operator=( const OEntryListHelper& ); // never implemented + }; + +//......................................................................... +} // namespace frm +//......................................................................... + + +#endif // FORMS_ENTRYLISTHELPER_HXX diff --git a/forms/source/component/errorbroadcaster.cxx b/forms/source/component/errorbroadcaster.cxx new file mode 100644 index 000000000000..e388a35480a1 --- /dev/null +++ b/forms/source/component/errorbroadcaster.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "errorbroadcaster.hxx" +#include <connectivity/dbtools.hxx> +#include <com/sun/star/sdb/SQLContext.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::dbtools; + + //===================================================================== + //= OErrorBroadcaster + //===================================================================== + //--------------------------------------------------------------------- + OErrorBroadcaster::OErrorBroadcaster( ::cppu::OBroadcastHelper& _rBHelper ) + :m_rBHelper( _rBHelper ) + ,m_aErrorListeners( _rBHelper.rMutex ) + { + } + + //--------------------------------------------------------------------- + OErrorBroadcaster::~OErrorBroadcaster( ) + { + OSL_ENSURE( m_rBHelper.bDisposed || m_rBHelper.bInDispose, + "OErrorBroadcaster::~OErrorBroadcaster: not disposed!" ); + // herein, we don't have a chance to do the dispose ourself .... + + OSL_ENSURE( 0 == m_aErrorListeners.getLength(), + "OErrorBroadcaster::~OErrorBroadcaster: still have listeners!" ); + // either we're not disposed, or the derived class did not call our dispose from within their dispose + } + + //--------------------------------------------------------------------- + void SAL_CALL OErrorBroadcaster::disposing() + { + EventObject aDisposeEvent( static_cast< XSQLErrorBroadcaster* >( this ) ); + m_aErrorListeners.disposeAndClear( aDisposeEvent ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::onError( const SQLException& _rException, const ::rtl::OUString& _rContextDescription ) + { + Any aError; + if ( _rContextDescription.getLength() ) + aError = makeAny( prependErrorInfo( _rException, static_cast< XSQLErrorBroadcaster* >( this ), _rContextDescription ) ); + else + aError = makeAny( _rException ); + + onError( SQLErrorEvent( static_cast< XSQLErrorBroadcaster* >( this ), aError ) ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::onError( const ::com::sun::star::sdb::SQLErrorEvent& _rError ) + { + if ( m_aErrorListeners.getLength() ) + { + + ::cppu::OInterfaceIteratorHelper aIter( m_aErrorListeners ); + while ( aIter.hasMoreElements() ) + static_cast< XSQLErrorListener* >( aIter.next() )->errorOccured( _rError ); + } + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::addSQLErrorListener( const Reference< XSQLErrorListener >& _rxListener ) throw( RuntimeException ) + { + m_aErrorListeners.addInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::removeSQLErrorListener( const Reference< XSQLErrorListener >& _rxListener ) throw( RuntimeException ) + { + m_aErrorListeners.removeInterface( _rxListener ); + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/errorbroadcaster.hxx b/forms/source/component/errorbroadcaster.hxx new file mode 100644 index 000000000000..c91cc220c58d --- /dev/null +++ b/forms/source/component/errorbroadcaster.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_ERRORBROADCASTER_HXX +#define FORMS_ERRORBROADCASTER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdb/SQLErrorEvent.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //===================================================================== + //= OErrorBroadcaster + //===================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::sdb::XSQLErrorBroadcaster + > OErrorBroadcaster_BASE; + + class OErrorBroadcaster : public OErrorBroadcaster_BASE + { + private: + ::cppu::OBroadcastHelper& m_rBHelper; + ::cppu::OInterfaceContainerHelper m_aErrorListeners; + + protected: + OErrorBroadcaster( ::cppu::OBroadcastHelper& _rBHelper ); + virtual ~OErrorBroadcaster( ); + + void SAL_CALL disposing(); + + void SAL_CALL onError( const ::com::sun::star::sdbc::SQLException& _rException, const ::rtl::OUString& _rContextDescription ); + void SAL_CALL onError( const ::com::sun::star::sdb::SQLErrorEvent& _rException ); + + protected: + // XSQLErrorBroadcaster + virtual void SAL_CALL addSQLErrorListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener >& _rListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSQLErrorListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener >& _rListener ) throw (::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_ERRORBROADCASTER_HXX + diff --git a/forms/source/component/findpos.cxx b/forms/source/component/findpos.cxx new file mode 100644 index 000000000000..87ea53b27e29 --- /dev/null +++ b/forms/source/component/findpos.cxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "sal/config.h" + +#include "findpos.hxx" + +#include "com/sun/star/uno/Sequence.hxx" +#include "comphelper/types.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <algorithm> + +namespace detail { + +sal_Int32 findPos( + const ::rtl::OUString& aStr, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rList) +{ + const ::rtl::OUString* pStrList = rList.getConstArray(); + const ::rtl::OUString* pResult = ::std::lower_bound( + pStrList, pStrList + rList.getLength(), aStr ); + if ( ( pResult != pStrList + rList.getLength() ) && ( *pResult == aStr ) ) + return ( pResult - pStrList ); + + return -1; +} + +} diff --git a/forms/source/component/findpos.hxx b/forms/source/component/findpos.hxx new file mode 100644 index 000000000000..67fb2a8996a3 --- /dev/null +++ b/forms/source/component/findpos.hxx @@ -0,0 +1,45 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_FORMS_SOURCE_COMPONENT_FINDPOS_HXX +#define INCLUDED_FORMS_SOURCE_COMPONENT_FINDPOS_HXX + +#include "sal/config.h" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace rtl { class OUString; } + +namespace detail { + +sal_Int32 findPos( + const ::rtl::OUString& aStr, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rList); + +} + +#endif diff --git a/forms/source/component/formcontrolfont.cxx b/forms/source/component/formcontrolfont.cxx new file mode 100644 index 000000000000..1029a7678536 --- /dev/null +++ b/forms/source/component/formcontrolfont.cxx @@ -0,0 +1,551 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "formcontrolfont.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "property.hxx" +#include <tools/debug.hxx> +#include <comphelper/property.hxx> +#include <comphelper/types.hxx> +#include <tools/color.hxx> +#include <toolkit/helper/emptyfontdescriptor.hxx> +#include <com/sun/star/awt/FontRelief.hpp> +#include <com/sun/star/awt/FontEmphasisMark.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::comphelper; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + + //------------------------------------------------------------------------------ + namespace + { + Any lcl_extractFontDescriptorAggregate( sal_Int32 _nHandle, const FontDescriptor& _rFont ) + { + Any aValue; + switch ( _nHandle ) + { + case PROPERTY_ID_FONT_NAME: + aValue <<= _rFont.Name; + break; + + case PROPERTY_ID_FONT_STYLENAME: + aValue <<= _rFont.StyleName; + break; + + case PROPERTY_ID_FONT_FAMILY: + aValue <<= (sal_Int16)_rFont.Family; + break; + + case PROPERTY_ID_FONT_CHARSET: + aValue <<= (sal_Int16)_rFont.CharSet; + break; + + case PROPERTY_ID_FONT_CHARWIDTH: + aValue <<= _rFont.CharacterWidth; + break; + + case PROPERTY_ID_FONT_KERNING: + aValue <<= _rFont.Kerning; + break; + + case PROPERTY_ID_FONT_ORIENTATION: + aValue <<= _rFont.Orientation; + break; + + case PROPERTY_ID_FONT_PITCH: + aValue <<= _rFont.Pitch; + break; + + case PROPERTY_ID_FONT_TYPE: + aValue <<= _rFont.Type; + break; + + case PROPERTY_ID_FONT_WIDTH: + aValue <<= _rFont.Width; + break; + + case PROPERTY_ID_FONT_HEIGHT: + aValue <<= (float)( _rFont.Height ); + break; + + case PROPERTY_ID_FONT_WEIGHT: + aValue <<= (float)_rFont.Weight; + break; + + case PROPERTY_ID_FONT_SLANT: + aValue = makeAny(_rFont.Slant); + break; + + case PROPERTY_ID_FONT_UNDERLINE: + aValue <<= (sal_Int16)_rFont.Underline; + break; + + case PROPERTY_ID_FONT_STRIKEOUT: + aValue <<= (sal_Int16)_rFont.Strikeout; + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + aValue = makeAny( (sal_Bool)_rFont.WordLineMode ); + break; + + default: + OSL_ENSURE( sal_False, "lcl_extractFontDescriptorAggregate: invalid handle!" ); + break; + } + return aValue; + } + } + + //===================================================================== + //= FontControlModel + //===================================================================== + //--------------------------------------------------------------------- + FontControlModel::FontControlModel( bool _bToolkitCompatibleDefaults ) + :m_nFontRelief( FontRelief::NONE ) + ,m_nFontEmphasis( FontEmphasisMark::NONE ) + ,m_bToolkitCompatibleDefaults( _bToolkitCompatibleDefaults ) + { + } + + //--------------------------------------------------------------------- + FontControlModel::FontControlModel( const FontControlModel* _pOriginal ) + { + m_aFont = _pOriginal->m_aFont; + m_nFontRelief = _pOriginal->m_nFontRelief; + m_nFontEmphasis = _pOriginal->m_nFontEmphasis; + m_aTextLineColor = _pOriginal->m_aTextLineColor; + m_aTextColor = _pOriginal->m_aTextColor; + m_bToolkitCompatibleDefaults = _pOriginal->m_bToolkitCompatibleDefaults; + } + + //--------------------------------------------------------------------- + bool FontControlModel::isFontRelatedProperty( sal_Int32 _nPropertyHandle ) const + { + return isFontAggregateProperty( _nPropertyHandle ) + || ( _nPropertyHandle == PROPERTY_ID_FONT ) + || ( _nPropertyHandle == PROPERTY_ID_FONTEMPHASISMARK ) + || ( _nPropertyHandle == PROPERTY_ID_FONTRELIEF ) + || ( _nPropertyHandle == PROPERTY_ID_TEXTLINECOLOR ) + || ( _nPropertyHandle == PROPERTY_ID_TEXTCOLOR ); + } + + //--------------------------------------------------------------------- + bool FontControlModel::isFontAggregateProperty( sal_Int32 _nPropertyHandle ) const + { + return ( _nPropertyHandle == PROPERTY_ID_FONT_CHARWIDTH ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_ORIENTATION ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_WIDTH ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_NAME ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_STYLENAME ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_FAMILY ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_CHARSET ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_HEIGHT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_WEIGHT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_SLANT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_UNDERLINE ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_STRIKEOUT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_WORDLINEMODE ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_PITCH ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_KERNING ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_TYPE ); + } + + //--------------------------------------------------------------------- + sal_Int32 FontControlModel::getTextColor( ) const + { + sal_Int32 nColor = COL_TRANSPARENT; + m_aTextColor >>= nColor; + return nColor; + } + + //--------------------------------------------------------------------- + sal_Int32 FontControlModel::getTextLineColor( ) const + { + sal_Int32 nColor = COL_TRANSPARENT; + m_aTextLineColor >>= nColor; + return nColor; + } + + //------------------------------------------------------------------------------ + void FontControlModel::describeFontRelatedProperties( Sequence< Property >& /* [out] */ _rProps ) const + { + sal_Int32 nPos = _rProps.getLength(); + _rProps.realloc( nPos + 21 ); + Property* pProperties = _rProps.getArray(); + + DECL_PROP2 ( FONT, FontDescriptor, BOUND, MAYBEDEFAULT ); + DECL_PROP2 ( FONTEMPHASISMARK, sal_Int16, BOUND, MAYBEDEFAULT ); + DECL_PROP2 ( FONTRELIEF, sal_Int16, BOUND, MAYBEDEFAULT ); + DECL_PROP3 ( TEXTCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ); + DECL_PROP3 ( TEXTLINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ); + + DECL_PROP1 ( FONT_CHARWIDTH, float, MAYBEDEFAULT ); + DECL_BOOL_PROP1 ( FONT_KERNING, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_ORIENTATION, float, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_PITCH, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_TYPE, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_WIDTH, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_NAME, ::rtl::OUString, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_STYLENAME, ::rtl::OUString, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_FAMILY, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_CHARSET, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_HEIGHT, float, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_WEIGHT, float, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_SLANT, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_UNDERLINE, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_STRIKEOUT, sal_Int16, MAYBEDEFAULT ); + DECL_BOOL_PROP1 ( FONT_WORDLINEMODE, MAYBEDEFAULT ); + } + + //--------------------------------------------------------------------- + void FontControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + _rValue = m_aTextColor; + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + _rValue <<= m_nFontEmphasis; + break; + + case PROPERTY_ID_FONTRELIEF: + _rValue <<= m_nFontRelief; + break; + + case PROPERTY_ID_TEXTLINECOLOR: + _rValue = m_aTextLineColor; + break; + + case PROPERTY_ID_FONT: + _rValue = makeAny( m_aFont ); + break; + + default: + _rValue = lcl_extractFontDescriptorAggregate( _nHandle, m_aFont ); + break; + } + } + + //--------------------------------------------------------------------- + sal_Bool FontControlModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw( IllegalArgumentException ) + { + sal_Bool bModified = sal_False; + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aTextColor, ::getCppuType( static_cast< const sal_Int32* >( NULL ) ) ); + break; + + case PROPERTY_ID_TEXTLINECOLOR: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aTextLineColor, ::getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nFontEmphasis ); + break; + + case PROPERTY_ID_FONTRELIEF: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nFontRelief ); + break; + + case PROPERTY_ID_FONT: + { + Any aWorkAroundGccLimitation = makeAny( m_aFont ); + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aWorkAroundGccLimitation, ::getCppuType( &m_aFont ) ); + } + break; + + case PROPERTY_ID_FONT_NAME: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aFont.Name ); + break; + + case PROPERTY_ID_FONT_STYLENAME: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aFont.StyleName ); + break; + + case PROPERTY_ID_FONT_FAMILY: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Family ); + break; + + case PROPERTY_ID_FONT_CHARSET: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.CharSet ); + break; + + case PROPERTY_ID_FONT_CHARWIDTH: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, float( m_aFont.CharacterWidth ) ); + break; + + case PROPERTY_ID_FONT_KERNING: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Kerning ); + break; + + case PROPERTY_ID_FONT_ORIENTATION: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, float( m_aFont.Orientation ) ); + break; + + case PROPERTY_ID_FONT_PITCH: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Pitch ); + break; + + case PROPERTY_ID_FONT_TYPE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Type ); + break; + + case PROPERTY_ID_FONT_WIDTH: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Width ); + break; + + case PROPERTY_ID_FONT_HEIGHT: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, float( m_aFont.Height ) ); + break; + + case PROPERTY_ID_FONT_WEIGHT: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aFont.Weight ); + break; + + case PROPERTY_ID_FONT_SLANT: + bModified = tryPropertyValueEnum( _rConvertedValue, _rOldValue, _rValue, m_aFont.Slant ); + break; + + case PROPERTY_ID_FONT_UNDERLINE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Underline ); + break; + + case PROPERTY_ID_FONT_STRIKEOUT: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Strikeout ); + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Bool)m_aFont.WordLineMode ); + break; + + default: + DBG_ERROR( "FontControlModel::convertFastPropertyValue: no font aggregate!" ); + } + return bModified; + } + + //------------------------------------------------------------------------------ + void FontControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + m_aTextColor = _rValue; + break; + + case PROPERTY_ID_TEXTLINECOLOR: + m_aTextLineColor = _rValue; + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + _rValue >>= m_nFontEmphasis; + break; + + case PROPERTY_ID_FONTRELIEF: + _rValue >>= m_nFontRelief; + break; + + case PROPERTY_ID_FONT: + _rValue >>= m_aFont; + break; + + case PROPERTY_ID_FONT_NAME: + _rValue >>= m_aFont.Name; + break; + + case PROPERTY_ID_FONT_STYLENAME: + _rValue >>= m_aFont.StyleName; + break; + + case PROPERTY_ID_FONT_FAMILY: + _rValue >>= m_aFont.Family; + break; + + case PROPERTY_ID_FONT_CHARSET: + _rValue >>= m_aFont.CharSet; + break; + + case PROPERTY_ID_FONT_CHARWIDTH: + _rValue >>= m_aFont.CharacterWidth; + break; + + case PROPERTY_ID_FONT_KERNING: + _rValue >>= m_aFont.Kerning; + break; + + case PROPERTY_ID_FONT_ORIENTATION: + _rValue >>= m_aFont.Orientation; + break; + + case PROPERTY_ID_FONT_PITCH: + _rValue >>= m_aFont.Pitch; + break; + + case PROPERTY_ID_FONT_TYPE: + _rValue >>= m_aFont.Type; + break; + + case PROPERTY_ID_FONT_WIDTH: + _rValue >>= m_aFont.Width; + break; + + case PROPERTY_ID_FONT_HEIGHT: + { + float nHeight = 0; + _rValue >>= nHeight; + m_aFont.Height = (sal_Int16)nHeight; + } + break; + + case PROPERTY_ID_FONT_WEIGHT: + _rValue >>= m_aFont.Weight; + break; + + case PROPERTY_ID_FONT_SLANT: + _rValue >>= m_aFont.Slant; + break; + + case PROPERTY_ID_FONT_UNDERLINE: + _rValue >>= m_aFont.Underline; + break; + + case PROPERTY_ID_FONT_STRIKEOUT: + _rValue >>= m_aFont.Strikeout; + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + { + sal_Bool bWordLineMode = sal_False; + _rValue >>= bWordLineMode; + m_aFont.WordLineMode = bWordLineMode; + } + break; + + default: + DBG_ERROR( "FontControlModel::setFastPropertyValue_NoBroadcast: invalid property!" ); + } + } + + //------------------------------------------------------------------------------ + Any FontControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aReturn; + // some defaults which are the same, not matter if we have toolkit-compatible + // defaults or not + bool bHandled = false; + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + // void + bHandled = true; + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + aReturn <<= FontEmphasisMark::NONE; + bHandled = true; + break; + + case PROPERTY_ID_FONTRELIEF: + aReturn <<= FontRelief::NONE; + bHandled = true; + break; + } + if ( bHandled ) + return aReturn; + + if ( m_bToolkitCompatibleDefaults ) + { + EmptyFontDescriptor aEmpty; + if ( PROPERTY_ID_FONT == _nHandle ) + return makeAny( (FontDescriptor)aEmpty ); + return lcl_extractFontDescriptorAggregate( _nHandle, aEmpty ); + } + + switch( _nHandle ) + { + case PROPERTY_ID_FONT: + aReturn <<= ::comphelper::getDefaultFont(); + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + aReturn = makeBoolAny(sal_False); + + case PROPERTY_ID_FONT_NAME: + case PROPERTY_ID_FONT_STYLENAME: + aReturn <<= ::rtl::OUString(); + + case PROPERTY_ID_FONT_FAMILY: + case PROPERTY_ID_FONT_CHARSET: + case PROPERTY_ID_FONT_SLANT: + case PROPERTY_ID_FONT_UNDERLINE: + case PROPERTY_ID_FONT_STRIKEOUT: + aReturn <<= (sal_Int16)1; + break; + + case PROPERTY_ID_FONT_KERNING: + aReturn = makeBoolAny(sal_False); + break; + + case PROPERTY_ID_FONT_PITCH: + case PROPERTY_ID_FONT_TYPE: + case PROPERTY_ID_FONT_WIDTH: + aReturn <<= (sal_Int16)0; + break; + + case PROPERTY_ID_FONT_HEIGHT: + case PROPERTY_ID_FONT_WEIGHT: + case PROPERTY_ID_FONT_CHARWIDTH: + case PROPERTY_ID_FONT_ORIENTATION: + aReturn <<= (float)0; + break; + + default: + DBG_ERROR( "FontControlModel::getPropertyDefaultByHandle: invalid property!" ); + } + + return aReturn; + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/imgprod.cxx b/forms/source/component/imgprod.cxx new file mode 100644 index 000000000000..8bd02173fc3f --- /dev/null +++ b/forms/source/component/imgprod.cxx @@ -0,0 +1,655 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "imgprod.hxx" + +#include <vcl/bmpacc.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/svapp.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svtools/filter.hxx> +#include <com/sun/star/io/XInputStream.hpp> + +#ifndef SVTOOLS_SOURCE_MISC_IMAGERESOURCEACCESS_HXX +#include "svtools/imageresourceaccess.hxx" +#endif +#include <comphelper/processfactory.hxx> + +// -------------------- +// - ImgProdLockBytes - +// -------------------- + +class ImgProdLockBytes : public SvLockBytes +{ + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xStmRef; + ::com::sun::star::uno::Sequence<sal_Int8> maSeq; + + ImgProdLockBytes() {}; + +public: + + ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner ); + ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStreamRef ); + virtual ~ImgProdLockBytes(); + + virtual ErrCode ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const; + virtual ErrCode WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten ); + virtual ErrCode Flush() const; + virtual ErrCode SetSize( sal_Size nSize ); + virtual ErrCode Stat( SvLockBytesStat*, SvLockBytesStatFlag ) const; +}; + +// ------------------------------------------------------------------------ + +ImgProdLockBytes::ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner ) : + SvLockBytes( pStm, bOwner ) +{ +} + +// ------------------------------------------------------------------------ + +ImgProdLockBytes::ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ) : + xStmRef( rStmRef ) +{ + if( xStmRef.is() ) + { + const sal_uInt32 nBytesToRead = 65535; + sal_uInt32 nRead; + + do + { + ::com::sun::star::uno::Sequence< sal_Int8 > aReadSeq; + + nRead = xStmRef->readSomeBytes( aReadSeq, nBytesToRead ); + + if( nRead ) + { + const sal_uInt32 nOldLength = maSeq.getLength(); + maSeq.realloc( nOldLength + nRead ); + rtl_copyMemory( maSeq.getArray() + nOldLength, aReadSeq.getConstArray(), aReadSeq.getLength() ); + } + } + while( nBytesToRead == nRead ); + } +} + +// ------------------------------------------------------------------------ + +ImgProdLockBytes::~ImgProdLockBytes() +{ +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const +{ + if( GetStream() ) + { + ( (SvStream*) GetStream() )->ResetError(); + const ErrCode nErr = SvLockBytes::ReadAt( nPos, pBuffer, nCount, pRead ); + ( (SvStream*) GetStream() )->ResetError(); + return nErr; + } + else + { + const sal_Size nSeqLen = maSeq.getLength(); + ErrCode nErr = ERRCODE_NONE; + + if( nPos < nSeqLen ) + { + if( ( nPos + nCount ) > nSeqLen ) + nCount = nSeqLen - nPos; + + memcpy( pBuffer, maSeq.getConstArray() + nPos, nCount ); + *pRead = nCount; + } + else + *pRead = 0UL; + + return nErr; + } +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten ) +{ + if( GetStream() ) + return SvLockBytes::WriteAt( nPos, pBuffer, nCount, pWritten ); + else + { + DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::WriteAt: xInputStream has no reference..." ); + return ERRCODE_IO_CANTWRITE; + } +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::Flush() const +{ + return ERRCODE_NONE; +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::SetSize( sal_Size nSize ) +{ + if( GetStream() ) + return SvLockBytes::SetSize( nSize ); + else + { + DBG_ERROR( "ImgProdLockBytes::SetSize not supported for xInputStream..." ); + return ERRCODE_IO_CANTWRITE; + } +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag ) const +{ + if( GetStream() ) + return SvLockBytes::Stat( pStat, eFlag ); + else + { + DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::Stat: xInputStream has no reference..." ); + pStat->nSize = maSeq.getLength(); + return ERRCODE_NONE; + } +} + +// ----------------- +// - ImageProducer - +// ----------------- + +ImageProducer::ImageProducer() : + mpStm ( NULL ), + mpFilter ( NULL ), + mnStatus ( 0UL ), + mbConsInit ( sal_False ), + mnLastError ( 0UL ), + mbAsync ( sal_False ) +{ + mpGraphic = new Graphic; + DBG_ASSERT( Application::GetFilterHdl().IsSet(), "ImageProducer::ImageProducer(): No filter handler set" ); +} + +// ------------------------------------------------------------ + +ImageProducer::~ImageProducer() +{ + delete mpGraphic; + mpGraphic = NULL; + + delete mpFilter; + mpFilter = NULL; + + delete mpStm; + mpStm = NULL; + + for( void* pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; +} + +// ------------------------------------------------------------ + +// ::com::sun::star::uno::XInterface +::com::sun::star::uno::Any ImageProducer::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) +{ + ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType, + SAL_STATIC_CAST( ::com::sun::star::lang::XInitialization*, this ), + SAL_STATIC_CAST( ::com::sun::star::awt::XImageProducer*, this ) ); + return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType )); +} + +// ------------------------------------------------------------ + +void ImageProducer::addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException) +{ + DBG_ASSERT( rxConsumer.is(), "::AddConsumer(...): No consumer referenced!" ); + if( rxConsumer.is() ) + maConsList.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( rxConsumer ), LIST_APPEND ); +} + +// ------------------------------------------------------------ + +void ImageProducer::removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException) +{ + for( sal_uInt32 n = maConsList.Count(); n; ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > * pRef = (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) maConsList.GetObject( --n ); + + if( *pRef == rxConsumer ) + { + delete pRef; + maConsList.Remove( n ); + break; + } + } +} + +// ------------------------------------------------------------ + +void ImageProducer::SetImage( const ::rtl::OUString& rPath ) +{ + maURL = rPath; + mpGraphic->Clear(); + mbConsInit = sal_False; + mbAsync = sal_False; + delete mpStm; + + if ( ::svt::GraphicAccess::isSupportedURL( maURL ) ) + { + mpStm = ::svt::GraphicAccess::getImageStream( ::comphelper::getProcessServiceFactory(), maURL ); + } + else if( maURL.getLength() ) + { + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_STD_READ ); + mpStm = pIStm ? new SvStream( new ImgProdLockBytes( pIStm, sal_True ) ) : NULL; + } + else + mpStm = NULL; +} + +// ------------------------------------------------------------ + +void ImageProducer::SetImage( SvStream& rStm ) +{ + maURL = ::rtl::OUString(); + mpGraphic->Clear(); + mbConsInit = sal_False; + mbAsync = sal_False; + + delete mpStm; + mpStm = new SvStream( new ImgProdLockBytes( &rStm, sal_False ) ); +} + +// ------------------------------------------------------------ + +void ImageProducer::setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rInputStmRef ) +{ + maURL = ::rtl::OUString(); + mpGraphic->Clear(); + mbConsInit = sal_False; + mbAsync = sal_False; + delete mpStm; + + if( rInputStmRef.is() ) + mpStm = new SvStream( new ImgProdLockBytes( rInputStmRef ) ); + else + mpStm = NULL; +} + +// ------------------------------------------------------------ + +void ImageProducer::NewDataAvailable() +{ + if( ( GRAPHIC_NONE == mpGraphic->GetType() ) || mpGraphic->GetContext() ) + startProduction(); +} + +// ------------------------------------------------------------ + +void ImageProducer::startProduction() throw(::com::sun::star::uno::RuntimeException) +{ + ResetLastError(); + + if( maConsList.Count() ) + { + bool bNotifyEmptyGraphics = false; + + // valid stream or filled graphic? => update consumers + if( mpStm || ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + { + // if we already have a graphic, we don't have to import again; + // graphic is cleared if a new Stream is set + if( ( mpGraphic->GetType() == GRAPHIC_NONE ) || mpGraphic->GetContext() ) + { + if( !ImplImportGraphic( *mpGraphic ) && maErrorHdl.IsSet() ) + maErrorHdl.Call( this ); + } + + if( mpGraphic->GetType() != GRAPHIC_NONE ) + ImplUpdateData( *mpGraphic ); + else + bNotifyEmptyGraphics = true; + } + else + bNotifyEmptyGraphics = true; + + if ( bNotifyEmptyGraphics ) + { + // reset image + List aTmp; + void* pCons; + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + { + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->init( 0, 0 ); + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this ); + } + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + } + } +} + +// ------------------------------------------------------------ + +sal_Bool ImageProducer::ImplImportGraphic( Graphic& rGraphic ) +{ + USHORT nFilter = GRFILTER_FORMAT_DONTKNOW; + short nRet; + sal_Bool bRet = sal_False; + + if( ERRCODE_IO_PENDING == mpStm->GetError() ) + mpStm->ResetError(); + + mpStm->Seek( 0UL ); + + if( mpFilter ) + nRet = mpFilter->ImportGraphic( rGraphic, String(), *mpStm, nFilter ); + else + { + if( GraphicConverter::Import( *mpStm, rGraphic ) == ERRCODE_NONE ) + nRet = GRFILTER_OK; + else + nRet = GRFILTER_FILTERERROR; + } + + if( ERRCODE_IO_PENDING == mpStm->GetError() ) + mpStm->ResetError(); + + if( nRet == GRFILTER_OK ) + bRet = sal_True; + else + mnLastError = nRet; + + return bRet; +} + +// ------------------------------------------------------------ + +void ImageProducer::ImplUpdateData( const Graphic& rGraphic ) +{ + // asynchronous? + if( mpGraphic->GetContext() ) + mbAsync = sal_True; + + ImplInitConsumer( rGraphic ); + + if( mbConsInit && maConsList.Count() ) + { + List aTmp; + void* pCons; + + ImplUpdateConsumer( rGraphic ); + mbConsInit = sal_False; + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->complete( mnStatus = ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this ); + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + } +} + +// ------------------------------------------------------------ + +void ImageProducer::ImplInitConsumer( const Graphic& rGraphic ) +{ + Bitmap aBmp( rGraphic.GetBitmapEx().GetBitmap() ); + BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess(); + + if( pBmpAcc ) + { + List aTmp; + void * pCons; + sal_uInt16 nPalCount = 0; + sal_uInt32 nRMask = 0; + sal_uInt32 nGMask = 0; + sal_uInt32 nBMask = 0; + sal_uInt32 nAMask = 0; + ::com::sun::star::uno::Sequence< sal_Int32 > aRGBPal; + + if( pBmpAcc->HasPalette() ) + { + nPalCount = pBmpAcc->GetPaletteEntryCount(); + + if( nPalCount ) + { + aRGBPal = ::com::sun::star::uno::Sequence< sal_Int32 >( nPalCount + 1 ); + + sal_Int32* pTmp = aRGBPal.getArray(); + + for( sal_uInt32 i = 0; i < nPalCount; i++, pTmp++ ) + { + const BitmapColor& rCol = pBmpAcc->GetPaletteColor( (sal_uInt16) i ); + + *pTmp = ( (sal_Int32) rCol.GetRed() ) << (sal_Int32)(24L); + *pTmp |= ( (sal_Int32) rCol.GetGreen() ) << (sal_Int32)(16L); + *pTmp |= ( (sal_Int32) rCol.GetBlue() ) << (sal_Int32)(8L); + *pTmp |= (sal_Int32)(0x000000ffL); + } + + if( rGraphic.IsTransparent() ) + { + // append transparent entry + *pTmp = (sal_Int32)(0xffffff00L); + mnTransIndex = nPalCount; + nPalCount++; + } + else + mnTransIndex = 0; + + } + } + else + { + nRMask = 0xff000000UL; + nGMask = 0x00ff0000UL; + nBMask = 0x0000ff00UL; + nAMask = 0x000000ffUL; + } + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + { + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->init( pBmpAcc->Width(), pBmpAcc->Height() ); + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setColorModel( pBmpAcc->GetBitCount(), + aRGBPal, nRMask, nGMask, nBMask, nAMask ); + } + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + + aBmp.ReleaseAccess( pBmpAcc ); + mbConsInit = sal_True; + } +} + +// ------------------------------------------------------------ + +void ImageProducer::ImplUpdateConsumer( const Graphic& rGraphic ) +{ + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + Bitmap aBmp( aBmpEx.GetBitmap() ); + BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess(); + + if( pBmpAcc ) + { + List aTmp; + void* pCons; + Bitmap aMask( aBmpEx.GetMask() ); + BitmapReadAccess* pMskAcc = !!aMask ? aMask.AcquireReadAccess() : NULL; + const long nWidth = pBmpAcc->Width(); + const long nHeight = pBmpAcc->Height(); + const long nStartX = 0L; + const long nEndX = nWidth - 1L; + const long nStartY = 0L; + const long nEndY = nHeight - 1L; + const long nPartWidth = nEndX - nStartX + 1; + const long nPartHeight = nEndY - nStartY + 1; + + if( !pMskAcc ) + { + aMask = Bitmap( aBmp.GetSizePixel(), 1 ); + aMask.Erase( COL_BLACK ); + pMskAcc = aMask.AcquireReadAccess(); + } + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + if( pBmpAcc->HasPalette() ) + { + const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + + if( mnTransIndex < 256 ) + { + ::com::sun::star::uno::Sequence<sal_Int8> aData( nPartWidth * nPartHeight ); + sal_Int8* pTmp = aData.getArray(); + + for( long nY = nStartY; nY <= nEndY; nY++ ) + { + for( long nX = nStartX; nX <= nEndX; nX++ ) + { + if( pMskAcc->GetPixel( nY, nX ) == aWhite ) + *pTmp++ = sal::static_int_cast< sal_Int8 >( + mnTransIndex ); + else + *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex(); + } + } + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setPixelsByBytes( nStartX, nStartY, nPartWidth, nPartHeight, + aData, 0UL, nPartWidth ); + } + else + { + ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight ); + sal_Int32* pTmp = aData.getArray(); + + for( long nY = nStartY; nY <= nEndY; nY++ ) + { + for( long nX = nStartX; nX <= nEndX; nX++ ) + { + if( pMskAcc->GetPixel( nY, nX ) == aWhite ) + *pTmp++ = mnTransIndex; + else + *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex(); + } + } + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, + aData, 0UL, nPartWidth ); + } + } + else + { + ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight ); + const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + sal_Int32* pTmp = aData.getArray(); + + for( long nY = nStartY; nY <= nEndY; nY++ ) + { + for( long nX = nStartX; nX <= nEndX; nX++, pTmp++ ) + { + const BitmapColor aCol( pBmpAcc->GetPixel( nY, nX ) ); + + *pTmp = ( (sal_Int32) aCol.GetRed() ) << (sal_Int32)(24L); + *pTmp |= ( (sal_Int32) aCol.GetGreen() ) << (sal_Int32)(16L); + *pTmp |= ( (sal_Int32) aCol.GetBlue() ) << (sal_Int32)(8L); + + if( pMskAcc->GetPixel( nY, nX ) != aWhite ) + *pTmp |= 0x000000ffUL; + } + } + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, + aData, 0UL, nPartWidth ); + } + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + + aBmp.ReleaseAccess( pBmpAcc ); + aMask.ReleaseAccess( pMskAcc ); + } +} + +void ImageProducer::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + if ( aArguments.getLength() == 1 ) + { + ::com::sun::star::uno::Any aArg = aArguments.getConstArray()[0]; + rtl::OUString aURL; + if ( aArg >>= aURL ) + { + SetImage( aURL ); + } + } +} + +namespace frm +{ +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL ImageProducer_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ) +{ + return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >( + ( ::cppu::OWeakObject* ) new ImageProducer ); +} +} // namespace frm diff --git a/forms/source/component/imgprod.hxx b/forms/source/component/imgprod.hxx new file mode 100644 index 000000000000..0da5d04755df --- /dev/null +++ b/forms/source/component/imgprod.hxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PRODUCE_HXX +#define _PRODUCE_HXX + +#include <tools/link.hxx> +#include <tools/string.hxx> +#include <tools/list.hxx> +#include <com/sun/star/awt/ImageStatus.hpp> +#include <com/sun/star/awt/XImageConsumer.hpp> +#include <com/sun/star/awt/XImageProducer.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/weak.hxx> + + +// ----------------- +// - ImageProducer - +// ----------------- + + + +class SvStream; +class ImageConsumer; +class Graphic; +class GraphicFilter; + +namespace com { namespace sun { namespace star { namespace io { + class XInputStream; +}}}} + + +class ImageProducer : public ::com::sun::star::awt::XImageProducer, + public ::com::sun::star::lang::XInitialization, + public ::cppu::OWeakObject +{ +private: + + ::rtl::OUString maURL; + List maConsList; + Graphic* mpGraphic; + SvStream* mpStm; + GraphicFilter* mpFilter; + sal_uInt32 mnTransIndex; + sal_uInt32 mnStatus; + sal_Bool mbConsInit; + sal_Bool mbStmDel; + Link maErrorHdl; + sal_uInt32 mnLastError; + + sal_uInt32 mnExtra2; + + sal_Bool mbAsync; + sal_Bool mbExtra1; + sal_Bool mbExtra2; + sal_Bool mbExtra3; + + sal_Bool ImplImportGraphic( Graphic& rGraphic ); + void ImplUpdateData( const Graphic& rGraphic ); + void ImplInitConsumer( const Graphic& rGraphic ); + void ImplUpdateConsumer( const Graphic& rGraphic ); + +public: + + ImageProducer(); + ~ImageProducer(); + + void SetImage( const ::rtl::OUString& rPath ); + void SetImage( SvStream& rStm ); + + void SetErrorHandler( const Link& rErrorHdl ) { maErrorHdl = rErrorHdl; } + const Link& GetErrorHandler() const { return maErrorHdl; } + + sal_uInt32 GetLastError() const { return mnLastError; } + void ResetLastError() { mnLastError = 0; } + + void NewDataAvailable(); + + // ::com::sun::star::uno::XInterface + ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + void SAL_CALL release() throw() { OWeakObject::release(); } + + // MT: ??? + void setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ); + + // ::com::sun::star::awt::XImageProducer + void SAL_CALL addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL startProduction( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization + void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + +}; + +#endif // _PRODUCE_HXX diff --git a/forms/source/component/makefile.mk b/forms/source/component/makefile.mk new file mode 100644 index 000000000000..c3bfce4d3247 --- /dev/null +++ b/forms/source/component/makefile.mk @@ -0,0 +1,95 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=.. +PRJNAME=forms +TARGET=component + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Types ------------------------------------- + +INCPRE+=$(SOLARINCDIR)$/offuh + +# --- Files ------------------------------------- + +.IF "$(COM)"=="GCC" +NOOPTFILES= $(SLO)$/EventThread.obj +.ENDIF + +SLOFILES= $(SLO)$/Grid.obj \ + $(SLO)$/Columns.obj \ + $(SLO)$/DatabaseForm.obj \ + $(SLO)$/GroupManager.obj \ + $(SLO)$/FormsCollection.obj \ + $(SLO)$/EventThread.obj \ + $(SLO)$/File.obj \ + $(SLO)$/Edit.obj \ + $(SLO)$/EditBase.obj \ + $(SLO)$/Numeric.obj \ + $(SLO)$/Pattern.obj \ + $(SLO)$/Currency.obj \ + $(SLO)$/Date.obj \ + $(SLO)$/Time.obj \ + $(SLO)$/FormattedField.obj \ + $(SLO)$/FormattedFieldWrapper.obj \ + $(SLO)$/ListBox.obj \ + $(SLO)$/ComboBox.obj \ + $(SLO)$/GroupBox.obj \ + $(SLO)$/Hidden.obj \ + $(SLO)$/CheckBox.obj \ + $(SLO)$/RadioButton.obj \ + $(SLO)$/FixedText.obj \ + $(SLO)$/FormComponent.obj \ + $(SLO)$/clickableimage.obj \ + $(SLO)$/Button.obj \ + $(SLO)$/ImageButton.obj \ + $(SLO)$/ImageControl.obj \ + $(SLO)$/errorbroadcaster.obj \ + $(SLO)$/cloneable.obj \ + $(SLO)$/Filter.obj \ + $(SLO)$/entrylisthelper.obj \ + $(SLO)$/scrollbar.obj \ + $(SLO)$/spinbutton.obj \ + $(SLO)$/navigationbar.obj \ + $(SLO)$/formcontrolfont.obj \ + $(SLO)$/refvaluecomponent.obj \ + $(SLO)$/imgprod.obj \ + $(SLO)$/findpos.obj \ + $(SLO)$/propertybaghelper.obj \ + $(SLO)$/cachedrowset.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/component/navigationbar.cxx b/forms/source/component/navigationbar.cxx new file mode 100644 index 000000000000..617c830f104d --- /dev/null +++ b/forms/source/component/navigationbar.cxx @@ -0,0 +1,509 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "navigationbar.hxx" +#include "frm_module.hxx" + +#include <com/sun/star/text/WritingMode2.hpp> + +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ONavigationBarModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ONavigationBarModel > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::container; + using namespace ::comphelper; + + namespace WritingMode2 = ::com::sun::star::text::WritingMode2; + +#define REGISTER_VOID_PROP( prop, memberAny, type ) \ + registerMayBeVoidProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID, \ + &memberAny, ::getCppuType( static_cast< type* >( NULL ) ) ); + + //================================================================== + // ONavigationBarModel + //================================================================== + DBG_NAME( ONavigationBarModel ) + //------------------------------------------------------------------ + ONavigationBarModel::ONavigationBarModel( const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel( _rxFactory, ::rtl::OUString() ) + ,FontControlModel( true ) + { + DBG_CTOR( ONavigationBarModel, NULL ); + + m_nClassId = FormComponentType::NAVIGATIONBAR; + implInitPropertyContainer(); + + getPropertyDefaultByHandle( PROPERTY_ID_DEFAULTCONTROL ) >>= m_sDefaultControl; + getPropertyDefaultByHandle( PROPERTY_ID_ICONSIZE ) >>= m_nIconSize; + getPropertyDefaultByHandle( PROPERTY_ID_BORDER ) >>= m_nBorder; + getPropertyDefaultByHandle( PROPERTY_ID_DELAY ) >>= m_nDelay; + getPropertyDefaultByHandle( PROPERTY_ID_ENABLED ) >>= m_bEnabled; + getPropertyDefaultByHandle( PROPERTY_ID_ENABLEVISIBLE ) >>= m_bEnableVisible; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_POSITION ) >>= m_bShowPosition; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_NAVIGATION ) >>= m_bShowNavigation; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_RECORDACTIONS ) >>= m_bShowActions; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_FILTERSORT ) >>= m_bShowFilterSort; + getPropertyDefaultByHandle( PROPERTY_ID_WRITING_MODE ) >>= m_nWritingMode; + getPropertyDefaultByHandle( PROPERTY_ID_CONTEXT_WRITING_MODE ) >>= m_nContextWritingMode; + } + + //------------------------------------------------------------------ + ONavigationBarModel::ONavigationBarModel( const ONavigationBarModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,FontControlModel( _pOriginal ) + { + DBG_CTOR( ONavigationBarModel, NULL ); + + implInitPropertyContainer(); + + m_aTabStop = _pOriginal->m_aTabStop; + m_aBackgroundColor = _pOriginal->m_aBackgroundColor; + m_sDefaultControl = _pOriginal->m_sDefaultControl; + m_sHelpText = _pOriginal->m_sHelpText; + m_sHelpURL = _pOriginal->m_sHelpURL; + m_bEnabled = _pOriginal->m_bEnabled; + m_bEnableVisible = _pOriginal->m_bEnableVisible; + m_nIconSize = _pOriginal->m_nIconSize; + m_nBorder = _pOriginal->m_nBorder; + m_nDelay = _pOriginal->m_nDelay; + m_bShowPosition = _pOriginal->m_bShowPosition; + m_bShowNavigation = _pOriginal->m_bShowNavigation; + m_bShowActions = _pOriginal->m_bShowActions; + m_bShowFilterSort = _pOriginal->m_bShowFilterSort; + m_nWritingMode = _pOriginal->m_nWritingMode; + m_nContextWritingMode = _pOriginal->m_nContextWritingMode; + } + + //------------------------------------------------------------------ + void ONavigationBarModel::implInitPropertyContainer() + { + REGISTER_PROP_2( DEFAULTCONTROL, m_sDefaultControl, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HELPTEXT, m_sHelpText, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HELPURL, m_sHelpURL, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ENABLED, m_bEnabled, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ENABLEVISIBLE, m_bEnableVisible, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ICONSIZE, m_nIconSize, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( BORDER, m_nBorder, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( DELAY, m_nDelay, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_POSITION, m_bShowPosition, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_NAVIGATION, m_bShowNavigation, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_RECORDACTIONS, m_bShowActions, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_FILTERSORT, m_bShowFilterSort, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( WRITING_MODE, m_nWritingMode, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_3( CONTEXT_WRITING_MODE,m_nContextWritingMode, BOUND, MAYBEDEFAULT, TRANSIENT ); + + REGISTER_VOID_PROP( TABSTOP, m_aTabStop, sal_Bool ); + REGISTER_VOID_PROP( BACKGROUNDCOLOR, m_aBackgroundColor, sal_Int32 ); + } + + //------------------------------------------------------------------ + ONavigationBarModel::~ONavigationBarModel() + { + if ( !OComponentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + DBG_DTOR( ONavigationBarModel, NULL ); + } + + //------------------------------------------------------------------ + Any SAL_CALL ONavigationBarModel::queryAggregation( const Type& _rType ) throw ( RuntimeException ) + { + Any aReturn = ONavigationBarModel_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OControlModel::queryAggregation( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ONavigationBarModel, OControlModel, ONavigationBarModel_BASE ) + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( ONavigationBarModel ) + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarModel::getImplementationName() throw(RuntimeException) + { + return getImplementationName_Static(); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ONavigationBarModel::getSupportedServiceNames() throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarModel::getImplementationName_Static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.form.ONavigationBarModel" ) ); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ONavigationBarModel::getSupportedServiceNames_Static() + { + Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames_Static(); + aSupported.realloc( aSupported.getLength() + 2 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 2 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlModel" ) ); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_NAVTOOLBAR; + return aSupported; + } + + //------------------------------------------------------------------ + Reference< XInterface > SAL_CALL ONavigationBarModel::Create( const Reference< XMultiServiceFactory >& _rxFactory ) + { + return *( new ONavigationBarModel( _rxFactory ) ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::disposing() + { + OControlModel::disposing( ); + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarModel::getServiceName() throw ( RuntimeException ) + { + return FRM_SUN_COMPONENT_NAVTOOLBAR; + } + + //------------------------------------------------------------------ + #define PERSIST_TABSTOP 0x0001 + #define PERSIST_BACKGROUND 0x0002 + #define PERSIST_TEXTCOLOR 0x0004 + #define PERSIST_TEXTLINECOLOR 0x0008 + + #define PERSIST_ENABLED 0x0001 + #define PERSIST_LARGEICONS 0x0002 + // leaf a leap here - this will allow for two more icon size values to be stored compatibly + #define PERSIST_SHOW_POSITION 0x0008 + #define PERSIST_SHOW_NAVIGATION 0x0010 + #define PERSIST_SHOW_ACTIONS 0x0020 + #define PERSIST_SHOW_FILTERSORT 0x0040 + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::write( const Reference< XObjectOutputStream >& _rxOutStream ) throw ( IOException, RuntimeException ) + { + // open a section for compatibility - if we later on write additional members, + // then older versions can skip them + Reference< XDataOutputStream > xDataOut( _rxOutStream, UNO_QUERY ); + OStreamSection aEnsureBlockCompat( xDataOut ); + + // base class + OControlModel::write( _rxOutStream ); + + { + OStreamSection aEnsureCompat( xDataOut ); + // determine which properties are not void and need to be written + sal_Int32 nNonVoids = 0; + if ( m_aTabStop.hasValue() ) + nNonVoids |= PERSIST_TABSTOP; + if ( m_aBackgroundColor.hasValue() ) + nNonVoids |= PERSIST_BACKGROUND; + if ( hasTextColor() ) + nNonVoids |= PERSIST_TEXTCOLOR; + if ( hasTextLineColor() ) + nNonVoids |= PERSIST_TEXTLINECOLOR; + + _rxOutStream->writeLong( nNonVoids ); + + // the maybeboid anys + if ( nNonVoids & PERSIST_TABSTOP ) + { + sal_Bool bTabStop( sal_False ); + m_aTabStop >>= bTabStop; + _rxOutStream->writeBoolean( bTabStop ); + } + if ( nNonVoids & PERSIST_BACKGROUND ) + { + sal_Int32 nBackgroundColor = 0; + m_aBackgroundColor >>= nBackgroundColor; + _rxOutStream->writeLong( nBackgroundColor ); + } + if ( nNonVoids & PERSIST_TEXTCOLOR ) + { + _rxOutStream->writeLong( getTextColor() ); + } + if ( nNonVoids & PERSIST_TEXTLINECOLOR ) + { + _rxOutStream->writeLong( getTextLineColor() ); + } + } + + { + OStreamSection aEnsureCompat( xDataOut ); + ::comphelper::operator<<( _rxOutStream, getFont() ); + } + + // our boolean flags + sal_Int32 nFlags = 0; + if ( m_bEnabled ) nFlags |= PERSIST_ENABLED; + if ( m_nIconSize ) nFlags |= PERSIST_LARGEICONS; // at the moment, this is quasi boolean + if ( m_bShowPosition ) nFlags |= PERSIST_SHOW_POSITION; + if ( m_bShowNavigation ) nFlags |= PERSIST_SHOW_NAVIGATION; + if ( m_bShowActions ) nFlags |= PERSIST_SHOW_ACTIONS; + if ( m_bShowFilterSort ) nFlags |= PERSIST_SHOW_FILTERSORT; + _rxOutStream->writeLong( nFlags ); + + // our strings + _rxOutStream->writeUTF( m_sHelpText ); + _rxOutStream->writeUTF( m_sHelpURL ); + _rxOutStream->writeUTF( m_sDefaultControl ); + + // misc + _rxOutStream->writeShort( m_nBorder ); + _rxOutStream->writeLong ( m_nDelay ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::read( const Reference< XObjectInputStream >& _rxInStream ) throw ( IOException, RuntimeException ) + { + Reference< XDataInputStream > xDataIn( _rxInStream, UNO_QUERY ); + OStreamSection aEnsureBlockCompat( xDataIn ); + + // base class + OControlModel::read( _rxInStream ); + + { + OStreamSection aEnsureCompat( xDataIn ); + // determine which properties were non-void + sal_Int32 nNonVoids = _rxInStream->readLong( ); + + // the maybeboid anys + if ( nNonVoids & PERSIST_TABSTOP ) + m_aTabStop = makeAny( _rxInStream->readBoolean() ); + else + m_aTabStop.clear(); + + if ( nNonVoids & PERSIST_BACKGROUND ) + m_aBackgroundColor = makeAny( _rxInStream->readLong() ); + else + m_aBackgroundColor.clear(); + + if ( nNonVoids & PERSIST_TEXTCOLOR ) + setTextColor( _rxInStream->readLong() ); + else + clearTextColor(); + + if ( nNonVoids & PERSIST_TEXTLINECOLOR ) + setTextLineColor( _rxInStream->readLong() ); + else + clearTextLineColor(); + } + + { + OStreamSection aEnsureCompat( xDataIn ); + FontDescriptor aFont; + ::comphelper::operator>>( _rxInStream, aFont ); + setFont( aFont ); + } + + // our boolean flags + sal_Int32 nFlags = _rxInStream->readLong( ); + m_bEnabled = ( nFlags & PERSIST_ENABLED ) ? sal_True : sal_False; + m_nIconSize = ( nFlags & PERSIST_LARGEICONS ) ? 1 : 0; + m_bShowPosition = ( nFlags & PERSIST_SHOW_POSITION ) ? sal_True : sal_False; + m_bShowNavigation = ( nFlags & PERSIST_SHOW_NAVIGATION ) ? sal_True : sal_False; + m_bShowActions = ( nFlags & PERSIST_SHOW_ACTIONS ) ? sal_True : sal_False; + m_bShowFilterSort = ( nFlags & PERSIST_SHOW_FILTERSORT ) ? sal_True : sal_False; + + // our strings + m_sHelpText = _rxInStream->readUTF( ); + m_sHelpURL = _rxInStream->readUTF( ); + m_sDefaultControl = _rxInStream->readUTF( ); + + // misc + m_nBorder = _rxInStream->readShort(); + m_nDelay = _rxInStream->readLong(); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + if ( isRegisteredProperty( _nHandle ) ) + { + OPropertyContainerHelper::getFastPropertyValue( _rValue, _nHandle ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + FontControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + else + { + OControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //------------------------------------------------------------------ + sal_Bool SAL_CALL ONavigationBarModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw( IllegalArgumentException ) + { + sal_Bool bModified = sal_False; + + if ( isRegisteredProperty( _nHandle ) ) + { + bModified = OPropertyContainerHelper::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + bModified = FontControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + else + { + bModified = OControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + + return bModified; + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + if ( isRegisteredProperty( _nHandle ) ) + { + OPropertyContainerHelper::setFastPropertyValue( _nHandle, _rValue ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + FontDescriptor aOldFont( getFont() ); + + FontControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + + if ( isFontAggregateProperty( _nHandle ) ) + firePropertyChange( PROPERTY_ID_FONT, makeAny( getFont() ), makeAny( aOldFont ) ); + } + else + { + OControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //------------------------------------------------------------------ + Any ONavigationBarModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aDefault; + + switch ( _nHandle ) + { + case PROPERTY_ID_TABSTOP: + case PROPERTY_ID_BACKGROUNDCOLOR: + /* void */ + break; + case PROPERTY_ID_WRITING_MODE: + case PROPERTY_ID_CONTEXT_WRITING_MODE: + aDefault <<= WritingMode2::CONTEXT; + break; + + case PROPERTY_ID_ENABLED: + case PROPERTY_ID_ENABLEVISIBLE: + case PROPERTY_ID_SHOW_POSITION: + case PROPERTY_ID_SHOW_NAVIGATION: + case PROPERTY_ID_SHOW_RECORDACTIONS: + case PROPERTY_ID_SHOW_FILTERSORT: + aDefault <<= (sal_Bool)sal_True; + break; + + case PROPERTY_ID_ICONSIZE: + aDefault <<= (sal_Int16)0; + break; + + case PROPERTY_ID_DEFAULTCONTROL: + aDefault <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.NavigationToolBar" ) ); + break; + + case PROPERTY_ID_HELPTEXT: + case PROPERTY_ID_HELPURL: + aDefault <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_BORDER: + aDefault <<= (sal_Int16)0; + break; + + case PROPERTY_ID_DELAY: + aDefault <<= (sal_Int32)20; + break; + + default: + if ( isFontRelatedProperty( _nHandle ) ) + aDefault = FontControlModel::getPropertyDefaultByHandle( _nHandle ); + else + aDefault = OControlModel::getPropertyDefaultByHandle( _nHandle ); + } + return aDefault; + } + + //------------------------------------------------------------------ + void ONavigationBarModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 1, OControlModel ) + DECL_PROP2( TABINDEX, sal_Int16, BOUND, MAYBEDEFAULT ); + END_DESCRIBE_PROPERTIES(); + + // properties which the OPropertyContainerHelper is responsible for + Sequence< Property > aContainedProperties; + describeProperties( aContainedProperties ); + + // properties which the FontControlModel is responsible for + Sequence< Property > aFontProperties; + describeFontRelatedProperties( aFontProperties ); + + _rProps = concatSequences( + aContainedProperties, + aFontProperties, + _rProps + ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/navigationbar.hxx b/forms/source/component/navigationbar.hxx new file mode 100644 index 000000000000..d57c6d1542ac --- /dev/null +++ b/forms/source/component/navigationbar.hxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_COMPONENT_NAVIGATION_BAR_HXX +#define FORMS_COMPONENT_NAVIGATION_BAR_HXX + +#include "FormComponent.hxx" +#include <com/sun/star/io/XPersistObject.hpp> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainerhelper.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include "formcontrolfont.hxx" + +#include <set> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //================================================================== + // ONavigationBarModel + //================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::awt::XControlModel + > ONavigationBarModel_BASE; + + class ONavigationBarModel + :public OControlModel + ,public FontControlModel + ,public OPropertyContainerHelper + ,public ONavigationBarModel_BASE + { + // <properties> + ::com::sun::star::uno::Any m_aTabStop; + ::com::sun::star::uno::Any m_aBackgroundColor; + ::rtl::OUString m_sDefaultControl; + ::rtl::OUString m_sHelpText; + ::rtl::OUString m_sHelpURL; + sal_Int16 m_nIconSize; + sal_Int16 m_nBorder; + sal_Int32 m_nDelay; + sal_Bool m_bEnabled; + sal_Bool m_bEnableVisible; + sal_Bool m_bShowPosition; + sal_Bool m_bShowNavigation; + sal_Bool m_bShowActions; + sal_Bool m_bShowFilterSort; + sal_Int16 m_nWritingMode; + sal_Int16 m_nContextWritingMode; + // </properties> + + public: + DECLARE_DEFAULT_LEAF_XTOR( ONavigationBarModel ); + + // XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + // UNO + DECLARE_UNO3_AGG_DEFAULTS( ONavigationBarModel, OControlModel ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + + protected: + DECLARE_XCLONEABLE(); + + private: + void implInitPropertyContainer(); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_COMPONENT_NAVIGATION_BAR_HXX + diff --git a/forms/source/component/propertybaghelper.cxx b/forms/source/component/propertybaghelper.cxx new file mode 100644 index 000000000000..0b049043cb28 --- /dev/null +++ b/forms/source/component/propertybaghelper.cxx @@ -0,0 +1,369 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "propertybaghelper.hxx" + +#include "property.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/PropertyExistException.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/NotRemoveableException.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +#include <comphelper/sequence.hxx> +#include <rtl/logfile.hxx> +#include "rtl/instance.hxx" + + +#define NEW_HANDLE_BASE 10000 + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::beans::Property; + using ::com::sun::star::uno::Any; + using ::com::sun::star::beans::PropertyExistException; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::beans::XMultiPropertySet; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::beans::NotRemoveableException; + using ::com::sun::star::beans::UnknownPropertyException; + /** === end UNO using === **/ + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + + //==================================================================== + //= helper + //==================================================================== + namespace + { + //---------------------------------------------------------------- + static ::comphelper::IPropertyInfoService& lcl_getPropertyInfos() + { + static ConcreteInfoService s_aPropInfos; + return s_aPropInfos; + } + } + + //==================================================================== + //= PropertyBagHelper + //==================================================================== + //-------------------------------------------------------------------- + PropertyBagHelper::PropertyBagHelper( IPropertyBagHelperContext& _rContext ) + :m_rContext( _rContext ) + ,m_pPropertyArrayHelper( NULL ) + ,m_bDisposed( false ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::PropertyBagHelper" ); + } + + //-------------------------------------------------------------------- + PropertyBagHelper::~PropertyBagHelper() + { + delete m_pPropertyArrayHelper, m_pPropertyArrayHelper = NULL; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::dispose() + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::dispose" ); + m_bDisposed = true; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::impl_nts_checkDisposed_throw() const + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_nts_checkDisposed_throw" ); + if ( m_bDisposed ) + throw DisposedException(); + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::impl_nts_invalidatePropertySetInfo() + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_nts_invalidatePropertySetInfo" ); + delete m_pPropertyArrayHelper, m_pPropertyArrayHelper = NULL; + } + + //-------------------------------------------------------------------- + sal_Int32 PropertyBagHelper::impl_findFreeHandle( const ::rtl::OUString& _rPropertyName ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_findFreeHandle" ); + ::comphelper::OPropertyArrayAggregationHelper& rPropInfo( impl_ts_getArrayHelper() ); + + // check the preferred handle + sal_Int32 nHandle = lcl_getPropertyInfos().getPreferedPropertyId( _rPropertyName ); + if ( ( nHandle != -1 ) && rPropInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) ) + nHandle = -1; + + // seach a free handle in <math>F_1009</math> + if ( nHandle == -1 ) + { + sal_Int32 nPrime = 1009; + sal_Int32 nFactor = 11; + sal_Int32 nNum = nFactor; + while ( nNum != 1 ) + { + if ( !rPropInfo.fillPropertyMembersByHandle( NULL, NULL, nNum + NEW_HANDLE_BASE ) ) + { + // handle not used, yet + nHandle = nNum + NEW_HANDLE_BASE; + break; + } + nNum = ( nNum * nFactor ) % nPrime; + } + } + + // search a free handle greater NEW_HANDLE_BASE + if ( nHandle == -1 ) + { + nHandle = NEW_HANDLE_BASE + 1009; + while ( rPropInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) ) + ++nHandle; + } + + return nHandle; + } + + //-------------------------------------------------------------------- + ::comphelper::OPropertyArrayAggregationHelper& PropertyBagHelper::impl_ts_getArrayHelper() const + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_ts_getArrayHelper" ); + //::osl::MutexGuard aGuard( m_rContext.getMutex() ); + OPropertyArrayAggregationHelper* p = m_pPropertyArrayHelper; + if ( !p ) + { + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + p = m_pPropertyArrayHelper; + if ( !p ) + { + // our own fixed and our aggregate's properties + Sequence< Property > aFixedProps; + Sequence< Property > aAggregateProps; + m_rContext.describeFixedAndAggregateProperties( aFixedProps, aAggregateProps ); + + // our dynamic properties + Sequence< Property > aDynamicProps; + m_aDynamicProperties.describeProperties( aDynamicProps ); + + Sequence< Property > aOwnProps( + ::comphelper::concatSequences( aFixedProps, aDynamicProps ) ); + + p = new OPropertyArrayAggregationHelper( aOwnProps, aAggregateProps, &lcl_getPropertyInfos(), NEW_HANDLE_BASE ); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + const_cast< PropertyBagHelper* >( this )->m_pPropertyArrayHelper = p; + } + } // if ( !p ) + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return *p; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::addProperty" ); + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + //---------------------------------------------- + // check name sanity + ::comphelper::OPropertyArrayAggregationHelper& aPropInfo( impl_ts_getArrayHelper() ); + if ( aPropInfo.hasPropertyByName( _rName ) ) + throw PropertyExistException( _rName, m_rContext.getPropertiesInterface() ); + + //---------------------------------------------- + // normalize the REMOVEABLE attribute - the FormComponent service + // requires that all dynamic properties are REMOVEABLE + _nAttributes |= PropertyAttribute::REMOVEABLE; + + //---------------------------------------------- + // find a free handle + sal_Int32 nHandle = impl_findFreeHandle( _rName ); + + //---------------------------------------------- + // register the property, and invalidate our property meta data + m_aDynamicProperties.addProperty( _rName, nHandle, _nAttributes, _rInitialValue ); + impl_nts_invalidatePropertySetInfo(); + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::removeProperty( const ::rtl::OUString& _rName ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::removeProperty" ); + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + // check whether it's removeable at all + Reference< XMultiPropertySet > xMe( m_rContext.getPropertiesInterface(), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xPSI( xMe->getPropertySetInfo(), UNO_QUERY_THROW ); + Property aProperty( xPSI->getPropertyByName( _rName ) ); + if ( ( aProperty.Attributes & PropertyAttribute::REMOVEABLE ) == 0 ) + throw NotRemoveableException( _rName, xMe ); + + m_aDynamicProperties.removeProperty( _rName ); + impl_nts_invalidatePropertySetInfo(); + } + + //-------------------------------------------------------------------- + namespace + { + //---------------------------------------------------------------- + struct SelectNameOfProperty : public ::std::unary_function< Property, ::rtl::OUString > + { + const ::rtl::OUString& operator()( const Property& _rProp ) const { return _rProp.Name; } + }; + + //---------------------------------------------------------------- + struct SelectNameOfPropertyValue : public ::std::unary_function< PropertyValue, ::rtl::OUString > + { + const ::rtl::OUString& operator()( const PropertyValue& _rProp ) const { return _rProp.Name; } + }; + + //---------------------------------------------------------------- + struct SelectValueOfPropertyValue : public ::std::unary_function< PropertyValue, Any > + { + const Any& operator()( const PropertyValue& _rProp ) const { return _rProp.Value; } + }; + + //---------------------------------------------------------------- + struct PropertyValueLessByName : public ::std::binary_function< PropertyValue, PropertyValue, bool > + { + bool operator()( const PropertyValue& _lhs, const PropertyValue _rhs ) const + { + return _lhs.Name < _rhs.Name; + } + }; + } + + //-------------------------------------------------------------------- + Sequence< PropertyValue > PropertyBagHelper::getPropertyValues() + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::getPropertyValues" ); + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + Reference< XMultiPropertySet > xMe( m_rContext.getPropertiesInterface(), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xPSI( xMe->getPropertySetInfo(), UNO_QUERY_THROW ); + + Sequence< Property > aProperties( xPSI->getProperties() ); + Sequence< ::rtl::OUString > aPropertyNames( aProperties.getLength() ); + ::std::transform( aProperties.getConstArray(), aProperties.getConstArray() + aProperties.getLength(), + aPropertyNames.getArray(), SelectNameOfProperty() ); + + Sequence< Any > aValues; + try + { + aValues = xMe->getPropertyValues( aPropertyNames ); + + if ( aValues.getLength() != aPropertyNames.getLength() ) + throw RuntimeException(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + Sequence< PropertyValue > aPropertyValues( aValues.getLength() ); + PropertyValue* pPropertyValue = aPropertyValues.getArray(); + + const ::rtl::OUString* pName = aPropertyNames.getConstArray(); + const ::rtl::OUString* pNameEnd = aPropertyNames.getConstArray() + aPropertyNames.getLength(); + const Any* pValue = aValues.getConstArray(); + for ( ; pName != pNameEnd; ++pName, ++pValue, ++pPropertyValue ) + { + pPropertyValue->Name = *pName; + pPropertyValue->Value = *pValue; + } + + return aPropertyValues; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::setPropertyValues( const Sequence< PropertyValue >& _rProps ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::setPropertyValues" ); + ::osl::ClearableMutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + sal_Int32 nPropertyValues = _rProps.getLength(); + + // XMultiPropertySet::setPropertyValues expects its arguments to be sorted by name + // while XPropertyAccess::setPropertyValues doesn't. So first of all, sort. + Sequence< PropertyValue > aSortedProps( _rProps ); + ::std::sort( aSortedProps.getArray(), aSortedProps.getArray() + nPropertyValues, PropertyValueLessByName() ); + + // also, XPropertyAccess::setPropertyValues is expected to throw an UnknownPropertyException + // for unsupported properties, while XMultiPropertySet::setPropertyValues is expected to ignore + // those. So, check for unsupported properties first. + ::comphelper::OPropertyArrayAggregationHelper& rArrayHelper( impl_ts_getArrayHelper() ); + for ( const PropertyValue* pProperties = aSortedProps.getConstArray(); + pProperties != aSortedProps.getConstArray() + nPropertyValues; + ++pProperties + ) + { + if ( !rArrayHelper.hasPropertyByName( pProperties->Name ) ) + throw UnknownPropertyException( pProperties->Name, m_rContext.getPropertiesInterface() ); + } + + // Now finally split into a Name and a Value sequence, and forward to + // XMultiPropertySet::setPropertyValues + Sequence< ::rtl::OUString > aNames( nPropertyValues ); + ::std::transform( aSortedProps.getConstArray(), aSortedProps.getConstArray() + nPropertyValues, + aNames.getArray(), SelectNameOfPropertyValue() ); + + Sequence< Any > aValues( nPropertyValues ); + ::std::transform( aSortedProps.getConstArray(), aSortedProps.getConstArray() + nPropertyValues, + aValues.getArray(), SelectValueOfPropertyValue() ); + + Reference< XMultiPropertySet > xMe( m_rContext.getPropertiesInterface(), UNO_QUERY_THROW ); + + aGuard.clear(); + xMe->setPropertyValues( aNames, aValues ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/component/refvaluecomponent.cxx b/forms/source/component/refvaluecomponent.cxx new file mode 100644 index 000000000000..3061a275378b --- /dev/null +++ b/forms/source/component/refvaluecomponent.cxx @@ -0,0 +1,301 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "refvaluecomponent.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +#include <list> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form::binding; + + //==================================================================== + //= + //==================================================================== + //-------------------------------------------------------------------- + OReferenceValueComponent::OReferenceValueComponent( const Reference< XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault, sal_Bool _bSupportNoCheckRefValue ) + :OBoundControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False, sal_True, sal_True ) + ,m_eDefaultChecked( STATE_NOCHECK ) + ,m_bSupportSecondRefValue( _bSupportNoCheckRefValue ) + { + } + + //-------------------------------------------------------------------- + OReferenceValueComponent::OReferenceValueComponent( const OReferenceValueComponent* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + { + m_sReferenceValue = _pOriginal->m_sReferenceValue; + m_sNoCheckReferenceValue = _pOriginal->m_sNoCheckReferenceValue; + m_eDefaultChecked = _pOriginal->m_eDefaultChecked; + m_bSupportSecondRefValue = _pOriginal->m_bSupportSecondRefValue; + + calculateExternalValueType(); + } + + //-------------------------------------------------------------------- + OReferenceValueComponent::~OReferenceValueComponent() + { + } + + //-------------------------------------------------------------------- + void OReferenceValueComponent::setReferenceValue( const ::rtl::OUString& _rRefValue ) + { + m_sReferenceValue = _rRefValue; + calculateExternalValueType(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OReferenceValueComponent::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch ( _nHandle ) + { + case PROPERTY_ID_REFVALUE: _rValue <<= m_sReferenceValue; break; + case PROPERTY_ID_DEFAULT_STATE: _rValue <<= (sal_Int16)m_eDefaultChecked; break; + + case PROPERTY_ID_UNCHECKED_REFVALUE: + OSL_ENSURE( m_bSupportSecondRefValue, "OReferenceValueComponent::getFastPropertyValue: not supported!" ); + _rValue <<= m_sNoCheckReferenceValue; + break; + + default: + OBoundControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OReferenceValueComponent::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) + { + switch ( _nHandle ) + { + case PROPERTY_ID_REFVALUE : + OSL_VERIFY( _rValue >>= m_sReferenceValue ); + calculateExternalValueType(); + break; + + case PROPERTY_ID_UNCHECKED_REFVALUE: + OSL_ENSURE( m_bSupportSecondRefValue, "OReferenceValueComponent::setFastPropertyValue_NoBroadcast: not supported!" ); + OSL_VERIFY( _rValue >>= m_sNoCheckReferenceValue ); + break; + + case PROPERTY_ID_DEFAULT_STATE: + { + sal_Int16 nDefaultChecked( (sal_Int16)STATE_NOCHECK ); + OSL_VERIFY( _rValue >>= nDefaultChecked ); + m_eDefaultChecked = (ToggleState)nDefaultChecked; + resetNoBroadcast(); + } + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OReferenceValueComponent::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException) + { + sal_Bool bModified = sal_False; + switch ( _nHandle ) + { + case PROPERTY_ID_REFVALUE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_sReferenceValue ); + break; + + case PROPERTY_ID_UNCHECKED_REFVALUE: + OSL_ENSURE( m_bSupportSecondRefValue, "OReferenceValueComponent::convertFastPropertyValue: not supported!" ); + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_sNoCheckReferenceValue ); + break; + + case PROPERTY_ID_DEFAULT_STATE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_eDefaultChecked ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; + } + + //------------------------------------------------------------------------------ + Any OReferenceValueComponent::getDefaultForReset() const + { + return makeAny( (sal_Int16)m_eDefaultChecked ); + } + + //-------------------------------------------------------------------- + void OReferenceValueComponent::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( m_bSupportSecondRefValue ? 3 : 2, OBoundControlModel ) + DECL_PROP1( REFVALUE, ::rtl::OUString, BOUND ); + DECL_PROP1( DEFAULT_STATE, sal_Int16, BOUND ); + if ( m_bSupportSecondRefValue ) + { + DECL_PROP1( UNCHECKED_REFVALUE, ::rtl::OUString, BOUND ); + } + END_DESCRIBE_PROPERTIES(); + } + + //----------------------------------------------------------------------------- + Sequence< Type > OReferenceValueComponent::getSupportedBindingTypes() + { + ::std::list< Type > aTypes; + aTypes.push_back( ::getCppuType( static_cast< sal_Bool* >( NULL ) ) ); + + if ( m_sReferenceValue.getLength() ) + aTypes.push_front( ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ) ); + // push_front, because this is the preferred type + + Sequence< Type > aTypesRet( aTypes.size() ); + ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() ); + return aTypesRet; + } + + //----------------------------------------------------------------------------- + Any OReferenceValueComponent::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + sal_Int16 nState = STATE_DONTKNOW; + + sal_Bool bExternalState = sal_False; + ::rtl::OUString sExternalValue; + if ( _rExternalValue >>= bExternalState ) + { + nState = ::sal::static_int_cast< sal_Int16 >( bExternalState ? STATE_CHECK : STATE_NOCHECK ); + } + else if ( _rExternalValue >>= sExternalValue ) + { + if ( sExternalValue == m_sReferenceValue ) + nState = STATE_CHECK; + else + { + if ( !m_bSupportSecondRefValue || ( sExternalValue == m_sNoCheckReferenceValue ) ) + nState = STATE_NOCHECK; + else + nState = STATE_DONTKNOW; + } + } + else if ( !_rExternalValue.hasValue() ) + { + nState = STATE_DONTKNOW; + } + else + { + OSL_ENSURE( false, "OReferenceValueComponent::translateExternalValueToControlValue: unexpected value type!" ); + } + + return makeAny( nState ); + } + + //----------------------------------------------------------------------------- + Any OReferenceValueComponent::translateControlValueToExternalValue( ) const + { + Any aExternalValue; + + try + { + Any aControlValue( m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) ); + sal_Int16 nControlValue = STATE_DONTKNOW; + aControlValue >>= nControlValue; + + bool bBooleanExchange = getExternalValueType().getTypeClass() == TypeClass_BOOLEAN; + bool bStringExchange = getExternalValueType().getTypeClass() == TypeClass_STRING; + OSL_ENSURE( bBooleanExchange || bStringExchange, + "OReferenceValueComponent::translateControlValueToExternalValue: unexpected value exchange type!" ); + + switch( nControlValue ) + { + case STATE_CHECK: + if ( bBooleanExchange ) + { + aExternalValue <<= (sal_Bool)sal_True; + } + else if ( bStringExchange ) + { + aExternalValue <<= m_sReferenceValue; + } + break; + + case STATE_NOCHECK: + if ( bBooleanExchange ) + { + aExternalValue <<= (sal_Bool)sal_False; + } + else if ( bStringExchange ) + { + aExternalValue <<= m_bSupportSecondRefValue ? m_sNoCheckReferenceValue : ::rtl::OUString(); + } + break; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OReferenceValueComponent::translateControlValueToExternalValue: caught an exception!" ); + } + + return aExternalValue; + } + + //----------------------------------------------------------------------------- + Any OReferenceValueComponent::translateControlValueToValidatableValue( ) const + { + if ( !m_xAggregateSet.is() ) + return Any(); + + Any aControlValue( m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) ); + sal_Int16 nControlValue = STATE_DONTKNOW; + aControlValue >>= nControlValue; + + Any aValidatableValue; + switch ( nControlValue ) + { + case STATE_CHECK: + aValidatableValue <<= (sal_Bool)sal_True; + break; + case STATE_NOCHECK: + aValidatableValue <<= (sal_Bool)sal_False; + break; + } + return aValidatableValue; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/component/refvaluecomponent.hxx b/forms/source/component/refvaluecomponent.hxx new file mode 100644 index 000000000000..dedc86c315be --- /dev/null +++ b/forms/source/component/refvaluecomponent.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_COMPONENT_REFVALUECOMPONENT_HXX +#define FORMS_SOURCE_COMPONENT_REFVALUECOMPONENT_HXX + +#include "FormComponent.hxx" +#include "togglestate.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OReferenceValueComponent + //==================================================================== + /** a OBoundControlModel which features the exchange of a reference value + */ + class OReferenceValueComponent : public OBoundControlModel + { + private: + // <properties> + ::rtl::OUString m_sReferenceValue; // the reference value to use for data exchange + ::rtl::OUString m_sNoCheckReferenceValue; // the reference value to be exchanged when the control is not checked + ToggleState m_eDefaultChecked; // the default check state + // </properties> + + sal_Bool m_bSupportSecondRefValue; // do we support the SecondaryRefValue property? + + protected: + const ::rtl::OUString& getReferenceValue() const { return m_sReferenceValue; } + void setReferenceValue( const ::rtl::OUString& _rRefValue ); + + const ::rtl::OUString& getNoCheckReferenceValue() const { return m_sNoCheckReferenceValue; } + + ToggleState getDefaultChecked() const { return m_eDefaultChecked; } + void setDefaultChecked( ToggleState _eChecked ) { m_eDefaultChecked = _eChecked; } + + protected: + OReferenceValueComponent( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _rUnoControlModelTypeName, + const ::rtl::OUString& _rDefault, + sal_Bool _bSupportNoCheckRefValue = sal_False + ); + DECLARE_DEFAULT_CLONE_CTOR( OReferenceValueComponent ) + DECLARE_DEFAULT_DTOR( OReferenceValueComponent ); + + // OPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + using ::cppu::OPropertySetHelper::getFastPropertyValue; + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_REFVALUECOMPONENT_HXX + diff --git a/forms/source/component/scrollbar.cxx b/forms/source/component/scrollbar.cxx new file mode 100644 index 000000000000..5bd5744164a6 --- /dev/null +++ b/forms/source/component/scrollbar.cxx @@ -0,0 +1,319 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "scrollbar.hxx" +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> +#include <rtl/math.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_OScrollBarModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::OScrollBarModel > aRegisterModel; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::form::binding; + + //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + Any translateExternalDoubleToControlIntValue( + const Any& _rExternalValue, const Reference< XPropertySet >& _rxProperties, + const ::rtl::OUString& _rMinValueName, const ::rtl::OUString& _rMaxValueName ) + { + OSL_ENSURE( _rxProperties.is(), "translateExternalDoubleToControlIntValue: no aggregate!?" ); + + sal_Int32 nControlValue( 0 ); + double nExternalValue = 0; + if ( _rExternalValue >>= nExternalValue ) + { + if ( ::rtl::math::isInf( nExternalValue ) ) + { + // set the minimum or maximum of the scroll values + ::rtl::OUString sLimitPropertyName = ::rtl::math::isSignBitSet( nExternalValue ) + ? _rMinValueName : _rMaxValueName; + if ( _rxProperties.is() ) + _rxProperties->getPropertyValue( sLimitPropertyName ) >>= nControlValue; + } + else + { + nControlValue = (sal_Int32)::rtl::math::round( nExternalValue ); + } + } + else + { + if ( _rxProperties.is() ) + _rxProperties->getPropertyValue( _rMinValueName ) >>= nControlValue; + } + + return makeAny( nControlValue ); + } + + //-------------------------------------------------------------------- + Any translateControlIntToExternalDoubleValue( const Any& _rControlIntValue ) + { + Any aExternalDoubleValue; + sal_Int32 nScrollValue = 0; + if ( _rControlIntValue >>= nScrollValue ) + aExternalDoubleValue <<= (double)nScrollValue; + else + { + OSL_ENSURE( sal_False, "translateControlIntToExternalDoubleValue: no integer scroll value!" ); + // aExternalDoubleValue is void here, which is okay for this purpose ... + } + + return aExternalDoubleValue; + } + + //==================================================================== + //= OScrollBarModel + //==================================================================== + //-------------------------------------------------------------------- + DBG_NAME( OScrollBarModel ) + //-------------------------------------------------------------------- + OScrollBarModel::OScrollBarModel( const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_SCROLLBAR, VCL_CONTROL_SCROLLBAR, sal_True, sal_True, sal_False ) + ,m_nDefaultScrollValue( 0 ) + { + DBG_CTOR( OScrollBarModel, NULL ); + + m_nClassId = FormComponentType::SCROLLBAR; + initValueProperty( PROPERTY_SCROLL_VALUE, PROPERTY_ID_SCROLL_VALUE ); + } + + //-------------------------------------------------------------------- + OScrollBarModel::OScrollBarModel( const OScrollBarModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + { + DBG_CTOR( OScrollBarModel, NULL ); + m_nDefaultScrollValue = _pOriginal->m_nDefaultScrollValue; + } + + //-------------------------------------------------------------------- + OScrollBarModel::~OScrollBarModel( ) + { + DBG_DTOR( OScrollBarModel, NULL ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_SERVICE_REGISTRATION_2( OScrollBarModel, OControlModel, FRM_SUN_COMPONENT_SCROLLBAR, BINDABLE_INTEGER_VALUE_RANGE ) + // note that we're passing OControlModel as "base class". This is because + // OBoundControlModel, our real base class, claims to support the DataAwareControlModel + // service, which isn't really true for us. We only derive from this class + // to benefit from the functionality for binding to spreadsheet cells + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( OScrollBarModel ) + + //------------------------------------------------------------------------------ + void SAL_CALL OScrollBarModel::disposing() + { + OBoundControlModel::disposing(); + } + + //-------------------------------------------------------------------- + void OScrollBarModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 3, OControlModel ) + DECL_PROP1( DEFAULT_SCROLL_VALUE, sal_Int32, BOUND ); + DECL_PROP1( TABINDEX, sal_Int16, BOUND ); + DECL_PROP2( CONTROLSOURCEPROPERTY,::rtl::OUString, READONLY, TRANSIENT ); + END_DESCRIBE_PROPERTIES(); + } + + //------------------------------------------------------------------------------ + void OScrollBarModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + _rValue <<= m_nDefaultScrollValue; + break; + + default: + OBoundControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //------------------------------------------------------------------------------ + void OScrollBarModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + OSL_VERIFY( _rValue >>= m_nDefaultScrollValue ); + resetNoBroadcast(); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OScrollBarModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) + throw ( IllegalArgumentException ) + { + sal_Bool bModified( sal_False ); + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nDefaultScrollValue ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; + } + + //-------------------------------------------------------------------- + Any OScrollBarModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aReturn; + + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + aReturn <<= (sal_Int32)0; + break; + + default: + aReturn = OBoundControlModel::getPropertyDefaultByHandle( _nHandle ); + break; + } + + return aReturn; + } + + //------------------------------------------------------------------------------ + Any OScrollBarModel::translateDbColumnToControlValue( ) + { + OSL_ENSURE( sal_False, "OScrollBarModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return Any(); + } + + //------------------------------------------------------------------------------ + sal_Bool OScrollBarModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) + { + OSL_ENSURE( sal_False, "OScrollBarModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return sal_True; + } + + //------------------------------------------------------------------------------ + Any OScrollBarModel::getDefaultForReset() const + { + return makeAny( (sal_Int32)m_nDefaultScrollValue ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OScrollBarModel::getServiceName() throw( RuntimeException ) + { + return FRM_SUN_COMPONENT_SCROLLBAR; + } + + //-------------------------------------------------------------------- + void SAL_CALL OScrollBarModel::write( const Reference< XObjectOutputStream >& _rxOutStream ) + throw( IOException, RuntimeException ) + { + OBoundControlModel::write( _rxOutStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + OStreamSection aSection( Reference< XDataOutputStream >( _rxOutStream, UNO_QUERY ) ); + + // version + _rxOutStream->writeShort( 0x0001 ); + + // properties + _rxOutStream << m_nDefaultScrollValue; + writeHelpTextCompatibly( _rxOutStream ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OScrollBarModel::read( const Reference< XObjectInputStream>& _rxInStream ) throw( IOException, RuntimeException ) + { + OBoundControlModel::read( _rxInStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + // version + { + OStreamSection aSection( Reference< XDataInputStream >( _rxInStream, UNO_QUERY ) ); + + sal_uInt16 nVersion = _rxInStream->readShort(); + if ( nVersion == 0x0001 ) + { + _rxInStream >> m_nDefaultScrollValue; + readHelpTextCompatibly( _rxInStream ); + } + else + defaultCommonProperties(); + + // here, everything in the stream section which is left will be skipped + } + } + + //-------------------------------------------------------------------- + Any OScrollBarModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + return translateExternalDoubleToControlIntValue( _rExternalValue, m_xAggregateSet, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScrollValueMin" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScrollValueMax" ) ) ); + } + + //-------------------------------------------------------------------- + Any OScrollBarModel::translateControlValueToExternalValue( ) const + { + // by definition, the base class simply obtains the property value + return translateControlIntToExternalDoubleValue( OBoundControlModel::translateControlValueToExternalValue() ); + } + + //-------------------------------------------------------------------- + Sequence< Type > OScrollBarModel::getSupportedBindingTypes() + { + return Sequence< Type >( &::getCppuType( static_cast< double* >( NULL ) ), 1 ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/component/scrollbar.hxx b/forms/source/component/scrollbar.hxx new file mode 100644 index 000000000000..1d528dabe8bc --- /dev/null +++ b/forms/source/component/scrollbar.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_COMPONENT_SCROLLBAR_HXX +#define FORMS_SOURCE_COMPONENT_SCROLLBAR_HXX + +#include "FormComponent.hxx" +#include "frm_module.hxx" + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OScrollBarModel + //==================================================================== + class OScrollBarModel :public OBoundControlModel + { + private: + // <properties> + sal_Int32 m_nDefaultScrollValue; + // </properties> + + protected: + DECLARE_DEFAULT_LEAF_XTOR( OScrollBarModel ); + + // XServiceInfo + DECLARE_SERVICE_REGISTRATION( OScrollBarModel ) + + // XPersistObject + DECLARE_XPERSISTOBJECT() + + // XCloneable + DECLARE_XCLONEABLE(); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw ( ::com::sun::star::uno::Exception ); + virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw ( ::com::sun::star::lang::IllegalArgumentException ); + + // OBoundControlModel + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + // XCoponent and related helpers + virtual void SAL_CALL disposing(); + + // prevent method hiding + using OBoundControlModel::disposing; + using OBoundControlModel::getFastPropertyValue; + + }; +//........................................................................ +} // namespacefrm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_SCROLLBAR_HXX diff --git a/forms/source/component/spinbutton.cxx b/forms/source/component/spinbutton.cxx new file mode 100644 index 000000000000..332fccd2e744 --- /dev/null +++ b/forms/source/component/spinbutton.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "spinbutton.hxx" +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_OSpinButtonModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::OSpinButtonModel > aRegisterModel; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::form::binding; + + //==================================================================== + //= OSpinButtonModel + //==================================================================== + // implemented elsewhere + Any translateExternalDoubleToControlIntValue( + const Any& _rExternalValue, const Reference< XPropertySet >& _rxProperties, + const ::rtl::OUString& _rMinValueName, const ::rtl::OUString& _rMaxValueName ); + Any translateControlIntToExternalDoubleValue( const Any& _rControlIntValue ); + + //==================================================================== + //= OSpinButtonModel + //==================================================================== + //-------------------------------------------------------------------- + DBG_NAME( OSpinButtonModel ) + //-------------------------------------------------------------------- + OSpinButtonModel::OSpinButtonModel( const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_SPINBUTTON, VCL_CONTROL_SPINBUTTON, sal_True, sal_True, sal_False ) + ,m_nDefaultSpinValue( 0 ) + { + DBG_CTOR( OSpinButtonModel, NULL ); + + m_nClassId = FormComponentType::SPINBUTTON; + initValueProperty( PROPERTY_SPIN_VALUE, PROPERTY_ID_SPIN_VALUE ); + } + + //-------------------------------------------------------------------- + OSpinButtonModel::OSpinButtonModel( const OSpinButtonModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + { + DBG_CTOR( OSpinButtonModel, NULL ); + m_nDefaultSpinValue = _pOriginal->m_nDefaultSpinValue; + } + + //-------------------------------------------------------------------- + OSpinButtonModel::~OSpinButtonModel( ) + { + DBG_DTOR( OSpinButtonModel, NULL ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_SERVICE_REGISTRATION_2( OSpinButtonModel, OControlModel, FRM_SUN_COMPONENT_SPINBUTTON, BINDABLE_INTEGER_VALUE_RANGE ) + // note that we're passing OControlModel as "base class". This is because + // OBoundControlModel, our real base class, claims to support the DataAwareControlModel + // service, which isn't really true for us. We only derive from this class + // to benefit from the functionality for binding to spreadsheet cells + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( OSpinButtonModel ) + + //------------------------------------------------------------------------------ + void SAL_CALL OSpinButtonModel::disposing() + { + OBoundControlModel::disposing(); + } + + //-------------------------------------------------------------------- + void OSpinButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 3, OControlModel ) + DECL_PROP1( DEFAULT_SPIN_VALUE, sal_Int32, BOUND ); + DECL_PROP1( TABINDEX, sal_Int16, BOUND ); + DECL_PROP2( CONTROLSOURCEPROPERTY,::rtl::OUString, READONLY, TRANSIENT ); + END_DESCRIBE_PROPERTIES(); + } + + //------------------------------------------------------------------------------ + void OSpinButtonModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + _rValue <<= m_nDefaultSpinValue; + break; + + default: + OBoundControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //------------------------------------------------------------------------------ + void OSpinButtonModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + OSL_VERIFY( _rValue >>= m_nDefaultSpinValue ); + resetNoBroadcast(); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OSpinButtonModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) + throw ( IllegalArgumentException ) + { + sal_Bool bModified( sal_False ); + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nDefaultSpinValue ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; + } + + //-------------------------------------------------------------------- + Any OSpinButtonModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aReturn; + + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + aReturn <<= (sal_Int32)0; + break; + + default: + aReturn = OBoundControlModel::getPropertyDefaultByHandle( _nHandle ); + break; + } + + return aReturn; + } + + //------------------------------------------------------------------------------ + Any OSpinButtonModel::translateDbColumnToControlValue( ) + { + OSL_ENSURE( sal_False, "OSpinButtonModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return Any(); + } + + //------------------------------------------------------------------------------ + sal_Bool OSpinButtonModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) + { + OSL_ENSURE( sal_False, "OSpinButtonModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return sal_True; + } + + //------------------------------------------------------------------------------ + Any OSpinButtonModel::getDefaultForReset() const + { + return makeAny( (sal_Int32)m_nDefaultSpinValue ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OSpinButtonModel::getServiceName() throw( RuntimeException ) + { + return FRM_SUN_COMPONENT_SPINBUTTON; + } + + //-------------------------------------------------------------------- + void SAL_CALL OSpinButtonModel::write( const Reference< XObjectOutputStream >& _rxOutStream ) + throw( IOException, RuntimeException ) + { + OBoundControlModel::write( _rxOutStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + OStreamSection aSection( Reference< XDataOutputStream >( _rxOutStream, UNO_QUERY ) ); + + // version + _rxOutStream->writeShort( 0x0001 ); + + // properties + _rxOutStream << m_nDefaultSpinValue; + writeHelpTextCompatibly( _rxOutStream ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OSpinButtonModel::read( const Reference< XObjectInputStream>& _rxInStream ) throw( IOException, RuntimeException ) + { + OBoundControlModel::read( _rxInStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + // version + { + OStreamSection aSection( Reference< XDataInputStream >( _rxInStream, UNO_QUERY ) ); + + sal_uInt16 nVersion = _rxInStream->readShort(); + if ( nVersion == 0x0001 ) + { + _rxInStream >> m_nDefaultSpinValue; + readHelpTextCompatibly( _rxInStream ); + } + else + defaultCommonProperties(); + + // here, everything in the stream section which is left will be skipped + } + } + + //-------------------------------------------------------------------- + Any OSpinButtonModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + return translateExternalDoubleToControlIntValue( _rExternalValue, m_xAggregateSet, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SpinValueMin" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SpinValueMax" ) ) ); + } + + //-------------------------------------------------------------------- + Any OSpinButtonModel::translateControlValueToExternalValue( ) const + { + // by definition, the base class simply obtains the property value + return translateControlIntToExternalDoubleValue( OBoundControlModel::translateControlValueToExternalValue() ); + } + + //-------------------------------------------------------------------- + Sequence< Type > OSpinButtonModel::getSupportedBindingTypes() + { + return Sequence< Type >( &::getCppuType( static_cast< double* >( NULL ) ), 1 ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/component/spinbutton.hxx b/forms/source/component/spinbutton.hxx new file mode 100644 index 000000000000..4e9437bb8d0e --- /dev/null +++ b/forms/source/component/spinbutton.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_COMPONENT_SPINBUTTON_HXX +#define FORMS_SOURCE_COMPONENT_SPINBUTTON_HXX + +#include "FormComponent.hxx" +#include "frm_module.hxx" + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OSpinButtonModel + //==================================================================== + class OSpinButtonModel :public OBoundControlModel + { + private: + // <properties> + sal_Int32 m_nDefaultSpinValue; + // </properties> + + protected: + DECLARE_DEFAULT_LEAF_XTOR( OSpinButtonModel ); + + // XServiceInfo + DECLARE_SERVICE_REGISTRATION( OSpinButtonModel ) + + // XPersistObject + DECLARE_XPERSISTOBJECT() + + // XCloneable + DECLARE_XCLONEABLE(); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw ( ::com::sun::star::uno::Exception ); + virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw ( ::com::sun::star::lang::IllegalArgumentException ); + + // OBoundControlModel + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + // XCoponent and related helpers + virtual void SAL_CALL disposing(); + + // prevent method hiding + using OBoundControlModel::disposing; + using OBoundControlModel::getFastPropertyValue; + + }; +//........................................................................ +} // namespacefrm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_SPINBUTTON_HXX diff --git a/forms/source/helper/commanddescriptionprovider.cxx b/forms/source/helper/commanddescriptionprovider.cxx new file mode 100644 index 000000000000..4248142d405d --- /dev/null +++ b/forms/source/helper/commanddescriptionprovider.cxx @@ -0,0 +1,140 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "commanddescriptionprovider.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +/** === end UNO includes === **/ + +#include <comphelper/namedvaluecollection.hxx> +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::beans::PropertyValue; + /** === end UNO using === **/ + + //==================================================================== + //= DefaultCommandDescriptionProvider + //==================================================================== + class DefaultCommandDescriptionProvider : public ICommandDescriptionProvider + { + public: + DefaultCommandDescriptionProvider( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + { + impl_init_nothrow( _rContext, _rxDocument ); + } + + ~DefaultCommandDescriptionProvider() + { + } + + // ICommandDescriptionProvider + virtual ::rtl::OUString getCommandDescription( const ::rtl::OUString& _rCommandURL ) const; + + private: + void impl_init_nothrow( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ); + + private: + Reference< XNameAccess > m_xCommandAccess; + }; + + + //-------------------------------------------------------------------- + void DefaultCommandDescriptionProvider::impl_init_nothrow( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + { + OSL_ENSURE( _rxDocument.is(), "DefaultCommandDescriptionProvider::impl_init_nothrow: no document => no command descriptions!" ); + if ( !_rxDocument.is() ) + return; + + try + { + Reference< XModuleManager > xModuleManager( _rContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + ::rtl::OUString sModuleID = xModuleManager->identify( _rxDocument ); + + Reference< XNameAccess > xUICommandDescriptions( _rContext.createComponent( "com.sun.star.frame.UICommandDescription" ), UNO_QUERY_THROW ); + m_xCommandAccess.set( xUICommandDescriptions->getByName( sModuleID ), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + ::rtl::OUString DefaultCommandDescriptionProvider::getCommandDescription( const ::rtl::OUString& _rCommandURL ) const + { + if ( !m_xCommandAccess.is() ) + return ::rtl::OUString(); + + try + { + ::comphelper::NamedValueCollection aCommandProperties( m_xCommandAccess->getByName( _rCommandURL ) ); + return aCommandProperties.getOrDefault( "Name", ::rtl::OUString() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return ::rtl::OUString(); + } + + //-------------------------------------------------------------------- + PCommandDescriptionProvider createDocumentCommandDescriptionProvider( + const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + { + PCommandDescriptionProvider pDescriptionProvider( new DefaultCommandDescriptionProvider( _rContext, _rxDocument ) ); + return pDescriptionProvider; + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/helper/commandimageprovider.cxx b/forms/source/helper/commandimageprovider.cxx new file mode 100644 index 000000000000..0b631d8c9d50 --- /dev/null +++ b/forms/source/helper/commandimageprovider.cxx @@ -0,0 +1,181 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "commandimageprovider.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/XImageManager.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/ui/ImageType.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::ui::XImageManager; + using ::com::sun::star::ui::XUIConfigurationManagerSupplier; + using ::com::sun::star::ui::XUIConfigurationManager; + using ::com::sun::star::ui::XModuleUIConfigurationManagerSupplier; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::graphic::XGraphic; + /** === end UNO using === **/ + namespace ImageType = ::com::sun::star::ui::ImageType; + + //==================================================================== + //= DocumentCommandImageProvider + //==================================================================== + class DocumentCommandImageProvider : public ICommandImageProvider + { + public: + DocumentCommandImageProvider( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + { + impl_init_nothrow( _rContext, _rxDocument ); + } + virtual ~DocumentCommandImageProvider() + { + } + + // ICommandImageProvider + virtual CommandImages getCommandImages( const CommandURLs& _rCommandURLs, const bool _bLarge, const bool _bHiContrast ) const; + + private: + void impl_init_nothrow( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ); + + private: + Reference< XImageManager > m_xDocumentImageManager; + Reference< XImageManager > m_xModuleImageManager; + }; + + //-------------------------------------------------------------------- + void DocumentCommandImageProvider::impl_init_nothrow( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + { + OSL_ENSURE( _rxDocument.is(), "DocumentCommandImageProvider::impl_init_nothrow: no document => no images!" ); + if ( !_rxDocument.is() ) + return; + + // obtain the image manager of the document + try + { + Reference< XUIConfigurationManagerSupplier > xSuppUIConfig( _rxDocument, UNO_QUERY_THROW ); + Reference< XUIConfigurationManager > xUIConfig( xSuppUIConfig->getUIConfigurationManager(), UNO_QUERY ); + m_xDocumentImageManager.set( xUIConfig->getImageManager(), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // obtain the image manager or the module + try + { + Reference< XModuleManager > xModuleManager( _rContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + ::rtl::OUString sModuleID = xModuleManager->identify( _rxDocument ); + + Reference< XModuleUIConfigurationManagerSupplier > xSuppUIConfig( + _rContext.createComponent( "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ), UNO_QUERY_THROW ); + Reference< XUIConfigurationManager > xUIConfig( + xSuppUIConfig->getUIConfigurationManager( sModuleID ), UNO_SET_THROW ); + m_xModuleImageManager.set( xUIConfig->getImageManager(), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + CommandImages DocumentCommandImageProvider::getCommandImages( const CommandURLs& _rCommandURLs, const bool _bLarge, const bool _bHiContrast ) const + { + const size_t nCommandCount = _rCommandURLs.getLength(); + CommandImages aImages( nCommandCount ); + try + { + const sal_Int16 nImageType = + ( _bLarge ? ImageType::SIZE_LARGE : ImageType::SIZE_DEFAULT ) + + ( _bHiContrast ? ImageType::COLOR_HIGHCONTRAST : ImageType::COLOR_NORMAL ); + + Sequence< Reference< XGraphic > > aDocImages( nCommandCount ); + Sequence< Reference< XGraphic > > aModImages( nCommandCount ); + + // first try the document image manager + if ( m_xDocumentImageManager.is() ) + aDocImages = m_xDocumentImageManager->getImages( nImageType, _rCommandURLs ); + + // then the module's image manager + if ( m_xModuleImageManager.is() ) + aModImages = m_xModuleImageManager->getImages( nImageType, _rCommandURLs ); + + ENSURE_OR_THROW( (size_t)aDocImages.getLength() == nCommandCount, "illegal array size returned by getImages (document image manager)" ); + ENSURE_OR_THROW( (size_t)aModImages.getLength() == nCommandCount, "illegal array size returned by getImages (module image manager)" ); + + for ( size_t i=0; i<nCommandCount; ++i ) + { + if ( aDocImages[i].is() ) + aImages[i] = Image( aDocImages[i] ); + else + aImages[i] = Image( aModImages[i] ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return aImages; + } + + //-------------------------------------------------------------------- + PCommandImageProvider createDocumentCommandImageProvider( + const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + { + PCommandImageProvider pImageProvider( new DocumentCommandImageProvider( _rContext, _rxDocument ) ); + return pImageProvider; + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/helper/controlfeatureinterception.cxx b/forms/source/helper/controlfeatureinterception.cxx new file mode 100644 index 000000000000..ea34c4fb219b --- /dev/null +++ b/forms/source/helper/controlfeatureinterception.cxx @@ -0,0 +1,170 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "controlfeatureinterception.hxx" +#include "urltransformer.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <tools/debug.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + + //==================================================================== + //= ControlFeatureInterception + //==================================================================== + //-------------------------------------------------------------------- + ControlFeatureInterception::ControlFeatureInterception( const Reference< XMultiServiceFactory >& _rxORB ) + :m_pUrlTransformer( new UrlTransformer( _rxORB ) ) + { + } + + //-------------------------------------------------------------------- + void SAL_CALL ControlFeatureInterception::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException ) + { + if ( !_rxInterceptor.is() ) + { + DBG_ERROR( "ControlFeatureInterception::registerDispatchProviderInterceptor: invalid interceptor!" ); + return; + } + + if ( m_xFirstDispatchInterceptor.is() ) + { + // there is already an interceptor; the new one will become its master + Reference< XDispatchProvider > xFirstProvider( m_xFirstDispatchInterceptor, UNO_QUERY ); + _rxInterceptor->setSlaveDispatchProvider( xFirstProvider ); + m_xFirstDispatchInterceptor->setMasterDispatchProvider( xFirstProvider ); + } + + // we are the master of the chain's first interceptor + m_xFirstDispatchInterceptor = _rxInterceptor; + m_xFirstDispatchInterceptor->setMasterDispatchProvider( NULL ); + // it's the first of the interceptor chain + } + + //-------------------------------------------------------------------- + void SAL_CALL ControlFeatureInterception::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException ) + { + if ( !_rxInterceptor.is() ) + { + DBG_ERROR( "ControlFeatureInterception::releaseDispatchProviderInterceptor: invalid interceptor!" ); + return; + } + + Reference< XDispatchProviderInterceptor > xChainWalk( m_xFirstDispatchInterceptor ); + + if ( m_xFirstDispatchInterceptor == _rxInterceptor ) + { // our chain will have a new first element + Reference< XDispatchProviderInterceptor > xSlave( m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY ); + m_xFirstDispatchInterceptor = xSlave; + } + // do this before removing the interceptor from the chain as we won't know it's slave afterwards) + + while ( xChainWalk.is() ) + { + // walk along the chain of interceptors and look for the interceptor that has to be removed + Reference< XDispatchProviderInterceptor > xSlave( xChainWalk->getSlaveDispatchProvider(), UNO_QUERY ); + + if ( xChainWalk == _rxInterceptor ) + { + // old master may be an interceptor too + Reference< XDispatchProviderInterceptor > xMaster( xChainWalk->getMasterDispatchProvider(), UNO_QUERY ); + + // unchain the interceptor that has to be removed + xChainWalk->setSlaveDispatchProvider( NULL ); + xChainWalk->setMasterDispatchProvider( NULL ); + + // reconnect the chain + if ( xMaster.is() ) + { + xMaster->setSlaveDispatchProvider( Reference< XDispatchProvider >::query( xSlave ) ); + } + + // if somebody has registered the same interceptor twice, then we will remove + // it once per call ... + break; + } + + xChainWalk = xSlave; + } + } + + //-------------------------------------------------------------------- + void ControlFeatureInterception::dispose() + { + // release all interceptors + Reference< XDispatchProviderInterceptor > xInterceptor( m_xFirstDispatchInterceptor ); + m_xFirstDispatchInterceptor.clear(); + while ( xInterceptor.is() ) + { + // tell the interceptor it has a new (means no) predecessor + xInterceptor->setMasterDispatchProvider( NULL ); + + // ask for it's successor + Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider(); + // and give it the new (means no) successoert + xInterceptor->setSlaveDispatchProvider( NULL ); + + // start over with the next chain element + xInterceptor = xInterceptor.query( xSlave ); + } + } + //-------------------------------------------------------------------- + Reference< XDispatch > ControlFeatureInterception::queryDispatch( const URL& _rURL, const ::rtl::OUString& _rTargetFrameName, ::sal_Int32 _nSearchFlags ) SAL_THROW((RuntimeException)) + { + Reference< XDispatch > xDispatcher; + if ( m_xFirstDispatchInterceptor.is() ) + xDispatcher = m_xFirstDispatchInterceptor->queryDispatch( _rURL, _rTargetFrameName, _nSearchFlags ); + return xDispatcher; + } + + //-------------------------------------------------------------------- + Reference< XDispatch > ControlFeatureInterception::queryDispatch( const URL& _rURL ) SAL_THROW((RuntimeException)) + { + return queryDispatch( _rURL, ::rtl::OUString(), 0 ); + } + + //-------------------------------------------------------------------- + Reference< XDispatch > ControlFeatureInterception::queryDispatch( const sal_Char* _pAsciiURL ) SAL_THROW((RuntimeException)) + { + return queryDispatch( m_pUrlTransformer->getStrictURLFromAscii( _pAsciiURL ) ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/helper/formnavigation.cxx b/forms/source/helper/formnavigation.cxx new file mode 100644 index 000000000000..8a2815938654 --- /dev/null +++ b/forms/source/helper/formnavigation.cxx @@ -0,0 +1,484 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "formnavigation.hxx" +#include "urltransformer.hxx" +#include "controlfeatureinterception.hxx" +#include "frm_strings.hxx" + +#include <com/sun/star/form/runtime/FormFeature.hpp> + +#include <tools/debug.hxx> + + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::frame; + namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; + + //================================================================== + //= OFormNavigationHelper + //================================================================== + DBG_NAME( OFormNavigationHelper ) + //------------------------------------------------------------------ + OFormNavigationHelper::OFormNavigationHelper( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + ,m_nConnectedFeatures( 0 ) + { + DBG_CTOR( OFormNavigationHelper, NULL ); + m_pFeatureInterception.reset( new ControlFeatureInterception( m_xORB ) ); + } + + //------------------------------------------------------------------ + OFormNavigationHelper::~OFormNavigationHelper() + { + DBG_DTOR( OFormNavigationHelper, NULL ); + } + + //------------------------------------------------------------------ + void SAL_CALL OFormNavigationHelper::dispose( ) throw( RuntimeException ) + { + m_pFeatureInterception->dispose(); + disconnectDispatchers(); + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::interceptorsChanged( ) + { + updateDispatches(); + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::featureStateChanged( sal_Int16 /*_nFeatureId*/, sal_Bool /*_bEnabled*/ ) + { + // not interested in + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::allFeatureStatesChanged( ) + { + // not interested in + } + + //------------------------------------------------------------------ + void SAL_CALL OFormNavigationHelper::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); + interceptorsChanged(); + } + + //------------------------------------------------------------------ + void SAL_CALL OFormNavigationHelper::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor ); + interceptorsChanged(); + } + + //------------------------------------------------------------------ + void SAL_CALL OFormNavigationHelper::statusChanged( const FeatureStateEvent& _rState ) throw (RuntimeException) + { + for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin(); + aFeature != m_aSupportedFeatures.end(); + ++aFeature + ) + { + if ( aFeature->second.aURL.Main == _rState.FeatureURL.Main ) + { + if ( ( aFeature->second.bCachedState != _rState.IsEnabled ) + || ( aFeature->second.aCachedAdditionalState != _rState.State ) + ) + { + // change the cached state + aFeature->second.bCachedState = _rState.IsEnabled; + aFeature->second.aCachedAdditionalState = _rState.State; + // tell derivees what happened + featureStateChanged( aFeature->first, _rState.IsEnabled ); + } + return; + } + } + + // unreachable + DBG_ERROR( "OFormNavigationHelper::statusChanged: huh? An invalid/unknown URL?" ); + } + + //------------------------------------------------------------------ + void SAL_CALL OFormNavigationHelper::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + // was it one of our external dispatchers? + if ( m_nConnectedFeatures ) + { + for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin(); + aFeature != m_aSupportedFeatures.end(); + ++aFeature + ) + { + if ( aFeature->second.xDispatcher == _rSource.Source ) + { + aFeature->second.xDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL ); + aFeature->second.xDispatcher = NULL; + aFeature->second.bCachedState = sal_False; + aFeature->second.aCachedAdditionalState.clear(); + --m_nConnectedFeatures; + + featureStateChanged( aFeature->first, sal_False ); + break; + } + } + } + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::updateDispatches() + { + if ( !m_nConnectedFeatures ) + { // we don't have any dispatchers yet -> do the initial connect + connectDispatchers(); + return; + } + + initializeSupportedFeatures(); + + m_nConnectedFeatures = 0; + + Reference< XDispatch > xNewDispatcher; + Reference< XDispatch > xCurrentDispatcher; + + for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin(); + aFeature != m_aSupportedFeatures.end(); + ++aFeature + ) + { + xNewDispatcher = queryDispatch( aFeature->second.aURL ); + xCurrentDispatcher = aFeature->second.xDispatcher; + if ( xNewDispatcher != xCurrentDispatcher ) + { + // the dispatcher for this particular URL changed + if ( xCurrentDispatcher.is() ) + xCurrentDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL ); + + xCurrentDispatcher = aFeature->second.xDispatcher = xNewDispatcher; + + if ( xCurrentDispatcher.is() ) + xCurrentDispatcher->addStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL ); + } + + if ( xCurrentDispatcher.is() ) + ++m_nConnectedFeatures; + else + aFeature->second.bCachedState = sal_False; + } + + // notify derivee that (potentially) all features changed their state + allFeatureStatesChanged( ); + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::connectDispatchers() + { + if ( m_nConnectedFeatures ) + { // already connected -> just do an update + updateDispatches(); + return; + } + + initializeSupportedFeatures(); + + m_nConnectedFeatures = 0; + + for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin(); + aFeature != m_aSupportedFeatures.end(); + ++aFeature + ) + { + aFeature->second.bCachedState = sal_False; + aFeature->second.aCachedAdditionalState.clear(); + aFeature->second.xDispatcher = queryDispatch( aFeature->second.aURL ); + if ( aFeature->second.xDispatcher.is() ) + { + ++m_nConnectedFeatures; + aFeature->second.xDispatcher->addStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL ); + } + } + + // notify derivee that (potentially) all features changed their state + allFeatureStatesChanged( ); + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::disconnectDispatchers() + { + if ( m_nConnectedFeatures ) + { + for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin(); + aFeature != m_aSupportedFeatures.end(); + ++aFeature + ) + { + if ( aFeature->second.xDispatcher.is() ) + aFeature->second.xDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL ); + + aFeature->second.xDispatcher = NULL; + aFeature->second.bCachedState = sal_False; + aFeature->second.aCachedAdditionalState.clear(); + } + + m_nConnectedFeatures = 0; + } + + // notify derivee that (potentially) all features changed their state + allFeatureStatesChanged( ); + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::initializeSupportedFeatures( ) + { + if ( m_aSupportedFeatures.empty() ) + { + // ask the derivee which feature ids it wants us to support + ::std::vector< sal_Int16 > aFeatureIds; + getSupportedFeatures( aFeatureIds ); + + OFormNavigationMapper aUrlMapper( m_xORB ); + + for ( ::std::vector< sal_Int16 >::const_iterator aLoop = aFeatureIds.begin(); + aLoop != aFeatureIds.end(); + ++aLoop + ) + { + FeatureInfo aFeatureInfo; + + bool bKnownId = + aUrlMapper.getFeatureURL( *aLoop, aFeatureInfo.aURL ); + DBG_ASSERT( bKnownId, "OFormNavigationHelper::initializeSupportedFeatures: unknown feature id!" ); + + if ( bKnownId ) + // add to our map + m_aSupportedFeatures.insert( FeatureMap::value_type( *aLoop, aFeatureInfo ) ); + } + } + } + + //------------------------------------------------------------------ + Reference< XDispatch > OFormNavigationHelper::queryDispatch( const URL& _rURL ) + { + return m_pFeatureInterception->queryDispatch( _rURL ); + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::dispatchWithArgument( sal_Int16 _nFeatureId, const sal_Char* _pParamAsciiName, + const Any& _rParamValue ) const + { + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + { + if ( aInfo->second.xDispatcher.is() ) + { + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = ::rtl::OUString::createFromAscii( _pParamAsciiName ); + aArgs[0].Value = _rParamValue; + + aInfo->second.xDispatcher->dispatch( aInfo->second.aURL, aArgs ); + } + } + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::dispatch( sal_Int16 _nFeatureId ) const + { + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + { + if ( aInfo->second.xDispatcher.is() ) + { + Sequence< PropertyValue > aEmptyArgs; + aInfo->second.xDispatcher->dispatch( aInfo->second.aURL, aEmptyArgs ); + } + } + } + + //------------------------------------------------------------------ + bool OFormNavigationHelper::isEnabled( sal_Int16 _nFeatureId ) const + { + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + return aInfo->second.bCachedState; + + return false; + } + + //------------------------------------------------------------------ + bool OFormNavigationHelper::getBooleanState( sal_Int16 _nFeatureId ) const + { + sal_Bool bState = sal_False; + + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + aInfo->second.aCachedAdditionalState >>= bState; + + return (bool)bState; + } + + //------------------------------------------------------------------ + ::rtl::OUString OFormNavigationHelper::getStringState( sal_Int16 _nFeatureId ) const + { + ::rtl::OUString sState; + + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + aInfo->second.aCachedAdditionalState >>= sState; + + return sState; + } + + //------------------------------------------------------------------ + sal_Int32 OFormNavigationHelper::getIntegerState( sal_Int16 _nFeatureId ) const + { + sal_Int32 nState = 0; + + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + aInfo->second.aCachedAdditionalState >>= nState; + + return nState; + } + + //------------------------------------------------------------------ + void OFormNavigationHelper::invalidateSupportedFeaturesSet() + { + disconnectDispatchers( ); + // no supported features anymore: + FeatureMap aEmpty; + m_aSupportedFeatures.swap( aEmpty ); + } + + //================================================================== + //= OFormNavigationMapper + //================================================================== + //------------------------------------------------------------------ + OFormNavigationMapper::OFormNavigationMapper( const Reference< XMultiServiceFactory >& _rxORB ) + { + m_pUrlTransformer.reset( new UrlTransformer( _rxORB ) ); + } + + //------------------------------------------------------------------ + OFormNavigationMapper::~OFormNavigationMapper( ) + { + } + + //------------------------------------------------------------------ + bool OFormNavigationMapper::getFeatureURL( sal_Int16 _nFeatureId, URL& /* [out] */ _rURL ) + { + // get the ascii version of the URL + const char* pAsciiURL = getFeatureURLAscii( _nFeatureId ); + if ( pAsciiURL ) + _rURL = m_pUrlTransformer->getStrictURLFromAscii( pAsciiURL ); + + return ( pAsciiURL != NULL ); + } + + //------------------------------------------------------------------ + namespace + { + struct FeatureURL + { + const sal_Int16 nFormFeature; + const sal_Char* pAsciiURL; + + FeatureURL( const sal_Int16 _nFormFeature, const sal_Char* _pAsciiURL ) + :nFormFeature( _nFormFeature ) + ,pAsciiURL( _pAsciiURL ) + { + } + }; + const FeatureURL* lcl_getFeatureTable() + { + static const FeatureURL s_aFeatureURLs[] = + { + FeatureURL( FormFeature::MoveAbsolute, URL_FORM_POSITION ), + FeatureURL( FormFeature::TotalRecords, URL_FORM_RECORDCOUNT ), + FeatureURL( FormFeature::MoveToFirst, URL_RECORD_FIRST ), + FeatureURL( FormFeature::MoveToPrevious, URL_RECORD_PREV ), + FeatureURL( FormFeature::MoveToNext, URL_RECORD_NEXT ), + FeatureURL( FormFeature::MoveToLast, URL_RECORD_LAST ), + FeatureURL( FormFeature::SaveRecordChanges, URL_RECORD_SAVE ), + FeatureURL( FormFeature::UndoRecordChanges, URL_RECORD_UNDO ), + FeatureURL( FormFeature::MoveToInsertRow, URL_RECORD_NEW ), + FeatureURL( FormFeature::DeleteRecord, URL_RECORD_DELETE ), + FeatureURL( FormFeature::ReloadForm, URL_FORM_REFRESH ), + FeatureURL( FormFeature::RefreshCurrentControl, URL_FORM_REFRESH_CURRENT_CONTROL ), + FeatureURL( FormFeature::SortAscending, URL_FORM_SORT_UP ), + FeatureURL( FormFeature::SortDescending, URL_FORM_SORT_DOWN ), + FeatureURL( FormFeature::InteractiveSort, URL_FORM_SORT ), + FeatureURL( FormFeature::AutoFilter, URL_FORM_AUTO_FILTER ), + FeatureURL( FormFeature::InteractiveFilter, URL_FORM_FILTER ), + FeatureURL( FormFeature::ToggleApplyFilter, URL_FORM_APPLY_FILTER ), + FeatureURL( FormFeature::RemoveFilterAndSort, URL_FORM_REMOVE_FILTER ), + FeatureURL( 0, NULL ) + }; + return s_aFeatureURLs; + } + } + + //------------------------------------------------------------------ + const char* OFormNavigationMapper::getFeatureURLAscii( sal_Int16 _nFeatureId ) + { + const FeatureURL* pFeatures = lcl_getFeatureTable(); + while ( pFeatures->pAsciiURL ) + { + if ( pFeatures->nFormFeature == _nFeatureId ) + return pFeatures->pAsciiURL; + ++pFeatures; + } + return NULL; + } + + //------------------------------------------------------------------ + sal_Int16 OFormNavigationMapper::getFeatureId( const ::rtl::OUString& _rCompleteURL ) + { + const FeatureURL* pFeatures = lcl_getFeatureTable(); + while ( pFeatures->pAsciiURL ) + { + if ( _rCompleteURL.compareToAscii( pFeatures->pAsciiURL ) == 0 ) + return pFeatures->nFormFeature; + ++pFeatures; + } + return -1; + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/helper/makefile.mk b/forms/source/helper/makefile.mk new file mode 100644 index 000000000000..e60526cb8b6b --- /dev/null +++ b/forms/source/helper/makefile.mk @@ -0,0 +1,58 @@ + +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=forms +TARGET=helper + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Types ------------------------------------- + +INCPRE+=$(SOLARINCDIR)$/offuh + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/formnavigation.obj \ + $(SLO)$/controlfeatureinterception.obj \ + $(SLO)$/urltransformer.obj \ + $(SLO)$/windowstateguard.obj \ + $(SLO)$/resettable.obj \ + $(SLO)$/commandimageprovider.obj \ + $(SLO)$/commanddescriptionprovider.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/helper/resettable.cxx b/forms/source/helper/resettable.cxx new file mode 100644 index 000000000000..0210c0ead56c --- /dev/null +++ b/forms/source/helper/resettable.cxx @@ -0,0 +1,102 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "resettable.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <cppuhelper/weak.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::form::XResetListener; + using ::com::sun::star::lang::EventObject; + /** === end UNO using === **/ + + //==================================================================== + //= ResetHelper + //==================================================================== + //-------------------------------------------------------------------- + void ResetHelper::addResetListener( const Reference< XResetListener >& _listener ) + { + m_aResetListeners.addInterface( _listener ); + } + + //-------------------------------------------------------------------- + void ResetHelper::removeResetListener( const Reference< XResetListener >& _listener ) + { + m_aResetListeners.removeInterface( _listener ); + } + + //-------------------------------------------------------------------- + bool ResetHelper::approveReset() + { + ::cppu::OInterfaceIteratorHelper aIter( m_aResetListeners ); + EventObject aResetEvent( m_rParent ); + + sal_Bool bContinue = sal_True; + while ( aIter.hasMoreElements() && bContinue ) + bContinue = static_cast< XResetListener* >( aIter.next() )->approveReset( aResetEvent ); + + return bContinue; + } + + //-------------------------------------------------------------------- + void ResetHelper::notifyResetted() + { + EventObject aResetEvent( m_rParent ); + m_aResetListeners.notifyEach( &XResetListener::resetted, aResetEvent ); + } + + //-------------------------------------------------------------------- + void ResetHelper::disposing() + { + EventObject aEvent( m_rParent ); + m_aResetListeners.disposeAndClear( aEvent ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/helper/urltransformer.cxx b/forms/source/helper/urltransformer.cxx new file mode 100644 index 000000000000..a74dbd40d5aa --- /dev/null +++ b/forms/source/helper/urltransformer.cxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "urltransformer.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <tools/debug.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + + //==================================================================== + //= UrlTransformer + //==================================================================== + //-------------------------------------------------------------------- + UrlTransformer::UrlTransformer( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + ,m_bTriedToCreateTransformer( false ) + { + DBG_ASSERT( _rxORB.is(), "UrlTransformer::UrlTransformer: invalid service factory!" ); + } + + //-------------------------------------------------------------------- + bool UrlTransformer::implEnsureTransformer() const + { + // create the transformer, if not already attempted to do so + if ( !m_xTransformer.is() && !m_bTriedToCreateTransformer ) + { + if ( m_xORB.is() ) + { + m_xTransformer = m_xTransformer.query( + m_xORB->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ) ) + ) + ); + DBG_ASSERT( m_xTransformer.is(), "UrlTransformer::getStrictURL: couldn't get an URL transformer!" ); + } + + m_bTriedToCreateTransformer = true; + } + return m_xTransformer.is(); + } + + //-------------------------------------------------------------------- + URL UrlTransformer::getStrictURL( const ::rtl::OUString& _rURL ) const + { + URL aReturn; + aReturn.Complete = _rURL; + if ( implEnsureTransformer() ) + m_xTransformer->parseStrict( aReturn ); + return aReturn; + } + + //-------------------------------------------------------------------- + URL UrlTransformer::getStrictURLFromAscii( const sal_Char* _pAsciiURL ) const + { + return getStrictURL( ::rtl::OUString::createFromAscii( _pAsciiURL ) ); + } + + //-------------------------------------------------------------------- + void UrlTransformer::parseSmartWithAsciiProtocol( ::com::sun::star::util::URL& _rURL, const sal_Char* _pAsciiURL ) const + { + if ( implEnsureTransformer() ) + m_xTransformer->parseSmart( _rURL, ::rtl::OUString::createFromAscii( _pAsciiURL ) ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/helper/windowstateguard.cxx b/forms/source/helper/windowstateguard.cxx new file mode 100644 index 000000000000..c4bb6154a4d5 --- /dev/null +++ b/forms/source/helper/windowstateguard.cxx @@ -0,0 +1,226 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "windowstateguard.hxx" +#include "frm_strings.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XWindowListener2.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/implbase1.hxx> +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::awt::XWindowListener2; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::awt::XWindow2; + using ::com::sun::star::awt::WindowEvent; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::awt::XControlModel; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::Exception; + /** === end UNO using === **/ + + //==================================================================== + //= WindowStateGuard_Impl + //==================================================================== + typedef ::cppu::WeakImplHelper1 < XWindowListener2 + > WindowStateGuard_Impl_Base; + class WindowStateGuard_Impl : public WindowStateGuard_Impl_Base + { + private: + ::osl::Mutex m_aMutex; + Reference< XWindow2 > m_xWindow; + Reference< XPropertySet > m_xModelProps; + + public: + /** constructs the instance + @param _rxWindow + the window at which to listen. Must not be <NULL/>. + @param _rxModel + the model which acts as the reference for the states to be enforced. Must not be <NULL/>. + */ + WindowStateGuard_Impl( const Reference< XWindow2 >& _rxWindow, const Reference< XPropertySet >& _rxMdelProps ); + + void dispose(); + + protected: + // XWindowListener2 + virtual void SAL_CALL windowEnabled( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowDisabled( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); + + // XWindowListener + virtual void SAL_CALL windowResized( const ::com::sun::star::awt::WindowEvent& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowMoved( const ::com::sun::star::awt::WindowEvent& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowShown( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowHidden( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + private: + /** ensures that the window's Enabled state matches what is described at the model + @precond + our mutex is locked + */ + void impl_ensureEnabledState_nothrow() const; + }; + + //-------------------------------------------------------------------- + WindowStateGuard_Impl::WindowStateGuard_Impl( const Reference< XWindow2 >& _rxWindow, const Reference< XPropertySet >& _rxMdelProps ) + :m_xWindow( _rxWindow ) + ,m_xModelProps( _rxMdelProps ) + { + if ( !m_xWindow.is() || !m_xModelProps.is() ) + throw RuntimeException(); + + osl_incrementInterlockedCount( &m_refCount ); + { + m_xWindow->addWindowListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + void WindowStateGuard_Impl::dispose() + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xWindow.is() ) + // already disposed + return; + + m_xWindow->removeWindowListener( this ); + m_xWindow.clear(); + } + + //-------------------------------------------------------------------- + void WindowStateGuard_Impl::impl_ensureEnabledState_nothrow() const + { + try + { + sal_Bool bEnabled = m_xWindow->isEnabled(); + sal_Bool bShouldBeEnabled = sal_False; + OSL_VERIFY( m_xModelProps->getPropertyValue( PROPERTY_ENABLED ) >>= bShouldBeEnabled ); + + if ( !bShouldBeEnabled && bEnabled ) + m_xWindow->setEnable( sal_False ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::windowEnabled( const EventObject& /*e*/ ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_ensureEnabledState_nothrow(); + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::windowDisabled( const EventObject& /*e*/ ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_ensureEnabledState_nothrow(); + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::windowResized( const WindowEvent& /*e*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::windowMoved( const WindowEvent& /*e*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::windowShown( const EventObject& /*e*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::windowHidden( const EventObject& /*e*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL WindowStateGuard_Impl::disposing( const EventObject& Source ) throw (RuntimeException) + { + OSL_ENSURE( Source.Source == m_xWindow, "WindowStateGuard_Impl::disposing: where does this come from?" ); + (void)Source; + dispose(); + } + + //==================================================================== + //= WindowStateGuard + //==================================================================== + //-------------------------------------------------------------------- + WindowStateGuard::WindowStateGuard() + { + } + + //-------------------------------------------------------------------- + WindowStateGuard::~WindowStateGuard() + { + } + + //-------------------------------------------------------------------- + void WindowStateGuard::attach( const Reference< XWindow2 >& _rxWindow, const Reference< XControlModel >& _rxModel ) + { + if ( m_pImpl.is() ) + { + m_pImpl->dispose(); + m_pImpl = NULL; + } + + Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY ); + OSL_ENSURE( xModelProps.is() || !_rxModel.is(), "WindowStateGuard::attach: a model which is no XPropertySet?" ); + if ( _rxWindow.is() && xModelProps.is() ) + m_pImpl = new WindowStateGuard_Impl( _rxWindow, xModelProps ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/inc/FormComponent.hxx b/forms/source/inc/FormComponent.hxx new file mode 100644 index 000000000000..de72e2b392e8 --- /dev/null +++ b/forms/source/inc/FormComponent.hxx @@ -0,0 +1,1298 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_FORMCOMPONENT_HXX_ +#define _FORMS_FORMCOMPONENT_HXX_ + +#include "cloneable.hxx" +#include "ids.hxx" +#include "property.hrc" +#include "property.hxx" +#include "propertybaghelper.hxx" +#include "resettable.hxx" +#include "services.hxx" +#include "windowstateguard.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/validation/XValidatableFormComponent.hpp> +#include <com/sun/star/form/validation/XValidityConstraintListener.hpp> +#include <com/sun/star/form/XBoundComponent.hpp> +#include <com/sun/star/form/XBoundControl.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/form/XLoadListener.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#include <com/sun/star/sdb/XRowSetChangeListener.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/uno/XAggregation.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/form/XLoadable.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/propagg.hxx> +#include <comphelper/propertybag.hxx> +#include <comphelper/propmultiplex.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/implbase7.hxx> +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> + +#include <memory> + +//......................................................................... +namespace frm +{ +//......................................................................... + + // default tab index for components + const sal_Int16 FRM_DEFAULT_TABINDEX = 0; + + // macros for quickly declaring/implementing XServiceInfo + #define DECLARE_XPERSISTOBJECT() \ + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); \ + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); \ + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); \ + + // old macro for quickly implementing XServiceInfo::getImplementationName + #define IMPLEMENTATION_NAME(ImplName) \ + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException) \ + { return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.") + ::rtl::OUString::createFromAscii(#ImplName); } + + class OControlModel; + + //========================================================================= + //= ControlModelLock + //========================================================================= + /** class whose instances lock a OControlModel + + Locking here merely means locking the OControlModel's mutex. + + In addition to the locking facility, the class is also able to fire property + change notifications. This happens when the last ControlModelLock instance on a stack + dies. + */ + class ControlModelLock + { + public: + ControlModelLock( OControlModel& _rModel ) + :m_rModel( _rModel ) + ,m_bLocked( false ) + { + acquire(); + } + + ~ControlModelLock() + { + if ( m_bLocked ) + release(); + } + inline void acquire(); + inline void release(); + + inline OControlModel& getModel() const { return m_rModel; }; + + /** adds a property change notification, which is to be fired when the last lock on the model + (in the current thread) is released. + */ + void addPropertyNotification( + const sal_Int32 _nHandle, + const ::com::sun::star::uno::Any& _rOldValue, + const ::com::sun::star::uno::Any& _rNewValue + ); + + private: + void impl_notifyAll_nothrow(); + + private: + OControlModel& m_rModel; + bool m_bLocked; + ::com::sun::star::uno::Sequence< sal_Int32 > m_aHandles; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aOldValues; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aNewValues; + + private: + ControlModelLock(); // never implemented + ControlModelLock( const ControlModelLock& ); // never implemented + ControlModelLock& operator=( const ControlModelLock& ); // never implemented + }; + +//========================================================================= +//= OControl +//= base class for form layer controls +//========================================================================= +typedef ::cppu::ImplHelper3 < ::com::sun::star::awt::XControl + , ::com::sun::star::lang::XEventListener + , ::com::sun::star::lang::XServiceInfo + > OControl_BASE; + +class OControl :public ::cppu::OComponentHelper + ,public OControl_BASE +{ +protected: + ::osl::Mutex m_aMutex; + OImplementationIdsRef m_aHoldIdHelper; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl > + m_xControl; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> + m_xAggregate; + + ::comphelper::ComponentContext m_aContext; + WindowStateGuard m_aWindowStateGuard; + +public: + /** constructs a control + + @param _rFactory + the service factory for this control + @param _rAggregateService + the service name of the component to aggregate + @param _bSetDelegator + set this to <FALSE/> if you don't want the constructor to set the delegator at + the aggregate. In this case, you <em>have</em> to call doSetDelegator within your + own constructor. + + This is helpfull, if your derived class wants to cache an interface of the aggregate. + In this case, the aggregate needs to be queried for this interface <b>before</b> the + <member scope="com::sun::star::uno">XAggregation::setDelegator</member> call. + + In such a case, pass <FALSE/> to this parameter. Then, cache the aggregate's interface(s) + as needed. Afterwards, call <member>doSetDelegator</member>. + + In your destructor, you need to call <member>doResetDelegator</member> before + resetting the cached interfaces. This will reset the aggregates delegator to <NULL/>, + which will ensure that the <member scope="com::sun::star::uno">XInterface::release</member> + calls on the cached interfaces are really applied to the aggregate, instead of + the <type>OControl</type> itself. + */ + OControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rFactory, + const ::rtl::OUString& _rAggregateService, + const sal_Bool _bSetDelegator = sal_True + ); + + /** initializes the given peer with various settings necessary for form controls + */ + static void initFormControlPeer( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _rxPeer ); + +protected: + virtual ~OControl(); + + /** sets the control as delegator at the aggregate + + This has to be called from within your derived class' constructor, if and only + if you passed <FALSE/> to the <arg>_bSetDelegator</arg> parameter of the + <type>OControl</type> constructor. + */ + void doSetDelegator(); + void doResetDelegator(); + +// UNO + DECLARE_UNO3_AGG_DEFAULTS(OControl, OComponentHelper); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + +// XTypeProvider + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// XComponent (as base of XControl) + virtual void SAL_CALL dispose( ) throw(::com::sun::star::uno::RuntimeException) + { OComponentHelper::dispose(); } + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException) + { OComponentHelper::addEventListener(_rxListener); } + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException) + { OComponentHelper::removeEventListener(_rxListener); } + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException) = 0; + +// XServiceInfo - static version + static StringSequence SAL_CALL getSupportedServiceNames_Static() throw(::com::sun::star::uno::RuntimeException); + +// XControl + virtual void SAL_CALL setContext(const InterfaceRef& Context) throw (::com::sun::star::uno::RuntimeException); + virtual InterfaceRef SAL_CALL getContext() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL createPeer(const ::com::sun::star::uno::Reference<starawt::XToolkit>& Toolkit, const ::com::sun::star::uno::Reference<starawt::XWindowPeer>& Parent) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference<starawt::XWindowPeer> SAL_CALL getPeer() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setModel(const ::com::sun::star::uno::Reference<starawt::XControlModel>& Model) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference<starawt::XControlModel> SAL_CALL getModel() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference<starawt::XView> SAL_CALL getView() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isDesignMode() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isTransparent() throw (::com::sun::star::uno::RuntimeException); + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + // overwrite this and call the base class if you have additional types + + ::com::sun::star::uno::Sequence< ::rtl::OUString > getAggregateServiceNames(); + +private: + void impl_resetStateGuard_nothrow(); +}; + +//================================================================== +//= OBoundControl +//= a form control implementing the XBoundControl interface +//================================================================== +typedef ::cppu::ImplHelper1 < ::com::sun::star::form::XBoundControl + > OBoundControl_BASE; +class OBoundControl :public OControl + ,public OBoundControl_BASE +{ +protected: + sal_Bool m_bLocked : 1; + + ::rtl::OUString m_sOriginalHelpText; // as long as the text/value is invalid, we change the help text of our peer + ::com::sun::star::awt::FontDescriptor + m_aOriginalFont; // as long as the text/value is invalid, we also change the font + sal_Int32 m_nOriginalTextLineColor; // (we add red underlining) + +public: + OBoundControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory, + const ::rtl::OUString& _rAggregateService, + const sal_Bool _bSetDelegator = sal_True + ); + + virtual ~OBoundControl(); + + DECLARE_UNO3_AGG_DEFAULTS(OBoundControl, OControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + + // XBoundControl + virtual sal_Bool SAL_CALL getLock() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLock(sal_Bool _bLock) throw(::com::sun::star::uno::RuntimeException); + // default implementation just disables the controls, overwrite _setLock to change this behaviour + + // XControl + virtual sal_Bool SAL_CALL setModel(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& Model) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + // implement the lock setting + virtual void _setLock(sal_Bool _bLock); +}; + +//================================================================== +//= OControlModel +//= model of a form layer control +//================================================================== + +typedef ::cppu::ImplHelper7 < ::com::sun::star::form::XFormComponent + , ::com::sun::star::io::XPersistObject + , ::com::sun::star::container::XNamed + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::util::XCloneable + , ::com::sun::star::beans::XPropertyContainer + , ::com::sun::star::beans::XPropertyAccess + > OControlModel_BASE; + +class OControlModel :public ::cppu::OComponentHelper + ,public OPropertySetAggregationHelper + ,public OControlModel_BASE + ,public OCloneableAggregation + ,public IPropertyBagHelperContext +{ + +protected: + ::comphelper::ComponentContext m_aContext; + + ::osl::Mutex m_aMutex; + oslInterlockedCount m_lockCount; + + InterfaceRef m_xParent; // ParentComponent + OImplementationIdsRef m_aHoldIdHelper; + PropertyBagHelper m_aPropertyBagHelper; + + const ::comphelper::ComponentContext& + getContext() const { return m_aContext; } + +// <properties> + ::rtl::OUString m_aName; // name of the control + ::rtl::OUString m_aTag; // tag for additional data + sal_Int16 m_nTabIndex; // index within the taborder + sal_Int16 m_nClassId; // type of the control + sal_Bool m_bNativeLook; // should the control use the native platform look? +// </properties> + + +protected: + OControlModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory, // factory to create the aggregate with + const ::rtl::OUString& _rUnoControlModelTypeName, // service name of te model to aggregate + const ::rtl::OUString& rDefault = ::rtl::OUString(), // service name of the default control + const sal_Bool _bSetDelegator = sal_True // set to FALSE if you want to call setDelegator later (after returning from this ctor) + ); + OControlModel( + const OControlModel* _pOriginal, // the original object to clone + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory, // factory to create the aggregate with + const sal_Bool _bCloneAggregate = sal_True, // should the aggregate of the original be cloned, too? + const sal_Bool _bSetDelegator = sal_True // set to FALSE if you want to call setDelegator later (after returning from this ctor) + ); + virtual ~OControlModel(); + + /** to be called after a OBoundControlModel (a derivee, respectively) has been cloned + + <p>This method contains late initializations which cannot be done in the + constructor of this base class, since the virtual method of derived classes do + not yet work there.</p> + */ + virtual void clonedFrom( const OControlModel* _pOriginal ); + + using OComponentHelper::rBHelper; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + void readHelpTextCompatibly(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& _rxInStream); + void writeHelpTextCompatibly(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& _rxOutStream); + + void doSetDelegator(); + void doResetDelegator(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > getAggregateServiceNames(); + +public: + DECLARE_UNO3_AGG_DEFAULTS(OControl, OComponentHelper); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + +// XTypeProvider + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// XNamed + virtual ::rtl::OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setName(const ::rtl::OUString& aName) throw(::com::sun::star::uno::RuntimeException); + +// XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException) = 0; + +// XSericeInfo - static version(s) + static StringSequence SAL_CALL getSupportedServiceNames_Static() throw(::com::sun::star::uno::RuntimeException); + +// XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + +// XChild (base of XFormComponent) + virtual InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + using ::cppu::OPropertySetHelper::getFastPropertyValue; + +// ::com::sun::star::beans::XPropertyState + virtual ::com::sun::star::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle); + virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle); + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + +// XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException) = 0; + +// XPropertyContainer + virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, ::sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException); + +// XPropertyAccess + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPropertyValues( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aProps ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +protected: + using OPropertySetAggregationHelper::setPropertyValues; + using OPropertySetAggregationHelper::getPropertyValues; + +protected: + virtual void writeAggregate( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& _rxOutStream ) const; + virtual void readAggregate( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& _rxInStream ); + +protected: + // XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException); + // OPropertySetHelper + virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + /** describes the properties provided by this class, or its respective + derived class + + Derived classes usually call the base class first, and then append own properties. + */ + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // IPropertyBagHelperContext + virtual ::osl::Mutex& getMutex(); + virtual void describeFixedAndAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rFixedProperties, + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rAggregateProperties + ) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet > + getPropertiesInterface(); + + /** describes the properties of our aggregate + + The default implementation simply asks m_xAggregateSet for its properties. + + You usually only need to overload this method if you want to filter the aggregate + properties. + */ + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + +public: + struct LockAccess { friend class ControlModelLock; private: LockAccess() { } }; + + void lockInstance( LockAccess ); + oslInterlockedCount unlockInstance( LockAccess ); + + void firePropertyChanges( + const ::com::sun::star::uno::Sequence< sal_Int32 >& _rHandles, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& _rOldValues, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& _rNewValues, + LockAccess + ); + + inline ::osl::Mutex& + getInstanceMutex() { return m_aMutex; } +}; + +//================================================================== +// simple destructor +#define DECLARE_DEFAULT_DTOR( classname ) \ + ~classname() \ + +// constructor for cloning a class +#define DECLARE_DEFAULT_CLONE_CTOR( classname ) \ + classname( \ + const classname* _pOriginal, \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory \ + ); \ + +// all xtors for an inner class of the object hierarchy +#define DECLARE_DEFAULT_XTOR( classname ) \ + classname( \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, \ + const ::rtl::OUString& _rUnoControlModelTypeName, \ + const ::rtl::OUString& _rDefault \ + ); \ + DECLARE_DEFAULT_CLONE_CTOR( classname ) \ + DECLARE_DEFAULT_DTOR( classname ) \ + +// all xtors for an inner class of the object hierarchy which is *bound* +#define DECLARE_DEFAULT_BOUND_XTOR( classname ) \ + classname( \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, \ + const ::rtl::OUString& _rUnoControlModelTypeName, \ + const ::rtl::OUString& _rDefault, \ + const sal_Bool _bSupportExternalBinding, \ + const sal_Bool _bSupportsValidation \ + ); \ + DECLARE_DEFAULT_CLONE_CTOR( classname ) \ + DECLARE_DEFAULT_DTOR( classname ) \ + +// all xtors for a leas class of the object hierarchy +#define DECLARE_DEFAULT_LEAF_XTOR( classname ) \ + classname( \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory \ + ); \ + classname( \ + const classname* _pOriginal, \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory \ + ); \ + DECLARE_DEFAULT_DTOR( classname ) \ + +//================================================================== +// XCloneable +#define DECLARE_XCLONEABLE( ) \ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException) + +#define IMPLEMENT_DEFAULT_CLONING( classname ) \ + ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL classname::createClone( ) throw (::com::sun::star::uno::RuntimeException) \ + { \ + classname* pClone = new classname( this, getContext().getLegacyServiceFactory() ); \ + pClone->clonedFrom( this ); \ + return pClone; \ + } + +//================================================================== +//= OBoundControlModel +//= model of a form layer control which is bound to a data source field +//================================================================== +typedef ::cppu::ImplHelper4 < ::com::sun::star::form::XLoadListener + , ::com::sun::star::form::XReset + , ::com::sun::star::beans::XPropertyChangeListener + , ::com::sun::star::sdb::XRowSetChangeListener + > OBoundControlModel_BASE1; + +// separated into an own base class since derivees can disable the support for this +// interface, thus we want to easily exclude it in the queryInterface and getTypes +typedef ::cppu::ImplHelper1 < ::com::sun::star::form::XBoundComponent + > OBoundControlModel_COMMITTING; + +// dito +typedef ::cppu::ImplHelper2 < ::com::sun::star::form::binding::XBindableValue + , ::com::sun::star::util::XModifyListener + > OBoundControlModel_BINDING; + +// dito +typedef ::cppu::ImplHelper2 < ::com::sun::star::form::validation::XValidityConstraintListener + , ::com::sun::star::form::validation::XValidatableFormComponent + > OBoundControlModel_VALIDATION; + +class OBoundControlModel :public OControlModel + ,public OBoundControlModel_BASE1 + ,public OBoundControlModel_COMMITTING + ,public OBoundControlModel_BINDING + ,public OBoundControlModel_VALIDATION + ,public ::comphelper::OPropertyChangeListener +{ +protected: + enum ValueChangeInstigator + { + eDbColumnBinding, + eExternalBinding, + eOther + }; + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xField; + // the form which controls supplies the field we bind to. + ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadable > + m_xAmbientForm; + + ::rtl::OUString m_sValuePropertyName; + sal_Int32 m_nValuePropertyAggregateHandle; + sal_Int32 m_nFieldType; + ::com::sun::star::uno::Type m_aValuePropertyType; + bool m_bValuePropertyMayBeVoid; + + ResetHelper m_aResetHelper; + ::cppu::OInterfaceContainerHelper m_aUpdateListeners; + ::cppu::OInterfaceContainerHelper m_aFormComponentListeners; + + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > + m_xExternalBinding; + ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator > + m_xValidator; + ::com::sun::star::uno::Type m_aExternalValueType; + +// <properties> + ::rtl::OUString m_aControlSource; // Datenquelle, Name des Feldes + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xLabelControl; // reference to a sibling control (model) which is our label + sal_Bool m_bInputRequired; +// </properties> + + ::comphelper::OPropertyChangeMultiplexer* + m_pAggPropMultiplexer; + + bool m_bFormListening : 1; // are we currently a XLoadListener at our ambient form? + sal_Bool m_bLoaded : 1; + sal_Bool m_bRequired : 1; + const sal_Bool m_bCommitable : 1; // do we support XBoundComponent? + const sal_Bool m_bSupportsExternalBinding : 1; // do we support XBindableValue? + const sal_Bool m_bSupportsValidation : 1; // do we support XValidatable? + sal_Bool m_bForwardValueChanges : 1; // do we currently handle changes in the bound database field? + sal_Bool m_bTransferingValue : 1; // true if we're currently transfering our value to an external binding + sal_Bool m_bIsCurrentValueValid : 1; // flag specifying whether our current value is valid, relative to our external validator + sal_Bool m_bBindingControlsRO : 1; // is our ReadOnly property currently controlled by our external binding? + sal_Bool m_bBindingControlsEnable : 1; // is our Enabled property currently controlled by our external binding? + + ValueChangeInstigator m_eControlValueChangeInstigator; + +protected: + ::rtl::OUString m_aLabelServiceName; + // when setting the label for our control (property FM_PROP_CONTROLLABEL, member m_xLabelControl), + // we accept only objects supporting an XControlModel interface, an XServiceInfo interface and + // support for a service (XServiceInfo::supportsService) determined by this string. + // Any other arguments will throw an IllegalArgumentException. + // The default value is FM_COMPONENT_FIXEDTEXT. + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > + m_xCursor; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XColumnUpdate > + m_xColumnUpdate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XColumn > + m_xColumn; + +protected: + inline const ::rtl::OUString& getValuePropertyName( ) const { return m_sValuePropertyName; } + inline sal_Int32 getValuePropertyAggHandle( ) const { return m_nValuePropertyAggregateHandle; } + inline const ::rtl::OUString& getControlSource( ) const { return m_aControlSource; } + inline sal_Bool isRequired() const { return m_bRequired; } + inline sal_Bool isLoaded() const { return m_bLoaded; } + +protected: + + OBoundControlModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory, + // factory to create the aggregate with + const ::rtl::OUString& _rUnoControlModelTypeName, // service name of te model to aggregate + const ::rtl::OUString& _rDefault, // service name of the default control + const sal_Bool _bCommitable, // is the control (model) commitable ? + const sal_Bool _bSupportExternalBinding, // set to TRUE if you want to support XBindableValue + const sal_Bool _bSupportsValidation // set to TRUE if you want to support XValidatable + ); + OBoundControlModel( + const OBoundControlModel* _pOriginal, // the original object to clone + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory + // factory to create the aggregate with + ); + virtual ~OBoundControlModel(); + + /// late ctor after cloning + virtual void clonedFrom( const OControlModel* _pOriginal ); + + /** initializes the part of the class which is related to the control value. + + <p>Kind of late ctor, to be called for derivees which have a dedicated value property.<br/> + The value property is the property which's value is synced with either the database + column the object is bound to, or with the external value binding, if present.<br/> + E.g. for a text control model, this property will most probably be "Text".</p> + + <p>Derived classes are stronly recommend to call this method - at least the + "DataFieldProperty" (exposed in getFastPropertyValue) relies on the information + given herein, and needs to be supplied otherwise else.</p> + + <p>If this method has been called properly, then <member>setControlValue</member> + does not need to be overridden - it will simply set the property value at the + aggregate then.</p> + + @precond + The method has not be called before during the life time of the object. + + @param _rValuePropertyName + the name of the value property + @param _nValuePropertyExternalHandle + the handle of the property, as exposed to external components.<br/> + Normally, this information can be obtained dynamically (e.g. from describeFixedProperties), + but since this method is to be called from within the constructor of derived classes, + we prefer to be on the *really* safe side here .... + + @see setControlValue + @see suspendValueListening + @see resumeValueListening + @see describeFixedProperties + */ + void initValueProperty( + const ::rtl::OUString& _rValuePropertyName, + sal_Int32 _nValuePropertyExternalHandle + ); + + /** suspends listening at the value property + + <p>As long as this listening is suspended, changes in the value property will not be + recognized and not be handled.</p> + + @see initValueProperty + @see resumeValueListening + */ + void suspendValueListening( ); + + /** resumes listening at the value property + + <p>As long as this listening is suspended, changes in the value property will not be + recognized and not be handled.</p> + + @precond + listening at the value property is currently suspended + + @see initValueProperty + @see resumeValueListening + */ + void resumeValueListening( ); + + /** starts listening at the aggregate, for changes in the given property + + <p>The OBoundControlModel automatically registers a multiplexer which listens for + changes in the aggregate property values. By default, only the control value property + is observed. You may add additional properties to be observed with this method.</p> + + @see initValueProperty + @see _propertyChanged + */ + void startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName ); + + /** returns the default which should be used when resetting the control + + <p>The default implementation returns an empty Any.</p> + + @see resetNoBroadcast + */ + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + /** translates a db column value into a control value. + + <p>Must transform the very current value of the database column we're bound to + (<member>m_xColumn</member>) into a value which can be used as current value + for the control.</p> + + @see setControlValue + @pure + */ + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ) = 0; + + /** returns the data types which the control could use to exchange data with + an external value binding + + The types returned here are completely independent from the concrete value binding, + they're just candidates which depend on the control type, and possible the concrete state + of the control (i.e. some property value). + + If a control implementation supports multiple types, the ordering in the returned + sequence indicates preference: Preferred types are mentioned first. + + The default implementation returns the type of our value property. + */ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + + /** translates the given value, which was obtained from the current external value binding, + to a value which can be used in setControlValue + + <p>The default implementation returns the value itself, exception when it is VOID, and + our value property is not allowed to be void - in this case, the returned value is a + default-constructed value of the type required by our value property. + + @see hasExternalValueBinding + @see getExternalValueType + */ + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + + /** commits the current control value to our external value binding + + <p>The default implementation simply calls getControlValue.</p> + + @see hasExternalValueBinding + @see initValueProperty + */ + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + /** commits the current control value to the database column we're bound to + @precond + we're properly bound to a database column, especially <member>m_xColumnUpdate</member> + is not <NULL/> + @param _bPostReset + <TRUE/> if and only if the current control value results from a reset (<member>getDefaultForReset</member>) + @pure + */ + virtual sal_Bool commitControlValueToDbColumn( + bool _bPostReset + ) = 0; + + /** sets the given value as new current value for the control + + Besides some administrative work (such as caring for <member>m_eControlValueChangeInstigator</member>), + this method simply calls <member>doSetControlValue</member>. + + @precond + Our own mutex is locked. + @param _rValue + The value to set. This value is guaranteed to be created by + <member>translateDbColumnToControlValue</member> or + <member>translateExternalValueToControlValue</member> + @param _eInstigator + the instigator of the value change + */ + void setControlValue( + const ::com::sun::star::uno::Any& _rValue, + ValueChangeInstigator _eInstigator + ); + /** + <p>The default implementation will forward the given value to the aggregate, using + m_nValuePropertyAggregateHandle and/or m_sValuePropertyName.</p> + + @precond + Our own mutex is locked. + @param _rValue + The value to set. This value is guaranteed to be created by + <member>translateDbColumnToControlValue</member> or + <member>translateExternalValueToControlValue</member> + */ + virtual void doSetControlValue( + const ::com::sun::star::uno::Any& _rValue + ); + + /** retrieves the current value of the control + + <p>The default implementation will ask the aggregate for the property value + determined by either m_nValuePropertyAggregateHandle and/or m_sValuePropertyName.</p> + + @precond + Our own mutex is locked. + */ + virtual ::com::sun::star::uno::Any + getControlValue( ) const; + + /** called whenever a connection to a database column has been established + */ + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + /** called whenever a connection to a database column has been suspended + */ + virtual void onDisconnectedDbColumn(); + + /** called whenever a connection to an external supplier of values (XValueBinding) has been established + @see m_xExternalBinding + */ + virtual void onConnectedExternalValue( ); + /** called whenever a connection to an external supplier of values (XValueBinding) has been suspended + */ + virtual void onDisconnectedExternalValue(); + + /** called whenever an external validator has been registered + */ + virtual void onConnectedValidator( ); + /** called whenever an external validator has been revoked + */ + virtual void onDisconnectedValidator( ); + + /** nFieldType ist der Typ des Feldes, an das das Model gebunden werden soll. + Das Binden erfolgt genau dann, wenn Rueckgabewert sal_True. + Die Standard-Implementation erlaubt alles ausser den drei binary-Typen und + FieldType_OTHER. + */ + virtual sal_Bool approveDbColumnType(sal_Int32 _nColumnType); + + /** retrieves the current value of the control, in a shape which can be used with our + external validator. + + The default implementation simply calls <member>>translateControlValueToExternalValue</member>. + + @precond + Our own mutex is locked. + */ + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + /** retrieves the current value of the form component + + This is the implementation method for XValidatableFormComponent::getCurrentValue. The default implementation + calls translateControlValueToValidatableValue if a validator is present, otherwise getControlValue. + + @precond + our mutex is locked when this method is called + */ + virtual ::com::sun::star::uno::Any + getCurrentFormComponentValue() const; + + /** We can't write (new) common properties in this base class, as the file format doesn't allow this + (unfortunally). So derived classes may use the following to methods. They secure the written + data with marks, so any new common properties in newer versions will be skipped by older ones. + */ + void writeCommonProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + void readCommonProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + // the next method may be used in derived classes's read when an unknown version is encountered + void defaultCommonProperties(); + + /** called to reset the control to some kind of default. + + <p>The semantics of "default" is finally defined by the derived class (in particular, + by <member>getDefaultForReset</member>).</p> + + <p>No listener notification needs to be done in the derived class.</p> + + <p>Normally, you won't override this method, but <member>getDefaultForReset</member> instead.</p> + + @see getDefaultForReset + */ + virtual void resetNoBroadcast(); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + /// sets m_xField to the given new value, without notifying our listeners + void impl_setField_noNotify( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _rxField + ); + inline bool hasField() const + { + return m_xField.is(); + } + inline sal_Int32 getFieldType() const + { + return m_nFieldType; + } + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +public: + inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& getField() const + { + return m_xField; + } + +public: + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OBoundControlModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XReset + virtual void SAL_CALL reset( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual StringSequence SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo - static version + static StringSequence SAL_CALL getSupportedServiceNames_Static() throw(::com::sun::star::uno::RuntimeException); + + // XChild + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual void SAL_CALL write( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& OutStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& InStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XBoundComponent + virtual sal_Bool SAL_CALL commit() throw(::com::sun::star::uno::RuntimeException); + + // XUpdateBroadcaster (base of XBoundComponent) + virtual void SAL_CALL addUpdateListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeUpdateListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + using ::cppu::OPropertySetHelper::getFastPropertyValue; + +// ::com::sun::star::beans::XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + + // XRowSetChangeListener + virtual void SAL_CALL onRowSetChanged( const ::com::sun::star::lang::EventObject& i_Event ) throw (::com::sun::star::uno::RuntimeException); + +// XLoadListener + virtual void SAL_CALL loaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unloading( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unloaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reloading( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reloaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + +private: + // XBindableValue + virtual void SAL_CALL setValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding ) throw (::com::sun::star::form::binding::IncompatibleTypesException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > SAL_CALL getValueBinding( ) throw (::com::sun::star::uno::RuntimeException); + + // XModifyListener + virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& _rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XValidatable + virtual void SAL_CALL setValidator( const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator >& Validator ) throw (::com::sun::star::util::VetoException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator > SAL_CALL getValidator( ) throw (::com::sun::star::uno::RuntimeException); + + // XValidityConstraintListener + virtual void SAL_CALL validityConstraintChanged( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // XValidatableFormComponent + virtual sal_Bool SAL_CALL isValid( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getCurrentValue( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addFormComponentValidityListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XFormComponentValidityListener >& Listener ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeFormComponentValidityListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XFormComponentValidityListener >& Listener ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); + +protected: + // OPropertyChangeListener + virtual void + _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& _rEvt ) throw ( ::com::sun::star::uno::RuntimeException ); + + /// checks whether we currently have an external value binding in place + inline bool hasExternalValueBinding() const { return m_xExternalBinding.is(); } + + // checks whether we currently have an external validator + inline bool hasValidator() const { return m_xValidator.is(); } + + /** transfers the very current value of the db column we're bound to the control + @precond + our own mutex is locked + @precond + we don't have an external binding in place + */ + void transferDbValueToControl( ); + + /** transfers the current value of the active external binding to the control + @precond + we do have an active external binding in place + */ + void transferExternalValueToControl( ControlModelLock& _rInstanceLock ); + + /** transfers the control value to the external binding + @precond + our own mutex is locked, and _rInstanceLock is the guard locking it + @precond + we do have an active external binding in place + */ + void transferControlValueToExternal( ControlModelLock& _rInstanceLock ); + + /** calculates the type which is to be used to communicate with the current external binding, + and stores it in m_aExternalValueType + + The method checks the possible type candidates as returned by getSupportedBindingTypes, + and the types supported by the current external binding, if any. + */ + void calculateExternalValueType(); + + /** returns the type which should be used to exchange data with our external value binding + + @see initValueProperty + */ + const ::com::sun::star::uno::Type& + getExternalValueType() const { return m_aExternalValueType; } + + /** initializes the control from m_xField + + Basically, this method calls transferDbValueToControl - but only if our cursor is positioned + on a valid row. Otherwise, the control is reset. + + @precond + m_xField is not <NULL/> + */ + void initFromField( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& _rxForm ); + +private: + sal_Bool connectToField( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& _rxForm ); + void resetField(); + + /** does a new validation of the control value + + If necessary, our <member>m_bIsCurrentValueValid</member> member will be adjusted, + and changes will be notified. + + Note that it's not necessary that we're connected to a validator. If we are not, + it's assumed that our value is valid, and this is handled appropriately. + + Use this method if there is a potential that <b>only</b> the validity flag changed. If + any of the other aspects (our current value, or our current text) changed, then + pass <TRUE/> for <member>_bForceNotification</member>. + + @param _bForceNotification + if <TRUE/>, then the validity listeners will be notified, not matter whether the validity + changed. + */ + void recheckValidity( bool _bForceNotification ); + + /// initializes m_pAggPropMultiplexer + void implInitAggMultiplexer( ); + + /// initializes listening at the value property + void implInitValuePropertyListening( ) const; + + /** adds or removes the component as load listener to/from our form, and (if necessary) as RowSetChange listener at + our parent. + + @precond there must no external value binding be in place + */ + void doFormListening( const bool _bStart ); + + inline bool isFormListening() const { return m_bFormListening; } + + /** determines the new value of m_xAmbientForm + */ + void impl_determineAmbientForm_nothrow(); + + /** connects to a value supplier which is an database column. + + The column is take from our parent, which must be a database form respectively row set. + + @precond The control does not have an external value supplier + + @param _bFromReload + Determines whether the connection is made after the row set has been loaded (<FALSE/>) + or reloaded (<TRUE/>) + + @see impl_disconnectDatabaseColumn_noNotify + */ + void impl_connectDatabaseColumn_noNotify( + bool _bFromReload + ); + + /** disconnects from a value supplier which is an database column + + @precond The control does not have an external value supplier + @see impl_connectDatabaseColumn_noNotify + */ + void impl_disconnectDatabaseColumn_noNotify(); + + /** connects to an external value binding + + <p>Note that by definition, external data bindings superseede the SQL data binding which + is defined by our RowSet-column-related properties. This means that in case we're currently + connected to a database column when this is called, this connection is suspended.</p> + + @precond + the new external binding has already been approved (see <member>impl_approveValueBinding_nolock</member>) + @precond + there currently is no external binding in place + */ + void connectExternalValueBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding, + ControlModelLock& _rInstanceLock + ); + + /** disconnects from an external value binding + + @precond + there currently is an external binding in place + */ + void disconnectExternalValueBinding( ); + + /** connects the component to an external validator + + @precond + there currently is no active validator + @precond + our mutex is currently locked exactly once + */ + void connectValidator( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator >& _rxValidator + ); + + /** disconnects the component from it's current an external validator + + @precond + there currently is an active validator + @precond + our mutex is currently locked exactly once + */ + void disconnectValidator( ); + + /** called from within <member scope="com::sun::star:::form::binding">XBindableValue::setValueBinding</member> + to approve the new binding + + The default implementation approves the binding if and only if it is not <NULL/>, and supports + the type returned by getExternalValueType. + + @param _rxBinding + the binding which applies for being responsible for our value, Must not be + <NULL/> + @return + <TRUE/> if and only if the given binding can supply values in the proper type + + @seealso getExternalValueType + */ + sal_Bool impl_approveValueBinding_nolock( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + ); +}; + + //========================================================================= + //= inlines + //========================================================================= + inline void ControlModelLock::acquire() + { + m_rModel.lockInstance( OControlModel::LockAccess() ); + m_bLocked = true; + } + inline void ControlModelLock::release() + { + OSL_ENSURE( m_bLocked, "ControlModelLock::release: not locked!" ); + m_bLocked = false; + + if ( 0 == m_rModel.unlockInstance( OControlModel::LockAccess() ) ) + impl_notifyAll_nothrow(); + } + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_FORMCOMPONENT_HXX_ + diff --git a/forms/source/inc/InterfaceContainer.hxx b/forms/source/inc/InterfaceContainer.hxx new file mode 100644 index 000000000000..427d0c6ed190 --- /dev/null +++ b/forms/source/inc/InterfaceContainer.hxx @@ -0,0 +1,328 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_INTERFACE_CONTAINER_HXX_ +#define _FRM_INTERFACE_CONTAINER_HXX_ + +#include <hash_map> +#include <comphelper/stl_types.hxx> +#include <comphelper/types.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/container/XIndexReplace.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/script/XEventAttacherManager.hpp> +#include <com/sun/star/script/ScriptEvent.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <osl/mutex.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/implbase8.hxx> + +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + + +//================================================================== + struct ElementDescription + { + public: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInterface; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropertySet; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XChild > xChild; + ::com::sun::star::uno::Any aElementTypeInterface; + + public: + ElementDescription( ); + virtual ~ElementDescription(); + + private: + ElementDescription( const ElementDescription& ); // never implemented + ElementDescription& operator=( const ElementDescription& ); // never implemented + }; + +typedef ::std::vector<InterfaceRef> OInterfaceArray; +typedef ::std::hash_multimap< ::rtl::OUString, InterfaceRef, ::comphelper::UStringHash, ::comphelper::UStringEqual> OInterfaceMap; + +//================================================================== +// OInterfaceContainer +// implements a container for form components +//================================================================== +typedef ::cppu::ImplHelper8 < ::com::sun::star::container::XNameContainer + , ::com::sun::star::container::XIndexContainer + , ::com::sun::star::container::XContainer + , ::com::sun::star::container::XEnumerationAccess + , ::com::sun::star::script::XEventAttacherManager + , ::com::sun::star::beans::XPropertyChangeListener + , ::com::sun::star::io::XPersistObject + , ::com::sun::star::util::XCloneable + > OInterfaceContainer_BASE; + +class OInterfaceContainer : public OInterfaceContainer_BASE +{ +protected: + ::osl::Mutex& m_rMutex; + + OInterfaceArray m_aItems; + OInterfaceMap m_aMap; + ::cppu::OInterfaceContainerHelper m_aContainerListeners; + + const ::com::sun::star::uno::Type m_aElementType; + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory> m_xServiceFactory; + + + // EventManager + ::com::sun::star::uno::Reference< ::com::sun::star::script::XEventAttacherManager> m_xEventAttacher; + +public: + OInterfaceContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Type& _rElementType); + + OInterfaceContainer( ::osl::Mutex& _rMutex, const OInterfaceContainer& _cloneSource ); + + // late constructor for cloning + void clonedFrom( const OInterfaceContainer& _cloneSource ); + +protected: + virtual ~OInterfaceContainer(); + +public: +// ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName( ) throw(::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL write( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& OutStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& InStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw (::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException) ; + virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XEnumerationAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration> SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getElementNames( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameReplace + virtual void SAL_CALL replaceByName(const ::rtl::OUString& Name, const ::com::sun::star::uno::Any& _rElement) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameContainer + virtual void SAL_CALL insertByName(const ::rtl::OUString& Name, const ::com::sun::star::uno::Any& _rElement) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeByName(const ::rtl::OUString& Name) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XIndexAccess + virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getByIndex(sal_Int32 _nIndex) throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XIndexReplace + virtual void SAL_CALL replaceByIndex(sal_Int32 _nIndex, const ::com::sun::star::uno::Any& _rElement) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XIndexContainer + virtual void SAL_CALL insertByIndex(sal_Int32 _nIndex, const ::com::sun::star::uno::Any& Element) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeByIndex(sal_Int32 _nIndex) throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XContainer + virtual void SAL_CALL addContainerListener(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::script::XEventAttacherManager + virtual void SAL_CALL registerScriptEvent( sal_Int32 nIndex, const ::com::sun::star::script::ScriptEventDescriptor& aScriptEvent ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL registerScriptEvents( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& aScriptEvents ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL revokeScriptEvent( sal_Int32 nIndex, const ::rtl::OUString& aListenerType, const ::rtl::OUString& aEventMethod, const ::rtl::OUString& aRemoveListenerParam ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL revokeScriptEvents( sal_Int32 nIndex ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertEntry( sal_Int32 nIndex ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEntry( sal_Int32 nIndex ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor > SAL_CALL getScriptEvents( sal_Int32 Index ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL attach( sal_Int32 nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xObject, const ::com::sun::star::uno::Any& aHelper ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ServiceNotRegisteredException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL detach( sal_Int32 nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xObject ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addScriptListener( const ::com::sun::star::uno::Reference< ::com::sun::star::script::XScriptListener >& xListener ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeScriptListener( const ::com::sun::star::uno::Reference< ::com::sun::star::script::XScriptListener >& Listener ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + +protected: + // helper + virtual void SAL_CALL disposing(); + virtual void removeElementsNoEvents(sal_Int32 nIndex); + + /** to be overridden if elements which are to be inserted into the container shall be checked + + <p>the ElementDescription given can be used to cache information about the object - it will be passed + later on to implInserted/implReplaced.</p> + */ + virtual void approveNewElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject, + ElementDescription* _pElement + ); + + virtual ElementDescription* createElementMetaData( ); + + /** inserts an object into our internal structures + + @param _nIndex + the index at which position it should be inserted + @param _bEvents + if <TRUE/>, event knittings will be done + @param _pApprovalResult + must contain the result of an approveNewElement call. Can be <NULL/>, in this case, the approval + is done within implInsert. + @param _bFire + if <TRUE/>, a notification about the insertion will be fired + */ + void implInsert( + sal_Int32 _nIndex, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject, + sal_Bool _bEvents /* = sal_True */, + ElementDescription* _pApprovalResult /* = NULL */ , + sal_Bool _bFire /* = sal_True */ + ) throw(::com::sun::star::lang::IllegalArgumentException); + + // called after the object is inserted, but before the "real listeners" are notified + virtual void implInserted( const ElementDescription* _pElement ); + // called after the object is removed, but before the "real listeners" are notified + virtual void implRemoved(const InterfaceRef& _rxObject); + + /** called after an object was replaced. The default implementation notifies our listeners, after releasing + the instance lock. + */ + virtual void impl_replacedElement( + const ::com::sun::star::container::ContainerEvent& _rEvent, + ::osl::ClearableMutexGuard& _rInstanceLock + ); + + void SAL_CALL writeEvents(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + void SAL_CALL readEvents(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + + /** replace an element, specified by position + + @precond <arg>_nIndex</arg> is a valid index + @precond our mutex is locked exactly once, by the guard specified with <arg>_rClearBeforeNotify</arg> + + */ + void implReplaceByIndex( + const sal_Int32 _nIndex, + const ::com::sun::star::uno::Any& _rNewElement, + ::osl::ClearableMutexGuard& _rClearBeforeNotify + ); + + /** removes an element, specified by position + + @precond <arg>_nIndex</arg> is a valid index + @precond our mutex is locked exactly once, by the guard specified with <arg>_rClearBeforeNotify</arg> + + */ + void implRemoveByIndex( + const sal_Int32 _nIndex, + ::osl::ClearableMutexGuard& _rClearBeforeNotify + ); + + /** validates the given index + @throws ::com::sun::star::lang::IndexOutOfBoundsException + if the given index does not denote a valid position in our childs array + */ + void implCheckIndex( const sal_Int32 _nIndex ) SAL_THROW( ( ::com::sun::star::lang::IndexOutOfBoundsException ) ); + +private: + // hack for Vba Events + void fakeVbaEventsHack( sal_Int32 _nIndex ); + + // the runtime event format has changed from version SO5.2 to OOo + enum EventFormat + { + efVersionSO5x, + efVersionSO6x + }; + void transformEvents( const EventFormat _eTargetFormat ); + + void impl_createEventAttacher_nothrow(); +}; + +//================================================================== +//= OFormComponents +//================================================================== +typedef ::cppu::ImplHelper1< ::com::sun::star::form::XFormComponent> OFormComponents_BASE; +typedef ::cppu::OComponentHelper FormComponentsBase; + // else MSVC kills itself on some statements +class OFormComponents :public FormComponentsBase + ,public OInterfaceContainer + ,public OFormComponents_BASE +{ +protected: + ::osl::Mutex m_aMutex; + ::comphelper::InterfaceRef m_xParent; + +public: + OFormComponents(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + OFormComponents( const OFormComponents& _cloneSource ); + virtual ~OFormComponents(); + + DECLARE_UNO3_AGG_DEFAULTS(OFormComponents, FormComponentsBase); + + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// ::com::sun::star::form::XFormComponent + virtual ::comphelper::InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent(const ::comphelper::InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XEventListener + using OInterfaceContainer::disposing; +}; +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_INTERFACE_CONTAINER_HXX_ + diff --git a/forms/source/inc/cloneable.hxx b/forms/source/inc/cloneable.hxx new file mode 100644 index 000000000000..da3641d305bc --- /dev/null +++ b/forms/source/inc/cloneable.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_COMPONENT_CLONEABLE_HXX +#define FORMS_COMPONENT_CLONEABLE_HXX + +#include <com/sun/star/uno/XAggregation.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //==================================================================== + //= OCloneableAggregation + //==================================================================== + class OCloneableAggregation + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; + + protected: + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation > createAggregateClone( const OCloneableAggregation* _pOriginal ); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_COMPONENT_CLONEABLE_HXX + diff --git a/forms/source/inc/commanddescriptionprovider.hxx b/forms/source/inc/commanddescriptionprovider.hxx new file mode 100644 index 000000000000..f5d4823af477 --- /dev/null +++ b/forms/source/inc/commanddescriptionprovider.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef COMMANDDESCRIPTIONPROVIDER_HXX +#define COMMANDDESCRIPTIONPROVIDER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XModel.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> + +#include <boost/shared_ptr.hpp> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= ICommandDescriptionProvider + //==================================================================== + class SAL_NO_VTABLE ICommandDescriptionProvider + { + public: + virtual ::rtl::OUString getCommandDescription( const ::rtl::OUString& _rCommandURL ) const = 0; + + virtual ~ICommandDescriptionProvider() { } + }; + + typedef ::boost::shared_ptr< const ICommandDescriptionProvider > PCommandDescriptionProvider; + + //===================================================================== + //= factory + //===================================================================== + PCommandDescriptionProvider + createDocumentCommandDescriptionProvider( + const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument + ); + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // COMMANDDESCRIPTIONPROVIDER_HXX diff --git a/forms/source/inc/commandimageprovider.hxx b/forms/source/inc/commandimageprovider.hxx new file mode 100644 index 000000000000..d5d5b86a9b41 --- /dev/null +++ b/forms/source/inc/commandimageprovider.hxx @@ -0,0 +1,78 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef COMMANDIMAGEPROVIDER_HXX +#define COMMANDIMAGEPROVIDER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XModel.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <vcl/image.hxx> + +#include <boost/shared_ptr.hpp> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //===================================================================== + //= ICommandImageProvider + //===================================================================== + typedef ::rtl::OUString CommandURL; + typedef ::com::sun::star::uno::Sequence< CommandURL > CommandURLs; + typedef ::std::vector< Image > CommandImages; + + class SAL_NO_VTABLE ICommandImageProvider + { + public: + virtual CommandImages getCommandImages( + const CommandURLs& _rCommandURLs, + const bool _bLarge, + const bool _bHiContrast + ) const = 0; + + virtual ~ICommandImageProvider() { } + }; + + typedef ::boost::shared_ptr< const ICommandImageProvider > PCommandImageProvider; + + //===================================================================== + //= factory + //===================================================================== + PCommandImageProvider + createDocumentCommandImageProvider( + const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument + ); + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // COMMANDIMAGEPROVIDER_HXX diff --git a/forms/source/inc/componenttools.hxx b/forms/source/inc/componenttools.hxx new file mode 100644 index 000000000000..73771f19783a --- /dev/null +++ b/forms/source/inc/componenttools.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_INC_COMPONENTTOOLS_HXX +#define FORMS_SOURCE_INC_COMPONENTTOOLS_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/frame/XModel.hpp> +/** === end UNO includes === **/ + +#include <set> +#include <functional> + +//........................................................................ +namespace frm +{ +//........................................................................ + + struct TypeCompareLess : public ::std::binary_function< ::com::sun::star::uno::Type, ::com::sun::star::uno::Type, bool > + { + private: + typedef ::com::sun::star::uno::Type Type; + + public: + bool operator()( const Type& _rLHS, const Type& _rRHS ) + { + return _rLHS.getTypeName() < _rRHS.getTypeName(); + } + }; + + //==================================================================== + //= TypeBag + //==================================================================== + /** a helper class which merges sequences of <type scope="com::sun::star::uno">Type</type>s, + so that the resulting sequence contains every type at most once + */ + class TypeBag + { + public: + typedef ::com::sun::star::uno::Type Type; + typedef ::com::sun::star::uno::Sequence< Type > TypeSequence; + typedef ::std::set< Type, TypeCompareLess > TypeSet; + + private: + TypeSet m_aTypes; + + public: + TypeBag( + const TypeSequence& _rTypes1 + ); + + TypeBag( + const TypeSequence& _rTypes1, + const TypeSequence& _rTypes2 + ); + TypeBag( + const TypeSequence& _rTypes1, + const TypeSequence& _rTypes2, + const TypeSequence& _rTypes3 + ); + + void addTypes( const TypeSequence& _rTypes ); + + /** returns the types represented by this bag + */ + TypeSequence getTypes() const; + }; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > getXModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent ); + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_INC_COMPONENTTOOLS_HXX + diff --git a/forms/source/inc/controlfeatureinterception.hxx b/forms/source/inc/controlfeatureinterception.hxx new file mode 100644 index 000000000000..73f3b9d876c8 --- /dev/null +++ b/forms/source/inc/controlfeatureinterception.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_INC_CONTROLFEATUREINTERCEPTION_HXX +#define FORMS_SOURCE_INC_CONTROLFEATUREINTERCEPTION_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp> +/** === end UNO includes === **/ + +#include <memory> + +//........................................................................ +namespace frm +{ +//........................................................................ + + class UrlTransformer; + //==================================================================== + //= ControlFeatureInterception + //==================================================================== + /** helper class for controls which allow some of their features to be intercepted + by external instances + + For using this class, instantiate it as member, derive yourself from + <type scope="com::sun::star::frame">XDispatchProviderInterception</type>, and forward all + respective methods to this member. + + Additionally, don't forget to call <member>dispose</member> when your class is disposed itself. + */ + class ControlFeatureInterception + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > + m_xFirstDispatchInterceptor; + ::std::auto_ptr< UrlTransformer > m_pUrlTransformer; + + public: + /** retrieves our URL transformer, so our clients may use it, too + */ + const UrlTransformer& getTransformer() const { return *m_pUrlTransformer; } + + public: + ControlFeatureInterception( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ); + + // XDispatchProviderInterception + void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException ); + void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException ); + + // XComponent + void SAL_CALL dispose(); + + /** queries the interceptor chain for the given dispatch + */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > + queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& _rTargetFrameName, ::sal_Int32 _nSearchFlags ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** queries the interceptor chain for the given dispatch, with a blank target frame and no frame search flags + */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > + queryDispatch( const ::com::sun::star::util::URL& _rURL ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** queries the interceptor chain for the URL given as ASCII string, + with a blank target frame and no frame search flags + */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > + queryDispatch( const sal_Char* _pAsciiURL ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_INC_CONTROLFEATUREINTERCEPTION_HXX + diff --git a/forms/source/inc/featuredispatcher.hxx b/forms/source/inc/featuredispatcher.hxx new file mode 100644 index 000000000000..eec111c00406 --- /dev/null +++ b/forms/source/inc/featuredispatcher.hxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOLAR_DISPATCHER_HXX +#define FORMS_SOLAR_DISPATCHER_HXX + +#include <rtl/ustring.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //========================================================================= + //= IFeatureDispatcher + //========================================================================= + class IFeatureDispatcher + { + public: + /** dispatches a feature + + @param _nFeatureId + the id of the feature to dispatch + */ + virtual void dispatch( sal_Int16 _nFeatureId ) const = 0; + + /** dispatches a feature, with an additional named parameter + + @param _nFeatureId + the id of the feature to dispatch + + @param _pParamAsciiName + the Ascii name of the parameter of the dispatch call + + @param _rParamValue + the value of the parameter of the dispatch call + */ + virtual void dispatchWithArgument( + sal_Int16 _nFeatureId, + const sal_Char* _pParamName, + const ::com::sun::star::uno::Any& _rParamValue + ) const = 0; + + /** checks whether a given feature is enabled + */ + virtual bool isEnabled( sal_Int16 _nFeatureId ) const = 0; + + /** returns the boolean state of a feature + + Certain features may support more status information than only the enabled/disabled + state. The type of such additional information is fixed relative to a given feature, but + may differ between different features. + + This method allows retrieving status information about features which have an additional + boolean information associated with it. + */ + virtual bool getBooleanState( sal_Int16 _nFeatureId ) const = 0; + + /** returns the string state of a feature + + Certain features may support more status information than only the enabled/disabled + state. The type of such additional information is fixed relative to a given feature, but + may differ between different features. + + This method allows retrieving status information about features which have an additional + string information associated with it. + */ + virtual ::rtl::OUString getStringState( sal_Int16 _nFeatureId ) const = 0; + + /** returns the integer state of a feature + + Certain features may support more status information than only the enabled/disabled + state. The type of such additional information is fixed relative to a given feature, but + may differ between different features. + + This method allows retrieving status information about features which have an additional + integer information associated with it. + */ + virtual sal_Int32 getIntegerState( sal_Int16 _nFeatureId ) const = 0; + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_SOLAR_DISPATCHER_HXX diff --git a/forms/source/inc/formcontrolfont.hxx b/forms/source/inc/formcontrolfont.hxx new file mode 100644 index 000000000000..d14203046b7d --- /dev/null +++ b/forms/source/inc/formcontrolfont.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_COMPONENT_FORMCONTROLFONT_HXX +#define FORMS_SOURCE_COMPONENT_FORMCONTROLFONT_HXX + +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //===================================================================== + //= FontControlModel + //===================================================================== + class FontControlModel + { + private: + // <properties> + ::com::sun::star::awt::FontDescriptor m_aFont; + sal_Int16 m_nFontRelief; + sal_Int16 m_nFontEmphasis; + ::com::sun::star::uno::Any m_aTextLineColor; + ::com::sun::star::uno::Any m_aTextColor; + // </properties> + + bool m_bToolkitCompatibleDefaults; + + protected: + const ::com::sun::star::awt::FontDescriptor& getFont() const { return m_aFont; } + void setFont( const ::com::sun::star::awt::FontDescriptor& _rFont ) { m_aFont = _rFont; } + + void setTextColor( sal_Int32 _nColor ) { m_aTextColor <<= _nColor; } + void clearTextColor( ) { m_aTextColor.clear(); } + bool hasTextColor( ) const { return m_aTextColor.hasValue(); } + sal_Int32 getTextColor( ) const; + + void setTextLineColor( sal_Int32 _nColor ) { m_aTextLineColor <<= _nColor; } + void clearTextLineColor( ) { m_aTextLineColor.clear(); } + bool hasTextLineColor( ) const { return m_aTextLineColor.hasValue(); } + sal_Int32 getTextLineColor( ) const; + + protected: + FontControlModel( bool _bToolkitCompatibleDefaults ); + FontControlModel( const FontControlModel* _pOriginal ); + + protected: + bool isFontRelatedProperty( sal_Int32 _nPropertyHandle ) const; + bool isFontAggregateProperty( sal_Int32 _nPropertyHandle ) const; + + /// appends (!) the description of all font related properties to the given sequence + void describeFontRelatedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps ) const; + + void getFastPropertyValue ( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + sal_Bool convertFastPropertyValue ( ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw( ::com::sun::star::lang::IllegalArgumentException ); + void setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw ( ::com::sun::star::uno::Exception ); + ::com::sun::star::uno::Any + getPropertyDefaultByHandle ( sal_Int32 _nHandle ) const; + + private: + + private: + FontControlModel(); // never implemented + FontControlModel( const FontControlModel& ); // never implemented + FontControlModel& operator=( const FontControlModel& ); // never implemented + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_SOURCE_COMPONENT_FORMCONTROLFONT_HXX diff --git a/forms/source/inc/formnavigation.hxx b/forms/source/inc/formnavigation.hxx new file mode 100644 index 000000000000..6dc848bd8abe --- /dev/null +++ b/forms/source/inc/formnavigation.hxx @@ -0,0 +1,235 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_FORM_NAVIGATION_HXX +#define FORMS_FORM_NAVIGATION_HXX + +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <cppuhelper/implbase2.hxx> +#include "featuredispatcher.hxx" +#include <vector> +#include <map> +#include <memory> + + +//......................................................................... +namespace frm +{ +//......................................................................... + + class UrlTransformer; + class ControlFeatureInterception; + + //================================================================== + //= OFormNavigationHelper + //================================================================== + typedef ::cppu::ImplHelper2 < ::com::sun::star::frame::XDispatchProviderInterception + , ::com::sun::star::frame::XStatusListener + > OFormNavigationHelper_Base; + + class OFormNavigationHelper + :public OFormNavigationHelper_Base + ,public IFeatureDispatcher + { + private: + struct FeatureInfo + { + ::com::sun::star::util::URL aURL; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDispatcher; + sal_Bool bCachedState; + ::com::sun::star::uno::Any aCachedAdditionalState; + + FeatureInfo() : bCachedState( sal_False ) { } + }; + typedef ::std::map< sal_Int16, FeatureInfo > FeatureMap; + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + m_xORB; + ::std::auto_ptr< ControlFeatureInterception > + m_pFeatureInterception; + + // all supported features + FeatureMap m_aSupportedFeatures; + // all features which we have an external dispatcher for + sal_Int32 m_nConnectedFeatures; + + protected: + inline const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + getORB( ) const { return m_xORB; } + + protected: + OFormNavigationHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ); + virtual ~OFormNavigationHelper(); + + // XComponent + void SAL_CALL dispose( ) throw( ::com::sun::star::uno::RuntimeException ); + + // XDispatchProviderInterception + virtual void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + + // XStatusListener + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& State ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // IFeatureDispatcher + virtual void dispatch( sal_Int16 _nFeatureId ) const; + virtual void dispatchWithArgument( sal_Int16 _nFeatureId, const sal_Char* _pParamName, const ::com::sun::star::uno::Any& _rParamValue ) const; + virtual bool isEnabled( sal_Int16 _nFeatureId ) const; + virtual bool getBooleanState( sal_Int16 _nFeatureId ) const; + virtual ::rtl::OUString getStringState( sal_Int16 _nFeatureId ) const; + virtual sal_Int32 getIntegerState( sal_Int16 _nFeatureId ) const; + + // own overridables + /** is called when the interceptors have. + <p>The default implementations simply calls <member>updateDispatches</member>, + derived classes can prevent this in certain cases, or do additional handling.</p> + */ + virtual void interceptorsChanged( ); + + /** called when the status of a feature changed + + <p>The default implementation does nothing.</p> + + <p>If the feature in question does support more state information that just the + enabled/disabled state, then this additional information is to be retrieved in + a separate call.</p> + + @param _nFeatureId + the id of the feature + @param _bEnabled + determines if the features is enabled or disabled + @see getBooleanState + */ + virtual void featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ); + + /** notification for (potential) changes in the state of all features + <p>The base class implementation does nothing. Derived classes could force + their peer to update it's state, depending on the result of calls to + <member>IFeatureDispatcher::isEnabled</member>.</p> + */ + virtual void allFeatureStatesChanged( ); + + /** retrieves the list of supported features + <p>To be overridden by derived classes</p> + @param _rFeatureIds + the array of features to support. Out parameter to fill by the derivee's implementation + @pure + */ + virtual void getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ) = 0; + + protected: + /** update all our dispatches which are controlled by our dispatch interceptors + */ + void updateDispatches(); + + /** connect to the dispatch interceptors + */ + void connectDispatchers(); + + /** disconnect from the dispatch interceptors + */ + void disconnectDispatchers(); + + /** queries the interceptor chain for a dispatcher for the given URL + */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > + queryDispatch( const ::com::sun::star::util::URL& _rURL ); + + /** invalidates the set of supported features + + <p>This will invalidate all structures which are tied to the set of supported + features. All dispatches will be disconnected.<br/> + No automatic re-connection to potential external dispatchers is done, instead, + you have to call updateDispatches explicitly, if necessary.</p> + */ + void invalidateSupportedFeaturesSet(); + + private: + /** initialize m_aSupportedFeatures, if necessary + */ + void initializeSupportedFeatures(); + }; + + //================================================================== + //= OFormNavigationMapper + //================================================================== + /** helper class mapping between feature ids and feature URLs + */ + class OFormNavigationMapper + { + private: + ::std::auto_ptr< UrlTransformer > m_pUrlTransformer; + + public: + OFormNavigationMapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB + ); + ~OFormNavigationMapper( ); + + /** retrieves the ASCII representation of a feature URL belonging to an id + + @complexity O(log n) + @return NULL if the given id is not a known feature id (which is a valid usage) + */ + const char* getFeatureURLAscii( sal_Int16 _nFeatureId ); + + /** retrieves the feature URL belonging to an feature id + + @complexity O(log n), with n being the number of all potentially known URLs + @return + <TRUE/> if and only if the given id is a known feature id + (which is a valid usage) + */ + bool getFeatureURL( sal_Int16 _nFeatureId, ::com::sun::star::util::URL& /* [out] */ _rURL ); + + /** retrieves the feature id belonging to an feature URL + + @complexity O(n), with n being the number of all potentially known URLs + @return + the id of the feature URL, or -1 if the URl is not known + (which is a valid usage) + */ + sal_Int16 getFeatureId( const ::rtl::OUString& _rCompleteURL ); + + private: + OFormNavigationMapper( ); // never implemented + OFormNavigationMapper( const OFormNavigationMapper& ); // never implemented + OFormNavigationMapper& operator=( const OFormNavigationMapper& ); // never implemented + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_FORM_NAVIGATION_HXX diff --git a/forms/source/inc/forms_module.hxx b/forms/source/inc/forms_module.hxx new file mode 100644 index 000000000000..6655fb750e8d --- /dev/null +++ b/forms/source/inc/forms_module.hxx @@ -0,0 +1,332 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_MODULE_INCLUDE_CONTEXT + #error "not to be included directly! use 'foo_module.hxx instead'!" +#endif + +#ifndef FORMS_MODULE_NAMESPACE + #error "set FORMS_MODULE_NAMESPACE to your namespace identifier!" +#endif + +#include <osl/mutex.hxx> +#include <tools/resid.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <cppuhelper/factory.hxx> +#include <rtl/string.hxx> + +//......................................................................... +namespace FORMS_MODULE_NAMESPACE +{ +//......................................................................... + + typedef ::com::sun::star::uno::Reference< ::com::sun::star::lang::XSingleServiceFactory > (SAL_CALL *FactoryInstantiation) + ( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rServiceManager, + const ::rtl::OUString & _rComponentName, + ::cppu::ComponentInstantiation _pCreateFunction, + const ::com::sun::star::uno::Sequence< ::rtl::OUString > & _rServiceNames, + rtl_ModuleCount* _pModuleCounter + ); + + //========================================================================= + //= OFormsModule + //========================================================================= + class OFormsModule + { + private: + OFormsModule(); + // not implemented. OFormsModule is a static class + + protected: + // auto registration administration + static ::com::sun::star::uno::Sequence< ::rtl::OUString >* + s_pImplementationNames; + static ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > >* + s_pSupportedServices; + static ::com::sun::star::uno::Sequence< sal_Int64 >* + s_pCreationFunctionPointers; + static ::com::sun::star::uno::Sequence< sal_Int64 >* + s_pFactoryFunctionPointers; + + public: + /** register a component implementing a service with the given data. + @param _rImplementationName + the implementation name of the component + @param _rServiceNames + the services the component supports + @param _pCreateFunction + a function for creating an instance of the component + @param _pFactoryFunction + a function for creating a factory for that component + @see revokeComponent + */ + static void registerComponent( + const ::rtl::OUString& _rImplementationName, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rServiceNames, + ::cppu::ComponentInstantiation _pCreateFunction, + FactoryInstantiation _pFactoryFunction); + + /** revoke the registration for the specified component + @param _rImplementationName + the implementation name of the component + */ + static void revokeComponent( + const ::rtl::OUString& _rImplementationName); + + /** write the registration information of all known components + <p>writes the registration information of all components which are currently registered into the + specified registry.<p/> + <p>Usually used from within component_writeInfo.<p/> + @param _rxServiceManager + the service manager + @param _rRootKey + the registry key under which the information will be stored + @return + sal_True if the registration of all implementations was successfull, sal_False otherwise + */ + static sal_Bool writeComponentInfos( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxServiceManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::registry::XRegistryKey >& _rRootKey); + + /** creates a Factory for the component with the given implementation name. + <p>Usually used from within component_getFactory.<p/> + @param _rxServiceManager + a pointer to an XMultiServiceFactory interface as got in component_getFactory + @param _pImplementationName + the implementation name of the component + @return + the XInterface access to a factory for the component + */ + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getComponentFactory( + const ::rtl::OUString& _rImplementationName, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxServiceManager + ); + + private: + /** ensure that the impl class exists + @precond m_aMutex is guarded when this method gets called + */ + static void ensureImpl(); + }; + + //========================================================================== + //= OMultiInstanceAutoRegistration + //========================================================================== + template <class TYPE> + class OMultiInstanceAutoRegistration + { + public: + /** automatically registeres a multi instance component + <p>Assumed that the template argument has the three methods + <ul> + <li><code>static ::rtl::OUString getImplementationName_Static()</code><li/> + <li><code>static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static()</code><li/> + <li><code>static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&)</code> + </li> + <ul/> + the instantiation of this object will automatically register the class via <method>OFormsModule::registerComponent</method>. + <p/> + <p>The factory creation function used is <code>::cppu::createSingleFactory</code>.</p> + + @see OOneInstanceAutoRegistration + */ + OMultiInstanceAutoRegistration(); + ~OMultiInstanceAutoRegistration(); + }; + + template <class TYPE> + OMultiInstanceAutoRegistration<TYPE>::OMultiInstanceAutoRegistration() + { + OFormsModule::registerComponent( + TYPE::getImplementationName_Static(), + TYPE::getSupportedServiceNames_Static(), + TYPE::Create, + ::cppu::createSingleFactory + ); + } + + template <class TYPE> + OMultiInstanceAutoRegistration<TYPE>::~OMultiInstanceAutoRegistration() + { + OFormsModule::revokeComponent(TYPE::getImplementationName_Static()); + } + + //========================================================================== + //= OOneInstanceAutoRegistration + //========================================================================== + template <class TYPE> + class OOneInstanceAutoRegistration + { + public: + /** automatically registeres a single instance component + <p>Assumed that the template argument has the three methods + <ul> + <li><code>static ::rtl::OUString getImplementationName_Static()</code><li/> + <li><code>static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static()</code><li/> + <li><code>static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&)</code> + </li> + <ul/> + the instantiation of this object will automatically register the class via <method>OFormsModule::registerComponent</method>. + <p/> + The factory creation function used is <code>::cppu::createOneInstanceFactory</code>. + @see OOneInstanceAutoRegistration + */ + OOneInstanceAutoRegistration(); + ~OOneInstanceAutoRegistration(); + }; + + template <class TYPE> + OOneInstanceAutoRegistration<TYPE>::OOneInstanceAutoRegistration() + { + OFormsModule::registerComponent( + TYPE::getImplementationName_Static(), + TYPE::getSupportedServiceNames_Static(), + TYPE::Create, + ::cppu::createOneInstanceFactory + ); + } + + template <class TYPE> + OOneInstanceAutoRegistration<TYPE>::~OOneInstanceAutoRegistration() + { + OFormsModule::revokeComponent(TYPE::getImplementationName_Static()); + } + + //========================================================================== + //= helper for classes implementing the service handling via + //= OMultiInstanceAutoRegistration or OOneInstanceAutoRegistration + //========================================================================== + #define DECLARE_SERVICE_REGISTRATION( classname ) \ + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); \ + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); \ + \ + static ::rtl::OUString SAL_CALL getImplementationName_Static(); \ + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); \ + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); \ + \ + friend class OOneInstanceAutoRegistration< classname >; \ + friend class OMultiInstanceAutoRegistration< classname >; \ + + #define IMPLEMENT_SERVICE_REGISTRATION_BASE( classname, baseclass ) \ + \ + ::rtl::OUString SAL_CALL classname::getImplementationName( ) throw ( RuntimeException ) \ + { return getImplementationName_Static(); } \ + \ + Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames( ) throw (RuntimeException) \ + { \ + return ::comphelper::concatSequences( \ + getAggregateServiceNames(), \ + getSupportedServiceNames_Static() \ + ); \ + } \ + \ + ::rtl::OUString SAL_CALL classname::getImplementationName_Static() \ + { return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms."#classname ) ); } \ + \ + Reference< XInterface > SAL_CALL classname::Create( const Reference< XMultiServiceFactory >& _rxFactory ) \ + { return static_cast< XServiceInfo* >( new classname( _rxFactory ) ); } \ + \ + + #define IMPLEMENT_SERVICE_REGISTRATION_1( classname, baseclass, service1 ) \ + IMPLEMENT_SERVICE_REGISTRATION_BASE( classname, baseclass ) \ + \ + Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames_Static() \ + { \ + Sequence< ::rtl::OUString > aOwnNames( 1 ); \ + aOwnNames[ 0 ] = service1; \ + \ + return ::comphelper::concatSequences( \ + baseclass::getSupportedServiceNames_Static(), \ + aOwnNames \ + ); \ + } \ + + #define IMPLEMENT_SERVICE_REGISTRATION_2( classname, baseclass, service1, service2 ) \ + IMPLEMENT_SERVICE_REGISTRATION_BASE( classname, baseclass ) \ + \ + Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames_Static() \ + { \ + Sequence< ::rtl::OUString > aOwnNames( 2 ); \ + aOwnNames[ 0 ] = service1; \ + aOwnNames[ 1 ] = service2; \ + \ + return ::comphelper::concatSequences( \ + baseclass::getSupportedServiceNames_Static(), \ + aOwnNames \ + ); \ + } \ + + #define IMPLEMENT_SERVICE_REGISTRATION_7( classname, baseclass, service1, service2, service3, service4 , service5, service6, service7 ) \ + IMPLEMENT_SERVICE_REGISTRATION_BASE( classname, baseclass ) \ + \ + Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames_Static() \ + { \ + Sequence< ::rtl::OUString > aOwnNames( 7 ); \ + aOwnNames[ 0 ] = service1; \ + aOwnNames[ 1 ] = service2; \ + aOwnNames[ 2 ] = service3; \ + aOwnNames[ 3 ] = service4; \ + aOwnNames[ 4 ] = service5; \ + aOwnNames[ 5 ] = service6; \ + aOwnNames[ 6 ] = service7; \ + \ + return ::comphelper::concatSequences( \ + baseclass::getSupportedServiceNames_Static(), \ + aOwnNames \ + ); \ + } \ + + #define IMPLEMENT_SERVICE_REGISTRATION_8( classname, baseclass, service1, service2, service3, service4 , service5, service6, service7, service8 ) \ + IMPLEMENT_SERVICE_REGISTRATION_BASE( classname, baseclass ) \ + \ + Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames_Static() \ + { \ + Sequence< ::rtl::OUString > aOwnNames( 8 ); \ + aOwnNames[ 0 ] = service1; \ + aOwnNames[ 1 ] = service2; \ + aOwnNames[ 2 ] = service3; \ + aOwnNames[ 3 ] = service4; \ + aOwnNames[ 4 ] = service5; \ + aOwnNames[ 5 ] = service6; \ + aOwnNames[ 6 ] = service7; \ + aOwnNames[ 6 ] = service8; \ + \ + return ::comphelper::concatSequences( \ + baseclass::getSupportedServiceNames_Static(), \ + aOwnNames \ + ); \ + } \ + +//......................................................................... +} // namespace FORMS_MODULE_NAMESPACE +//......................................................................... diff --git a/forms/source/inc/forms_module_impl.hxx b/forms/source/inc/forms_module_impl.hxx new file mode 100644 index 000000000000..a2c0e50e55e7 --- /dev/null +++ b/forms/source/inc/forms_module_impl.hxx @@ -0,0 +1,209 @@ +#ifndef FORMS_MODULE_IMPLEMENTATION_INCLUDE_CONTEXT + #error "not to be included directly! use 'foo_module.hxx instead'!" +#endif + +#ifndef FORMS_MODULE_NAMESPACE + #error "set FORMS_MODULE_NAMESPACE to your namespace identifier!" +#endif + +#include <comphelper/sequence.hxx> + +//......................................................................... +namespace FORMS_MODULE_NAMESPACE +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::registry; + using namespace ::comphelper; + using namespace ::cppu; + + //========================================================================= + //= OFormsModule + //========================================================================= + + //-------------------------------------------------------------------------- + //- registration helper + //-------------------------------------------------------------------------- + + Sequence< ::rtl::OUString >* OFormsModule::s_pImplementationNames = NULL; + Sequence< Sequence< ::rtl::OUString > >* OFormsModule::s_pSupportedServices = NULL; + Sequence< sal_Int64 >* OFormsModule::s_pCreationFunctionPointers = NULL; + Sequence< sal_Int64 >* OFormsModule::s_pFactoryFunctionPointers = NULL; + + //-------------------------------------------------------------------------- + void OFormsModule::registerComponent( + const ::rtl::OUString& _rImplementationName, + const Sequence< ::rtl::OUString >& _rServiceNames, + ComponentInstantiation _pCreateFunction, + FactoryInstantiation _pFactoryFunction) + { + if (!s_pImplementationNames) + { + OSL_ENSURE(!s_pSupportedServices && !s_pCreationFunctionPointers && !s_pFactoryFunctionPointers, + "OFormsModule::registerComponent : inconsistent state (the pointers (1)) !"); + s_pImplementationNames = new Sequence< ::rtl::OUString >; + s_pSupportedServices = new Sequence< Sequence< ::rtl::OUString > >; + s_pCreationFunctionPointers = new Sequence< sal_Int64 >; + s_pFactoryFunctionPointers = new Sequence< sal_Int64 >; + } + OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers, + "OFormsModule::registerComponent : inconsistent state (the pointers (2)) !"); + + OSL_ENSURE( (s_pImplementationNames->getLength() == s_pSupportedServices->getLength()) + && (s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength()) + && (s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()), + "OFormsModule::registerComponent : inconsistent state !"); + + sal_Int32 nOldLen = s_pImplementationNames->getLength(); + s_pImplementationNames->realloc(nOldLen + 1); + s_pSupportedServices->realloc(nOldLen + 1); + s_pCreationFunctionPointers->realloc(nOldLen + 1); + s_pFactoryFunctionPointers->realloc(nOldLen + 1); + + s_pImplementationNames->getArray()[nOldLen] = _rImplementationName; + s_pSupportedServices->getArray()[nOldLen] = _rServiceNames; + s_pCreationFunctionPointers->getArray()[nOldLen] = reinterpret_cast<sal_Int64>(_pCreateFunction); + s_pFactoryFunctionPointers->getArray()[nOldLen] = reinterpret_cast<sal_Int64>(_pFactoryFunction); + } + + //-------------------------------------------------------------------------- + void OFormsModule::revokeComponent(const ::rtl::OUString& _rImplementationName) + { + if (!s_pImplementationNames) + { + OSL_ASSERT("OFormsModule::revokeComponent : have no class infos ! Are you sure called this method at the right time ?"); + return; + } + OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers, + "OFormsModule::revokeComponent : inconsistent state (the pointers) !"); + OSL_ENSURE( (s_pImplementationNames->getLength() == s_pSupportedServices->getLength()) + && (s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength()) + && (s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()), + "OFormsModule::revokeComponent : inconsistent state !"); + + sal_Int32 nLen = s_pImplementationNames->getLength(); + const ::rtl::OUString* pImplNames = s_pImplementationNames->getConstArray(); + for (sal_Int32 i=0; i<nLen; ++i, ++pImplNames) + { + if (pImplNames->equals(_rImplementationName)) + { + removeElementAt(*s_pImplementationNames, i); + removeElementAt(*s_pSupportedServices, i); + removeElementAt(*s_pCreationFunctionPointers, i); + removeElementAt(*s_pFactoryFunctionPointers, i); + break; + } + } + + if (s_pImplementationNames->getLength() == 0) + { + delete s_pImplementationNames; s_pImplementationNames = NULL; + delete s_pSupportedServices; s_pSupportedServices = NULL; + delete s_pCreationFunctionPointers; s_pCreationFunctionPointers = NULL; + delete s_pFactoryFunctionPointers; s_pFactoryFunctionPointers = NULL; + } + } + + //-------------------------------------------------------------------------- + sal_Bool OFormsModule::writeComponentInfos( + const Reference< XMultiServiceFactory >& /*_rxServiceManager*/, + const Reference< XRegistryKey >& _rxRootKey) + { + OSL_ENSURE(_rxRootKey.is(), "OFormsModule::writeComponentInfos : invalid argument !"); + + if (!s_pImplementationNames) + { + OSL_ASSERT("OFormsModule::writeComponentInfos : have no class infos ! Are you sure called this method at the right time ?"); + return sal_True; + } + OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers, + "OFormsModule::writeComponentInfos : inconsistent state (the pointers) !"); + OSL_ENSURE( (s_pImplementationNames->getLength() == s_pSupportedServices->getLength()) + && (s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength()) + && (s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()), + "OFormsModule::writeComponentInfos : inconsistent state !"); + + sal_Int32 nLen = s_pImplementationNames->getLength(); + const ::rtl::OUString* pImplName = s_pImplementationNames->getConstArray(); + const Sequence< ::rtl::OUString >* pServices = s_pSupportedServices->getConstArray(); + + ::rtl::OUString sRootKey("/", 1, RTL_TEXTENCODING_ASCII_US); + for (sal_Int32 i=0; i<nLen; ++i, ++pImplName, ++pServices) + { + ::rtl::OUString aMainKeyName(sRootKey); + aMainKeyName += *pImplName; + aMainKeyName += ::rtl::OUString::createFromAscii("/UNO/SERVICES"); + + try + { + Reference< XRegistryKey > xNewKey( _rxRootKey->createKey(aMainKeyName) ); + + const ::rtl::OUString* pService = pServices->getConstArray(); + for (sal_Int32 j=0; j<pServices->getLength(); ++j, ++pService) + xNewKey->createKey(*pService); + } + catch(Exception&) + { + OSL_ASSERT("OFormsModule::writeComponentInfos : something went wrong while creating the keys !"); + return sal_False; + } + } + + return sal_True; + } + + //-------------------------------------------------------------------------- + Reference< XInterface > OFormsModule::getComponentFactory( + const ::rtl::OUString& _rImplementationName, + const Reference< XMultiServiceFactory >& _rxServiceManager) + { + OSL_ENSURE(_rxServiceManager.is(), "OFormsModule::getComponentFactory : invalid argument (service manager) !"); + OSL_ENSURE(_rImplementationName.getLength(), "OFormsModule::getComponentFactory : invalid argument (implementation name) !"); + + if (!s_pImplementationNames) + { + OSL_ASSERT("OFormsModule::getComponentFactory : have no class infos ! Are you sure called this method at the right time ?"); + return NULL; + } + OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers, + "OFormsModule::getComponentFactory : inconsistent state (the pointers) !"); + OSL_ENSURE( (s_pImplementationNames->getLength() == s_pSupportedServices->getLength()) + && (s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength()) + && (s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()), + "OFormsModule::getComponentFactory : inconsistent state !"); + + + Reference< XInterface > xReturn; + + + sal_Int32 nLen = s_pImplementationNames->getLength(); + const ::rtl::OUString* pImplName = s_pImplementationNames->getConstArray(); + const Sequence< ::rtl::OUString >* pServices = s_pSupportedServices->getConstArray(); + const sal_Int64* pComponentFunction = s_pCreationFunctionPointers->getConstArray(); + const sal_Int64* pFactoryFunction = s_pFactoryFunctionPointers->getConstArray(); + + for (sal_Int32 i=0; i<nLen; ++i, ++pImplName, ++pServices, ++pComponentFunction, ++pFactoryFunction) + { + if (pImplName->equals(_rImplementationName)) + { + const FactoryInstantiation FactoryInstantiationFunction = reinterpret_cast<const FactoryInstantiation>(*pFactoryFunction); + const ComponentInstantiation ComponentInstantiationFunction = reinterpret_cast<const ComponentInstantiation>(*pComponentFunction); + + xReturn = FactoryInstantiationFunction( _rxServiceManager, *pImplName, ComponentInstantiationFunction, *pServices, NULL); + if (xReturn.is()) + { + xReturn->acquire(); + return xReturn.get(); + } + } + } + + return NULL; + } + +//......................................................................... +} // namespace FORMS_MODULE_NAMESPACE +//......................................................................... + diff --git a/forms/source/inc/frm_module.hxx b/forms/source/inc/frm_module.hxx new file mode 100644 index 000000000000..33d17d863d63 --- /dev/null +++ b/forms/source/inc/frm_module.hxx @@ -0,0 +1,37 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FRM_MODULE_HXX +#define FRM_MODULE_HXX + +#define FORMS_MODULE_INCLUDE_CONTEXT + #define FORMS_MODULE_NAMESPACE frm + #include "forms_module.hxx" +#undef FORMS_MODULE_INCLUDE_CONTEXT + +#endif // FRM_MODULE_HXX + diff --git a/forms/source/inc/frm_resource.hrc b/forms/source/inc/frm_resource.hrc new file mode 100644 index 000000000000..a35707cb1708 --- /dev/null +++ b/forms/source/inc/frm_resource.hrc @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_RESOURCE_HRC_ +#define _FRM_RESOURCE_HRC_ + +#ifndef _SOLAR_HRC +#include <svl/solar.hrc> +#endif + +//------------------------------------------------------------------------------ +#define RID_FRM_STRINGS_START RID_FORMLAYER_START + + + +//------------------------------------------------------------------------------ +//- String-IDs +#define RID_BASELISTBOX_ERROR_FILLLIST ( RID_FRM_STRINGS_START + 0 ) +#define RID_STR_IMPORT_GRAPHIC ( RID_FRM_STRINGS_START + 1 ) +#define RID_STR_CONTROL_SUBSTITUTED_NAME ( RID_FRM_STRINGS_START + 2 ) +#define RID_STR_CONTROL_SUBSTITUTED_EPXPLAIN ( RID_FRM_STRINGS_START + 3 ) +#define RID_STR_READERROR ( RID_FRM_STRINGS_START + 4 ) +#define RID_STR_CONNECTERROR ( RID_FRM_STRINGS_START + 5 ) +#define RID_ERR_LOADING_FORM ( RID_FRM_STRINGS_START + 6 ) +#define RID_ERR_REFRESHING_FORM ( RID_FRM_STRINGS_START + 7 ) +#define RID_STR_ERR_INSERTRECORD ( RID_FRM_STRINGS_START + 8 ) +#define RID_STR_ERR_UPDATERECORD ( RID_FRM_STRINGS_START + 9 ) +#define RID_STR_ERR_DELETERECORD ( RID_FRM_STRINGS_START + 10 ) +#define RID_STR_ERR_DELETERECORDS ( RID_FRM_STRINGS_START + 11 ) +#define RID_STR_NEED_NON_NULL_OBJECT ( RID_FRM_STRINGS_START + 12 ) +#define RID_STR_OPEN_GRAPHICS ( RID_FRM_STRINGS_START + 13 ) +#define RID_STR_CLEAR_GRAPHICS ( RID_FRM_STRINGS_START + 14 ) +#define RID_STR_INVALIDSTREAM ( RID_FRM_STRINGS_START + 15 ) +#define RID_STR_SYNTAXERROR ( RID_FRM_STRINGS_START + 16 ) +#define RID_STR_INCOMPATIBLE_TYPES ( RID_FRM_STRINGS_START + 17 ) +#define RID_STR_INVALID_VALIDATOR ( RID_FRM_STRINGS_START + 18 ) +#define RID_STR_LABEL_RECORD ( RID_FRM_STRINGS_START + 19 ) +#define RID_STR_LABEL_OF ( RID_FRM_STRINGS_START + 20 ) + +#define RID_STR_XFORMS_NO_BINDING_EXPRESSION ( RID_FRM_STRINGS_START + 21 ) +#define RID_STR_XFORMS_INVALID_BINDING_EXPRESSION (RID_FRM_STRINGS_START + 22) +#define RID_STR_XFORMS_INVALID_VALUE ( RID_FRM_STRINGS_START + 23 ) +#define RID_STR_XFORMS_REQUIRED ( RID_FRM_STRINGS_START + 24 ) +#define RID_STR_XFORMS_INVALID_CONSTRAINT ( RID_FRM_STRINGS_START + 25 ) +#define RID_STR_XFORMS_VALUE_IS_NOT_A ( RID_FRM_STRINGS_START + 26 ) +#define RID_STR_XFORMS_VALUE_MAX_INCL ( RID_FRM_STRINGS_START + 27 ) +#define RID_STR_XFORMS_VALUE_MAX_EXCL ( RID_FRM_STRINGS_START + 28 ) +#define RID_STR_XFORMS_VALUE_MIN_INCL ( RID_FRM_STRINGS_START + 29 ) +#define RID_STR_XFORMS_VALUE_MIN_EXCL ( RID_FRM_STRINGS_START + 30 ) +#define RID_STR_XFORMS_VALUE_PATTERN ( RID_FRM_STRINGS_START + 31 ) +#define RID_STR_XFORMS_VALUE_TOTAL_DIGITS ( RID_FRM_STRINGS_START + 32 ) +#define RID_STR_XFORMS_VALUE_FRACTION_DIGITS ( RID_FRM_STRINGS_START + 33 ) +#define RID_STR_XFORMS_VALUE_LENGTH ( RID_FRM_STRINGS_START + 34 ) +#define RID_STR_XFORMS_VALUE_MIN_LENGTH ( RID_FRM_STRINGS_START + 35 ) +#define RID_STR_XFORMS_VALUE_MAX_LENGTH ( RID_FRM_STRINGS_START + 36 ) + +#define RID_STR_DATATYPE_STRING ( RID_FRM_STRINGS_START + 37 ) +#define RID_STR_DATATYPE_URL ( RID_FRM_STRINGS_START + 38 ) +#define RID_STR_DATATYPE_BOOLEAN ( RID_FRM_STRINGS_START + 39 ) +#define RID_STR_DATATYPE_DECIMAL ( RID_FRM_STRINGS_START + 40 ) +#define RID_STR_DATATYPE_FLOAT ( RID_FRM_STRINGS_START + 41 ) +#define RID_STR_DATATYPE_DOUBLE ( RID_FRM_STRINGS_START + 42 ) +#define RID_STR_DATATYPE_DATE ( RID_FRM_STRINGS_START + 43 ) +#define RID_STR_DATATYPE_TIME ( RID_FRM_STRINGS_START + 44 ) +#define RID_STR_DATATYPE_DATETIME ( RID_FRM_STRINGS_START + 45 ) +#define RID_STR_DATATYPE_YEARMONTH ( RID_FRM_STRINGS_START + 46 ) +#define RID_STR_DATATYPE_YEAR ( RID_FRM_STRINGS_START + 47 ) +#define RID_STR_DATATYPE_MONTHDAY ( RID_FRM_STRINGS_START + 48 ) +#define RID_STR_DATATYPE_MONTH ( RID_FRM_STRINGS_START + 49 ) +#define RID_STR_DATATYPE_DAY ( RID_FRM_STRINGS_START + 50 ) + +#define RID_STR_XFORMS_CANT_EVALUATE ( RID_FRM_STRINGS_START + 51 ) +#define RID_STR_XFORMS_PATTERN_DOESNT_MATCH ( RID_FRM_STRINGS_START + 52 ) +#define RID_STR_XFORMS_BINDING_UI_NAME ( RID_FRM_STRINGS_START + 53 ) + +#define RID_STR_QUERY_SAVE_MODIFIED_ROW ( RID_FRM_STRINGS_START + 54 ) +#define RID_STR_COULD_NOT_SET_ORDER ( RID_FRM_STRINGS_START + 55 ) +#define RID_STR_COULD_NOT_SET_FILTER ( RID_FRM_STRINGS_START + 56 ) +#define RID_STR_FEATURE_REQUIRES_PARAMETERS ( RID_FRM_STRINGS_START + 57 ) +#define RID_STR_FEATURE_NOT_EXECUTABLE ( RID_FRM_STRINGS_START + 58 ) +#define RID_STR_FEATURE_UNKNOWN ( RID_FRM_STRINGS_START + 59 ) + +#endif // _FRM_RESOURCE_HRC_ + diff --git a/forms/source/inc/frm_resource.hxx b/forms/source/inc/frm_resource.hxx new file mode 100644 index 000000000000..33349e6ad620 --- /dev/null +++ b/forms/source/inc/frm_resource.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_RESOURCE_HXX_ +#define _FRM_RESOURCE_HXX_ + +#include <rtl/ustring.hxx> + +class SimpleResMgr; +//......................................................................... +namespace frm +{ + +#define FRM_RES_STRING(id) ResourceManager::loadString(id) + + //================================================================== + //= ResourceManager + //= handling ressources within the FormLayer library + //================================================================== + class ResourceManager + { + static SimpleResMgr* m_pImpl; + + private: + // no instantiation allowed + ResourceManager() { } + ~ResourceManager() { } + + // we'll instantiate one static member of the following class, which, in it's dtor, + // ensures that m_pImpl will be deleted + class EnsureDelete + { + public: + EnsureDelete() { } + ~EnsureDelete(); + }; + friend class EnsureDelete; + + protected: + static void ensureImplExists(); + + public: + /** loads the string with the specified resource id from the FormLayer resource file + */ + static ::rtl::OUString loadString(sal_uInt16 _nResId); + }; + +//......................................................................... +} +//......................................................................... + +#endif // _FRM_RESOURCE_HXX_ + diff --git a/forms/source/inc/frm_strings.hxx b/forms/source/inc/frm_strings.hxx new file mode 100644 index 000000000000..8a8105d2e1a7 --- /dev/null +++ b/forms/source/inc/frm_strings.hxx @@ -0,0 +1,360 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FRM_STRINGS_HXX +#define FRM_STRINGS_HXX + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +//.............................................................................. +namespace frm +{ +//.............................................................................. + + struct ConstAsciiString + { + const sal_Char* ascii; + sal_Int32 length; + + inline operator ::rtl::OUString () const; + inline operator const sal_Char* () const { return ascii; } + + inline ConstAsciiString(const sal_Char* _pAsciiZeroTerminated, const sal_Int32 _nLength); + inline ~ConstAsciiString(); + + private: + mutable ::rtl::OUString* ustring; + }; + + //------------------------------------------------------------ + inline ConstAsciiString::ConstAsciiString(const sal_Char* _pAsciiZeroTerminated, const sal_Int32 _nLength) + :ascii(_pAsciiZeroTerminated) + ,length(_nLength) + ,ustring(NULL) + { + } + + //------------------------------------------------------------ + inline ConstAsciiString::~ConstAsciiString() + { + delete ustring; + ustring = NULL; + } + + //------------------------------------------------------------ + inline ConstAsciiString::operator ::rtl::OUString () const + { + if ( !ustring ) + ustring = new ::rtl::OUString( ascii, length, RTL_TEXTENCODING_ASCII_US ); + return *ustring; + } + + #ifndef FORMS_IMPLEMENT_STRINGS + #define FORMS_CONSTASCII_STRING( ident, string ) \ + extern const ConstAsciiString ident + #else + #define FORMS_CONSTASCII_STRING( ident, string ) \ + extern const ConstAsciiString ident( string, sizeof( string )-1 ) + #endif + +//.............................................................................. +} // namespace frm +//.............................................................................. + +//.............................................................................. +namespace frm +{ +//.............................................................................. + + //-------------------------------------------------------------------------- + //- properties + //-------------------------------------------------------------------------- + FORMS_CONSTASCII_STRING( PROPERTY_TABINDEX, "TabIndex" ); + FORMS_CONSTASCII_STRING( PROPERTY_TAG, "Tag" ); + FORMS_CONSTASCII_STRING( PROPERTY_NAME, "Name" ); + FORMS_CONSTASCII_STRING( PROPERTY_CLASSID, "ClassId" ); + FORMS_CONSTASCII_STRING( PROPERTY_FETCHSIZE, "FetchSize" ); + FORMS_CONSTASCII_STRING( PROPERTY_VALUE, "Value" ); + FORMS_CONSTASCII_STRING( PROPERTY_TEXT, "Text" ); + FORMS_CONSTASCII_STRING( PROPERTY_LABEL, "Label" ); + FORMS_CONSTASCII_STRING( PROPERTY_CANINSERT, "CanInsert" ); + FORMS_CONSTASCII_STRING( PROPERTY_CANUPDATE, "CanUpdate" ); + FORMS_CONSTASCII_STRING( PROPERTY_CANDELETE, "CanDelete" ); + FORMS_CONSTASCII_STRING( PROPERTY_NAVIGATION, "NavigationBarMode" ); + FORMS_CONSTASCII_STRING( PROPERTY_HASNAVIGATION, "HasNavigationBar" ); + FORMS_CONSTASCII_STRING( PROPERTY_CYCLE, "Cycle" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTROLSOURCE, "DataField" ); + FORMS_CONSTASCII_STRING( PROPERTY_ENABLED, "Enabled" ); + FORMS_CONSTASCII_STRING( PROPERTY_ENABLEVISIBLE, "EnableVisible" ); + FORMS_CONSTASCII_STRING( PROPERTY_READONLY, "ReadOnly" ); + FORMS_CONSTASCII_STRING( PROPERTY_RELEVANT, "Relevant" ); + FORMS_CONSTASCII_STRING( PROPERTY_ISREADONLY, "IsReadOnly" ); + FORMS_CONSTASCII_STRING( PROPERTY_FILTER, "Filter" ); + FORMS_CONSTASCII_STRING( PROPERTY_WIDTH, "Width" ); + FORMS_CONSTASCII_STRING( PROPERTY_SEARCHABLE, "IsSearchable" ); + FORMS_CONSTASCII_STRING( PROPERTY_MULTILINE, "MultiLine" ); + FORMS_CONSTASCII_STRING( PROPERTY_TARGET_URL, "TargetURL" ); + FORMS_CONSTASCII_STRING( PROPERTY_TARGET_FRAME, "TargetFrame" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULTCONTROL, "DefaultControl" ); + FORMS_CONSTASCII_STRING( PROPERTY_MAXTEXTLEN, "MaxTextLen" ); + FORMS_CONSTASCII_STRING( PROPERTY_EDITMASK, "EditMask" ); + FORMS_CONSTASCII_STRING( PROPERTY_SIZE, "Size" ); + FORMS_CONSTASCII_STRING( PROPERTY_SPIN, "Spin" ); + FORMS_CONSTASCII_STRING( PROPERTY_DATE, "Date" ); + FORMS_CONSTASCII_STRING( PROPERTY_TIME, "Time" ); + FORMS_CONSTASCII_STRING( PROPERTY_STATE, "State" ); + FORMS_CONSTASCII_STRING( PROPERTY_TRISTATE, "TriState" ); + FORMS_CONSTASCII_STRING( PROPERTY_HIDDEN_VALUE, "HiddenValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_BUTTONTYPE, "ButtonType" ); + FORMS_CONSTASCII_STRING( PROPERTY_STRINGITEMLIST, "StringItemList" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_TEXT, "DefaultText" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_STATE, "DefaultState" ); + FORMS_CONSTASCII_STRING( PROPERTY_FORMATKEY, "FormatKey" ); + FORMS_CONSTASCII_STRING( PROPERTY_FORMATSSUPPLIER, "FormatsSupplier" ); + FORMS_CONSTASCII_STRING( PROPERTY_SUBMIT_ACTION, "SubmitAction" ); + FORMS_CONSTASCII_STRING( PROPERTY_SUBMIT_TARGET, "SubmitTarget" ); + FORMS_CONSTASCII_STRING( PROPERTY_SUBMIT_METHOD, "SubmitMethod" ); + FORMS_CONSTASCII_STRING( PROPERTY_SUBMIT_ENCODING, "SubmitEncoding" ); + FORMS_CONSTASCII_STRING( PROPERTY_IMAGE_URL, "ImageURL" ); + FORMS_CONSTASCII_STRING( PROPERTY_IMAGE_POSITION, "ImagePosition" ); + FORMS_CONSTASCII_STRING( PROPERTY_EMPTY_IS_NULL, "ConvertEmptyToNull" ); + FORMS_CONSTASCII_STRING( PROPERTY_LISTSOURCETYPE, "ListSourceType" ); + FORMS_CONSTASCII_STRING( PROPERTY_LISTSOURCE, "ListSource" ); + FORMS_CONSTASCII_STRING( PROPERTY_SELECT_SEQ, "SelectedItems" ); + FORMS_CONSTASCII_STRING( PROPERTY_VALUE_SEQ, "ValueItemList" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_SELECT_SEQ, "DefaultSelection" ); + FORMS_CONSTASCII_STRING( PROPERTY_MULTISELECTION, "MultiSelection" ); + FORMS_CONSTASCII_STRING( PROPERTY_ALIGN, "Align" ); + FORMS_CONSTASCII_STRING( PROPERTY_VERTICAL_ALIGN, "VerticalAlign" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_DATE, "DefaultDate" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_TIME, "DefaultTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_VALUE, "DefaultValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_DECIMAL_ACCURACY, "DecimalAccuracy" ); + FORMS_CONSTASCII_STRING( PROPERTY_CURSORSOURCE, "DataSelection" ); + FORMS_CONSTASCII_STRING( PROPERTY_CURSORSOURCETYPE, "DataSelectionType" ); + FORMS_CONSTASCII_STRING( PROPERTY_FIELDTYPE, "Type" ); + FORMS_CONSTASCII_STRING( PROPERTY_DECIMALS, "Decimals" ); + FORMS_CONSTASCII_STRING( PROPERTY_REFVALUE, "RefValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_UNCHECKED_REFVALUE, "SecondaryRefValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_VALUEMIN, "ValueMin" ); + FORMS_CONSTASCII_STRING( PROPERTY_VALUEMAX, "ValueMax" ); + FORMS_CONSTASCII_STRING( PROPERTY_STRICTFORMAT, "StrictFormat" ); + FORMS_CONSTASCII_STRING( PROPERTY_ALLOWADDITIONS, "AllowInserts" ); + FORMS_CONSTASCII_STRING( PROPERTY_ALLOWEDITS, "AllowUpdates" ); + FORMS_CONSTASCII_STRING( PROPERTY_ALLOWDELETIONS, "AllowDeletes" ); + FORMS_CONSTASCII_STRING( PROPERTY_MASTERFIELDS, "MasterFields" ); + FORMS_CONSTASCII_STRING( PROPERTY_ISPASSTHROUGH, "IsPassThrough" ); + FORMS_CONSTASCII_STRING( PROPERTY_QUERY, "Query" ); + FORMS_CONSTASCII_STRING( PROPERTY_LITERALMASK, "LiteralMask" ); + FORMS_CONSTASCII_STRING( PROPERTY_VALUESTEP, "ValueStep" ); + FORMS_CONSTASCII_STRING( PROPERTY_SHOWTHOUSANDSEP, "ShowThousandsSeparator" ); + FORMS_CONSTASCII_STRING( PROPERTY_CURRENCYSYMBOL, "CurrencySymbol" ); + FORMS_CONSTASCII_STRING( PROPERTY_DATEFORMAT, "DateFormat" ); + FORMS_CONSTASCII_STRING( PROPERTY_DATEMIN, "DateMin" ); + FORMS_CONSTASCII_STRING( PROPERTY_DATEMAX, "DateMax" ); + FORMS_CONSTASCII_STRING( PROPERTY_DATE_SHOW_CENTURY, "DateShowCentury" ); + FORMS_CONSTASCII_STRING( PROPERTY_TIMEFORMAT, "TimeFormat" ); + FORMS_CONSTASCII_STRING( PROPERTY_TIMEMIN, "TimeMin" ); + FORMS_CONSTASCII_STRING( PROPERTY_TIMEMAX, "TimeMax" ); + FORMS_CONSTASCII_STRING( PROPERTY_LINECOUNT, "LineCount" ); + FORMS_CONSTASCII_STRING( PROPERTY_BOUNDCOLUMN, "BoundColumn" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT, "FontDescriptor" ); + FORMS_CONSTASCII_STRING( PROPERTY_FILLCOLOR, "FillColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_LINECOLOR, "LineColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_DROPDOWN, "Dropdown" ); + FORMS_CONSTASCII_STRING( PROPERTY_HSCROLL, "HScroll" ); + FORMS_CONSTASCII_STRING( PROPERTY_VSCROLL, "VScroll" ); + FORMS_CONSTASCII_STRING( PROPERTY_TABSTOP, "Tabstop" ); + FORMS_CONSTASCII_STRING( PROPERTY_AUTOCOMPLETE, "Autocomplete" ); + FORMS_CONSTASCII_STRING( PROPERTY_HARDLINEBREAKS, "HardLineBreaks" ); + FORMS_CONSTASCII_STRING( PROPERTY_PRINTABLE, "Printable" ); + FORMS_CONSTASCII_STRING( PROPERTY_ECHO_CHAR, "EchoChar" ); + FORMS_CONSTASCII_STRING( PROPERTY_ROWHEIGHT, "RowHeight" ); + FORMS_CONSTASCII_STRING( PROPERTY_HELPTEXT, "HelpText" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_NAME, "FontName" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_STYLENAME, "FontStyleName" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_FAMILY, "FontFamily" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_CHARSET, "FontCharset" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_HEIGHT, "FontHeight" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_WEIGHT, "FontWeight" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_SLANT, "FontSlant" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_UNDERLINE, "FontUnderline" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_WORDLINEMODE, "FontWordLineMode" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_STRIKEOUT, "FontStrikeout" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONTEMPHASISMARK, "FontEmphasisMark" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONTRELIEF, "FontRelief" ); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_CHARWIDTH, "FontCharWidth"); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_KERNING, "FontKerning"); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_ORIENTATION, "FontOrientation"); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_PITCH, "FontPitch"); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_TYPE, "FontType"); + FORMS_CONSTASCII_STRING( PROPERTY_FONT_WIDTH, "FontWidth"); + FORMS_CONSTASCII_STRING( PROPERTY_HELPURL, "HelpURL" ); + FORMS_CONSTASCII_STRING( PROPERTY_RECORDMARKER, "HasRecordMarker" ); + FORMS_CONSTASCII_STRING( PROPERTY_BOUNDFIELD, "BoundField" ); + FORMS_CONSTASCII_STRING( PROPERTY_INPUT_REQUIRED, "InputRequired" ); + FORMS_CONSTASCII_STRING( PROPERTY_TREATASNUMERIC, "TreatAsNumber" ); + FORMS_CONSTASCII_STRING( PROPERTY_EFFECTIVE_VALUE, "EffectiveValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_EFFECTIVE_DEFAULT, "EffectiveDefault" ); + FORMS_CONSTASCII_STRING( PROPERTY_EFFECTIVE_MIN, "EffectiveMin" ); + FORMS_CONSTASCII_STRING( PROPERTY_EFFECTIVE_MAX, "EffectiveMax" ); + FORMS_CONSTASCII_STRING( PROPERTY_HIDDEN, "Hidden" ); + FORMS_CONSTASCII_STRING( PROPERTY_FILTERPROPOSAL, "UseFilterValueProposal" ); + FORMS_CONSTASCII_STRING( PROPERTY_FIELDSOURCE, "FieldSource" ); + FORMS_CONSTASCII_STRING( PROPERTY_TABLENAME, "TableName" ); + FORMS_CONSTASCII_STRING( PROPERTY_ISFILTERAPPLIED, "IsFilterApplied" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTROLLABEL, "LabelControl" ); + FORMS_CONSTASCII_STRING( PROPERTY_CURRSYM_POSITION, "PrependCurrencySymbol" ); + FORMS_CONSTASCII_STRING( PROPERTY_CURSORCOLOR, "CursorColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_ALWAYSSHOWCURSOR, "AlwaysShowCursor" ); + FORMS_CONSTASCII_STRING( PROPERTY_DISPLAYSYNCHRON, "DisplayIsSynchron" ); + FORMS_CONSTASCII_STRING( PROPERTY_TEXTCOLOR, "TextColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_DELAY, "RepeatDelay" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_SCROLL_VALUE, "DefaultScrollValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_SCROLL_VALUE, "ScrollValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_DEFAULT_SPIN_VALUE, "DefaultSpinValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_SPIN_VALUE, "SpinValue" ); + FORMS_CONSTASCII_STRING( PROPERTY_REFERENCE_DEVICE, "ReferenceDevice" ); + FORMS_CONSTASCII_STRING( PROPERTY_ISMODIFIED, "IsModified" ); + FORMS_CONSTASCII_STRING( PROPERTY_ISNEW, "IsNew" ); + FORMS_CONSTASCII_STRING( PROPERTY_PRIVILEGES, "Privileges" ); + FORMS_CONSTASCII_STRING( PROPERTY_COMMAND, "Command" ); + FORMS_CONSTASCII_STRING( PROPERTY_COMMANDTYPE, "CommandType" ); + FORMS_CONSTASCII_STRING( PROPERTY_RESULTSET_CONCURRENCY, "ResultSetConcurrency" ); + FORMS_CONSTASCII_STRING( PROPERTY_INSERTONLY, "IgnoreResult" ); + FORMS_CONSTASCII_STRING( PROPERTY_RESULTSET_TYPE, "ResultSetType" ); + FORMS_CONSTASCII_STRING( PROPERTY_ESCAPE_PROCESSING, "EscapeProcessing" ); + FORMS_CONSTASCII_STRING( PROPERTY_APPLYFILTER, "ApplyFilter" ); + FORMS_CONSTASCII_STRING( PROPERTY_ROWCOUNT, "RowCount" ); + FORMS_CONSTASCII_STRING( PROPERTY_ROWCOUNTFINAL, "IsRowCountFinal" ); + + FORMS_CONSTASCII_STRING( PROPERTY_ISNULLABLE, "IsNullable" ); + FORMS_CONSTASCII_STRING( PROPERTY_ACTIVECOMMAND, "ActiveCommand" ); + FORMS_CONSTASCII_STRING( PROPERTY_ISCURRENCY, "IsCurrency" ); + FORMS_CONSTASCII_STRING( PROPERTY_URL, "URL" ); + FORMS_CONSTASCII_STRING( PROPERTY_TITLE, "Title" ); + FORMS_CONSTASCII_STRING( PROPERTY_ACTIVE_CONNECTION, "ActiveConnection" ); + FORMS_CONSTASCII_STRING( PROPERTY_SCALE, "Scale" ); + FORMS_CONSTASCII_STRING( PROPERTY_SORT, "Order" ); + FORMS_CONSTASCII_STRING( PROPERTY_DATASOURCE, "DataSourceName" ); + FORMS_CONSTASCII_STRING( PROPERTY_DETAILFIELDS, "DetailFields" ); + + FORMS_CONSTASCII_STRING( PROPERTY_COLUMNSERVICENAME, "ColumnServiceName" ); + FORMS_CONSTASCII_STRING( PROPERTY_REALNAME, "RealName" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTROLSOURCEPROPERTY, "DataFieldProperty" ); + FORMS_CONSTASCII_STRING( PROPERTY_USER, "User" ); + FORMS_CONSTASCII_STRING( PROPERTY_PASSWORD, "Password" ); + FORMS_CONSTASCII_STRING( PROPERTY_DISPATCHURLINTERNAL, "DispatchURLInternal" ); + FORMS_CONSTASCII_STRING( PROPERTY_PERSISTENCE_MAXTEXTLENGTH,"PersistenceMaxTextLength" ); + FORMS_CONSTASCII_STRING( PROPERTY_RICH_TEXT, "RichText" ); + FORMS_CONSTASCII_STRING( PROPERTY_ENFORCE_FORMAT, "EnforceFormat" ); + FORMS_CONSTASCII_STRING( PROPERTY_LINEEND_FORMAT, "LineEndFormat" ); + FORMS_CONSTASCII_STRING( PROPERTY_WRITING_MODE, "WritingMode" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTEXT_WRITING_MODE, "ContextWritingMode" ); + + FORMS_CONSTASCII_STRING( PROPERTY_NATIVE_LOOK, "NativeWidgetLook" ); + FORMS_CONSTASCII_STRING( PROPERTY_BORDER, "Border" ); + FORMS_CONSTASCII_STRING( PROPERTY_BORDERCOLOR, "BorderColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_BACKGROUNDCOLOR, "BackgroundColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_ICONSIZE, "IconSize" ); + FORMS_CONSTASCII_STRING( PROPERTY_TEXTLINECOLOR, "TextLineColor" ); + FORMS_CONSTASCII_STRING( PROPERTY_HIDEINACTIVESELECTION, "HideInactiveSelection" ); + + FORMS_CONSTASCII_STRING( PROPERTY_SHOW_POSITION, "ShowPosition" ); + FORMS_CONSTASCII_STRING( PROPERTY_SHOW_NAVIGATION, "ShowNavigation" ); + FORMS_CONSTASCII_STRING( PROPERTY_SHOW_RECORDACTIONS, "ShowRecordActions" ); + FORMS_CONSTASCII_STRING( PROPERTY_SHOW_FILTERSORT, "ShowFilterSort" ); + + FORMS_CONSTASCII_STRING( PROPERTY_XSD_WHITESPACE, "WhiteSpace" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_PATTERN, "Pattern" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_LENGTH, "Length" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_LENGTH, "MinLength" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_LENGTH, "MaxLength" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_TOTAL_DIGITS, "TotalDigits" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_FRACTION_DIGITS, "FractionDigits" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_INCLUSIVE_INT, "MaxInclusiveInt" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_EXCLUSIVE_INT, "MaxExclusiveInt" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_INCLUSIVE_INT, "MinInclusiveInt" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_EXCLUSIVE_INT, "MinExclusiveInt" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_INCLUSIVE_DOUBLE, "MaxInclusiveDouble" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_EXCLUSIVE_DOUBLE, "MaxExclusiveDouble" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_INCLUSIVE_DOUBLE, "MinInclusiveDouble" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_EXCLUSIVE_DOUBLE, "MinExclusiveDouble" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_INCLUSIVE_DATE, "MaxInclusiveDate" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_EXCLUSIVE_DATE, "MaxExclusiveDate" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_INCLUSIVE_DATE, "MinInclusiveDate" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_EXCLUSIVE_DATE, "MinExclusiveDate" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_INCLUSIVE_TIME, "MaxInclusiveTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_EXCLUSIVE_TIME, "MaxExclusiveTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_INCLUSIVE_TIME, "MinInclusiveTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_EXCLUSIVE_TIME, "MinExclusiveTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_INCLUSIVE_DATE_TIME, "MaxInclusiveDateTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MAX_EXCLUSIVE_DATE_TIME, "MaxExclusiveDateTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_INCLUSIVE_DATE_TIME, "MinInclusiveDateTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_MIN_EXCLUSIVE_DATE_TIME, "MinExclusiveDateTime" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_IS_BASIC, "IsBasic" ); + FORMS_CONSTASCII_STRING( PROPERTY_XSD_TYPE_CLASS, "TypeClass" ); + + FORMS_CONSTASCII_STRING( PROPERTY_DYNAMIC_CONTROL_BORDER, "DynamicControlBorder" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTROL_BORDER_COLOR_FOCUS, "ControlBorderColorOnFocus" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTROL_BORDER_COLOR_MOUSE, "ControlBorderColorOnHover" ); + FORMS_CONSTASCII_STRING( PROPERTY_CONTROL_BORDER_COLOR_INVALID,"ControlBorderColorOnInvalid" ); + + //-------------------------------------------------------------------------- + //- URLs + //-------------------------------------------------------------------------- + FORMS_CONSTASCII_STRING( URL_CONTROLLER_PREFIX, ".uno:FormController/" ); + + FORMS_CONSTASCII_STRING( URL_FORM_POSITION, ".uno:FormController/positionForm" ); + FORMS_CONSTASCII_STRING( URL_FORM_RECORDCOUNT, ".uno:FormController/RecordCount" ); + FORMS_CONSTASCII_STRING( URL_RECORD_FIRST, ".uno:FormController/moveToFirst" ); + FORMS_CONSTASCII_STRING( URL_RECORD_PREV, ".uno:FormController/moveToPrev" ); + FORMS_CONSTASCII_STRING( URL_RECORD_NEXT, ".uno:FormController/moveToNext" ); + FORMS_CONSTASCII_STRING( URL_RECORD_LAST, ".uno:FormController/moveToLast" ); + FORMS_CONSTASCII_STRING( URL_RECORD_SAVE, ".uno:FormController/saveRecord" ); + FORMS_CONSTASCII_STRING( URL_RECORD_UNDO, ".uno:FormController/undoRecord" ); + FORMS_CONSTASCII_STRING( URL_RECORD_NEW, ".uno:FormController/moveToNew" ); + FORMS_CONSTASCII_STRING( URL_RECORD_DELETE, ".uno:FormController/deleteRecord" ); + FORMS_CONSTASCII_STRING( URL_FORM_REFRESH, ".uno:FormController/refreshForm" ); + FORMS_CONSTASCII_STRING( URL_FORM_REFRESH_CURRENT_CONTROL, + ".uno:FormController/refreshCurrentControl" ); + + FORMS_CONSTASCII_STRING( URL_FORM_SORT_UP, ".uno:FormController/sortUp" ); + FORMS_CONSTASCII_STRING( URL_FORM_SORT_DOWN, ".uno:FormController/sortDown" ); + FORMS_CONSTASCII_STRING( URL_FORM_SORT, ".uno:FormController/sort" ); + FORMS_CONSTASCII_STRING( URL_FORM_AUTO_FILTER, ".uno:FormController/autoFilter" ); + FORMS_CONSTASCII_STRING( URL_FORM_FILTER, ".uno:FormController/filter" ); + FORMS_CONSTASCII_STRING( URL_FORM_APPLY_FILTER, ".uno:FormController/applyFilter" ); + FORMS_CONSTASCII_STRING( URL_FORM_REMOVE_FILTER,".uno:FormController/removeFilterOrder" ); + +//.............................................................................. +} // namespace frm +//.............................................................................. + + +#endif // FRM_STRINGS_HXX diff --git a/forms/source/inc/ids.hxx b/forms/source/inc/ids.hxx new file mode 100644 index 000000000000..ef391341c1d4 --- /dev/null +++ b/forms/source/inc/ids.hxx @@ -0,0 +1,36 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_IDS_HXX_ +#define _FRM_IDS_HXX_ + +#include <unotools/idhelper.hxx> + +DECLARE_IMPLEMENTATIONID_HELPER(frm, OImplementationIds) + +#endif // _FRM_IDS_HXX_ + diff --git a/forms/source/inc/limitedformats.hxx b/forms/source/inc/limitedformats.hxx new file mode 100644 index 000000000000..fee3221ce17f --- /dev/null +++ b/forms/source/inc/limitedformats.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_LIMITED_FORMATS_HXX_ +#define _FORMS_LIMITED_FORMATS_HXX_ + +#include <osl/mutex.hxx> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/XFastPropertySet.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //===================================================================== + //= OLimitedFormats + //===================================================================== + /** maintains translation tables format key <-> enum value + <p>Used for controls which provide a limited number for (standard) formats, which + should be available as format keys.</p> + */ + class OLimitedFormats + { + private: + static sal_Int32 s_nInstanceCount; + static ::osl::Mutex s_aMutex; + static ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > + s_xStandardFormats; + + protected: + sal_Int32 m_nFormatEnumPropertyHandle; + const sal_Int16 m_nTableId; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet > + m_xAggregate; + + protected: + /** ctor + <p>The class id is used to determine the translation table to use. All instances which + pass the same value here share one table.</p> + */ + OLimitedFormats( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + const sal_Int16 _nClassId + ); + ~OLimitedFormats(); + + protected: + void setAggregateSet( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet >& _rxAggregate, + sal_Int32 _nOriginalPropertyHandle + ); + + protected: + void getFormatKeyPropertyValue( ::com::sun::star::uno::Any& _rValue ) const; + sal_Bool convertFormatKeyPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, + ::com::sun::star::uno::Any& _rOldValue, + const ::com::sun::star::uno::Any& _rNewValue + ); + void setFormatKeyPropertyValue( const ::com::sun::star::uno::Any& _rNewValue ); + // setFormatKeyPropertyValue should only be called with a value got from convertFormatKeyPropertyValue! + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > + getFormatsSupplier() const { return s_xStandardFormats; } + + private: + void acquireSupplier(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB); + void releaseSupplier(); + + static void ensureTableInitialized(const sal_Int16 _nTableId); + static void clearTable(const sal_Int16 _nTableId); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_LIMITED_FORMATS_HXX_ + diff --git a/forms/source/inc/listenercontainers.hxx b/forms/source/inc/listenercontainers.hxx new file mode 100644 index 000000000000..d4f088d4e180 --- /dev/null +++ b/forms/source/inc/listenercontainers.hxx @@ -0,0 +1,140 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_INC_LISTENERCONTAINERS_HXX +#define FORMS_SOURCE_INC_LISTENERCONTAINERS_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/form/XResetListener.hpp> +/** === end UNO includes === **/ +#include <comphelper/listenernotification.hxx> +#include <cppuhelper/weak.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //===================================================================== + //= EventListeners + //===================================================================== + template < class LISTENER > + class EventListeners : public ::comphelper::OListenerContainerBase< LISTENER, ::com::sun::star::lang::EventObject > + { + public: + typedef LISTENER ListenerClass; + typedef ::com::sun::star::lang::EventObject EventClass; + typedef ::comphelper::OListenerContainerBase< ListenerClass, EventClass > + EventListeners_Base; + + private: + ::cppu::OWeakObject& m_rInstigator; + + protected: + ::cppu::OWeakObject& getInstigator() { return m_rInstigator; } + + protected: + inline EventListeners( ::cppu::OWeakObject& _rInstigator, ::osl::Mutex& _rMutex ) + :EventListeners_Base( _rMutex ) + ,m_rInstigator( _rInstigator ) + { + } + + // still waiting to be overwritten + virtual bool implTypedNotify( + const ::com::sun::star::uno::Reference< ListenerClass >& _rxListener, + const EventClass& _rEvent + ) SAL_THROW( ( ::com::sun::star::uno::Exception ) ) = 0; + + public: + inline bool notify() + { + ::com::sun::star::lang::EventObject aEvent( m_rInstigator ); + return EventListeners_Base::notify( aEvent ); + } + + inline void disposing() + { + ::com::sun::star::lang::EventObject aEvent( m_rInstigator ); + EventListeners_Base::disposing( aEvent ); + } + protected: + using EventListeners_Base::notify; + using EventListeners_Base::disposing; + }; + + //===================================================================== + //= ResetListeners + //===================================================================== + typedef EventListeners < ::com::sun::star::form::XResetListener + > ResetListeners_Base; + class ResetListeners : public ResetListeners_Base + { + private: + enum NotificationType + { + eApproval, + eFinal + }; + NotificationType m_eCurrentNotificationType; + + public: + inline ResetListeners( ::cppu::OWeakObject& _rInstigator, ::osl::Mutex& _rMutex ) + :ResetListeners_Base( _rInstigator, _rMutex ) + ,m_eCurrentNotificationType( eApproval ) + { + } + + /** see whether all our listeners approve the reset + */ + sal_Bool approveReset() + { + m_eCurrentNotificationType = eApproval; + return notify(); + } + + /** tell all our listeners that the reset happened + */ + void resetted() + { + m_eCurrentNotificationType = eFinal; + notify(); + } + + protected: + virtual bool implTypedNotify( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& _rxListener, + const ::com::sun::star::lang::EventObject& _rEvent + ) SAL_THROW( ( ::com::sun::star::uno::Exception ) ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_INC_LISTENERCONTAINERS_HXX + diff --git a/forms/source/inc/property.hrc b/forms/source/inc/property.hrc new file mode 100644 index 000000000000..c1064e6d56b9 --- /dev/null +++ b/forms/source/inc/property.hrc @@ -0,0 +1,316 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _FRM_PROPERTY_HRC_ +#define _FRM_PROPERTY_HRC_ + +#ifndef _RTL_USTRING_HXX_ +#include <rtl/ustring.hxx> +#endif + +#ifndef FRM_STRINGS_HXX +#include "frm_strings.hxx" +#endif + +//......................................................................... +namespace frm +{ +//......................................................................... + +// PropertyId's, welche eine Zuordnung zu einen PropertyName haben +#define PROPERTY_ID_START 0 + +#define PROPERTY_ID_NAME (PROPERTY_ID_START + 1) +#define PROPERTY_ID_TABINDEX (PROPERTY_ID_START + 2) +#define PROPERTY_ID_CONTROLSOURCE (PROPERTY_ID_START + 3) +#define PROPERTY_ID_MASTERFIELDS (PROPERTY_ID_START + 4) +#define PROPERTY_ID_DATASOURCE (PROPERTY_ID_START + 6) +#define PROPERTY_ID_CLASSID (PROPERTY_ID_START + 9) +#define PROPERTY_ID_CURSORTYPE (PROPERTY_ID_START + 10) +#define PROPERTY_ID_READONLY (PROPERTY_ID_START + 11) +#define PROPERTY_ID_NAVIGATION (PROPERTY_ID_START + 13) +#define PROPERTY_ID_CYCLE (PROPERTY_ID_START + 14) +#define PROPERTY_ID_ALLOWADDITIONS (PROPERTY_ID_START + 15) +#define PROPERTY_ID_ALLOWEDITS (PROPERTY_ID_START + 16) +#define PROPERTY_ID_ALLOWDELETIONS (PROPERTY_ID_START + 17) +#define PROPERTY_ID_NATIVE_LOOK (PROPERTY_ID_START + 18) +#define PROPERTY_ID_INPUT_REQUIRED (PROPERTY_ID_START + 19) +#define PROPERTY_ID_WRITING_MODE (PROPERTY_ID_START + 20) +#define PROPERTY_ID_CONTEXT_WRITING_MODE (PROPERTY_ID_START + 21) +#define PROPERTY_ID_VERTICAL_ALIGN (PROPERTY_ID_START + 22) + // free + // free + // free + // free + // free + // free + // free + // free +#define PROPERTY_ID_VALUE (PROPERTY_ID_START + 31) // INT32 + // free +#define PROPERTY_ID_FORMATKEY (PROPERTY_ID_START + 33) // UINT32 + // free + // free + // free +#define PROPERTY_ID_SIZE (PROPERTY_ID_START + 37) // UINT32 +#define PROPERTY_ID_REFERENCE_DEVICE (PROPERTY_ID_START + 38) // XDevice + // free + // free + // free +#define PROPERTY_ID_WIDTH (PROPERTY_ID_START + 42) // UINT16 +#define PROPERTY_ID_DEFAULTCONTROL (PROPERTY_ID_START + 43) // string +#define PROPERTY_ID_BOUNDCOLUMN (PROPERTY_ID_START + 44) // UINT16 may be null +#define PROPERTY_ID_LISTSOURCETYPE (PROPERTY_ID_START + 45) // UINT16 +#define PROPERTY_ID_LISTSOURCE (PROPERTY_ID_START + 46) // string + // FREE +#define PROPERTY_ID_TEXT (PROPERTY_ID_START + 48) // string +#define PROPERTY_ID_STRINGITEMLIST (PROPERTY_ID_START + 49) // wsstringsequence +#define PROPERTY_ID_LABEL (PROPERTY_ID_START + 50) // string +#define PROPERTY_ID_HIDEINACTIVESELECTION (PROPERTY_ID_START + 51) // sal_Bool +#define PROPERTY_ID_STATE (PROPERTY_ID_START + 52) // UINT16 +#define PROPERTY_ID_DELAY (PROPERTY_ID_START + 53) // sal_Int32 +#define PROPERTY_ID_FONT (PROPERTY_ID_START + 54) // font +#define PROPERTY_ID_HASNAVIGATION (PROPERTY_ID_START + 55) +#define PROPERTY_ID_BORDERCOLOR (PROPERTY_ID_START + 56) // sal_Int32 +#define PROPERTY_ID_ROWHEIGHT (PROPERTY_ID_START + 57) // UINT16 +#define PROPERTY_ID_BACKGROUNDCOLOR (PROPERTY_ID_START + 58) // sal_Int32 +#define PROPERTY_ID_FILLCOLOR (PROPERTY_ID_START + 59) // UINT32 +#define PROPERTY_ID_TEXTCOLOR (PROPERTY_ID_START + 60) // UINT32 +#define PROPERTY_ID_LINECOLOR (PROPERTY_ID_START + 61) // UINT32 +#define PROPERTY_ID_BORDER (PROPERTY_ID_START + 62) // UINT16 +#define PROPERTY_ID_ALIGN (PROPERTY_ID_START + 63) // UINT16 +#define PROPERTY_ID_DROPDOWN (PROPERTY_ID_START + 64) // BOOL +#define PROPERTY_ID_UNCHECKED_REFVALUE (PROPERTY_ID_START + 65) // ::rtl::OUString +#define PROPERTY_ID_HSCROLL (PROPERTY_ID_START + 66) // BOOL +#define PROPERTY_ID_VSCROLL (PROPERTY_ID_START + 67) // BOOL +#define PROPERTY_ID_TABSTOP (PROPERTY_ID_START + 68) // BOOL +#define PROPERTY_ID_REFVALUE (PROPERTY_ID_START + 69) // ::rtl::OUString +#define PROPERTY_ID_BUTTONTYPE (PROPERTY_ID_START + 70) // UINT16 +#define PROPERTY_ID_DEFAULT_TEXT (PROPERTY_ID_START + 71) // ::rtl::OUString +#define PROPERTY_ID_SUBMIT_ACTION (PROPERTY_ID_START + 72) // string +#define PROPERTY_ID_SUBMIT_METHOD (PROPERTY_ID_START + 73) // FmSubmitMethod +#define PROPERTY_ID_SUBMIT_ENCODING (PROPERTY_ID_START + 74) // FmSubmitEncoding +#define PROPERTY_ID_DEFAULT_VALUE (PROPERTY_ID_START + 75) // ::rtl::OUString +#define PROPERTY_ID_SUBMIT_TARGET (PROPERTY_ID_START + 76) // ::rtl::OUString +#define PROPERTY_ID_DEFAULT_STATE (PROPERTY_ID_START + 77) // UINT16 +#define PROPERTY_ID_VALUE_SEQ (PROPERTY_ID_START + 78) // StringSeq +#define PROPERTY_ID_IMAGE_URL (PROPERTY_ID_START + 79) // ::rtl::OUString + // free + // free + // free + // free + // free + // free + // free + // free + // free + // free + // free +#define PROPERTY_ID_SELECT_SEQ (PROPERTY_ID_START + 91) // INT16Seq +#define PROPERTY_ID_DEFAULT_SELECT_SEQ (PROPERTY_ID_START + 92) // INT16Seq +#define PROPERTY_ID_MULTISELECTION (PROPERTY_ID_START + 93) // BOOL +#define PROPERTY_ID_MULTILINE (PROPERTY_ID_START + 94) // BOOL +#define PROPERTY_ID_DATE (PROPERTY_ID_START + 95) // UINT32 +#define PROPERTY_ID_DATEMIN (PROPERTY_ID_START + 96) // UINT32 +#define PROPERTY_ID_DATEMAX (PROPERTY_ID_START + 97) // UINT32 +#define PROPERTY_ID_DATEFORMAT (PROPERTY_ID_START + 98) // UINT16 +#define PROPERTY_ID_TIME (PROPERTY_ID_START + 99) // UINT32 +#define PROPERTY_ID_TIMEMIN (PROPERTY_ID_START +100) // UINT32 +#define PROPERTY_ID_TIMEMAX (PROPERTY_ID_START +101) // UINT32 +#define PROPERTY_ID_TIMEFORMAT (PROPERTY_ID_START +102) // UINT16 +#define PROPERTY_ID_VALUEMIN (PROPERTY_ID_START +103) // INT32 +#define PROPERTY_ID_VALUEMAX (PROPERTY_ID_START +104) // INT32 +#define PROPERTY_ID_VALUESTEP (PROPERTY_ID_START +105) // INT32 +#define PROPERTY_ID_CURRENCYSYMBOL (PROPERTY_ID_START +106) // ::rtl::OUString +#define PROPERTY_ID_EDITMASK (PROPERTY_ID_START +107) // ::rtl::OUString +#define PROPERTY_ID_LITERALMASK (PROPERTY_ID_START +108) // ::rtl::OUString +#define PROPERTY_ID_ENABLED (PROPERTY_ID_START +109) // BOOL +#define PROPERTY_ID_AUTOCOMPLETE (PROPERTY_ID_START +110) // BOOL +#define PROPERTY_ID_LINECOUNT (PROPERTY_ID_START +111) // UINT16 +#define PROPERTY_ID_MAXTEXTLEN (PROPERTY_ID_START +112) // UINT16 +#define PROPERTY_ID_SPIN (PROPERTY_ID_START +113) // BOOL +#define PROPERTY_ID_STRICTFORMAT (PROPERTY_ID_START +114) // BOOL +#define PROPERTY_ID_SHOWTHOUSANDSEP (PROPERTY_ID_START +115) // BOOL +#define PROPERTY_ID_HARDLINEBREAKS (PROPERTY_ID_START +116) // BOOL +#define PROPERTY_ID_PRINTABLE (PROPERTY_ID_START +117) // BOOL +#define PROPERTY_ID_TARGET_URL (PROPERTY_ID_START +118) // ::rtl::OUString +#define PROPERTY_ID_TARGET_FRAME (PROPERTY_ID_START +119) // ::rtl::OUString +#define PROPERTY_ID_TAG (PROPERTY_ID_START +120) // ::rtl::OUString +#define PROPERTY_ID_ECHO_CHAR (PROPERTY_ID_START +121) // UINT16 +#define PROPERTY_ID_SHOW_POSITION (PROPERTY_ID_START +122) // sal_Bool +#define PROPERTY_ID_SHOW_NAVIGATION (PROPERTY_ID_START +123) // sal_Bool +#define PROPERTY_ID_SHOW_RECORDACTIONS (PROPERTY_ID_START +124) // sal_Bool +#define PROPERTY_ID_SHOW_FILTERSORT (PROPERTY_ID_START +125) // sal_Bool +#define PROPERTY_ID_EMPTY_IS_NULL (PROPERTY_ID_START +126) // Bool +#define PROPERTY_ID_DECIMAL_ACCURACY (PROPERTY_ID_START +127) // UINT16 +#define PROPERTY_ID_DATE_SHOW_CENTURY (PROPERTY_ID_START +128) // Bool +#define PROPERTY_ID_TRISTATE (PROPERTY_ID_START +129) // Bool +#define PROPERTY_ID_DEFAULT_BUTTON (PROPERTY_ID_START +130) // Bool +#define PROPERTY_ID_HIDDEN_VALUE (PROPERTY_ID_START +131) // ::rtl::OUString +#define PROPERTY_ID_DECIMALS (PROPERTY_ID_START +132) // UINT16 +#define PROPERTY_ID_AUTOINCREMENT (PROPERTY_ID_START +133) // UINT16 + // free +#define PROPERTY_ID_FILTER (PROPERTY_ID_START +135) // ::rtl::OUString + // free +#define PROPERTY_ID_QUERY (PROPERTY_ID_START +137) // ::rtl::OUString +#define PROPERTY_ID_DEFAULT_LONG_VALUE (PROPERTY_ID_START +138) // Double +#define PROPERTY_ID_DEFAULT_DATE (PROPERTY_ID_START +139) // UINT32 +#define PROPERTY_ID_DEFAULT_TIME (PROPERTY_ID_START +140) +#define PROPERTY_ID_HELPTEXT (PROPERTY_ID_START +141) +#define PROPERTY_ID_FONT_NAME (PROPERTY_ID_START +142) +#define PROPERTY_ID_FONT_STYLENAME (PROPERTY_ID_START +143) +#define PROPERTY_ID_FONT_FAMILY (PROPERTY_ID_START +144) +#define PROPERTY_ID_FONT_CHARSET (PROPERTY_ID_START +145) +#define PROPERTY_ID_FONT_HEIGHT (PROPERTY_ID_START +146) +#define PROPERTY_ID_FONT_WEIGHT (PROPERTY_ID_START +147) +#define PROPERTY_ID_FONT_SLANT (PROPERTY_ID_START +148) +#define PROPERTY_ID_FONT_UNDERLINE (PROPERTY_ID_START +149) +#define PROPERTY_ID_FONT_STRIKEOUT (PROPERTY_ID_START +150) +#define PROPERTY_ID_ISPASSTHROUGH (PROPERTY_ID_START +151) +#define PROPERTY_ID_HELPURL (PROPERTY_ID_START +152) // ::rtl::OUString +#define PROPERTY_ID_RECORDMARKER (PROPERTY_ID_START +153) +#define PROPERTY_ID_BOUNDFIELD (PROPERTY_ID_START +154) +#define PROPERTY_ID_FORMATSSUPPLIER (PROPERTY_ID_START +155) // XNumberFormatsSupplier +#define PROPERTY_ID_TREATASNUMERIC (PROPERTY_ID_START +156) // BOOL +#define PROPERTY_ID_EFFECTIVE_VALUE (PROPERTY_ID_START +157) // ANY (string or double) +#define PROPERTY_ID_EFFECTIVE_DEFAULT (PROPERTY_ID_START +158) // dito +#define PROPERTY_ID_EFFECTIVE_MIN (PROPERTY_ID_START +159) // dito +#define PROPERTY_ID_EFFECTIVE_MAX (PROPERTY_ID_START +160) // dito +#define PROPERTY_ID_HIDDEN (PROPERTY_ID_START +161) // BOOL +#define PROPERTY_ID_FILTERPROPOSAL (PROPERTY_ID_START +162) // BOOL +#define PROPERTY_ID_FIELDSOURCE (PROPERTY_ID_START +163) // String +#define PROPERTY_ID_TABLENAME (PROPERTY_ID_START +164) // String +#define PROPERTY_ID_ENABLEVISIBLE (PROPERTY_ID_START +165) // BOOL + // FREE + // FREE + // FREE + // FREE +#define PROPERTY_ID_CONTROLLABEL (PROPERTY_ID_START +171) // XPropertySet +#define PROPERTY_ID_CURRSYM_POSITION (PROPERTY_ID_START +172) // String + // FREE +#define PROPERTY_ID_CURSORCOLOR (PROPERTY_ID_START +174) // INT32 +#define PROPERTY_ID_ALWAYSSHOWCURSOR (PROPERTY_ID_START +175) // BOOL +#define PROPERTY_ID_DISPLAYSYNCHRON (PROPERTY_ID_START +176) // BOOL +#define PROPERTY_ID_ISMODIFIED (PROPERTY_ID_START +177) // BOOL +#define PROPERTY_ID_ISNEW (PROPERTY_ID_START +178) // BOOL +#define PROPERTY_ID_PRIVILEGES (PROPERTY_ID_START +179) // INT32 +#define PROPERTY_ID_DETAILFIELDS (PROPERTY_ID_START +180) // Sequence< ::rtl::OUString > +#define PROPERTY_ID_COMMAND (PROPERTY_ID_START +181) // String +#define PROPERTY_ID_COMMANDTYPE (PROPERTY_ID_START +182) // INT32 (com::sun::star::sdb::CommandType) +#define PROPERTY_ID_RESULTSET_CONCURRENCY (PROPERTY_ID_START +183)// INT32 (com::sun::star::sdbc::ResultSetConcurrency) +#define PROPERTY_ID_INSERTONLY (PROPERTY_ID_START +184) // BOOL +#define PROPERTY_ID_RESULTSET_TYPE (PROPERTY_ID_START +185) // INT32 (com::sun::star::sdbc::ResultSetType) +#define PROPERTY_ID_ESCAPE_PROCESSING (PROPERTY_ID_START +186) // BOOL +#define PROPERTY_ID_APPLYFILTER (PROPERTY_ID_START +187) // BOOL + +#define PROPERTY_ID_ISNULLABLE (PROPERTY_ID_START +188) // BOOL +#define PROPERTY_ID_ACTIVECOMMAND (PROPERTY_ID_START +189) // String +#define PROPERTY_ID_ISCURRENCY (PROPERTY_ID_START +190) // BOOL +#define PROPERTY_ID_URL (PROPERTY_ID_START +192) // String +#define PROPERTY_ID_TITLE (PROPERTY_ID_START +193) // String +#define PROPERTY_ID_ACTIVE_CONNECTION (PROPERTY_ID_START +194) // com::sun::star::sdbc::XConnection +#define PROPERTY_ID_SCALE (PROPERTY_ID_START +195) // INT32 +#define PROPERTY_ID_SORT (PROPERTY_ID_START +196) // String + + // free + // free +#define PROPERTY_ID_FETCHSIZE (PROPERTY_ID_START +199) + // free +#define PROPERTY_ID_SEARCHABLE (PROPERTY_ID_START +201) +#define PROPERTY_ID_ISREADONLY (PROPERTY_ID_START +202) + // free +#define PROPERTY_ID_FIELDTYPE (PROPERTY_ID_START +204) +#define PROPERTY_ID_COLUMNSERVICENAME (PROPERTY_ID_START +205) +#define PROPERTY_ID_CONTROLSOURCEPROPERTY (PROPERTY_ID_START +206) +#define PROPERTY_ID_REALNAME (PROPERTY_ID_START +207) +#define PROPERTY_ID_FONT_WORDLINEMODE (PROPERTY_ID_START +208) +#define PROPERTY_ID_TEXTLINECOLOR (PROPERTY_ID_START +209) +#define PROPERTY_ID_FONTEMPHASISMARK (PROPERTY_ID_START +210) +#define PROPERTY_ID_FONTRELIEF (PROPERTY_ID_START +211) + +#define PROPERTY_ID_DISPATCHURLINTERNAL ( PROPERTY_ID_START + 212 ) // sal_Bool +#define PROPERTY_ID_PERSISTENCE_MAXTEXTLENGTH ( PROPERTY_ID_START + 213 ) // sal_Int16 +#define PROPERTY_ID_DEFAULT_SCROLL_VALUE ( PROPERTY_ID_START + 214 ) // sal_Int32 +#define PROPERTY_ID_DEFAULT_SPIN_VALUE ( PROPERTY_ID_START + 215 ) // sal_Int32 +#define PROPERTY_ID_SCROLL_VALUE ( PROPERTY_ID_START + 216 ) // sal_Int32 +#define PROPERTY_ID_SPIN_VALUE ( PROPERTY_ID_START + 217 ) // sal_Int32 +#define PROPERTY_ID_ICONSIZE ( PROPERTY_ID_START + 218 ) // sal_Int16 + +#define PROPERTY_ID_FONT_CHARWIDTH ( PROPERTY_ID_START + 219 ) // float +#define PROPERTY_ID_FONT_KERNING ( PROPERTY_ID_START + 220 ) // sal_Bool +#define PROPERTY_ID_FONT_ORIENTATION ( PROPERTY_ID_START + 221 ) // float +#define PROPERTY_ID_FONT_PITCH ( PROPERTY_ID_START + 222 ) // sal_Int16 +#define PROPERTY_ID_FONT_TYPE ( PROPERTY_ID_START + 223 ) // sal_Int16 +#define PROPERTY_ID_FONT_WIDTH ( PROPERTY_ID_START + 224 ) // sal_Int16 +#define PROPERTY_ID_RICH_TEXT ( PROPERTY_ID_START + 225 ) // sal_Bool + +#define PROPERTY_ID_DYNAMIC_CONTROL_BORDER ( PROPERTY_ID_START + 226 ) // sal_Bool +#define PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS ( PROPERTY_ID_START + 227 ) // sal_Int32 +#define PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE ( PROPERTY_ID_START + 228 ) // sal_Int32 +#define PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID ( PROPERTY_ID_START + 229 ) // sal_Int32 + +#define PROPERTY_ID_XSD_PATTERN ( PROPERTY_ID_START + 230 ) +#define PROPERTY_ID_XSD_WHITESPACE ( PROPERTY_ID_START + 231 ) +#define PROPERTY_ID_XSD_LENGTH ( PROPERTY_ID_START + 232 ) +#define PROPERTY_ID_XSD_MIN_LENGTH ( PROPERTY_ID_START + 233 ) +#define PROPERTY_ID_XSD_MAX_LENGTH ( PROPERTY_ID_START + 234 ) +#define PROPERTY_ID_XSD_TOTAL_DIGITS ( PROPERTY_ID_START + 235 ) +#define PROPERTY_ID_XSD_FRACTION_DIGITS ( PROPERTY_ID_START + 236 ) +#define PROPERTY_ID_XSD_MAX_INCLUSIVE_INT ( PROPERTY_ID_START + 237 ) +#define PROPERTY_ID_XSD_MAX_EXCLUSIVE_INT ( PROPERTY_ID_START + 238 ) +#define PROPERTY_ID_XSD_MIN_INCLUSIVE_INT ( PROPERTY_ID_START + 239 ) +#define PROPERTY_ID_XSD_MIN_EXCLUSIVE_INT ( PROPERTY_ID_START + 240 ) +#define PROPERTY_ID_XSD_MAX_INCLUSIVE_DOUBLE ( PROPERTY_ID_START + 241 ) +#define PROPERTY_ID_XSD_MAX_EXCLUSIVE_DOUBLE ( PROPERTY_ID_START + 242 ) +#define PROPERTY_ID_XSD_MIN_INCLUSIVE_DOUBLE ( PROPERTY_ID_START + 243 ) +#define PROPERTY_ID_XSD_MIN_EXCLUSIVE_DOUBLE ( PROPERTY_ID_START + 244 ) +#define PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE ( PROPERTY_ID_START + 245 ) +#define PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE ( PROPERTY_ID_START + 246 ) +#define PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE ( PROPERTY_ID_START + 247 ) +#define PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE ( PROPERTY_ID_START + 248 ) +#define PROPERTY_ID_XSD_MAX_INCLUSIVE_TIME ( PROPERTY_ID_START + 249 ) +#define PROPERTY_ID_XSD_MAX_EXCLUSIVE_TIME ( PROPERTY_ID_START + 250 ) +#define PROPERTY_ID_XSD_MIN_INCLUSIVE_TIME ( PROPERTY_ID_START + 251 ) +#define PROPERTY_ID_XSD_MIN_EXCLUSIVE_TIME ( PROPERTY_ID_START + 252 ) +#define PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE_TIME ( PROPERTY_ID_START + 253 ) +#define PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE_TIME ( PROPERTY_ID_START + 254 ) +#define PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE_TIME ( PROPERTY_ID_START + 255 ) +#define PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE_TIME ( PROPERTY_ID_START + 256 ) +#define PROPERTY_ID_XSD_IS_BASIC ( PROPERTY_ID_START + 257 ) +#define PROPERTY_ID_XSD_TYPE_CLASS ( PROPERTY_ID_START + 258 ) + +#define PROPERTY_ID_LINEEND_FORMAT ( PROPERTY_ID_START + 259 ) // css.awt.LineEndFormat + +// start ID fuer aggregierte Properties +#define PROPERTY_ID_AGGREGATE_ID (PROPERTY_ID_START + 10000) + +//......................................................................... +} +//......................................................................... + + +#endif // _FRM_PROPERTY_HRC_ + diff --git a/forms/source/inc/property.hxx b/forms/source/inc/property.hxx new file mode 100644 index 000000000000..e2b6f08377cd --- /dev/null +++ b/forms/source/inc/property.hxx @@ -0,0 +1,236 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_PROPERTY_HXX_ +#define _FRM_PROPERTY_HXX_ + +#include <com/sun/star/uno/XAggregation.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/propshlp.hxx> +#include <cppuhelper/proptypehlp.hxx> +#include <comphelper/property.hxx> +#include <comphelper/propagg.hxx> +#include <comphelper/stl_types.hxx> + +using namespace comphelper; + +//========================================================================= +//= property helper classes +//========================================================================= + +//... namespace frm ....................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= assigment property handle <-> property name +//= used by the PropertySetAggregationHelper +//================================================================== + +class PropertyInfoService +{ + //.................................................................. + struct PropertyAssignment + { + ::rtl::OUString sName; + sal_Int32 nHandle; + + PropertyAssignment() { nHandle = -1; } + PropertyAssignment(const PropertyAssignment& _rSource) + :sName(_rSource.sName), nHandle(_rSource.nHandle) { } + PropertyAssignment(const ::rtl::OUString& _rName, sal_Int32 _nHandle) + :sName(_rName), nHandle(_nHandle) { } + + }; + + DECLARE_STL_VECTOR(PropertyAssignment, PropertyMap); + static PropertyMap s_AllKnownProperties; + + //.................................................................. + // comparing two PropertyAssignment's +public: + typedef PropertyAssignment PUBLIC_SOLARIS_COMPILER_HACK; + // did not get the following compiled under with SUNPRO 5 without this + // public typedef +private: + friend struct PropertyAssignmentNameCompareLess; + typedef ::std::binary_function< PUBLIC_SOLARIS_COMPILER_HACK, PUBLIC_SOLARIS_COMPILER_HACK, sal_Bool > PropertyAssignmentNameCompareLess_Base; + struct PropertyAssignmentNameCompareLess : public PropertyAssignmentNameCompareLess_Base + { + inline sal_Bool operator() (const PUBLIC_SOLARIS_COMPILER_HACK& _rL, const PUBLIC_SOLARIS_COMPILER_HACK& _rR) const + { + return (_rL.sName.compareTo(_rR.sName) < 0); + } + }; + +public: + PropertyInfoService() { } + +public: + static sal_Int32 getPropertyId(const ::rtl::OUString& _rName); + static ::rtl::OUString getPropertyName(sal_Int32 _nHandle); + +private: + static void initialize(); +}; + +//.................................................................. +// a class implementing the comphelper::IPropertyInfoService +class ConcreteInfoService : public ::comphelper::IPropertyInfoService +{ +public: + virtual sal_Int32 getPreferedPropertyId(const ::rtl::OUString& _rName); +}; + +//------------------------------------------------------------------------------ +#define DECL_PROP_IMPL(varname, type) \ + *pProperties++ = com::sun::star::beans::Property(PROPERTY_##varname, PROPERTY_ID_##varname, ::getCppuType(reinterpret_cast< type* >(NULL)), + +//------------------------------------------------------------------------------ +#define DECL_BOOL_PROP_IMPL(varname) \ + *pProperties++ = com::sun::star::beans::Property(PROPERTY_##varname, PROPERTY_ID_##varname, ::getBooleanCppuType(), + +//------------------------------------------------------------------------------ +#define DECL_IFACE_PROP_IMPL(varname, type) \ + *pProperties++ = com::sun::star::beans::Property(PROPERTY_##varname, PROPERTY_ID_##varname, ::getCppuType(reinterpret_cast< com::sun::star::uno::Reference< type >* >(NULL)), + +//------------------------------------------------------------------------------ +#define BEGIN_DESCRIBE_PROPERTIES( count, baseclass ) \ + baseclass::describeFixedProperties( _rProps ); \ + sal_Int32 nOldCount = _rProps.getLength(); \ + _rProps.realloc( nOldCount + ( count ) ); \ + ::com::sun::star::beans::Property* pProperties = _rProps.getArray() + nOldCount; \ + +//------------------------------------------------------------------------------ +#define BEGIN_DESCRIBE_BASE_PROPERTIES( count ) \ + _rProps.realloc( count ); \ + ::com::sun::star::beans::Property* pProperties = _rProps.getArray(); \ + +//------------------------------------------------------------------------------ +#define BEGIN_DESCRIBE_AGGREGATION_PROPERTIES( count, aggregate ) \ + _rProps.realloc( count ); \ + ::com::sun::star::beans::Property* pProperties = _rProps.getArray(); \ + \ + if (aggregate.is()) \ + _rAggregateProps = aggregate->getPropertySetInfo()->getProperties(); \ + +// === +//------------------------------------------------------------------------------ +#define DECL_PROP0(varname, type) \ + DECL_PROP_IMPL(varname, type) 0) + +//------------------------------------------------------------------------------ +#define DECL_PROP1(varname, type, attrib1) \ + DECL_PROP_IMPL(varname, type) com::sun::star::beans::PropertyAttribute::attrib1) + +//------------------------------------------------------------------------------ +#define DECL_PROP2(varname, type, attrib1, attrib2) \ + DECL_PROP_IMPL(varname, type) com::sun::star::beans::PropertyAttribute::attrib1 | com::sun::star::beans::PropertyAttribute::attrib2) + +//------------------------------------------------------------------------------ +#define DECL_PROP3(varname, type, attrib1, attrib2, attrib3) \ + DECL_PROP_IMPL(varname, type) com::sun::star::beans::PropertyAttribute::attrib1 | com::sun::star::beans::PropertyAttribute::attrib2 | com::sun::star::beans::PropertyAttribute::attrib3) + +//------------------------------------------------------------------------------ +#define DECL_PROP4(varname, type, attrib1, attrib2, attrib3, attrib4) \ + DECL_PROP_IMPL(varname, type) com::sun::star::beans::PropertyAttribute::attrib1 | com::sun::star::beans::PropertyAttribute::attrib2 | com::sun::star::beans::PropertyAttribute::attrib3 | com::sun::star::beans::PropertyAttribute::attrib4) + +// === some property types require special handling +// === such as interfaces +//------------------------------------------------------------------------------ +#define DECL_IFACE_PROP0(varname, type) \ + DECL_IFACE_PROP_IMPL(varname, type) 0) + +//------------------------------------------------------------------------------ +#define DECL_IFACE_PROP1(varname, type, attrib1) \ + DECL_IFACE_PROP_IMPL(varname, type) starbeans::PropertyAttribute::attrib1) + +//------------------------------------------------------------------------------ +#define DECL_IFACE_PROP2(varname, type, attrib1, attrib2) \ + DECL_IFACE_PROP_IMPL(varname, type) com::sun::star::beans::PropertyAttribute::attrib1 | com::sun::star::beans::PropertyAttribute::attrib2) + +//------------------------------------------------------------------------------ +#define DECL_IFACE_PROP3(varname, type, attrib1, attrib2, attrib3) \ + DECL_IFACE_PROP_IMPL(varname, type) starbeans::PropertyAttribute::attrib1 | starbeans::PropertyAttribute::attrib2 | starbeans::PropertyAttribute::attrib3) + +//------------------------------------------------------------------------------ +#define DECL_IFACE_PROP4(varname, type, attrib1, attrib2, attrib3, attrib4) \ + DECL_IFACE_PROP_IMPL(varname, type) starbeans::PropertyAttribute::attrib1 | starbeans::PropertyAttribute::attrib2 | starbeans::PropertyAttribute::attrib3 | PropertyAttribute::attrib4) + +// === or Boolean properties +//------------------------------------------------------------------------------ +#define DECL_BOOL_PROP0(varname) \ + DECL_BOOL_PROP_IMPL(varname) 0) + +//------------------------------------------------------------------------------ +#define DECL_BOOL_PROP1(varname, attrib1) \ + DECL_BOOL_PROP_IMPL(varname) com::sun::star::beans::PropertyAttribute::attrib1) + +//------------------------------------------------------------------------------ +#define DECL_BOOL_PROP2(varname, attrib1, attrib2) \ + DECL_BOOL_PROP_IMPL(varname) com::sun::star::beans::PropertyAttribute::attrib1 | com::sun::star::beans::PropertyAttribute::attrib2) + +//------------------------------------------------------------------------------ +#define DECL_BOOL_PROP3( varname, attrib1, attrib2, attrib3 ) \ + DECL_BOOL_PROP_IMPL(varname) com::sun::star::beans::PropertyAttribute::attrib1 | com::sun::star::beans::PropertyAttribute::attrib2 | com::sun::star::beans::PropertyAttribute::attrib3 ) + +// === +//------------------------------------------------------------------------------ +#define END_DESCRIBE_PROPERTIES() \ + DBG_ASSERT( pProperties == _rProps.getArray() + _rProps.getLength(), "<...>::describeFixedProperties/getInfoHelper: forgot to adjust the count ?"); \ + +//============================================================================== +//------------------------------------------------------------------------------ +#define REGISTER_PROP_1( prop, member, attrib1 ) \ + registerProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::attrib1, \ + &member, ::getCppuType( &member ) ); + +#define REGISTER_PROP_2( prop, member, attrib1, attrib2 ) \ + registerProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::attrib1 | PropertyAttribute::attrib2, \ + &member, ::getCppuType( &member ) ); + +#define REGISTER_PROP_3( prop, member, attrib1, attrib2, attrib3 ) \ + registerProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::attrib1 | PropertyAttribute::attrib2 | PropertyAttribute::attrib3, \ + &member, ::getCppuType( &member ) ); + +//------------------------------------------------------------------------------ +#define REGISTER_VOID_PROP_1( prop, memberAny, type, attrib1 ) \ + registerMayBeVoidProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::MAYBEVOID | PropertyAttribute::attrib1, \ + &memberAny, ::getCppuType( static_cast< type* >( NULL ) ) ); + +#define REGISTER_VOID_PROP_2( prop, memberAny, type, attrib1, attrib2 ) \ + registerMayBeVoidProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::MAYBEVOID | PropertyAttribute::attrib1 | PropertyAttribute::attrib2, \ + &memberAny, ::getCppuType( static_cast< type* >( NULL ) ) ); + +//......................................................................... +} +//... namespace frm ....................................................... + +#endif // _FRM_PROPERTY_HXX_ + diff --git a/forms/source/inc/propertybaghelper.hxx b/forms/source/inc/propertybaghelper.hxx new file mode 100644 index 000000000000..9d135516f964 --- /dev/null +++ b/forms/source/inc/propertybaghelper.hxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_PROPERTYBAGHELPER_HXX +#define FORMS_PROPERTYBAGHELPER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyValue.hpp> +/** === end UNO includes === **/ + +#include <comphelper/propertybag.hxx> +#include <comphelper/propagg.hxx> + +#include <boost/noncopyable.hpp> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= class IPropertyBagHelperContext + //==================================================================== + class SAL_NO_VTABLE IPropertyBagHelperContext + { + public: + virtual ::osl::Mutex& getMutex() = 0; + + virtual void describeFixedAndAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rFixedProperties, + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rAggregateProperties + ) const = 0; + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet > + getPropertiesInterface() = 0; + }; + + //==================================================================== + //= class PropertyBagHelper + //==================================================================== + class PropertyBagHelper : public ::boost::noncopyable + { + private: + IPropertyBagHelperContext& m_rContext; + ::comphelper::OPropertyArrayAggregationHelper* m_pPropertyArrayHelper; + ::comphelper::PropertyBag m_aDynamicProperties; + bool m_bDisposed; + + public: + PropertyBagHelper( IPropertyBagHelperContext& _rContext ); + ~PropertyBagHelper(); + + // XComponent equivalent + void dispose(); + + // OPropertySetHelper equivalent + inline ::comphelper::OPropertyArrayAggregationHelper& getInfoHelper() const; + + // XPropertyContainer equivalent + void addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const ::com::sun::star::uno::Any& _rInitialValue ); + void removeProperty( const ::rtl::OUString& _rName ); + + // XPropertyAccess equivalent + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPropertyValues(); + void setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rProps ); + + // forwards to m_aDynamicProperties + inline void getDynamicFastPropertyValue( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _out_rValue ) const; + inline bool convertDynamicFastPropertyValue( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::com::sun::star::uno::Any& _out_rConvertedValue, ::com::sun::star::uno::Any& _out_rCurrentValue ) const; + inline void setDynamicFastPropertyValue( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ); + inline void getDynamicPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _out_rValue ) const; + inline bool hasDynamicPropertyByName( const ::rtl::OUString& _rName ) const; + inline bool hasDynamicPropertyByHandle( sal_Int32 _nHandle ) const; + + private: + void impl_nts_checkDisposed_throw() const; + + /** invalidates our property set info, so subsequent calls to impl_ts_getArrayHelper and thus + getInfoHelper will return a newly created instance + */ + void impl_nts_invalidatePropertySetInfo(); + + /** returns the IPropertyArrayHelper instance used by |this| + */ + ::comphelper::OPropertyArrayAggregationHelper& impl_ts_getArrayHelper() const; + + /** finds a free property handle + @param _rPropertyName + the name of the property to find a handle for. If possible, the handle as determined by + our ConcreteInfoService instance will be used + */ + sal_Int32 impl_findFreeHandle( const ::rtl::OUString& _rPropertyName ); + }; + + //-------------------------------------------------------------------- + inline ::comphelper::OPropertyArrayAggregationHelper& PropertyBagHelper::getInfoHelper() const + { + return impl_ts_getArrayHelper(); + } + + //-------------------------------------------------------------------- + inline void PropertyBagHelper::getDynamicFastPropertyValue( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _out_rValue ) const + { + m_aDynamicProperties.getFastPropertyValue( _nHandle, _out_rValue ); + } + + //-------------------------------------------------------------------- + inline bool PropertyBagHelper::convertDynamicFastPropertyValue( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::com::sun::star::uno::Any& _out_rConvertedValue, ::com::sun::star::uno::Any& _out_rCurrentValue ) const + { + return m_aDynamicProperties.convertFastPropertyValue( _nHandle, _rNewValue, _out_rConvertedValue, _out_rCurrentValue ); + } + + //-------------------------------------------------------------------- + inline void PropertyBagHelper::setDynamicFastPropertyValue( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + { + m_aDynamicProperties.setFastPropertyValue( _nHandle, _rValue ); + } + + //-------------------------------------------------------------------- + inline void PropertyBagHelper::getDynamicPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _out_rValue ) const + { + m_aDynamicProperties.getPropertyDefaultByHandle( _nHandle, _out_rValue ); + } + + //-------------------------------------------------------------------- + inline bool PropertyBagHelper::hasDynamicPropertyByName( const ::rtl::OUString& _rName ) const + { + return m_aDynamicProperties.hasPropertyByName( _rName ); + } + + //-------------------------------------------------------------------- + inline bool PropertyBagHelper::hasDynamicPropertyByHandle( sal_Int32 _nHandle ) const + { + return m_aDynamicProperties.hasPropertyByHandle( _nHandle ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_PROPERTYBAGHELPER_HXX + diff --git a/forms/source/inc/resettable.hxx b/forms/source/inc/resettable.hxx new file mode 100644 index 000000000000..1e743806fb23 --- /dev/null +++ b/forms/source/inc/resettable.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef FORMS_RESETTABLE_HXX +#define FORMS_RESETTABLE_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/form/XResetListener.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/interfacecontainer.hxx> + +namespace cppu +{ + class OWeakObject; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= ResetHelper + //==================================================================== + class ResetHelper + { + public: + ResetHelper( ::cppu::OWeakObject& _parent, ::osl::Mutex& _mutex ) + :m_rParent( _parent ) + ,m_aResetListeners( _mutex ) + { + } + + // XReset equivalents + void addResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& _listener ); + void removeResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& _listener ); + + // calling listeners + bool approveReset(); + void notifyResetted(); + void disposing(); + + private: + ::cppu::OWeakObject& m_rParent; + ::cppu::OInterfaceContainerHelper m_aResetListeners; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_RESETTABLE_HXX diff --git a/forms/source/inc/services.hxx b/forms/source/inc/services.hxx new file mode 100644 index 000000000000..9fcb5db408a1 --- /dev/null +++ b/forms/source/inc/services.hxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_SERVICES_HXX_ +#define _FRM_SERVICES_HXX_ + +#include <rtl/ustring.hxx> +#include "frm_strings.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + + FORMS_CONSTASCII_STRING( AWT_CONTROL_TEXTFIELD, "com.sun.star.awt.TextField" ); + + FORMS_CONSTASCII_STRING( VCL_CONTROL_EDIT, "stardiv.vcl.control.Edit" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_LISTBOX, "stardiv.vcl.control.ListBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_COMBOBOX, "stardiv.vcl.control.ComboBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_RADIOBUTTON, "stardiv.vcl.control.RadioButton" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_GROUPBOX, "stardiv.vcl.control.GroupBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_FIXEDTEXT, "stardiv.vcl.control.FixedText" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_COMMANDBUTTON, "stardiv.vcl.control.Button" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_CHECKBOX, "stardiv.vcl.control.CheckBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_IMAGEBUTTON, "stardiv.vcl.control.ImageButton" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_FILECONTROL, "stardiv.vcl.control.FileControl" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_TIMEFIELD, "stardiv.vcl.control.TimeField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_DATEFIELD, "stardiv.vcl.control.DateField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_NUMERICFIELD, "stardiv.vcl.control.NumericField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_CURRENCYFIELD, "stardiv.vcl.control.CurrencyField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_PATTERNFIELD, "stardiv.vcl.control.PatternField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_FORMATTEDFIELD, "stardiv.vcl.control.FormattedField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_IMAGECONTROL, "stardiv.vcl.control.ImageControl" ); + + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_EDIT, "stardiv.vcl.controlmodel.Edit" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_LISTBOX, "stardiv.vcl.controlmodel.ListBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_COMBOBOX, "stardiv.vcl.controlmodel.ComboBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_RADIOBUTTON, "stardiv.vcl.controlmodel.RadioButton" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_GROUPBOX, "stardiv.vcl.controlmodel.GroupBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_FIXEDTEXT, "stardiv.vcl.controlmodel.FixedText" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_COMMANDBUTTON, "stardiv.vcl.controlmodel.Button" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_CHECKBOX, "stardiv.vcl.controlmodel.CheckBox" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_IMAGEBUTTON, "stardiv.vcl.controlmodel.ImageButton" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_FILECONTROL, "stardiv.vcl.controlmodel.FileControl" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_TIMEFIELD, "stardiv.vcl.controlmodel.TimeField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_DATEFIELD, "stardiv.vcl.controlmodel.DateField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_NUMERICFIELD, "stardiv.vcl.controlmodel.NumericField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_CURRENCYFIELD, "stardiv.vcl.controlmodel.CurrencyField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_PATTERNFIELD, "stardiv.vcl.controlmodel.PatternField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_FORMATTEDFIELD, "stardiv.vcl.controlmodel.FormattedField" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_IMAGECONTROL, "stardiv.vcl.controlmodel.ImageControl" ); + + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_SCROLLBAR, "com.sun.star.awt.UnoControlScrollBarModel" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_SCROLLBAR, "com.sun.star.awt.UnoControlScrollBar" ); + FORMS_CONSTASCII_STRING( VCL_CONTROLMODEL_SPINBUTTON, "com.sun.star.awt.UnoControlSpinButtonModel" ); + FORMS_CONSTASCII_STRING( VCL_CONTROL_SPINBUTTON, "com.sun.star.awt.UnoControlSpinButton" ); + + // ----------------------- + // service names for compatibility + // ----------------------- + FORMS_CONSTASCII_STRING( FRM_COMPONENT_FORM, "stardiv.one.form.component.Form" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_EDIT, "stardiv.one.form.component.Edit" ); // compatibility + FORMS_CONSTASCII_STRING( FRM_COMPONENT_TEXTFIELD, "stardiv.one.form.component.TextField" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_LISTBOX, "stardiv.one.form.component.ListBox" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_COMBOBOX, "stardiv.one.form.component.ComboBox" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_RADIOBUTTON, "stardiv.one.form.component.RadioButton" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_GROUPBOX, "stardiv.one.form.component.GroupBox" ); // compatibility + FORMS_CONSTASCII_STRING( FRM_COMPONENT_FIXEDTEXT, "stardiv.one.form.component.FixedText" ); // compatibility + FORMS_CONSTASCII_STRING( FRM_COMPONENT_COMMANDBUTTON, "stardiv.one.form.component.CommandButton" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_CHECKBOX, "stardiv.one.form.component.CheckBox" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_GRID, "stardiv.one.form.component.Grid" ); // compatibility + FORMS_CONSTASCII_STRING( FRM_COMPONENT_GRIDCONTROL, "stardiv.one.form.component.GridControl" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_IMAGEBUTTON, "stardiv.one.form.component.ImageButton" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_FILECONTROL, "stardiv.one.form.component.FileControl" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_TIMEFIELD, "stardiv.one.form.component.TimeField" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_DATEFIELD, "stardiv.one.form.component.DateField" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_NUMERICFIELD, "stardiv.one.form.component.NumericField" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_CURRENCYFIELD, "stardiv.one.form.component.CurrencyField" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_PATTERNFIELD, "stardiv.one.form.component.PatternField" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_HIDDEN, "stardiv.one.form.component.Hidden" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_HIDDENCONTROL, "stardiv.one.form.component.HiddenControl" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_IMAGECONTROL, "stardiv.one.form.component.ImageControl" ); + FORMS_CONSTASCII_STRING( FRM_COMPONENT_FORMATTEDFIELD, "stardiv.one.form.component.FormattedField" ); + + // <compatibility_I> + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_COMMANDBUTTON, "stardiv.one.form.control.CommandButton" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_RADIOBUTTON, "stardiv.one.form.control.RadioButton" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_CHECKBOX, "stardiv.one.form.control.CheckBox" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_EDIT, "stardiv.one.form.control.Edit" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_LISTBOX, "stardiv.one.form.control.ListBox" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_COMBOBOX, "stardiv.one.form.control.ComboBox" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_GROUPBOX, "stardiv.one.form.control.GroupBox" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_TEXTFIELD, "stardiv.one.form.control.TextField" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_GRID, "stardiv.one.form.control.Grid" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_IMAGEBUTTON, "stardiv.one.form.control.ImageButton" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_TIMEFIELD, "stardiv.one.form.control.TimeField" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_DATEFIELD, "stardiv.one.form.control.DateField" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_NUMERICFIELD, "stardiv.one.form.control.NumericField" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_CURRENCYFIELD, "stardiv.one.form.control.CurrencyField" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_PATTERNFIELD, "stardiv.one.form.control.PatternField" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_IMAGECONTROL, "stardiv.one.form.control.ImageControl" ); + FORMS_CONSTASCII_STRING( STARDIV_ONE_FORM_CONTROL_FORMATTEDFIELD, "stardiv.one.form.control.FormattedField"); + // </compatibility_I> + + // ----------------------- + // new (sun) service names + // ----------------------- + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_FORM, "com.sun.star.form.component.Form" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_HTMLFORM, "com.sun.star.form.component.HTMLForm" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATAFORM, "com.sun.star.form.component.DataForm" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_TEXTFIELD, "com.sun.star.form.component.TextField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_LISTBOX, "com.sun.star.form.component.ListBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_COMBOBOX, "com.sun.star.form.component.ComboBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_RADIOBUTTON, "com.sun.star.form.component.RadioButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_GROUPBOX, "com.sun.star.form.component.GroupBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_FIXEDTEXT, "com.sun.star.form.component.FixedText" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_COMMANDBUTTON, "com.sun.star.form.component.CommandButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_CHECKBOX, "com.sun.star.form.component.CheckBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_GRIDCONTROL, "com.sun.star.form.component.GridControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_IMAGEBUTTON, "com.sun.star.form.component.ImageButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_FILECONTROL, "com.sun.star.form.component.FileControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_TIMEFIELD, "com.sun.star.form.component.TimeField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATEFIELD, "com.sun.star.form.component.DateField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_NUMERICFIELD, "com.sun.star.form.component.NumericField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_CURRENCYFIELD, "com.sun.star.form.component.CurrencyField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_PATTERNFIELD, "com.sun.star.form.component.PatternField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_HIDDENCONTROL, "com.sun.star.form.component.HiddenControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_FORMATTEDFIELD, "com.sun.star.form.component.FormattedField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_SCROLLBAR, "com.sun.star.form.component.ScrollBar" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_SPINBUTTON, "com.sun.star.form.component.SpinButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_RICHTEXTCONTROL, "com.sun.star.form.component.RichTextControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_NAVTOOLBAR, "com.sun.star.form.component.NavigationToolBar" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_SUBMITBUTTON, "com.sun.star.form.component.SubmitButton" ); + + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_IMAGECONTROL, "com.sun.star.form.component.DatabaseImageControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_RADIOBUTTON, "com.sun.star.form.component.DatabaseRadioButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_CHECKBOX, "com.sun.star.form.component.DatabaseCheckBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_LISTBOX, "com.sun.star.form.component.DatabaseListBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_COMBOBOX, "com.sun.star.form.component.DatabaseComboBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD, "com.sun.star.form.component.DatabaseFormattedField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_TEXTFIELD, "com.sun.star.form.component.DatabaseTextField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_DATEFIELD, "com.sun.star.form.component.DatabaseDateField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_TIMEFIELD, "com.sun.star.form.component.DatabaseTimeField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_NUMERICFIELD, "com.sun.star.form.component.DatabaseNumericField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_CURRENCYFIELD, "com.sun.star.form.component.DatabaseCurrencyField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_COMPONENT_DATABASE_PATTERNFIELD, "com.sun.star.form.component.DatabasePatternField" ); + + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_TEXTFIELD, "com.sun.star.form.control.TextField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_LISTBOX, "com.sun.star.form.control.ListBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_COMBOBOX, "com.sun.star.form.control.ComboBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_RADIOBUTTON, "com.sun.star.form.control.RadioButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_GROUPBOX, "com.sun.star.form.control.GroupBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_FIXEDTEXT, "com.sun.star.form.control.FixedText" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_COMMANDBUTTON, "com.sun.star.form.control.CommandButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_CHECKBOX, "com.sun.star.form.control.CheckBox" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_GRIDCONTROL, "com.sun.star.form.control.GridControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_IMAGEBUTTON, "com.sun.star.form.control.ImageButton" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_TIMEFIELD, "com.sun.star.form.control.TimeField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_DATEFIELD, "com.sun.star.form.control.DateField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_NUMERICFIELD, "com.sun.star.form.control.NumericField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_CURRENCYFIELD, "com.sun.star.form.control.CurrencyField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_PATTERNFIELD, "com.sun.star.form.control.PatternField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_IMAGECONTROL, "com.sun.star.form.control.ImageControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_FORMATTEDFIELD, "com.sun.star.form.control.FormattedField" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_RICHTEXTCONTROL,"com.sun.star.form.control.RichTextControl" ); + FORMS_CONSTASCII_STRING( FRM_SUN_CONTROL_SUBMITBUTTON, "com.sun.star.form.control.SubmitButton" ); + + FORMS_CONSTASCII_STRING( FRM_SUN_FORMS_COLLECTION, "com.sun.star.form.Forms" ); + + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_CHECK_BOX, "com.sun.star.form.binding.BindableDatabaseCheckBox" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_COMBO_BOX, "com.sun.star.form.binding.BindableDatabaseComboBox" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_FORMATTED_FIELD,"com.sun.star.form.binding.BindableDatabaseFormattedField" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_LIST_BOX, "com.sun.star.form.binding.BindableDatabaseListBox" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_NUMERIC_FIELD, "com.sun.star.form.binding.BindableDatabaseNumericField" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_RADIO_BUTTON, "com.sun.star.form.binding.BindableDatabaseRadioButton" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_TEXT_FIELD, "com.sun.star.form.binding.BindableDatabaseTextField" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_DATE_FIELD, "com.sun.star.form.binding.BindableDatabaseDateField" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATABASE_TIME_FIELD, "com.sun.star.form.binding.BindableDatabaseTimeField" ); + + FORMS_CONSTASCII_STRING( BINDABLE_CONTROL_MODEL, "com.sun.star.form.binding.BindableControlModel" ); + FORMS_CONSTASCII_STRING( BINDABLE_INTEGER_VALUE_RANGE, "com.sun.star.form.binding.BindableIntegerValueRange" ); + FORMS_CONSTASCII_STRING( BINDABLE_DATA_AWARE_CONTROL_MODEL, "com.sun.star.form.binding.BindableDataAwareControlModel" ); + FORMS_CONSTASCII_STRING( DATA_AWARE_CONTROL_MODEL, "com.sun.star.form.binding.DataAwareControlModel" ); + FORMS_CONSTASCII_STRING( VALIDATABLE_CONTROL_MODEL, "com.sun.star.form.binding.ValidatableControlModel" ); + FORMS_CONSTASCII_STRING( VALIDATABLE_BINDABLE_CONTROL_MODEL,"com.sun.star.form.binding.ValidatableBindableControlModel" ); + + // ----------------------- + // common + // ----------------------- + FORMS_CONSTASCII_STRING( FRM_SUN_FORMCOMPONENT, "com.sun.star.form.FormComponent" ); + + // ----------------------- + // misc + // ----------------------- + FORMS_CONSTASCII_STRING( SRV_AWT_POINTER, "com.sun.star.awt.Pointer" ); + FORMS_CONSTASCII_STRING( SRV_AWT_IMAGEPRODUCER, "com.sun.star.awt.ImageProducer" ); + FORMS_CONSTASCII_STRING( FRM_NUMBER_FORMATTER, "com.sun.star.util.NumberFormatter" ); + FORMS_CONSTASCII_STRING( FRM_NUMBER_FORMATS_SUPPLIER, "com.sun.star.util.NumberFormatsSupplier" ); + + FORMS_CONSTASCII_STRING( SRV_SDB_ROWSET, "com.sun.star.sdb.RowSet" ); + FORMS_CONSTASCII_STRING( SRV_SDB_CONNECTION, "com.sun.star.sdb.Connection" ); + + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_SERVICES_HXX_ + diff --git a/forms/source/inc/togglestate.hxx b/forms/source/inc/togglestate.hxx new file mode 100644 index 000000000000..30efa6f14ed5 --- /dev/null +++ b/forms/source/inc/togglestate.hxx @@ -0,0 +1,44 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef FORMS_TOGGLESTATE_HXX +#define FORMS_TOGGLESTATE_HXX + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace frm +{ +//........................................................................ + + enum ToggleState { STATE_NOCHECK = 0, STATE_CHECK = 1, STATE_DONTKNOW = 2 }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_TOGGLESTATE_HXX diff --git a/forms/source/inc/urltransformer.hxx b/forms/source/inc/urltransformer.hxx new file mode 100644 index 000000000000..2e8bdf1f684a --- /dev/null +++ b/forms/source/inc/urltransformer.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_INC_URLTRANSFORMER_HXX +#define FORMS_SOURCE_INC_URLTRANSFORMER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/URL.hpp> +/** === end UNO includes === **/ + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= UrlTransformer + //==================================================================== + class UrlTransformer + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + m_xORB; + mutable ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > + m_xTransformer; + mutable bool m_bTriedToCreateTransformer; + + public: + UrlTransformer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ); + + /** returns an URL object for the given URL string + */ + ::com::sun::star::util::URL + getStrictURL( const ::rtl::OUString& _rURL ) const; + + /** returns an URL object for the given URL ASCII string + */ + ::com::sun::star::util::URL + getStrictURLFromAscii( const sal_Char* _pAsciiURL ) const; + + /** parses a given URL smartly, with a protocol given by ASCII string + */ + void + parseSmartWithAsciiProtocol( ::com::sun::star::util::URL& _rURL, const sal_Char* _pAsciiURL ) const; + + private: + /** ensures that we have an URLTransformer instance in <member>m_xTransformer</member> + + @return + <TRUE/> if and only if m_xTransformer is not <NULL/> + */ + bool implEnsureTransformer() const; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_INC_URLTRANSFORMER_HXX + diff --git a/forms/source/inc/windowstateguard.hxx b/forms/source/inc/windowstateguard.hxx new file mode 100644 index 000000000000..b4c93636f825 --- /dev/null +++ b/forms/source/inc/windowstateguard.hxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_WINDOWSTATEGUARD_HXX +#define FORMS_WINDOWSTATEGUARD_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +/** === end UNO includes === **/ +#include <rtl/ref.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= WindowStateGuard + //==================================================================== + class WindowStateGuard_Impl; + + /** a helper class which monitors certain states of an XWindow2, and ensures + that they're consistent with respective properties at an XModel. + + For form controls, window states - such as "Enabled" - can be set by various + means. You can set the respective control model property, you can directly manipulate + the XWindow2, or the state can change implicitly due to VCL actions. In any case, + we need to ensure that the state does not contradict the model property "too much". + + As an example, consider a form control which, according to its model's property, is disabled. + Now when the parent VCL window of the control's VCL window is enabled, then the the control's + window is enabled, too - which contradicts the model property. + + A WindowStateGuard helps you preventing such inconsistent states. + + The class is not threadsafe. + */ + class WindowStateGuard + { + private: + ::rtl::Reference< WindowStateGuard_Impl > m_pImpl; + + public: + WindowStateGuard(); + ~WindowStateGuard(); + + void attach( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow2 >& _rxWindow, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& _rxModel + ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_WINDOWSTATEGUARD_HXX + diff --git a/forms/source/misc/InterfaceContainer.cxx b/forms/source/misc/InterfaceContainer.cxx new file mode 100644 index 000000000000..b594df158d17 --- /dev/null +++ b/forms/source/misc/InterfaceContainer.cxx @@ -0,0 +1,1358 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "InterfaceContainer.hxx" +#include "property.hrc" +#include "services.hxx" + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/io/WrongFormatException.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +#include <comphelper/container.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/eventattachermgr.hxx> +#include <comphelper/property.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/logfile.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> +#include <memory> + +//......................................................................... +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/document/XCodeNameQuery.hpp> +#include <ooo/vba/XVBAToOOEventDescGen.hpp> +#include <comphelper/processfactory.hxx> + +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::util; + +namespace +{ + //--------------------------------------------------------------------- + static void lcl_throwIllegalArgumentException() + { + throw IllegalArgumentException(); + } +} + +bool +lcl_hasVbaEvents( const Sequence< ScriptEventDescriptor >& sEvents ) +{ + const ScriptEventDescriptor* pDesc = sEvents.getConstArray(); + const ScriptEventDescriptor* pEnd = ( pDesc + sEvents.getLength() ); + for ( ; pDesc != pEnd; ++pDesc ) + { + if ( pDesc->ScriptType.equals( rtl::OUString::createFromAscii( "VBAInterop" ) ) ) + return true; + } + return false; +} + +Sequence< ScriptEventDescriptor > +lcl_stripVbaEvents( const Sequence< ScriptEventDescriptor >& sEvents ) +{ + Sequence< ScriptEventDescriptor > sStripped( sEvents.getLength() ); + + const ScriptEventDescriptor* pDesc = sEvents.getConstArray(); + const ScriptEventDescriptor* pEnd = ( pDesc + sEvents.getLength() ); + sal_Int32 nCopied = 0; + for ( ; pDesc != pEnd; ++pDesc ) + { + if ( !pDesc->ScriptType.equals( rtl::OUString::createFromAscii( "VBAInterop" ) ) ) + { + sStripped[ nCopied++ ] = *pDesc; + } + } + if ( nCopied ) + sStripped.realloc( nCopied ); + return sStripped; +} + +void +OInterfaceContainer::fakeVbaEventsHack( sal_Int32 _nIndex ) +{ + // we are dealing with form controls + try + { + Reference< XFormComponent > xForm( static_cast< XContainer* >(this), UNO_QUERY_THROW ); + // grand-parent should be the model, no parent ? if not + // we'll ignore, we'll get called back here anyway ) + Reference< XChild > xChild( xForm->getParent(), UNO_QUERY_THROW ); + Reference< XModel > xDocOwner( xChild->getParent(), UNO_QUERY ); + OSL_TRACE(" Is DOC ????? %s", xDocOwner.is() ? "true" : "false" ); + if ( xDocOwner.is() ) + { + bool hasVBABindings = lcl_hasVbaEvents( m_xEventAttacher->getScriptEvents( _nIndex ) ); + if ( hasVBABindings ) + { + OSL_TRACE("Has VBA bindings already, returning "); + return; + } + Reference< XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory(), UNO_QUERY ); + Reference< XMultiServiceFactory > xDocFac( xDocOwner, UNO_QUERY ); + if ( xFac.is() && xDocFac.is() ) + { + try + { + Reference< ooo::vba::XVBAToOOEventDescGen > xDescSupplier( xFac->createInstance( rtl::OUString::createFromAscii( "ooo.vba.VBAToOOEventDesc" ) ), UNO_QUERY_THROW ); + Reference< XInterface > xIf( getByIndex( _nIndex ) , UNO_QUERY_THROW ); + Reference< XCodeNameQuery > xNameQuery( xDocFac->createInstance( rtl::OUString::createFromAscii( "ooo.vba.VBACodeNameProvider" ) ), UNO_QUERY_THROW ); + + rtl::OUString sCodeName; + sCodeName = xNameQuery->getCodeNameForObject( xIf ); + Reference< XPropertySet > xProps( xIf, UNO_QUERY ); + rtl::OUString sServiceName; + xProps->getPropertyValue( rtl::OUString::createFromAscii("DefaultControl" ) ) >>= sServiceName; + + Sequence< ScriptEventDescriptor > vbaEvents = xDescSupplier->getEventDescriptions( xFac->createInstance( sServiceName ), sCodeName ); + // register the vba script events + if ( m_xEventAttacher.is() ) + m_xEventAttacher->registerScriptEvents( _nIndex, vbaEvents ); + } + catch( Exception& ){ OSL_TRACE("lcl_fakevbaevents - Caught Exception trying to create control eventstuff "); } + } + + } + } + catch( Exception& ) + { + } + +} +//================================================================== +//= ElementDescription +//================================================================== +//------------------------------------------------------------------ +ElementDescription::ElementDescription( ) +{ +} + +//------------------------------------------------------------------ +ElementDescription::~ElementDescription() +{ +} + +//================================================================== +//= OInterfaceContainer +//================================================================== +//------------------------------------------------------------------ +OInterfaceContainer::OInterfaceContainer( + const Reference<XMultiServiceFactory>& _rxFactory, + ::osl::Mutex& _rMutex, + const Type& _rElementType) + :OInterfaceContainer_BASE() + ,m_rMutex(_rMutex) + ,m_aContainerListeners(_rMutex) + ,m_aElementType(_rElementType) + ,m_xServiceFactory(_rxFactory) +{ + impl_createEventAttacher_nothrow(); +} + +//------------------------------------------------------------------------------ +OInterfaceContainer::OInterfaceContainer( ::osl::Mutex& _rMutex, const OInterfaceContainer& _cloneSource ) + :OInterfaceContainer_BASE() + ,m_rMutex( _rMutex ) + ,m_aContainerListeners( _rMutex ) + ,m_aElementType( _cloneSource.m_aElementType ) + ,m_xServiceFactory( _cloneSource.m_xServiceFactory ) +{ + impl_createEventAttacher_nothrow(); +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::clonedFrom( const OInterfaceContainer& _cloneSource ) +{ + try + { + const Reference< XIndexAccess > xSourceHierarchy( const_cast< OInterfaceContainer* >( &_cloneSource ) ); + const sal_Int32 nCount = xSourceHierarchy->getCount(); + for ( sal_Int32 i=0; i<nCount; ++i ) + { + Reference< XCloneable > xCloneable( xSourceHierarchy->getByIndex( i ), UNO_QUERY_THROW ); + Reference< XInterface > xClone( xCloneable->createClone() ); + insertByIndex( i, makeAny( xClone ) ); + } + } + catch( const Exception& ) + { + throw WrappedTargetException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not clone the given interface hierarchy." ) ), + static_cast< XIndexContainer* >( const_cast< OInterfaceContainer* >( &_cloneSource ) ), + ::cppu::getCaughtException() + ); + } +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::impl_createEventAttacher_nothrow() +{ + try + { + m_xEventAttacher.set( ::comphelper::createEventAttacherManager( m_xServiceFactory ), UNO_SET_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +OInterfaceContainer::~OInterfaceContainer() +{ +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::disposing() +{ + // dispose all elements + for (sal_Int32 i = m_aItems.size(); i > 0; --i) + { + Reference<XPropertySet> xSet(m_aItems[i - 1], UNO_QUERY); + if (xSet.is()) + xSet->removePropertyChangeListener(PROPERTY_NAME, this); + + // revoke event knittings + if ( m_xEventAttacher.is() ) + { + Reference< XInterface > xIfc( xSet, UNO_QUERY ); + m_xEventAttacher->detach( i - 1, xIfc ); + m_xEventAttacher->removeEntry( i - 1 ); + } + + Reference<XComponent> xComponent(xSet, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + } + m_aMap.clear(); + m_aItems.clear(); + + EventObject aEvt(static_cast<XContainer*>(this)); + m_aContainerListeners.disposeAndClear(aEvt); +} + +// XPersistObject +//------------------------------------------------------------------------------ +namespace +{ + //.......................................................................... + void lcl_saveEvents( ::std::vector< Sequence< ScriptEventDescriptor > >& _rSave, + const Reference< XEventAttacherManager >& _rxManager, const sal_Int32 _nItemCount ) + { + OSL_ENSURE( _rxManager.is(), "lcl_saveEvents: invalid event attacher manager!" ); + if ( !_rxManager.is() ) + return; + + // reserve the space needed + _rSave.reserve( _nItemCount ); + + // copy the events + for (sal_Int32 i=0; i<_nItemCount; ++i) + _rSave.push_back(_rxManager->getScriptEvents( i )); + } + + //.......................................................................... + void lcl_restoreEvents( const ::std::vector< Sequence< ScriptEventDescriptor > >& _rSave, + const Reference< XEventAttacherManager >& _rxManager ) + { + OSL_ENSURE( _rxManager.is(), "lcl_restoreEvents: invalid event attacher manager!" ); + if ( !_rxManager.is() ) + return; + + ::std::vector< Sequence< ScriptEventDescriptor > >::const_iterator aLoop = _rSave.begin(); + ::std::vector< Sequence< ScriptEventDescriptor > >::const_iterator aEnd = _rSave.end(); + for ( sal_Int32 i=0; aLoop != aEnd; ++aLoop, ++i ) + { + _rxManager->revokeScriptEvents( i ); + _rxManager->registerScriptEvents( i, *aLoop ); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::writeEvents(const Reference<XObjectOutputStream>& _rxOutStream) +{ + // We're writing a document in SO 5.2 format (or even from earlier versions) + // -> convert the events from the new runtime format to the format of the 5.2 files + // but before, remember the current script events set for our children + ::std::vector< Sequence< ScriptEventDescriptor > > aSave; + if ( m_xEventAttacher.is() ) + lcl_saveEvents( aSave, m_xEventAttacher, m_aItems.size() ); + + transformEvents( efVersionSO5x ); + + try + { + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + sal_Int32 nMark = xMark->createMark(); + + sal_Int32 nObjLen = 0; + _rxOutStream->writeLong(nObjLen); + + Reference<XPersistObject> xScripts(m_xEventAttacher, UNO_QUERY); + if (xScripts.is()) + xScripts->write(_rxOutStream); + + // feststellen der Laenge + nObjLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nObjLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + } + catch( const Exception& ) + { + // restore the events + if ( m_xEventAttacher.is() ) + lcl_restoreEvents( aSave, m_xEventAttacher ); + throw; + } + + // restore the events + if ( m_xEventAttacher.is() ) + lcl_restoreEvents( aSave, m_xEventAttacher ); +} + +//------------------------------------------------------------------------------ +struct TransformEventTo52Format : public ::std::unary_function< ScriptEventDescriptor, void > +{ + void operator()( ScriptEventDescriptor& _rDescriptor ) + { + if ( 0 == _rDescriptor.ScriptType.compareToAscii( "StarBasic" ) ) + { // it's a starbasic macro + sal_Int32 nPrefixLength = _rDescriptor.ScriptCode.indexOf( ':' ); + if ( 0 <= nPrefixLength ) + { // the macro name does not already contain a : +#ifdef DBG_UTIL + const ::rtl::OUString sPrefix = _rDescriptor.ScriptCode.copy( 0, nPrefixLength ); + DBG_ASSERT( 0 == sPrefix.compareToAscii( "document" ) + || 0 == sPrefix.compareToAscii( "application" ), + "TransformEventTo52Format: invalid (unknown) prefix!" ); +#endif + // cut the prefix + _rDescriptor.ScriptCode = _rDescriptor.ScriptCode.copy( nPrefixLength + 1 ); + } + } + } +}; + +//------------------------------------------------------------------------------ +struct TransformEventTo60Format : public ::std::unary_function< ScriptEventDescriptor, void > +{ + void operator()( ScriptEventDescriptor& _rDescriptor ) + { + if ( 0 == _rDescriptor.ScriptType.compareToAscii( "StarBasic" ) ) + { // it's a starbasic macro + if ( _rDescriptor.ScriptCode.indexOf( ':' ) < 0 ) + { // the macro name does not already contain a : + // -> default the type to "document" + ::rtl::OUString sNewScriptCode( RTL_CONSTASCII_USTRINGPARAM( "document:" ) ); + sNewScriptCode += _rDescriptor.ScriptCode; + _rDescriptor.ScriptCode = sNewScriptCode; + } + } + } +}; + +//------------------------------------------------------------------------------ +void OInterfaceContainer::transformEvents( const EventFormat _eTargetFormat ) +{ + OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::transformEvents: no event attacher manager!" ); + if ( !m_xEventAttacher.is() ) + return; + + try + { + // loop through all our children + sal_Int32 nItems = m_aItems.size(); + Sequence< ScriptEventDescriptor > aChildEvents; + + for (sal_Int32 i=0; i<nItems; ++i) + { + // get the script events for this object + aChildEvents = m_xEventAttacher->getScriptEvents( i ); + + if ( aChildEvents.getLength() ) + { + // the "iterators" for the events for this child + ScriptEventDescriptor* pChildEvents = aChildEvents.getArray(); + ScriptEventDescriptor* pChildEventsEnd = pChildEvents + aChildEvents.getLength(); + + // do the transformation + if ( efVersionSO6x == _eTargetFormat ) + ::std::for_each( pChildEvents, pChildEventsEnd, TransformEventTo60Format() ); + else + ::std::for_each( pChildEvents, pChildEventsEnd, TransformEventTo52Format() ); + + // revoke the script events + m_xEventAttacher->revokeScriptEvents( i ); + // and re-register them + m_xEventAttacher->registerScriptEvents( i, aChildEvents ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::readEvents(const Reference<XObjectInputStream>& _rxInStream) +{ + ::osl::MutexGuard aGuard( m_rMutex ); + + // Scripting Info lesen + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + sal_Int32 nObjLen = _rxInStream->readLong(); + if (nObjLen) + { + sal_Int32 nMark = xMark->createMark(); + Reference<XPersistObject> xObj(m_xEventAttacher, UNO_QUERY); + if (xObj.is()) + xObj->read(_rxInStream); + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nObjLen); + xMark->deleteMark(nMark); + } + + // Attachement lesen + if ( m_xEventAttacher.is() ) + { + OInterfaceArray::const_iterator aAttach = m_aItems.begin(); + OInterfaceArray::const_iterator aAttachEnd = m_aItems.end(); + for ( sal_Int32 i=0; aAttach != aAttachEnd; ++aAttach, ++i ) + { + Reference< XInterface > xAsIFace( *aAttach, UNO_QUERY ); // important to normalize this .... + Reference< XPropertySet > xAsSet( xAsIFace, UNO_QUERY ); + m_xEventAttacher->attach( i, xAsIFace, makeAny( xAsSet ) ); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::write( const Reference< XObjectOutputStream >& _rxOutStream ) throw(IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_rMutex ); + sal_Int32 nLen = m_aItems.size(); + + // schreiben der laenge + _rxOutStream->writeLong(nLen); + + if (nLen) + { + // 1. Version + _rxOutStream->writeShort(0x0001); + + // 2. Objekte + for (sal_Int32 i = 0; i < nLen; i++) + { + Reference<XPersistObject> xObj(m_aItems[i], UNO_QUERY); + if (xObj.is()) + _rxOutStream->writeObject(xObj); + else + { + // ::com::sun::star::chaos::Error + } + } + + // 3. Scripts + writeEvents(_rxOutStream); + } +} + +//------------------------------------------------------------------------------ +namespace +{ + Reference< XPersistObject > lcl_createPlaceHolder( const Reference< XMultiServiceFactory >& _rxORB ) + { + Reference< XPersistObject > xObject( _rxORB->createInstance( FRM_COMPONENT_HIDDENCONTROL ), UNO_QUERY ); + DBG_ASSERT( xObject.is(), "lcl_createPlaceHolder: could not create a substitute for the unknown object!" ); + if ( xObject.is() ) + { + // set some properties describing what we did + Reference< XPropertySet > xObjProps( xObject, UNO_QUERY ); + if ( xObject.is() ) + { + try + { + xObjProps->setPropertyValue( PROPERTY_NAME, makeAny( FRM_RES_STRING( RID_STR_CONTROL_SUBSTITUTED_NAME ) ) ); + xObjProps->setPropertyValue( PROPERTY_TAG, makeAny( FRM_RES_STRING( RID_STR_CONTROL_SUBSTITUTED_EPXPLAIN ) ) ); + } + catch(Exception&) + { + } + } + } + return xObject; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::read( const Reference< XObjectInputStream >& _rxInStream ) throw(IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_rMutex ); + + // after ::read the object is expected to be in the state it was when ::write was called, so we have + // to empty ourself here + // FS - 71598 - 12.01.00 + while (getCount()) + removeByIndex(0); + + // Schreibt nur in Abhaengigkeit der Laenge + sal_Int32 nLen = _rxInStream->readLong(); + + if (nLen) + { + // 1. Version + sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion; + + // 2. Objekte + for (sal_Int32 i = 0; i < nLen; i++) + { + Reference<XPersistObject> xObj; + try + { + xObj = _rxInStream->readObject(); + } + catch(WrongFormatException& e) + { + (void)e; // make compiler happy + // the object could not be read + // create a object (so the readEvents below will assign the events to the right controls) + xObj = lcl_createPlaceHolder( m_xServiceFactory ); + if ( !xObj.is() ) + // couldn't handle it + throw; + // 72133 - 09.02.00 - FS + } + catch(Exception&) + { + // unsere Map leeren + while (!m_aItems.empty()) + removeElementsNoEvents(0); + + // und die Exception nach aussen + throw; + } + + if ( xObj.is() ) + { + Reference< XPropertySet > xElement( xObj, UNO_QUERY ); + try + { + implInsert( + m_aItems.size(), // position + xElement, // element to insert + sal_False, // no event attacher manager handling + NULL, // not yet approved - let implInsert do it + sal_True // fire the event + ); + } + catch( const Exception& ) + { + DBG_ERROR( "OInterfaceContainerHelper::read: reading succeeded, but not inserting!" ); + // create a placeholder + xElement = xElement.query( lcl_createPlaceHolder( m_xServiceFactory ) ); + if ( !xElement.is() ) + // couldn't handle it + throw; + // insert the placeholder + implInsert( m_aItems.size(), xElement, sal_False, NULL, sal_True ); + } + } + } + + readEvents(_rxInStream); + } + else + { + try + { + m_xEventAttacher = ::comphelper::createEventAttacherManager( m_xServiceFactory ); + OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::read: could not create an event attacher manager!" ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +// XContainer +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::addContainerListener(const Reference<XContainerListener>& _rxListener) throw( RuntimeException ) +{ + m_aContainerListeners.addInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::removeContainerListener(const Reference<XContainerListener>& _rxListener) throw( RuntimeException ) +{ + m_aContainerListeners.removeInterface(_rxListener); +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::disposing(const EventObject& _rSource) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_rMutex ); + + Reference< XInterface > xSource( _rSource.Source, UNO_QUERY ); + // normalized source + + OInterfaceArray::iterator j; + for ( j = m_aItems.begin(); j != m_aItems.end(); ++j ) + { + DBG_ASSERT( j->get() == Reference< XInterface >( *j, UNO_QUERY ).get(), + "OInterfaceContainer::disposing: vector element not normalized!" ); + + if ( xSource.get() == j->get() ) + // found the element + break; + } + + if ( m_aItems.end() != j ) + { + m_aItems.erase(j); + + // look up in, and erase from, m_aMap, too + OInterfaceMap::iterator i = m_aMap.begin(); + while ( i != m_aMap.end() ) + { + DBG_ASSERT( i->second.get() == Reference< XInterface >( i->second, UNO_QUERY ).get(), + "OInterfaceContainer::disposing: map element not normalized!" ); + + if ( i->second.get() == xSource.get() ) + { + // found it + m_aMap.erase(i); + break; + } + + ++i; + + DBG_ASSERT( i != m_aMap.end(), "OInterfaceContainer::disposing: inconsistency: the element was in m_aItems, but not in m_aMap!" ); + } + } +} + +// XPropertyChangeListener +//------------------------------------------------------------------------------ +void OInterfaceContainer::propertyChange(const PropertyChangeEvent& evt) +throw (::com::sun::star::uno::RuntimeException) { + if (evt.PropertyName == PROPERTY_NAME) + { + ::osl::MutexGuard aGuard( m_rMutex ); + OInterfaceMap::iterator i = ::std::find(m_aMap.begin(), m_aMap.end(), + ::std::pair<const ::rtl::OUString, InterfaceRef >(::comphelper::getString(evt.OldValue),evt.Source)); + if (i != m_aMap.end()) + { + InterfaceRef xCorrectType((*i).second); + m_aMap.erase(i); + m_aMap.insert(::std::pair<const ::rtl::OUString, InterfaceRef >(::comphelper::getString(evt.NewValue),xCorrectType)); + } + } +} + +// XElementAccess +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OInterfaceContainer::hasElements() throw( RuntimeException ) +{ + return !m_aMap.empty(); +} + +//------------------------------------------------------------------------------ +Type SAL_CALL OInterfaceContainer::getElementType() throw(RuntimeException) +{ + return m_aElementType; +} + +// XEnumerationAccess +//------------------------------------------------------------------------------ +Reference<XEnumeration> SAL_CALL OInterfaceContainer::createEnumeration() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_rMutex ); + return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this)); +} + +// XNameAccess +//------------------------------------------------------------------------------ +Any SAL_CALL OInterfaceContainer::getByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ::std::pair <OInterfaceMap::iterator, + OInterfaceMap::iterator> aPair = m_aMap.equal_range(_rName); + + if (aPair.first == aPair.second) + throw NoSuchElementException(); + + return (*aPair.first).second->queryInterface( m_aElementType ); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OInterfaceContainer::getElementNames() throw(RuntimeException) +{ + StringSequence aNameList(m_aItems.size()); + ::rtl::OUString* pStringArray = aNameList.getArray(); + + for (OInterfaceMap::const_iterator i = m_aMap.begin(); i != m_aMap.end(); ++i, ++pStringArray) + { + *pStringArray = (*i).first; + } + return aNameList; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OInterfaceContainer::hasByName( const ::rtl::OUString& _rName ) throw(RuntimeException) +{ + ::std::pair <OInterfaceMap::iterator, + OInterfaceMap::iterator> aPair = m_aMap.equal_range(_rName); + return aPair.first != aPair.second; +} + +// XIndexAccess +//------------------------------------------------------------------------------ +sal_Int32 OInterfaceContainer::getCount() throw( RuntimeException ) +{ + return m_aItems.size(); +} + +//------------------------------------------------------------------------------ +Any OInterfaceContainer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + if (_nIndex < 0 || (_nIndex >= (sal_Int32)m_aItems.size())) + throw IndexOutOfBoundsException(); + + return m_aItems[_nIndex]->queryInterface( m_aElementType ); +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement ) +{ + // it has to be non-NULL + if ( !_rxObject.is() ) + throw IllegalArgumentException(FRM_RES_STRING(RID_STR_NEED_NON_NULL_OBJECT), static_cast<XContainer*>(this), 1); + + // it has to support our element type interface + Any aCorrectType = _rxObject->queryInterface( m_aElementType ); + if ( !aCorrectType.hasValue() ) + lcl_throwIllegalArgumentException(); + + // it has to have a "Name" property + if ( !hasProperty( PROPERTY_NAME, _rxObject ) ) + lcl_throwIllegalArgumentException(); + + // it has to be a child, and it must not have a parent already + Reference< XChild > xChild( _rxObject, UNO_QUERY ); + if ( !xChild.is() || xChild->getParent().is() ) + { +#ifdef FS_PRIV_DEBUG + ::rtl::OUString sChildName, sParentName; + Reference< XNamed > xNamed( xChild, UNO_QUERY ); + if ( xNamed.is() ) + sChildName = xNamed->getName(); + if ( xChild.is() ) + { + xNamed = xNamed.query( xChild->getParent() ); + if ( xNamed.is() ) + sParentName = xNamed->getName(); + } +#endif + lcl_throwIllegalArgumentException(); + } + + // passed all tests. cache the information we have so far + DBG_ASSERT( _pElement, "OInterfaceContainer::approveNewElement: invalid event descriptor!" ); + if ( _pElement ) + { + _pElement->xPropertySet = _rxObject; + _pElement->xChild = xChild; + _pElement->aElementTypeInterface = aCorrectType; + _pElement->xInterface = Reference< XInterface >( _rxObject, UNO_QUERY ); // normalized XInterface + } +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const Reference< XPropertySet >& _rxElement, + sal_Bool _bEvents, ElementDescription* _pApprovalResult, sal_Bool _bFire ) throw( IllegalArgumentException ) +{ + RTL_LOGFILE_CONTEXT( aLogger, "forms::OInterfaceContainer::implInsert" ); + + ::osl::ClearableMutexGuard aGuard( m_rMutex ); + + ::std::auto_ptr< ElementDescription > aAutoDeleteMetaData; + ElementDescription* pElementMetaData = _pApprovalResult; + if ( !pElementMetaData ) + { // not yet approved by the caller -> do ourself + pElementMetaData = createElementMetaData(); + DBG_ASSERT( pElementMetaData, "OInterfaceContainer::implInsert: createElementMetaData returned nonsense!" ); + + // ensure that the meta data structure will be deleted later on + aAutoDeleteMetaData = ::std::auto_ptr< ElementDescription >( pElementMetaData ); + + // will throw an exception if necessary + approveNewElement( _rxElement, pElementMetaData ); + } + + + // approveNewElement (no matter if called here or outside) has ensure that all relevant interfaces + // exist + + // set the name, and add as change listener for the name + ::rtl::OUString sName; + _rxElement->getPropertyValue(PROPERTY_NAME) >>= sName; + _rxElement->addPropertyChangeListener(PROPERTY_NAME, this); + + // insert the object into our internal structures + if (_nIndex > (sal_Int32)m_aItems.size()) // ermitteln des tatsaechlichen Indexs + { + _nIndex = m_aItems.size(); + m_aItems.push_back( pElementMetaData->xInterface ); + } + else + m_aItems.insert( m_aItems.begin() + _nIndex, pElementMetaData->xInterface ); + + m_aMap.insert( ::std::pair< const ::rtl::OUString, InterfaceRef >( sName, pElementMetaData->xInterface ) ); + + // announce ourself as parent to the new element + { + RTL_LOGFILE_CONTEXT( aLogger, "forms::OInterfaceContainer::implInsert::settingParent" ); + pElementMetaData->xChild->setParent(static_cast<XContainer*>(this)); + } + + // handle the events + if ( _bEvents && m_xEventAttacher.is() ) + { + m_xEventAttacher->insertEntry(_nIndex); + m_xEventAttacher->attach( _nIndex, pElementMetaData->xInterface, makeAny( _rxElement ) ); + // insert fake events? + Reference< XEventAttacherManager > xMgr ( pElementMetaData->xInterface, UNO_QUERY ); + if ( xMgr.is() ) + { + OInterfaceContainer* pIfcMgr = dynamic_cast< OInterfaceContainer* >( xMgr.get() ); + sal_Int32 nLen = pIfcMgr->getCount(); + for ( sal_Int32 i = 0; (i < nLen) && pIfcMgr ; ++i ) + { + // add fake events to the control at index i + pIfcMgr->fakeVbaEventsHack( i ); + } + } + else + { + // add fake events to the control at index i + fakeVbaEventsHack( _nIndex ); + } + } + + // notify derived classes + implInserted( pElementMetaData ); + + // fire the notification about the change + if ( _bFire ) + { + // notify listeners + ContainerEvent aEvt; + aEvt.Source = static_cast<XContainer*>(this); + aEvt.Accessor <<= _nIndex; + aEvt.Element = pElementMetaData->aElementTypeInterface; + + aGuard.clear(); + m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt ); + } +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::removeElementsNoEvents(sal_Int32 nIndex) +{ + OInterfaceArray::iterator i = m_aItems.begin() + nIndex; + InterfaceRef xElement(*i); + + OInterfaceMap::iterator j = m_aMap.begin(); + while (j != m_aMap.end() && (*j).second != xElement) ++j; + + m_aItems.erase(i); + m_aMap.erase(j); + + Reference<XPropertySet> xSet(xElement, UNO_QUERY); + if (xSet.is()) + xSet->removePropertyChangeListener(PROPERTY_NAME, this); + + Reference<XChild> xChild(xElement, UNO_QUERY); + if (xChild.is()) + xChild->setParent(InterfaceRef ()); +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::implInserted( const ElementDescription* /*_pElement*/ ) +{ + // not inrerested in +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::implRemoved( const InterfaceRef& /*_rxObject*/ ) +{ + // not inrerested in +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::impl_replacedElement( const ContainerEvent& _rEvent, ::osl::ClearableMutexGuard& _rInstanceLock ) +{ + _rInstanceLock.clear(); + m_aContainerListeners.notifyEach( &XContainerListener::elementReplaced, _rEvent ); +} + +// XIndexContainer +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::insertByIndex( sal_Int32 _nIndex, const Any& _rElement ) throw(IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + Reference< XPropertySet > xElement; + _rElement >>= xElement; + implInsert( _nIndex, xElement, sal_True /* event handling */ , NULL /* not yet approved */ , sal_True /* notification */ ); +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::implReplaceByIndex( const sal_Int32 _nIndex, const Any& _rNewElement, ::osl::ClearableMutexGuard& _rClearBeforeNotify ) +{ + OSL_PRECOND( ( _nIndex >= 0 ) && ( _nIndex < (sal_Int32)m_aItems.size() ), "OInterfaceContainer::implReplaceByIndex: precondition not met (index)!" ); + + // approve the new object + ::std::auto_ptr< ElementDescription > aElementMetaData( createElementMetaData() ); + DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::implReplaceByIndex: createElementMetaData returned nonsense!" ); + { + Reference< XPropertySet > xElementProps; + _rNewElement >>= xElementProps; + approveNewElement( xElementProps, aElementMetaData.get() ); + } + + // get the old element + InterfaceRef xOldElement( m_aItems[ _nIndex ] ); + DBG_ASSERT( xOldElement.get() == Reference< XInterface >( xOldElement, UNO_QUERY ).get(), + "OInterfaceContainer::implReplaceByIndex: elements should be held normalized!" ); + + // locate the old element in the map + OInterfaceMap::iterator j = m_aMap.begin(); + while ( ( j != m_aMap.end() ) && ( j->second.get() != xOldElement.get() ) ) + ++j; + + // remove event knittings + if ( m_xEventAttacher.is() ) + { + InterfaceRef xNormalized( xOldElement, UNO_QUERY ); + m_xEventAttacher->detach( _nIndex, xNormalized ); + m_xEventAttacher->removeEntry( _nIndex ); + } + + // don't listen for property changes anymore + Reference<XPropertySet> xSet( xOldElement, UNO_QUERY ); + if (xSet.is()) + xSet->removePropertyChangeListener(PROPERTY_NAME, this); + + // give the old element a new (void) parent + Reference<XChild> xChild(xOldElement, UNO_QUERY); + if (xChild.is()) + xChild->setParent(InterfaceRef ()); + + // remove the old one + m_aMap.erase(j); + + // examine the new element + ::rtl::OUString sName; + DBG_ASSERT( aElementMetaData.get()->xPropertySet.is(), "OInterfaceContainer::implReplaceByIndex: what did approveNewElement do?" ); + + aElementMetaData.get()->xPropertySet->getPropertyValue(PROPERTY_NAME) >>= sName; + aElementMetaData.get()->xPropertySet->addPropertyChangeListener(PROPERTY_NAME, this); + + // insert the new one + m_aMap.insert( ::std::pair<const ::rtl::OUString, InterfaceRef >( sName, aElementMetaData.get()->xInterface ) ); + m_aItems[ _nIndex ] = aElementMetaData.get()->xInterface; + + aElementMetaData.get()->xChild->setParent(static_cast<XContainer*>(this)); + + if ( m_xEventAttacher.is() ) + { + m_xEventAttacher->insertEntry( _nIndex ); + m_xEventAttacher->attach( _nIndex, aElementMetaData.get()->xInterface, makeAny( aElementMetaData.get()->xPropertySet ) ); + } + + ContainerEvent aReplaceEvent; + aReplaceEvent.Source = static_cast< XContainer* >( this ); + aReplaceEvent.Accessor <<= _nIndex; + aReplaceEvent.Element = aElementMetaData.get()->xInterface->queryInterface( m_aElementType ); + aReplaceEvent.ReplacedElement = xOldElement->queryInterface( m_aElementType ); + + impl_replacedElement( aReplaceEvent, _rClearBeforeNotify ); +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::implCheckIndex( const sal_Int32 _nIndex ) SAL_THROW( ( ::com::sun::star::lang::IndexOutOfBoundsException ) ) +{ + if (_nIndex < 0 || _nIndex >= (sal_Int32)m_aItems.size()) + throw IndexOutOfBoundsException(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::replaceByIndex(sal_Int32 _nIndex, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ::osl::ClearableMutexGuard aGuard( m_rMutex ); + // check the index + implCheckIndex( _nIndex ); + // do the replace + implReplaceByIndex( _nIndex, Element, aGuard ); +} + +//------------------------------------------------------------------------------ +void OInterfaceContainer::implRemoveByIndex( const sal_Int32 _nIndex, ::osl::ClearableMutexGuard& _rClearBeforeNotify ) +{ + OSL_PRECOND( ( _nIndex >= 0 ) && ( _nIndex < (sal_Int32)m_aItems.size() ), "OInterfaceContainer::implRemoveByIndex: precondition not met (index)!" ); + + OInterfaceArray::iterator i = m_aItems.begin() + _nIndex; + InterfaceRef xElement(*i); + + OInterfaceMap::iterator j = m_aMap.begin(); + while (j != m_aMap.end() && (*j).second != xElement) ++j; + + m_aItems.erase(i); + m_aMap.erase(j); + + // remove event knittings + if ( m_xEventAttacher.is() ) + { + InterfaceRef xNormalized( xElement, UNO_QUERY ); + m_xEventAttacher->detach( _nIndex, xNormalized ); + m_xEventAttacher->removeEntry( _nIndex ); + } + + Reference<XPropertySet> xSet(xElement, UNO_QUERY); + if (xSet.is()) + xSet->removePropertyChangeListener(PROPERTY_NAME, this); + + Reference<XChild> xChild(xElement, UNO_QUERY); + if (xChild.is()) + xChild->setParent(InterfaceRef ()); + + // notify derived classes + implRemoved(xElement); + + // notify listeners + ContainerEvent aEvt; + aEvt.Source = static_cast<XContainer*>(this); + aEvt.Element = xElement->queryInterface( m_aElementType ); + aEvt.Accessor <<= _nIndex; + + _rClearBeforeNotify.clear(); + m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::removeByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ::osl::ClearableMutexGuard aGuard( m_rMutex ); + // check the index + implCheckIndex( _nIndex ); + // do the removal + implRemoveByIndex( _nIndex, aGuard ); +} + +//------------------------------------------------------------------------ +ElementDescription* OInterfaceContainer::createElementMetaData( ) +{ + return new ElementDescription; +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::insertByName(const ::rtl::OUString& _rName, const Any& _rElement) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) +{ + Reference< XPropertySet > xElementProps; + + ::std::auto_ptr< ElementDescription > aElementMetaData( createElementMetaData() ); + DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::insertByName: createElementMetaData returned nonsense!" ); + + // ensure the correct name of the element + try + { + _rElement >>= xElementProps; + approveNewElement( xElementProps, aElementMetaData.get() ); + + xElementProps->setPropertyValue( PROPERTY_NAME, makeAny( _rName ) ); + } + catch( const IllegalArgumentException& ) + { + throw; // allowed to leave + } + catch( const ElementExistException& ) + { + throw; // allowed to leave + } + catch( const Exception& ) + { + DBG_ERROR( "OInterfaceContainer::insertByName: caught an exception!" ); + } + implInsert( m_aItems.size(), xElementProps, sal_True, aElementMetaData.get(), sal_True ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::replaceByName(const ::rtl::OUString& Name, const Any& Element) throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + ::osl::ClearableMutexGuard aGuard( m_rMutex ); + ::std::pair <OInterfaceMap::iterator, + OInterfaceMap::iterator> aPair = m_aMap.equal_range(Name); + if (aPair.first == aPair.second) + throw NoSuchElementException(); + + if (Element.getValueType().getTypeClass() != TypeClass_INTERFACE) + lcl_throwIllegalArgumentException(); + + Reference<XPropertySet> xSet; + Element >>= xSet; + if (xSet.is()) + { + if (!hasProperty(PROPERTY_NAME, xSet)) + lcl_throwIllegalArgumentException(); + + xSet->setPropertyValue(PROPERTY_NAME, makeAny(Name)); + } + + // determine the element pos + sal_Int32 nPos = ::std::find(m_aItems.begin(), m_aItems.end(), (*aPair.first).second) - m_aItems.begin(); + + implReplaceByIndex( nPos, Element, aGuard ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::removeByName(const ::rtl::OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_rMutex ); + ::std::pair <OInterfaceMap::iterator, + OInterfaceMap::iterator> aPair = m_aMap.equal_range(Name); + if (aPair.first == aPair.second) + throw NoSuchElementException(); + + sal_Int32 nPos = ::std::find(m_aItems.begin(), m_aItems.end(), (*aPair.first).second) - m_aItems.begin(); + removeByIndex(nPos); +} + + +// XEventAttacherManager +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::registerScriptEvent( sal_Int32 nIndex, const ScriptEventDescriptor& aScriptEvent ) throw(IllegalArgumentException, RuntimeException) +{ + OSL_TRACE("*** registerScriptEvent %d", nIndex); + if ( m_xEventAttacher.is() ) + { + m_xEventAttacher->registerScriptEvent( nIndex, aScriptEvent ); + fakeVbaEventsHack( nIndex ); // add fake vba events + } +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::registerScriptEvents( sal_Int32 nIndex, const Sequence< ScriptEventDescriptor >& aScriptEvents ) throw(IllegalArgumentException, RuntimeException) +{ + OSL_TRACE("*** registerScriptEvent(s) %d", nIndex); + if ( m_xEventAttacher.is() ) + { + m_xEventAttacher->registerScriptEvents( nIndex, aScriptEvents ); + fakeVbaEventsHack( nIndex ); // add fake vba events + } +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::revokeScriptEvent( sal_Int32 nIndex, const ::rtl::OUString& aListenerType, const ::rtl::OUString& aEventMethod, const ::rtl::OUString& aRemoveListenerParam ) throw(IllegalArgumentException, RuntimeException) +{ + OSL_TRACE("*** revokeScriptEvent %d listenertype %s, eventMethod %s", nIndex, rtl::OUStringToOString( aListenerType, RTL_TEXTENCODING_UTF8 ).getStr(), rtl::OUStringToOString( aEventMethod, RTL_TEXTENCODING_UTF8 ).getStr()); + if ( m_xEventAttacher.is() ) + m_xEventAttacher->revokeScriptEvent( nIndex, aListenerType, aEventMethod, aRemoveListenerParam ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::revokeScriptEvents( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->revokeScriptEvents( nIndex ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::insertEntry( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->insertEntry( nIndex ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::removeEntry( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->removeEntry( nIndex ); +} + +//------------------------------------------------------------------------ +Sequence< ScriptEventDescriptor > SAL_CALL OInterfaceContainer::getScriptEvents( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException) +{ + OSL_TRACE("getScriptEvents"); + Sequence< ScriptEventDescriptor > aReturn; + if ( m_xEventAttacher.is() ) + { + aReturn = m_xEventAttacher->getScriptEvents( nIndex ); + if ( lcl_hasVbaEvents( aReturn ) ) + { + aReturn = lcl_stripVbaEvents( aReturn ); + } + } + return aReturn; +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::attach( sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any& aHelper ) throw(IllegalArgumentException, ServiceNotRegisteredException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->attach( nIndex, xObject, aHelper ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::detach( sal_Int32 nIndex, const Reference< XInterface >& xObject ) throw(IllegalArgumentException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->detach( nIndex, xObject ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::addScriptListener( const Reference< XScriptListener >& xListener ) throw(IllegalArgumentException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->addScriptListener( xListener ); +} + +//------------------------------------------------------------------------ +void SAL_CALL OInterfaceContainer::removeScriptListener( const Reference< XScriptListener >& xListener ) throw(IllegalArgumentException, RuntimeException) +{ + if ( m_xEventAttacher.is() ) + m_xEventAttacher->removeScriptListener( xListener ); +} + +//================================================================== +//= OFormComponents +//================================================================== +//------------------------------------------------------------------------------ +Any SAL_CALL OFormComponents::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = OFormComponents_BASE::queryInterface(_rType); + if (!aReturn.hasValue()) + { + aReturn = OInterfaceContainer::queryInterface(_rType); + + if (!aReturn.hasValue()) + aReturn = FormComponentsBase::queryAggregation(_rType); + } + + return aReturn; +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL OFormComponents::getTypes() throw(RuntimeException) +{ + return ::comphelper::concatSequences(OInterfaceContainer::getTypes(), FormComponentsBase::getTypes(), OFormComponents_BASE::getTypes()); +} + +//------------------------------------------------------------------------------ +OFormComponents::OFormComponents(const Reference<XMultiServiceFactory>& _rxFactory) + :FormComponentsBase( m_aMutex ) + ,OInterfaceContainer( _rxFactory, m_aMutex, XFormComponent::static_type() ) + ,OFormComponents_BASE() +{ +} + +//------------------------------------------------------------------------------ +OFormComponents::OFormComponents( const OFormComponents& _cloneSource ) + :FormComponentsBase( m_aMutex ) + ,OInterfaceContainer( m_aMutex, _cloneSource ) + ,OFormComponents_BASE() +{ +} + +//------------------------------------------------------------------------------ +OFormComponents::~OFormComponents() +{ + if (!FormComponentsBase::rBHelper.bDisposed) + { + acquire(); + dispose(); + } +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OFormComponents::disposing() +{ + OInterfaceContainer::disposing(); + FormComponentsBase::disposing(); + m_xParent = NULL; +} + +//XChild +//------------------------------------------------------------------------------ +void OFormComponents::setParent(const InterfaceRef& Parent) throw( NoSupportException, RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_xParent = Parent; +} + +//------------------------------------------------------------------------------ +InterfaceRef OFormComponents::getParent() throw( RuntimeException ) +{ + return m_xParent; +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/misc/componenttools.cxx b/forms/source/misc/componenttools.cxx new file mode 100644 index 000000000000..80e772dbd0da --- /dev/null +++ b/forms/source/misc/componenttools.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "componenttools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XChild.hpp> +/** === end UNO includes === **/ + +#include <algorithm> +#include <iterator> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::frame::XModel; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::container::XChild; + /** === end UNO using === **/ + + //==================================================================== + //= TypeBag + //==================================================================== + //-------------------------------------------------------------------- + TypeBag::TypeBag( const TypeSequence& _rTypes1 ) + { + addTypes( _rTypes1 ); + } + + //-------------------------------------------------------------------- + TypeBag::TypeBag( const TypeSequence& _rTypes1, const TypeSequence& _rTypes2 ) + { + addTypes( _rTypes1 ); + addTypes( _rTypes2 ); + } + + //-------------------------------------------------------------------- + TypeBag::TypeBag( const TypeSequence& _rTypes1, const TypeSequence& _rTypes2, const TypeSequence& _rTypes3 ) + { + addTypes( _rTypes1 ); + addTypes( _rTypes2 ); + addTypes( _rTypes3 ); + } + + //-------------------------------------------------------------------- + void TypeBag::addTypes( const TypeSequence& _rTypes ) + { + ::std::copy( + _rTypes.getConstArray(), + _rTypes.getConstArray() + _rTypes.getLength(), + ::std::insert_iterator< TypeSet >( m_aTypes, m_aTypes.begin() ) + ); + } + + //-------------------------------------------------------------------- + TypeBag::TypeSequence TypeBag::getTypes() const + { + TypeSequence aTypes( m_aTypes.size() ); + ::std::copy( m_aTypes.begin(), m_aTypes.end(), aTypes.getArray() ); + return aTypes; + } + + //==================================================================== + Reference< XModel > getXModel( const Reference< XInterface >& _rxComponent ) + { + Reference< XInterface > xParent = _rxComponent; + Reference< XModel > xModel( xParent, UNO_QUERY );; + while ( xParent.is() && !xModel.is() ) + { + Reference< XChild > xChild( xParent, UNO_QUERY ); + xParent.set( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY ); + xModel.set( xParent, UNO_QUERY ); + } + return xModel; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/misc/frm_module.cxx b/forms/source/misc/frm_module.cxx new file mode 100644 index 000000000000..c83a6f8a91e6 --- /dev/null +++ b/forms/source/misc/frm_module.cxx @@ -0,0 +1,36 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "frm_module.hxx" + +#define FORMS_MODULE_IMPLEMENTATION_INCLUDE_CONTEXT + #define FORMS_MODULE_NAMESPACE frm + #include "forms_module_impl.hxx" +#undef FORMS_MODULE_IMPLEMENTATION_INCLUDE_CONTEXT + diff --git a/forms/source/misc/frm_strings.cxx b/forms/source/misc/frm_strings.cxx new file mode 100644 index 000000000000..0236422fbb7c --- /dev/null +++ b/forms/source/misc/frm_strings.cxx @@ -0,0 +1,34 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#define FORMS_IMPLEMENT_STRINGS +#include "frm_strings.hxx" +#include "services.hxx" + diff --git a/forms/source/misc/ids.cxx b/forms/source/misc/ids.cxx new file mode 100644 index 000000000000..deae7e8debc4 --- /dev/null +++ b/forms/source/misc/ids.cxx @@ -0,0 +1,36 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "ids.hxx" + +IMPLEMENT_IMPLEMENTATIONID_HELPER(frm, OImplementationIds) + + diff --git a/forms/source/misc/limitedformats.cxx b/forms/source/misc/limitedformats.cxx new file mode 100644 index 000000000000..1b7473114d1c --- /dev/null +++ b/forms/source/misc/limitedformats.cxx @@ -0,0 +1,402 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "limitedformats.hxx" +#include "services.hxx" +#include <osl/diagnose.h> +#include <comphelper/types.hxx> +#include <comphelper/extract.hxx> +#include <com/sun/star/form/FormComponentType.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::beans; + + sal_Int32 OLimitedFormats::s_nInstanceCount(0); + ::osl::Mutex OLimitedFormats::s_aMutex; + Reference< XNumberFormatsSupplier > OLimitedFormats::s_xStandardFormats; + + //===================================================================== + //= + //===================================================================== + //--------------------------------------------------------------------- + enum LocaleType + { + ltEnglishUS, + ltGerman, + ltSystem + }; + + //--------------------------------------------------------------------- + static const Locale& getLocale(LocaleType _eType) + { + static const Locale s_aEnglishUS( ::rtl::OUString::createFromAscii("en"), ::rtl::OUString::createFromAscii("us"), ::rtl::OUString() ); + static const Locale s_aGerman( ::rtl::OUString::createFromAscii("de"), ::rtl::OUString::createFromAscii("DE"), ::rtl::OUString() ); + static const ::rtl::OUString s_sEmptyString; + static const Locale s_aSystem( s_sEmptyString, s_sEmptyString, s_sEmptyString ); + + switch (_eType) + { + case ltEnglishUS: + return s_aEnglishUS; + + case ltGerman: + return s_aGerman; + + case ltSystem: + return s_aSystem; + } + + OSL_ENSURE(sal_False, "getLocale: invalid enum value!"); + return s_aSystem; + } + + //--------------------------------------------------------------------- + struct FormatEntry + { + const sal_Char* pDescription; + sal_Int32 nKey; + LocaleType eLocale; + }; + + //--------------------------------------------------------------------- + static const FormatEntry* lcl_getFormatTable(sal_Int16 nTableId) + { + switch (nTableId) + { + case FormComponentType::TIMEFIELD: + { + static FormatEntry s_aFormats[] = { + { "HH:MM", -1, ltEnglishUS }, + { "HH:MM:SS", -1, ltEnglishUS }, + { "HH:MM AM/PM", -1, ltEnglishUS }, + { "HH:MM:SS AM/PM", -1, ltEnglishUS }, + { NULL, -1, ltSystem } + }; + // don't switch this table here to const. The compiler could be tempted to really place this + // in a non-writeable segment, but we want to fill in the format keys later .... + return s_aFormats; + } + case FormComponentType::DATEFIELD: + { + static FormatEntry s_aFormats[] = { + { "T-M-JJ", -1, ltGerman }, + { "TT-MM-JJ", -1, ltGerman }, + { "TT-MM-JJJJ", -1, ltGerman }, + { "NNNNT. MMMM JJJJ", -1, ltGerman }, + + { "DD/MM/YY", -1, ltEnglishUS }, + { "MM/DD/YY", -1, ltEnglishUS }, + { "YY/MM/DD", -1, ltEnglishUS }, + { "DD/MM/YYYY", -1, ltEnglishUS }, + { "MM/DD/YYYY", -1, ltEnglishUS }, + { "YYYY/MM/DD", -1, ltEnglishUS }, + + { "JJ-MM-TT", -1, ltGerman }, + { "JJJJ-MM-TT", -1, ltGerman }, + + { NULL, -1, ltSystem } + }; + return s_aFormats; + } + } + + OSL_ENSURE(sal_False, "lcl_getFormatTable: invalid id!"); + return NULL; + } + + //===================================================================== + //= OLimitedFormats + //===================================================================== + //--------------------------------------------------------------------- + OLimitedFormats::OLimitedFormats(const Reference< XMultiServiceFactory >& _rxORB, const sal_Int16 _nClassId) + :m_nFormatEnumPropertyHandle(-1) + ,m_nTableId(_nClassId) + { + OSL_ENSURE(_rxORB.is(), "OLimitedFormats::OLimitedFormats: invalid service factory!"); + acquireSupplier(_rxORB); + ensureTableInitialized(m_nTableId); + } + + //--------------------------------------------------------------------- + OLimitedFormats::~OLimitedFormats() + { + releaseSupplier(); + } + + //--------------------------------------------------------------------- + void OLimitedFormats::ensureTableInitialized(const sal_Int16 _nTableId) + { + const FormatEntry* pFormatTable = lcl_getFormatTable(_nTableId); + if (-1 == pFormatTable->nKey) + { + ::osl::MutexGuard aGuard(s_aMutex); + if (-1 == pFormatTable->nKey) + { + // initialize the keys + Reference<XNumberFormats> xStandardFormats; + if (s_xStandardFormats.is()) + xStandardFormats = s_xStandardFormats->getNumberFormats(); + OSL_ENSURE(xStandardFormats.is(), "OLimitedFormats::ensureTableInitialized: don't have a formats supplier!"); + + if (xStandardFormats.is()) + { + // loop through the table + FormatEntry* pLoopFormats = const_cast<FormatEntry*>(pFormatTable); + while (pLoopFormats->pDescription) + { + // get the key for the description + pLoopFormats->nKey = xStandardFormats->queryKey( + ::rtl::OUString::createFromAscii(pLoopFormats->pDescription), + getLocale(pLoopFormats->eLocale), + sal_False + ); + + if (-1 == pLoopFormats->nKey) + { + pLoopFormats->nKey = xStandardFormats->addNew( + ::rtl::OUString::createFromAscii(pLoopFormats->pDescription), + getLocale(pLoopFormats->eLocale) + ); +#ifdef DBG_UTIL + try + { + xStandardFormats->getByKey(pLoopFormats->nKey); + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OLimitedFormats::ensureTableInitialized: adding the key to the formats collection failed!"); + } +#endif + } + + // next + ++pLoopFormats; + } + } + } + } + } + + //--------------------------------------------------------------------- + void OLimitedFormats::clearTable(const sal_Int16 _nTableId) + { + ::osl::MutexGuard aGuard(s_aMutex); + const FormatEntry* pFormats = lcl_getFormatTable(_nTableId); + FormatEntry* pResetLoop = const_cast<FormatEntry*>(pFormats); + while (pResetLoop->pDescription) + { + pResetLoop->nKey = -1; + ++pResetLoop; + } + } + + //--------------------------------------------------------------------- + void OLimitedFormats::setAggregateSet(const Reference< XFastPropertySet >& _rxAggregate, sal_Int32 _nOriginalPropertyHandle) + { + // changes (NULL -> not NULL) and (not NULL -> NULL) are allowed + OSL_ENSURE(!m_xAggregate.is() || !_rxAggregate.is(), "OLimitedFormats::setAggregateSet: already have an aggregate!"); + OSL_ENSURE(_rxAggregate.is() || m_xAggregate.is(), "OLimitedFormats::setAggregateSet: invalid new aggregate!"); + + m_xAggregate = _rxAggregate; + m_nFormatEnumPropertyHandle = _nOriginalPropertyHandle; +#ifdef DBG_UTIL + if (m_xAggregate.is()) + { + try + { + m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OLimitedFormats::setAggregateSet: invalid handle!"); + } + } +#endif + } + + //--------------------------------------------------------------------- + void OLimitedFormats::getFormatKeyPropertyValue( Any& _rValue ) const + { + _rValue.clear(); + + OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::getFormatKeyPropertyValue: not initialized!"); + if (m_xAggregate.is()) + { + // get the aggregate's enum property value + Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); + sal_Int32 nValue = -1; + ::cppu::enum2int(nValue, aEnumPropertyValue); + + // get the translation table + const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId); + + // seek to the nValue'th entry + sal_Int32 nLookup = 0; + for ( ; + (NULL != pFormats->pDescription) && (nLookup < nValue); + ++pFormats, ++nLookup + ) + ; + OSL_ENSURE(NULL != pFormats->pDescription, "OLimitedFormats::getFormatKeyPropertyValue: did not find the value!"); + if (pFormats->pDescription) + _rValue <<= pFormats->nKey; + } + + // TODO: should use a standard format for the control type we're working for + } + + //--------------------------------------------------------------------- + sal_Bool OLimitedFormats::convertFormatKeyPropertyValue(Any& _rConvertedValue, Any& _rOldValue, const Any& _rNewValue) + { + OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::convertFormatKeyPropertyValue: not initialized!"); + + if (m_xAggregate.is()) + { + // the new format key to set + sal_Int32 nNewFormat = 0; + if (!(_rNewValue >>= nNewFormat)) + throw IllegalArgumentException(); + + // get the old (enum) value from the aggregate + Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); + sal_Int32 nOldEnumValue = -1; + ::cppu::enum2int(nOldEnumValue, aEnumPropertyValue); + + // get the translation table + const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId); + + _rOldValue.clear(); + _rConvertedValue.clear(); + + // look for the entry with the given format key + sal_Int32 nTablePosition = 0; + for ( ; + (NULL != pFormats->pDescription) && (nNewFormat != pFormats->nKey); + ++pFormats, ++nTablePosition + ) + { + if (nTablePosition == nOldEnumValue) + _rOldValue <<= pFormats->nKey; + } + + sal_Bool bFoundIt = (NULL != pFormats->pDescription); + sal_Bool bModified = sal_False; + if (bFoundIt) + { + _rConvertedValue <<= (sal_Int16)nTablePosition; + bModified = nTablePosition != nOldEnumValue; + } + + if (!_rOldValue.hasValue()) + { // did not reach the end of the table (means we found nNewFormat) + // -> go to the end to ensure that _rOldValue is set + while (pFormats->pDescription) + { + if (nTablePosition == nOldEnumValue) + { + _rOldValue <<= pFormats->nKey; + break; + } + + ++pFormats; + ++nTablePosition; + } + } + + OSL_ENSURE(_rOldValue.hasValue(), "OLimitedFormats::convertFormatKeyPropertyValue: did not find the old enum value in the table!"); + + if (!bFoundIt) + { // somebody gave us an format which we can't translate + ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("This control supports only a very limited number of formats."); + throw IllegalArgumentException(sMessage, NULL, 2); + } + + return bModified; + } + + return sal_False; + } + + //--------------------------------------------------------------------- + void OLimitedFormats::setFormatKeyPropertyValue( const Any& _rNewValue ) + { + OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::setFormatKeyPropertyValue: not initialized!"); + + if (m_xAggregate.is()) + { // this is to be called after convertFormatKeyPropertyValue, where + // we translated the format key into a enum value. + // So now we can simply forward this enum value to our aggreate + m_xAggregate->setFastPropertyValue(m_nFormatEnumPropertyHandle, _rNewValue); + } + } + + //--------------------------------------------------------------------- + void OLimitedFormats::acquireSupplier(const Reference< XMultiServiceFactory >& _rxORB) + { + ::osl::MutexGuard aGuard(s_aMutex); + if ((1 == ++s_nInstanceCount) && _rxORB.is()) + { // create the standard formatter + + Sequence< Any > aInit(1); + aInit[0] <<= getLocale(ltEnglishUS); + + Reference< XInterface > xSupplier = _rxORB->createInstanceWithArguments(FRM_NUMBER_FORMATS_SUPPLIER, aInit); + OSL_ENSURE(xSupplier.is(), "OLimitedFormats::OLimitedFormats: could not create a formats supplier!"); + + s_xStandardFormats = Reference< XNumberFormatsSupplier >(xSupplier, UNO_QUERY); + OSL_ENSURE(s_xStandardFormats.is() || !xSupplier.is(), "OLimitedFormats::OLimitedFormats: missing an interface!"); + } + } + + //--------------------------------------------------------------------- + void OLimitedFormats::releaseSupplier() + { + ::osl::MutexGuard aGuard(s_aMutex); + if (0 == --s_nInstanceCount) + { + ::comphelper::disposeComponent(s_xStandardFormats); + s_xStandardFormats = NULL; + + clearTable(FormComponentType::TIMEFIELD); + clearTable(FormComponentType::DATEFIELD); + } + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/misc/listenercontainers.cxx b/forms/source/misc/listenercontainers.cxx new file mode 100644 index 000000000000..4c7e438d37d8 --- /dev/null +++ b/forms/source/misc/listenercontainers.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#ifndef FORMS_SOURCE_MISC_LISTENERCONTAINERS_HXX +#include "listenercontainers.hxx" +#endif + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::form; + + //==================================================================== + //= ResetListeners + //==================================================================== + //--------------------------------------------------------------------- + bool ResetListeners::implTypedNotify( const Reference< XResetListener >& _rxListener, + const EventObject& _rEvent ) SAL_THROW( ( Exception ) ) + { + switch ( m_eCurrentNotificationType ) + { + case eApproval: + if ( !_rxListener->approveReset( _rEvent ) ) + return false; + return true; + case eFinal: + _rxListener->resetted( _rEvent ); + break; + default: + OSL_ENSURE( sal_False, "ResetListeners::implNotify: invalid notification type!" ); + } + return true; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/misc/makefile.mk b/forms/source/misc/makefile.mk new file mode 100644 index 000000000000..64af07b00c01 --- /dev/null +++ b/forms/source/misc/makefile.mk @@ -0,0 +1,70 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=.. +PRJNAME=forms +TARGET=common + +ENABLE_EXCEPTIONS=TRUE +#TARGETTYPE=GUI + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Types ------------------------------------- + +INCPRE+=$(SOLARINCDIR)$/offuh +INCPRE*=$(INCCOM)$/$(TARGET) + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/limitedformats.obj \ + $(SLO)$/property.obj \ + $(SLO)$/services.obj \ + $(SLO)$/InterfaceContainer.obj \ + $(SLO)$/ids.obj \ + $(SLO)$/frm_module.obj \ + $(SLO)$/frm_strings.obj \ + $(SLO)$/listenercontainers.obj \ + $(SLO)$/componenttools.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + +ALLTAR : \ + $(MISC)$/$(TARGET).don \ + +$(SLOFILES) : $(MISC)$/$(TARGET).don + +$(MISC)$/$(TARGET).don : $(SOLARBINDIR)$/oovbaapi.rdb + +$(CPPUMAKER) -O$(INCCOM)$/$(TARGET) -BUCR $(SOLARBINDIR)$/oovbaapi.rdb -X$(SOLARBINDIR)$/types.rdb && echo > $@ + echo $@ + diff --git a/forms/source/misc/property.cxx b/forms/source/misc/property.cxx new file mode 100644 index 000000000000..04bc9c8c8911 --- /dev/null +++ b/forms/source/misc/property.cxx @@ -0,0 +1,257 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "frm_strings.hxx" +#include "property.hxx" + +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include <cppuhelper/queryinterface.hxx> +#include <tools/debug.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <algorithm> + +//... namespace frm ....................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= PropertyInfoService +//================================================================== +PropertyInfoService::PropertyMap PropertyInfoService::s_AllKnownProperties; +//------------------------------------------------------------------ +sal_Int32 PropertyInfoService::getPropertyId(const ::rtl::OUString& _rName) +{ + initialize(); + + PropertyAssignment aCompareName(_rName, -1); + + ::std::pair<PropertyMapIterator,PropertyMapIterator> aPair = equal_range( + s_AllKnownProperties.begin(), + s_AllKnownProperties.end(), + aCompareName, + PropertyAssignmentNameCompareLess()); + + sal_Int32 nHandle = -1; + if (aPair.first != aPair.second) + { // we found something _and_ we have an identity + nHandle = aPair.first->nHandle; + } + + return nHandle; +} + +//------------------------------------------------------------------ +sal_Int32 ConcreteInfoService::getPreferedPropertyId(const ::rtl::OUString& _rName) +{ + return PropertyInfoService::getPropertyId(_rName); +} + +//------------------------------------------------------------------ +#define ADD_PROP_ASSIGNMENT(varname) \ + s_AllKnownProperties.push_back(PropertyAssignment(PROPERTY_##varname, PROPERTY_ID_##varname)) +//.................................................................. +void PropertyInfoService::initialize() +{ + if (!s_AllKnownProperties.empty()) + return; + + s_AllKnownProperties.reserve(220); + + ADD_PROP_ASSIGNMENT(NAME); + ADD_PROP_ASSIGNMENT(TAG); + ADD_PROP_ASSIGNMENT(TABINDEX); + ADD_PROP_ASSIGNMENT(CLASSID); + ADD_PROP_ASSIGNMENT(ALIGN); + ADD_PROP_ASSIGNMENT(FETCHSIZE); + ADD_PROP_ASSIGNMENT(VALUE); + ADD_PROP_ASSIGNMENT(VALUEMIN); + ADD_PROP_ASSIGNMENT(VALUEMAX); + ADD_PROP_ASSIGNMENT(VALUESTEP); + ADD_PROP_ASSIGNMENT(TEXT); + ADD_PROP_ASSIGNMENT(LABEL); + ADD_PROP_ASSIGNMENT(NAVIGATION); + ADD_PROP_ASSIGNMENT(CYCLE); + ADD_PROP_ASSIGNMENT(CONTROLSOURCE); + ADD_PROP_ASSIGNMENT(ENABLED); + ADD_PROP_ASSIGNMENT(ENABLEVISIBLE); + ADD_PROP_ASSIGNMENT(SPIN); + ADD_PROP_ASSIGNMENT(READONLY); + ADD_PROP_ASSIGNMENT(FILTER); + ADD_PROP_ASSIGNMENT(WIDTH); + ADD_PROP_ASSIGNMENT(SEARCHABLE); + ADD_PROP_ASSIGNMENT(MULTILINE); + ADD_PROP_ASSIGNMENT(TARGET_URL); + ADD_PROP_ASSIGNMENT(DEFAULTCONTROL); + ADD_PROP_ASSIGNMENT(MAXTEXTLEN); + ADD_PROP_ASSIGNMENT(SIZE); + ADD_PROP_ASSIGNMENT(DATE); + ADD_PROP_ASSIGNMENT(TIME); + ADD_PROP_ASSIGNMENT(STATE); + ADD_PROP_ASSIGNMENT(TRISTATE); + ADD_PROP_ASSIGNMENT(HIDDEN_VALUE); + ADD_PROP_ASSIGNMENT(TARGET_FRAME); + ADD_PROP_ASSIGNMENT(BUTTONTYPE); + ADD_PROP_ASSIGNMENT(STRINGITEMLIST); + ADD_PROP_ASSIGNMENT(DEFAULT_TEXT); + ADD_PROP_ASSIGNMENT(DEFAULT_STATE); + ADD_PROP_ASSIGNMENT(DEFAULT_DATE); + ADD_PROP_ASSIGNMENT(DEFAULT_TIME); + ADD_PROP_ASSIGNMENT(DEFAULT_VALUE); + ADD_PROP_ASSIGNMENT(FORMATKEY); + ADD_PROP_ASSIGNMENT(FORMATSSUPPLIER); + ADD_PROP_ASSIGNMENT(SUBMIT_ACTION); + ADD_PROP_ASSIGNMENT(SUBMIT_TARGET); + ADD_PROP_ASSIGNMENT(SUBMIT_METHOD); + ADD_PROP_ASSIGNMENT(SUBMIT_ENCODING); + ADD_PROP_ASSIGNMENT(IMAGE_URL); + ADD_PROP_ASSIGNMENT(EMPTY_IS_NULL); + ADD_PROP_ASSIGNMENT(LISTSOURCETYPE); + ADD_PROP_ASSIGNMENT(LISTSOURCE); + ADD_PROP_ASSIGNMENT(SELECT_SEQ); + ADD_PROP_ASSIGNMENT(VALUE_SEQ); + ADD_PROP_ASSIGNMENT(DEFAULT_SELECT_SEQ); + ADD_PROP_ASSIGNMENT(MULTISELECTION); + ADD_PROP_ASSIGNMENT(DECIMAL_ACCURACY); + ADD_PROP_ASSIGNMENT(EDITMASK); + ADD_PROP_ASSIGNMENT(ISREADONLY); + ADD_PROP_ASSIGNMENT(FIELDTYPE); + ADD_PROP_ASSIGNMENT(DECIMALS); + ADD_PROP_ASSIGNMENT(REFVALUE); + ADD_PROP_ASSIGNMENT(STRICTFORMAT); + ADD_PROP_ASSIGNMENT(DATASOURCE); + ADD_PROP_ASSIGNMENT(ALLOWADDITIONS); + ADD_PROP_ASSIGNMENT(ALLOWEDITS); + ADD_PROP_ASSIGNMENT(ALLOWDELETIONS); + ADD_PROP_ASSIGNMENT(MASTERFIELDS); + ADD_PROP_ASSIGNMENT(ISPASSTHROUGH); + ADD_PROP_ASSIGNMENT(QUERY); + ADD_PROP_ASSIGNMENT(LITERALMASK); + ADD_PROP_ASSIGNMENT(SHOWTHOUSANDSEP); + ADD_PROP_ASSIGNMENT(CURRENCYSYMBOL); + ADD_PROP_ASSIGNMENT(DATEFORMAT); + ADD_PROP_ASSIGNMENT(DATEMIN); + ADD_PROP_ASSIGNMENT(DATEMAX); + ADD_PROP_ASSIGNMENT(DATE_SHOW_CENTURY); + ADD_PROP_ASSIGNMENT(TIMEFORMAT); + ADD_PROP_ASSIGNMENT(TIMEMIN); + ADD_PROP_ASSIGNMENT(TIMEMAX); + ADD_PROP_ASSIGNMENT(LINECOUNT); + ADD_PROP_ASSIGNMENT(BOUNDCOLUMN); + ADD_PROP_ASSIGNMENT(HASNAVIGATION); + ADD_PROP_ASSIGNMENT(FONT); + ADD_PROP_ASSIGNMENT(BACKGROUNDCOLOR); + ADD_PROP_ASSIGNMENT(FILLCOLOR); + ADD_PROP_ASSIGNMENT(TEXTCOLOR); + ADD_PROP_ASSIGNMENT(LINECOLOR); + ADD_PROP_ASSIGNMENT(BORDER); + ADD_PROP_ASSIGNMENT(DROPDOWN); + ADD_PROP_ASSIGNMENT(HSCROLL); + ADD_PROP_ASSIGNMENT(VSCROLL); + ADD_PROP_ASSIGNMENT(TABSTOP); + ADD_PROP_ASSIGNMENT(AUTOCOMPLETE); + ADD_PROP_ASSIGNMENT(HARDLINEBREAKS); + ADD_PROP_ASSIGNMENT(PRINTABLE); + ADD_PROP_ASSIGNMENT(ECHO_CHAR); + ADD_PROP_ASSIGNMENT(ROWHEIGHT); + ADD_PROP_ASSIGNMENT(HELPTEXT); + ADD_PROP_ASSIGNMENT(FONT_NAME); + ADD_PROP_ASSIGNMENT(FONT_STYLENAME); + ADD_PROP_ASSIGNMENT(FONT_FAMILY); + ADD_PROP_ASSIGNMENT(FONT_CHARSET); + ADD_PROP_ASSIGNMENT(FONT_HEIGHT); + ADD_PROP_ASSIGNMENT(FONT_WEIGHT); + ADD_PROP_ASSIGNMENT(FONT_SLANT); + ADD_PROP_ASSIGNMENT(FONT_UNDERLINE); + ADD_PROP_ASSIGNMENT(FONT_WORDLINEMODE); + ADD_PROP_ASSIGNMENT(FONT_STRIKEOUT); + ADD_PROP_ASSIGNMENT(TEXTLINECOLOR); + ADD_PROP_ASSIGNMENT(FONTEMPHASISMARK); + ADD_PROP_ASSIGNMENT(FONTRELIEF); + ADD_PROP_ASSIGNMENT(HELPURL); + ADD_PROP_ASSIGNMENT(RECORDMARKER); + ADD_PROP_ASSIGNMENT(BOUNDFIELD); + ADD_PROP_ASSIGNMENT(INPUT_REQUIRED); + ADD_PROP_ASSIGNMENT(TREATASNUMERIC); + ADD_PROP_ASSIGNMENT(EFFECTIVE_VALUE); + ADD_PROP_ASSIGNMENT(EFFECTIVE_DEFAULT); + ADD_PROP_ASSIGNMENT(EFFECTIVE_MIN); + ADD_PROP_ASSIGNMENT(EFFECTIVE_MAX); + ADD_PROP_ASSIGNMENT(HIDDEN); + ADD_PROP_ASSIGNMENT(FILTERPROPOSAL); + ADD_PROP_ASSIGNMENT(FIELDSOURCE); + ADD_PROP_ASSIGNMENT(TABLENAME); + ADD_PROP_ASSIGNMENT(CONTROLLABEL); + ADD_PROP_ASSIGNMENT(CURRSYM_POSITION); + ADD_PROP_ASSIGNMENT(CURSORCOLOR); + ADD_PROP_ASSIGNMENT(ALWAYSSHOWCURSOR); + ADD_PROP_ASSIGNMENT(DISPLAYSYNCHRON); + ADD_PROP_ASSIGNMENT(ISMODIFIED); + ADD_PROP_ASSIGNMENT(ISNEW); + ADD_PROP_ASSIGNMENT(PRIVILEGES); + ADD_PROP_ASSIGNMENT(DETAILFIELDS); + ADD_PROP_ASSIGNMENT(COMMAND); + ADD_PROP_ASSIGNMENT(COMMANDTYPE); + ADD_PROP_ASSIGNMENT(RESULTSET_CONCURRENCY); + ADD_PROP_ASSIGNMENT(INSERTONLY); + ADD_PROP_ASSIGNMENT(RESULTSET_TYPE); + ADD_PROP_ASSIGNMENT(ESCAPE_PROCESSING); + ADD_PROP_ASSIGNMENT(APPLYFILTER); + ADD_PROP_ASSIGNMENT(ISNULLABLE); + ADD_PROP_ASSIGNMENT(ACTIVECOMMAND); + ADD_PROP_ASSIGNMENT(ISCURRENCY); + ADD_PROP_ASSIGNMENT(URL); + ADD_PROP_ASSIGNMENT(TITLE); + ADD_PROP_ASSIGNMENT(ACTIVE_CONNECTION); + ADD_PROP_ASSIGNMENT(SCALE); + ADD_PROP_ASSIGNMENT(SORT); + ADD_PROP_ASSIGNMENT(PERSISTENCE_MAXTEXTLENGTH); + ADD_PROP_ASSIGNMENT(SCROLL_VALUE); + ADD_PROP_ASSIGNMENT(SPIN_VALUE); + ADD_PROP_ASSIGNMENT(DEFAULT_SCROLL_VALUE); + ADD_PROP_ASSIGNMENT(DEFAULT_SPIN_VALUE); + ADD_PROP_ASSIGNMENT( WRITING_MODE ); + ADD_PROP_ASSIGNMENT( CONTEXT_WRITING_MODE ); + + // now sort the array by name + + std::sort( + s_AllKnownProperties.begin(), + s_AllKnownProperties.end(), + PropertyAssignmentNameCompareLess() + ); +} + +//......................................................................... +} +//... namespace frm ....................................................... + diff --git a/forms/source/misc/services.cxx b/forms/source/misc/services.cxx new file mode 100644 index 000000000000..dbda0ae3896d --- /dev/null +++ b/forms/source/misc/services.cxx @@ -0,0 +1,464 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "services.hxx" +#include "frm_module.hxx" +#include <cppuhelper/factory.hxx> +#include <uno/lbnames.h> +#include <osl/diagnose.h> +#include <uno/mapping.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +//--------------------------------------------------------------------------------------- +//....................................................................................... +#define DECLARE_SERVICE_INFO(classImplName) \ + namespace frm { \ + extern ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> SAL_CALL classImplName##_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory) throw (::com::sun::star::uno::RuntimeException); \ + } + +//--------------------------------------------------------------------------------------- +DECLARE_SERVICE_INFO(OFixedTextModel) +DECLARE_SERVICE_INFO(ORadioButtonModel) +DECLARE_SERVICE_INFO(ORadioButtonControl) +DECLARE_SERVICE_INFO(OCheckBoxModel) +DECLARE_SERVICE_INFO(OCheckBoxControl) +DECLARE_SERVICE_INFO(OHiddenModel) +DECLARE_SERVICE_INFO(OGroupBoxModel) +DECLARE_SERVICE_INFO(OGroupBoxControl) +DECLARE_SERVICE_INFO(OListBoxControl) +DECLARE_SERVICE_INFO(OListBoxModel) +DECLARE_SERVICE_INFO(OComboBoxControl) +DECLARE_SERVICE_INFO(OComboBoxModel) +DECLARE_SERVICE_INFO(OEditControl) +DECLARE_SERVICE_INFO(OEditModel) +DECLARE_SERVICE_INFO(ONumericControl) +DECLARE_SERVICE_INFO(ONumericModel) +DECLARE_SERVICE_INFO(OPatternControl) +DECLARE_SERVICE_INFO(OPatternModel) +DECLARE_SERVICE_INFO(OCurrencyControl) +DECLARE_SERVICE_INFO(OCurrencyModel) +DECLARE_SERVICE_INFO(ODateControl) +DECLARE_SERVICE_INFO(ODateModel) +DECLARE_SERVICE_INFO(OTimeControl) +DECLARE_SERVICE_INFO(OTimeModel) +DECLARE_SERVICE_INFO(OFormattedControl) +DECLARE_SERVICE_INFO(OFormattedModel) +DECLARE_SERVICE_INFO(OFileControlModel) +DECLARE_SERVICE_INFO(OButtonControl) +DECLARE_SERVICE_INFO(OButtonModel) +DECLARE_SERVICE_INFO(OImageButtonControl) +DECLARE_SERVICE_INFO(OImageButtonModel) + +DECLARE_SERVICE_INFO(OImageControlControl) +DECLARE_SERVICE_INFO(OImageControlModel) +DECLARE_SERVICE_INFO(OGridControlModel) + +// XForms objects +DECLARE_SERVICE_INFO(Binding) +DECLARE_SERVICE_INFO(Model) +DECLARE_SERVICE_INFO(XForms) + +// some special handling for the FormattedFieldWrapper which can act as FormattedModel or as EditModel +DECLARE_SERVICE_INFO(OFormattedFieldWrapper) + // this is for a service, which is instantiated through the EditModel service name + // and which acts mostly as Edit (mostly means : if somebody uses XPersistObject::read immediately after + // the object was instantiated and the stream contains a FormattedModel, it switches permanently to + // formatted.) +namespace frm { \ + extern Reference< XInterface > SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException); \ +} + +DECLARE_SERVICE_INFO(OFormsCollection) +DECLARE_SERVICE_INFO(ImageProducer) + +//--------------------------------------------------------------------------------------- + +static Sequence< ::rtl::OUString > s_aClassImplementationNames; +static Sequence<Sequence< ::rtl::OUString > > s_aClassServiceNames; +static Sequence<sal_Int64> s_aFactories; + // need to use sal_Int64 instead of ComponentInstantiation, as ComponentInstantiation has no cppuType, so + // it can't be used with sequences + +//--------------------------------------------------------------------------------------- +void registerClassInfo( + ::rtl::OUString _rClassImplName, // the ImplName of the class + const Sequence< ::rtl::OUString >& _rServiceNames, // the services supported by this class + ::cppu::ComponentInstantiation _pCreateFunction // the method for instantiating such a class + ) +{ + sal_Int32 nCurrentLength = s_aClassImplementationNames.getLength(); + OSL_ENSURE((nCurrentLength == s_aClassServiceNames.getLength()) + && (nCurrentLength == s_aFactories.getLength()), + "forms::registerClassInfo : invalid class infos !"); + + s_aClassImplementationNames.realloc(nCurrentLength + 1); + s_aClassServiceNames.realloc(nCurrentLength + 1); + s_aFactories.realloc(nCurrentLength + 1); + + s_aClassImplementationNames.getArray()[nCurrentLength] = _rClassImplName; + s_aClassServiceNames.getArray()[nCurrentLength] = _rServiceNames; + s_aFactories.getArray()[nCurrentLength] = reinterpret_cast<sal_Int64>(_pCreateFunction); +} + +//--------------------------------------------------------------------------------------- +//....................................................................................... +#define REGISTER_CLASS_CORE(classImplName) \ + registerClassInfo( \ + ::rtl::OUString::createFromAscii("com.sun.star.form.") + ::rtl::OUString::createFromAscii(#classImplName), \ + aServices, \ + frm::classImplName##_CreateInstance) + +//....................................................................................... +#define REGISTER_CLASS1(classImplName, service1) \ + aServices.realloc(1); \ + aServices.getArray()[0] = frm::service1; \ + REGISTER_CLASS_CORE(classImplName) + +//....................................................................................... +#define REGISTER_CLASS2(classImplName, service1, service2) \ + aServices.realloc(2); \ + aServices.getArray()[0] = frm::service1; \ + aServices.getArray()[1] = frm::service2; \ + REGISTER_CLASS_CORE(classImplName) + +//....................................................................................... +#define REGISTER_CLASS3(classImplName, service1, service2, service3) \ + aServices.realloc(3); \ + aServices.getArray()[0] = frm::service1; \ + aServices.getArray()[1] = frm::service2; \ + aServices.getArray()[2] = frm::service3; \ + REGISTER_CLASS_CORE(classImplName) + +//....................................................................................... +#define REGISTER_CLASS4(classImplName, service1, service2, service3, service4) \ + aServices.realloc(4); \ + aServices.getArray()[0] = frm::service1; \ + aServices.getArray()[1] = frm::service2; \ + aServices.getArray()[2] = frm::service3; \ + aServices.getArray()[3] = frm::service4; \ + REGISTER_CLASS_CORE(classImplName) + +//--------------------------------------------------------------------------------------- +void ensureClassInfos() +{ + if (s_aClassImplementationNames.getLength()) + // nothing to do + return; + Sequence< ::rtl::OUString > aServices; + + // ======================================================================== + // = ControlModels + // ------------------------------------------------------------------------ + // - FixedText + REGISTER_CLASS2(OFixedTextModel, FRM_COMPONENT_FIXEDTEXT, FRM_SUN_COMPONENT_FIXEDTEXT); + // - Hidden + REGISTER_CLASS3(OHiddenModel, FRM_COMPONENT_HIDDENCONTROL, FRM_SUN_COMPONENT_HIDDENCONTROL, FRM_COMPONENT_HIDDEN); + // - FileControl + REGISTER_CLASS2(OFileControlModel, FRM_COMPONENT_FILECONTROL, FRM_SUN_COMPONENT_FILECONTROL); + // - ImageButton + REGISTER_CLASS2(OImageButtonModel, FRM_COMPONENT_IMAGEBUTTON, FRM_SUN_COMPONENT_IMAGEBUTTON); + // - GridControl + REGISTER_CLASS3(OGridControlModel, FRM_COMPONENT_GRID /* compatibility */, FRM_COMPONENT_GRIDCONTROL, FRM_SUN_COMPONENT_GRIDCONTROL); + // - GroupBox + REGISTER_CLASS2(OGroupBoxModel, FRM_COMPONENT_GROUPBOX, FRM_SUN_COMPONENT_GROUPBOX); + + // - RadioButton + REGISTER_CLASS4( ORadioButtonModel, FRM_COMPONENT_RADIOBUTTON, FRM_SUN_COMPONENT_RADIOBUTTON, FRM_SUN_COMPONENT_DATABASE_RADIOBUTTON, BINDABLE_DATABASE_RADIO_BUTTON ); + // - CheckBox + REGISTER_CLASS4( OCheckBoxModel, FRM_COMPONENT_CHECKBOX, FRM_SUN_COMPONENT_CHECKBOX, FRM_SUN_COMPONENT_DATABASE_CHECKBOX, BINDABLE_DATABASE_CHECK_BOX ); + // - ListBox + REGISTER_CLASS4( OListBoxModel, FRM_COMPONENT_LISTBOX, FRM_SUN_COMPONENT_LISTBOX, FRM_SUN_COMPONENT_DATABASE_LISTBOX, BINDABLE_DATABASE_LIST_BOX ); + // - ComboBox + REGISTER_CLASS4( OComboBoxModel, FRM_COMPONENT_COMBOBOX, FRM_SUN_COMPONENT_COMBOBOX, FRM_SUN_COMPONENT_DATABASE_COMBOBOX, BINDABLE_DATABASE_COMBO_BOX ); + // - EditControl + REGISTER_CLASS4( OEditModel, FRM_COMPONENT_TEXTFIELD, FRM_SUN_COMPONENT_TEXTFIELD, FRM_SUN_COMPONENT_DATABASE_TEXTFIELD, BINDABLE_DATABASE_TEXT_FIELD ); + // - DateControl + REGISTER_CLASS3( ODateModel, FRM_COMPONENT_DATEFIELD, FRM_SUN_COMPONENT_DATEFIELD, FRM_SUN_COMPONENT_DATABASE_DATEFIELD ); + // - TimeControl + REGISTER_CLASS3( OTimeModel, FRM_COMPONENT_TIMEFIELD, FRM_SUN_COMPONENT_TIMEFIELD, FRM_SUN_COMPONENT_DATABASE_TIMEFIELD ); + // - NumericField + REGISTER_CLASS4( ONumericModel, FRM_COMPONENT_NUMERICFIELD, FRM_SUN_COMPONENT_NUMERICFIELD, FRM_SUN_COMPONENT_DATABASE_NUMERICFIELD, BINDABLE_DATABASE_NUMERIC_FIELD ); + // - CurrencyField + REGISTER_CLASS3( OCurrencyModel, FRM_COMPONENT_CURRENCYFIELD, FRM_SUN_COMPONENT_CURRENCYFIELD, FRM_SUN_COMPONENT_DATABASE_CURRENCYFIELD ); + // - PatternField + REGISTER_CLASS3( OPatternModel, FRM_COMPONENT_PATTERNFIELD, FRM_SUN_COMPONENT_PATTERNFIELD, FRM_SUN_COMPONENT_DATABASE_PATTERNFIELD ); + // - Button + REGISTER_CLASS2( OButtonModel, FRM_COMPONENT_COMMANDBUTTON, FRM_SUN_COMPONENT_COMMANDBUTTON ); + // - ImageControl + REGISTER_CLASS2( OImageControlModel, FRM_COMPONENT_IMAGECONTROL, FRM_SUN_COMPONENT_IMAGECONTROL ); + + // - FormattedField + REGISTER_CLASS1(OFormattedFieldWrapper, FRM_COMPONENT_EDIT); + // since SRC568 both OFormattedModel and OEditModel use FRM_COMPONENT_EDIT for persistence, + // and while reading a wrapper determines which kind of model it is + // register the wrapper for the FormattedField, as it handles the XPersistObject::write + // so that version <= 5.1 are able to read it + aServices.realloc(4); + aServices.getArray()[0] = frm::FRM_COMPONENT_FORMATTEDFIELD; + aServices.getArray()[1] = frm::FRM_SUN_COMPONENT_FORMATTEDFIELD; + aServices.getArray()[2] = frm::FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD; + aServices.getArray()[3] = frm::BINDABLE_DATABASE_FORMATTED_FIELD; + + registerClassInfo(::rtl::OUString::createFromAscii("com.sun.star.comp.forms.OFormattedFieldWrapper_ForcedFormatted"), + aServices, + frm::OFormattedFieldWrapper_CreateInstance_ForceFormatted); + + // ======================================================================== + // = Controls + // - RadioButton + REGISTER_CLASS2(ORadioButtonControl, STARDIV_ONE_FORM_CONTROL_RADIOBUTTON, FRM_SUN_CONTROL_RADIOBUTTON); + // - CheckBox + REGISTER_CLASS2(OCheckBoxControl, STARDIV_ONE_FORM_CONTROL_CHECKBOX, FRM_SUN_CONTROL_CHECKBOX); + // - GroupBox + REGISTER_CLASS2(OGroupBoxControl, STARDIV_ONE_FORM_CONTROL_GROUPBOX, FRM_SUN_CONTROL_GROUPBOX); + // - ListBox + REGISTER_CLASS2(OListBoxControl, STARDIV_ONE_FORM_CONTROL_LISTBOX, FRM_SUN_CONTROL_LISTBOX); + // - ComboBox + REGISTER_CLASS2(OComboBoxControl, STARDIV_ONE_FORM_CONTROL_COMBOBOX, FRM_SUN_CONTROL_COMBOBOX); + // - EditControl + REGISTER_CLASS3(OEditControl, STARDIV_ONE_FORM_CONTROL_TEXTFIELD, FRM_SUN_CONTROL_TEXTFIELD, STARDIV_ONE_FORM_CONTROL_EDIT); + // - DateControl + REGISTER_CLASS2(ODateControl, STARDIV_ONE_FORM_CONTROL_DATEFIELD, FRM_SUN_CONTROL_DATEFIELD); + // - TimeControl + REGISTER_CLASS2(OTimeControl, STARDIV_ONE_FORM_CONTROL_TIMEFIELD, FRM_SUN_CONTROL_TIMEFIELD); + // - NumericField + REGISTER_CLASS2(ONumericControl, STARDIV_ONE_FORM_CONTROL_NUMERICFIELD, FRM_SUN_CONTROL_NUMERICFIELD); + // - CurrencyField + REGISTER_CLASS2(OCurrencyControl, STARDIV_ONE_FORM_CONTROL_CURRENCYFIELD, FRM_SUN_CONTROL_CURRENCYFIELD); + // - PatternField + REGISTER_CLASS2(OPatternControl, STARDIV_ONE_FORM_CONTROL_PATTERNFIELD, FRM_SUN_CONTROL_PATTERNFIELD); + // - FormattedField + REGISTER_CLASS2(OFormattedControl, STARDIV_ONE_FORM_CONTROL_FORMATTEDFIELD, FRM_SUN_CONTROL_FORMATTEDFIELD); + // - Button + REGISTER_CLASS2(OButtonControl, STARDIV_ONE_FORM_CONTROL_COMMANDBUTTON, FRM_SUN_CONTROL_COMMANDBUTTON); + // - ImageButton + REGISTER_CLASS2(OImageButtonControl, STARDIV_ONE_FORM_CONTROL_IMAGEBUTTON, FRM_SUN_CONTROL_IMAGEBUTTON); + // - ImageControl + REGISTER_CLASS2(OImageControlControl, STARDIV_ONE_FORM_CONTROL_IMAGECONTROL, FRM_SUN_CONTROL_IMAGECONTROL); + + + // ======================================================================== + // = various + REGISTER_CLASS1(OFormsCollection, FRM_SUN_FORMS_COLLECTION); + REGISTER_CLASS1(ImageProducer, SRV_AWT_IMAGEPRODUCER); + + // ======================================================================== + // = XForms core +#define REGISTER_XFORMS_CLASS(name) \ + aServices.realloc(1); \ + aServices.getArray()[0] = rtl::OUString::createFromAscii( "com.sun.star.xforms." #name ); \ + REGISTER_CLASS_CORE(name) + + REGISTER_XFORMS_CLASS(Model); + REGISTER_XFORMS_CLASS(XForms); + +} + +//--------------------------------------------------------------------------------------- +void registerServiceProvider(const ::rtl::OUString& _rServiceImplName, const Sequence< ::rtl::OUString >& _rServices, XRegistryKey* _pKey) +{ + ::rtl::OUString sMainKeyName = ::rtl::OUString::createFromAscii("/"); + sMainKeyName += _rServiceImplName; + sMainKeyName += ::rtl::OUString::createFromAscii("/UNO/SERVICES"); + Reference< XRegistryKey > xNewKey = _pKey->createKey(sMainKeyName); + OSL_ENSURE(xNewKey.is(), "forms::registerProvider : could not create a registry key !"); + if (!xNewKey.is()) + return; + + const ::rtl::OUString* pSupportedServices = _rServices.getConstArray(); + for (sal_Int32 i=0; i<_rServices.getLength(); ++i, ++pSupportedServices) + xNewKey->createKey(*pSupportedServices); +} + +//======================================================================================= +extern "C" +{ + +//--------------------------------------------------------------------------------------- +void SAL_CALL createRegistryInfo_ODatabaseForm(); +void SAL_CALL createRegistryInfo_OFilterControl(); +void SAL_CALL createRegistryInfo_OScrollBarModel(); +void SAL_CALL createRegistryInfo_OSpinButtonModel(); +void SAL_CALL createRegistryInfo_ONavigationBarModel(); +void SAL_CALL createRegistryInfo_ONavigationBarControl(); +void SAL_CALL createRegistryInfo_ORichTextModel(); +void SAL_CALL createRegistryInfo_ORichTextControl(); +void SAL_CALL createRegistryInfo_CLibxml2XFormsExtension(); +void SAL_CALL createRegistryInfo_FormOperations(); + +//--------------------------------------------------------------------------------------- +void SAL_CALL createRegistryInfo_FORMS() +{ + static sal_Bool bInit = sal_False; + if (!bInit) + { + createRegistryInfo_ODatabaseForm(); + createRegistryInfo_OFilterControl(); + createRegistryInfo_OScrollBarModel(); + createRegistryInfo_OSpinButtonModel(); + createRegistryInfo_ONavigationBarModel(); + createRegistryInfo_ONavigationBarControl(); + createRegistryInfo_ORichTextModel(); + createRegistryInfo_ORichTextControl(); + createRegistryInfo_CLibxml2XFormsExtension(); + createRegistryInfo_FormOperations(); + bInit = sal_True; + } +} + +//--------------------------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char** _ppEnvTypeName, uno_Environment** /*_ppEnv*/) +{ + *_ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//--------------------------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(void* _pServiceManager, XRegistryKey* _pRegistryKey) +{ + if (_pRegistryKey) + { + try + { + // ======================================================================== + // the real way - use the OModule + createRegistryInfo_FORMS(); + if ( !::frm::OFormsModule::writeComponentInfos( + static_cast<XMultiServiceFactory*>( _pServiceManager ), + static_cast<XRegistryKey*>( _pRegistryKey ) ) + ) + return sal_False; + + // ======================================================================== + // a lot of stuff which is implemented "manually" here in this file + + // collect the class infos + ensureClassInfos(); + + // both our static sequences should have the same length ... + sal_Int32 nClasses = s_aClassImplementationNames.getLength(); + OSL_ENSURE(s_aClassServiceNames.getLength() == nClasses, + "forms::component_writeInfo : invalid class infos !"); + + // loop through the sequences and register the service providers + const ::rtl::OUString* pClasses = s_aClassImplementationNames.getConstArray(); + const Sequence< ::rtl::OUString >* pServices = s_aClassServiceNames.getConstArray(); + + for (sal_Int32 i=0; i<nClasses; ++i, ++pClasses, ++pServices) + registerServiceProvider(*pClasses, *pServices, _pRegistryKey); + + s_aClassImplementationNames.realloc(0); + s_aClassServiceNames.realloc(0); + s_aFactories.realloc(0); + + return sal_True; + } + catch ( InvalidRegistryException& ) + { + OSL_ENSURE(sal_False, "forms::component_writeInfo : InvalidRegistryException !"); + } + } + s_aClassImplementationNames.realloc(0); + s_aClassServiceNames.realloc(0); + s_aFactories.realloc(0); + return sal_False; +} + +//--------------------------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory(const sal_Char* _pImplName, XMultiServiceFactory* _pServiceManager, void* /*_pRegistryKey*/) +{ + if (!_pServiceManager || !_pImplName) + return NULL; + + // ======================================================================== + // a lot of stuff which is implemented "manually" here in this file + void* pRet = NULL; + + // collect the class infos + ensureClassInfos(); + + // both our static sequences should have the same length ... + sal_Int32 nClasses = s_aClassImplementationNames.getLength(); + OSL_ENSURE((s_aClassServiceNames.getLength() == nClasses) && + (s_aFactories.getLength() == nClasses), + "forms::component_writeInfo : invalid class infos !"); + + // loop through the sequences and register the service providers + const ::rtl::OUString* pClasses = s_aClassImplementationNames.getConstArray(); + const Sequence< ::rtl::OUString >* pServices = s_aClassServiceNames.getConstArray(); + const sal_Int64* pFunctionsAsInts = s_aFactories.getConstArray(); + + for (sal_Int32 i=0; i<nClasses; ++i, ++pClasses, ++pServices, ++pFunctionsAsInts) + { + if (rtl_ustr_ascii_compare(*pClasses, _pImplName) == 0) + { + ::cppu::ComponentInstantiation aCurrentCreateFunction = + reinterpret_cast< ::cppu::ComponentInstantiation>(*pFunctionsAsInts); + + Reference<XSingleServiceFactory> xFactory( + ::cppu::createSingleFactory( + _pServiceManager, + *pClasses, + aCurrentCreateFunction, + *pServices + ) + ); + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + break; + } + } + } + + // ======================================================================== + // the real way - use the OModule + if ( !pRet ) + { + createRegistryInfo_FORMS(); + { + // let the module look for the component + Reference< XInterface > xRet; + xRet = ::frm::OFormsModule::getComponentFactory( + ::rtl::OUString::createFromAscii( _pImplName ), + static_cast< XMultiServiceFactory* >( _pServiceManager ) ); + + if ( xRet.is() ) + xRet->acquire(); + pRet = xRet.get(); + } + } + + return pRet; +} + +} diff --git a/forms/source/resource/frm_resource.cxx b/forms/source/resource/frm_resource.cxx new file mode 100644 index 000000000000..67e9c5889326 --- /dev/null +++ b/forms/source/resource/frm_resource.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "frm_resource.hxx" +#include <tools/simplerm.hxx> + +// ---- needed as long as we have no contexts for components --- +#include <vcl/svapp.hxx> +//--------------------------------------------------- + +#ifndef _SOLAR_HRC +#include <svl/solar.hrc> +#endif + +//......................................................................... +namespace frm +{ + + //================================================================== + //= ResourceManager + //================================================================== + SimpleResMgr* ResourceManager::m_pImpl = NULL; + + //------------------------------------------------------------------ + ResourceManager::EnsureDelete::~EnsureDelete() + { + delete ResourceManager::m_pImpl; + } + + //------------------------------------------------------------------ + void ResourceManager::ensureImplExists() + { + if (m_pImpl) + return; + + ByteString sFileName("frm"); + + m_pImpl = SimpleResMgr::Create(sFileName.GetBuffer(), Application::GetSettings().GetUILocale()); + + if (m_pImpl) + { + // no that we have a impl class make sure it's deleted on unloading the library + static ResourceManager::EnsureDelete s_aDeleteTheImplClas; + } + } + + //------------------------------------------------------------------ + ::rtl::OUString ResourceManager::loadString(sal_uInt16 _nResId) + { + ::rtl::OUString sReturn; + + ensureImplExists(); + if (m_pImpl) + sReturn = m_pImpl->ReadString(_nResId); + + return sReturn; + } + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/resource/makefile.mk b/forms/source/resource/makefile.mk new file mode 100644 index 000000000000..cde68a98a339 --- /dev/null +++ b/forms/source/resource/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=.. +PRJNAME=forms +TARGET=resource + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SRS1NAME=resource +SRC1FILES= \ + strings.src \ + xforms.src + +SLOFILES= $(SLO)$/frm_resource.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk diff --git a/forms/source/resource/strings.src b/forms/source/resource/strings.src new file mode 100644 index 000000000000..96f2c1d95dfb --- /dev/null +++ b/forms/source/resource/strings.src @@ -0,0 +1,161 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif + +String RID_BASELISTBOX_ERROR_FILLLIST +{ + Text [ en-US ] = "The contents of a combo box or list field could not be determined."; +}; + +String RID_STR_IMPORT_GRAPHIC +{ + Text [ en-US ] = "Insert graphics" ; +}; + +String RID_STR_CONTROL_SUBSTITUTED_NAME +{ + Text [ en-US ] = "substituted"; +}; + +String RID_STR_CONTROL_SUBSTITUTED_EPXPLAIN +{ + Text [ en-US ] = "An error occurred while this control was being loaded. It was therefore replaced with a placeholder."; +}; + +String RID_STR_READERROR +{ + Text [ en-US ] = "Error reading data from database" ; +}; + +String RID_STR_CONNECTERROR +{ + Text [ en-US ] = "Connection failed" ; +}; + +String RID_ERR_LOADING_FORM +{ + Text [ en-US ] = "The data content could not be loaded."; +}; + +String RID_ERR_REFRESHING_FORM +{ + Text [ en-US ] = "The data content could not be updated"; +}; + +String RID_STR_ERR_INSERTRECORD +{ + Text [ en-US ] = "Error inserting the new record"; +}; + +String RID_STR_ERR_UPDATERECORD +{ + Text [ en-US ] = "Error updating the current record"; +}; + +String RID_STR_ERR_DELETERECORD +{ + Text [ en-US ] = "Error deleting the current record"; +}; + +String RID_STR_ERR_DELETERECORDS +{ + Text [ en-US ] = "Error deleting the specified records"; +}; + +String RID_STR_NEED_NON_NULL_OBJECT +{ + Text [ en-US ] = "The object cannot be NULL."; +}; + +String RID_STR_OPEN_GRAPHICS +{ + Text [ en-US ] = "Insert graphics from..."; +}; + +String RID_STR_CLEAR_GRAPHICS +{ + Text [ en-US ] = "Remove graphics"; +}; + + +String RID_STR_INVALIDSTREAM +{ + Text [ en-US ] = "The given stream is invalid."; +}; + +String RID_STR_SYNTAXERROR +{ + Text [ en-US ] = "Syntax error in query expression" ; +}; + +String RID_STR_INCOMPATIBLE_TYPES +{ + Text [ en-US ] = "The value types supported by the binding cannot be used for exchanging data with this control."; +}; + +String RID_STR_LABEL_RECORD +{ + Text [ en-US ] = "Record"; +}; + +String RID_STR_INVALID_VALIDATOR +{ + Text [ en-US ] = "The control is connected to an external value binding, which at the same time acts as validator. You need to revoke the value binding, before you can set a new validator."; +}; + +String RID_STR_LABEL_OF +{ + Text [ en-US ] = "of"; +}; + +String RID_STR_QUERY_SAVE_MODIFIED_ROW +{ + Text [ en-US ] = "The content of the current form has been modified.\nDo you want to save your changes?"; +}; +String RID_STR_COULD_NOT_SET_ORDER +{ + Text [ en-US ] = "Error setting the sort criteria"; +}; +String RID_STR_COULD_NOT_SET_FILTER +{ + Text [ en-US ] = "Error setting the filter criteria"; +}; +String RID_STR_FEATURE_REQUIRES_PARAMETERS +{ + Text [ en-US ] = "To execute this function, parameters are needed."; +}; +String RID_STR_FEATURE_NOT_EXECUTABLE +{ + Text [ en-US ] = "This function cannot be executed, but is only for status queries."; +}; +String RID_STR_FEATURE_UNKNOWN +{ + Text [ en-US ] = "Unknown function."; +}; diff --git a/forms/source/resource/xforms.src b/forms/source/resource/xforms.src new file mode 100644 index 000000000000..4efa63320a6f --- /dev/null +++ b/forms/source/resource/xforms.src @@ -0,0 +1,196 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif + + +String RID_STR_XFORMS_NO_BINDING_EXPRESSION +{ + Text [ en-US ] = "Please enter a binding expression."; +}; + +String RID_STR_XFORMS_INVALID_BINDING_EXPRESSION +{ + Text [ en-US ] = "This is an invalid binding expression."; +}; + +String RID_STR_XFORMS_INVALID_VALUE +{ + Text [ en-US ] = "Value is invalid."; +}; + +String RID_STR_XFORMS_REQUIRED +{ + Text [ en-US ] = "A value is required."; +}; + +String RID_STR_XFORMS_INVALID_CONSTRAINT +{ + Text [ en-US ] = "The constraint '$1' not validated."; +}; + +String RID_STR_XFORMS_VALUE_IS_NOT_A +{ + Text [ en-US ] = "The value is not of the type '$2'."; +}; + +String RID_STR_XFORMS_VALUE_MAX_INCL +{ + Text [ en-US ] = "The value must be smaller than or equal to $2."; +}; + +String RID_STR_XFORMS_VALUE_MAX_EXCL +{ + Text [ en-US ] = "The value must be smaller than $2."; +}; + +String RID_STR_XFORMS_VALUE_MIN_INCL +{ + Text [ en-US ] = "The value must be greater than or equal to $2."; +}; + +String RID_STR_XFORMS_VALUE_MIN_EXCL +{ + Text [ en-US ] = "The value must be greater than $2."; +}; + +String RID_STR_XFORMS_VALUE_PATTERN +{ + Text [ en-US ] = "The value does not match the pattern '$2'."; +}; + +String RID_STR_XFORMS_VALUE_TOTAL_DIGITS +{ + Text [ en-US ] = "$2 digits allowed at most."; +}; + +String RID_STR_XFORMS_VALUE_FRACTION_DIGITS +{ + Text [ en-US ] = "$2 fraction digits allowed at most."; +}; + +String RID_STR_XFORMS_VALUE_LENGTH +{ + Text [ en-US ] = "The string must be $2 characters long."; +}; + +String RID_STR_XFORMS_VALUE_MIN_LENGTH +{ + Text [ en-US ] = "The string must be at least $2 characters long."; +}; + +String RID_STR_XFORMS_VALUE_MAX_LENGTH +{ + Text [ en-US ] = "The string can only be $2 characters long at most."; +}; + +String RID_STR_DATATYPE_STRING +{ + Text [ en-US ] = "String"; +}; + +String RID_STR_DATATYPE_URL +{ + Text [ en-US ] = "Hyperlink"; +}; + +String RID_STR_DATATYPE_BOOLEAN +{ + Text [ en-US ] = "True/False (Boolean)"; +}; + +String RID_STR_DATATYPE_DECIMAL +{ + Text [ en-US ] = "Decimal"; +}; + +String RID_STR_DATATYPE_FLOAT +{ + Text [ en-US ] = "Floating point"; +}; + +String RID_STR_DATATYPE_DOUBLE +{ + Text [ en-US ] = "Double"; +}; + +String RID_STR_DATATYPE_DATE +{ + Text [ en-US ] = "Date"; +}; + +String RID_STR_DATATYPE_TIME +{ + Text [ en-US ] = "Time"; +}; + +String RID_STR_DATATYPE_DATETIME +{ + Text [ en-US ] = "Date and Time"; +}; + +String RID_STR_DATATYPE_YEARMONTH +{ + Text [ en-US ] = "Month and year"; +}; + +String RID_STR_DATATYPE_YEAR +{ + Text [ en-US ] = "Year"; +}; + +String RID_STR_DATATYPE_MONTHDAY +{ + Text [ en-US ] = "Month and day"; +}; + +String RID_STR_DATATYPE_MONTH +{ + Text [ en-US ] = "Month"; +}; + +String RID_STR_DATATYPE_DAY +{ + Text [ en-US ] = "Day"; +}; + +String RID_STR_XFORMS_CANT_EVALUATE +{ + Text [ en-US ] = "Error during evaluation"; +}; + +String RID_STR_XFORMS_PATTERN_DOESNT_MATCH +{ + Text [ en-US ] = "The string '$1' does not match the required regular expression '$2'."; +}; + +String RID_STR_XFORMS_BINDING_UI_NAME +{ + Text [ en-US ] = "Binding" ; +}; diff --git a/forms/source/richtext/attributedispatcher.cxx b/forms/source/richtext/attributedispatcher.cxx new file mode 100644 index 000000000000..82df2c3fbbf1 --- /dev/null +++ b/forms/source/richtext/attributedispatcher.cxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "attributedispatcher.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <editeng/editview.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::beans; + + //==================================================================== + //= OAttributeDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OAttributeDispatcher::OAttributeDispatcher( EditView& _rView, AttributeId _nAttributeId, const URL& _rURL, + IMultiAttributeDispatcher* _pMasterDispatcher ) + :ORichTextFeatureDispatcher( _rView, _rURL ) + ,m_pMasterDispatcher( _pMasterDispatcher ) + ,m_nAttributeId( _nAttributeId ) + { + OSL_ENSURE( m_pMasterDispatcher, "OAttributeDispatcher::OAttributeDispatcher: invalid master dispatcher!" ); + } + + //-------------------------------------------------------------------- + OAttributeDispatcher::~OAttributeDispatcher( ) + { + acquire(); + dispose(); + } + + //-------------------------------------------------------------------- + void OAttributeDispatcher::disposing( ::osl::ClearableMutexGuard& _rClearBeforeNotify ) + { + m_pMasterDispatcher = NULL; + ORichTextFeatureDispatcher::disposing( _rClearBeforeNotify ); + } + + //-------------------------------------------------------------------- + void OAttributeDispatcher::fillFeatureEventFromAttributeState( FeatureStateEvent& _rEvent, const AttributeState& _rState ) const + { + if ( _rState.eSimpleState == eChecked ) + _rEvent.State <<= (sal_Bool)sal_True; + else if ( _rState.eSimpleState == eUnchecked ) + _rEvent.State <<= (sal_Bool)sal_False; + } + + //-------------------------------------------------------------------- + FeatureStateEvent OAttributeDispatcher::buildStatusEvent() const + { + FeatureStateEvent aEvent( ORichTextFeatureDispatcher::buildStatusEvent() ); + aEvent.IsEnabled = getEditView() ? !getEditView()->IsReadOnly() : sal_False; + + AttributeState aState; + if ( m_pMasterDispatcher ) + aState = m_pMasterDispatcher->getState( m_nAttributeId ); + + fillFeatureEventFromAttributeState( aEvent, aState ); + + return aEvent; + } + + //-------------------------------------------------------------------- + void SAL_CALL OAttributeDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + checkDisposed(); + + (void)_rURL; + (void)_rArguments; + + OSL_ENSURE( _rURL.Complete == getFeatureURL().Complete, "OAttributeDispatcher::dispatch: invalid URL!" ); +#if OSL_DEBUG_LEVEL > 0 + if ( _rArguments.getLength() ) + { + ::rtl::OString sMessage( "OAttributeDispatcher::dispatch: found arguments, but can't handle arguments at all" ); + sMessage += "\n (URL: "; + sMessage += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US ); + sMessage += ")"; + DBG_ERROR( sMessage.getStr() ); + } +#endif + + if ( m_pMasterDispatcher ) + m_pMasterDispatcher->executeAttribute( m_nAttributeId, NULL ); + } + + //-------------------------------------------------------------------- + void OAttributeDispatcher::onAttributeStateChanged( AttributeId _nAttributeId, const AttributeState& /*_rState*/ ) + { + OSL_ENSURE( _nAttributeId == m_nAttributeId, "OAttributeDispatcher::onAttributeStateChanged: wrong attribute!" ); + (void)_nAttributeId; + + FeatureStateEvent aEvent( buildStatusEvent() ); + ::cppu::OInterfaceIteratorHelper aIter( getStatusListeners() ); + while ( aIter.hasMoreElements() ) + doNotify( static_cast< XStatusListener* >( aIter.next() ), aEvent ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/richtext/attributedispatcher.hxx b/forms/source/richtext/attributedispatcher.hxx new file mode 100644 index 000000000000..6c9b7b461267 --- /dev/null +++ b/forms/source/richtext/attributedispatcher.hxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_ATTRIBUTEDISPATCHER_HXX +#define FORMS_SOURCE_RICHTEXT_ATTRIBUTEDISPATCHER_HXX + +#include "featuredispatcher.hxx" +#include "rtattributes.hxx" +#include "textattributelistener.hxx" + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OAttributeDispatcher + //==================================================================== + class OAttributeDispatcher :public ORichTextFeatureDispatcher + ,public ITextAttributeListener + { + protected: + IMultiAttributeDispatcher* m_pMasterDispatcher; + AttributeId m_nAttributeId; + + public: + /** ctor + @param _nAttributeId + the id of the attribute which this instance is responsible for + @param _rURL + the URL of the feature which this instance is responsible for + @param _pMasterDispatcher + the dispatcher which can execute the given attribute + @param _pConverter + an instance which is able to convert between SfxPoolItems and XDispatch-Parameters + If not <NULL/>, the parametrized version of IMultiAttributeDispatcher::executeAttribute + will be used. + */ + OAttributeDispatcher( + EditView& _rView, + AttributeId _nAttributeId, + const ::com::sun::star::util::URL& _rURL, + IMultiAttributeDispatcher* _pMasterDispatcher + ); + + /// notifies a new attribute state + void notifyAttributeState( const AttributeState& _rState ) SAL_THROW (()); + + protected: + ~OAttributeDispatcher( ); + + protected: + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& URL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::uno::RuntimeException); + + // ITextAttributeListener + virtual void onAttributeStateChanged( AttributeId _nAttributeId, const AttributeState& _rState ); + + // ORichTextFeatureDispatcher + virtual void disposing( ::osl::ClearableMutexGuard& _rClearBeforeNotify ); + + // ORichTextFeatureDispatcher + virtual ::com::sun::star::frame::FeatureStateEvent buildStatusEvent() const; + + // own overridables + virtual void fillFeatureEventFromAttributeState( ::com::sun::star::frame::FeatureStateEvent& _rEvent, const AttributeState& _rState ) const; + + protected: + /// notifies our feature state to one particular listener + void notifyState( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& _rxControl, + const AttributeState& _rState + ) SAL_THROW (()); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_ATTRIBUTEDISPATCHER_HXX + diff --git a/forms/source/richtext/clipboarddispatcher.cxx b/forms/source/richtext/clipboarddispatcher.cxx new file mode 100644 index 000000000000..97b2ec1cba84 --- /dev/null +++ b/forms/source/richtext/clipboarddispatcher.cxx @@ -0,0 +1,208 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "clipboarddispatcher.hxx" +#include <editeng/editview.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ +#include <svtools/cliplistener.hxx> +#include <svtools/transfer.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::beans; + + //==================================================================== + namespace + { + static URL createClipboardURL( OClipboardDispatcher::ClipboardFunc _eFunc ) + { + URL aURL; + switch ( _eFunc ) + { + case OClipboardDispatcher::eCut: + aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:Cut" ) ); + break; + case OClipboardDispatcher::eCopy: + aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:Copy" ) ); + break; + case OClipboardDispatcher::ePaste: + aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:Paste" ) ); + break; + } + return aURL; + } + } + + //==================================================================== + //= OClipboardDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OClipboardDispatcher::OClipboardDispatcher( EditView& _rView, ClipboardFunc _eFunc ) + :ORichTextFeatureDispatcher( _rView, createClipboardURL( _eFunc ) ) + ,m_eFunc( _eFunc ) + ,m_bLastKnownEnabled( sal_True ) + { + } + + //-------------------------------------------------------------------- + sal_Bool OClipboardDispatcher::implIsEnabled( ) const + { + sal_Bool bEnabled = sal_False; + switch ( m_eFunc ) + { + case eCut: + bEnabled = !getEditView()->IsReadOnly() && getEditView()->HasSelection(); + break; + + case eCopy: + bEnabled = getEditView()->HasSelection(); + break; + + case ePaste: + bEnabled = !getEditView()->IsReadOnly(); + break; + } + return bEnabled; + } + + //-------------------------------------------------------------------- + FeatureStateEvent OClipboardDispatcher::buildStatusEvent() const + { + FeatureStateEvent aEvent( ORichTextFeatureDispatcher::buildStatusEvent() ); + aEvent.IsEnabled = implIsEnabled(); + return aEvent; + } + + //-------------------------------------------------------------------- + void OClipboardDispatcher::invalidateFeatureState_Broadcast() + { + sal_Bool bEnabled = implIsEnabled(); + if ( m_bLastKnownEnabled == bEnabled ) + // nothing changed -> no notification + return; + m_bLastKnownEnabled = bEnabled; + + ORichTextFeatureDispatcher::invalidateFeatureState_Broadcast(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClipboardDispatcher::dispatch( const URL& /*_rURL*/, const Sequence< PropertyValue >& /*Arguments*/ ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !getEditView() ) + throw DisposedException(); + + switch ( m_eFunc ) + { + case eCut: + getEditView()->Cut(); + break; + + case eCopy: + getEditView()->Copy(); + break; + + case ePaste: + getEditView()->Paste(); + break; + } + } + + //==================================================================== + //= OPasteClipboardDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OPasteClipboardDispatcher::OPasteClipboardDispatcher( EditView& _rView ) + :OClipboardDispatcher( _rView, ePaste ) + ,m_pClipListener( NULL ) + ,m_bPastePossible( sal_False ) + { + m_pClipListener = new TransferableClipboardListener( LINK( this, OPasteClipboardDispatcher, OnClipboardChanged ) ); + m_pClipListener->acquire(); + m_pClipListener->AddRemoveListener( _rView.GetWindow(), TRUE ); + + // initial state + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( _rView.GetWindow() ) ); + m_bPastePossible = ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) || aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); + } + + //-------------------------------------------------------------------- + OPasteClipboardDispatcher::~OPasteClipboardDispatcher() + { + if ( !isDisposed() ) + { + acquire(); + dispose(); + } + } + + //-------------------------------------------------------------------- + IMPL_LINK( OPasteClipboardDispatcher, OnClipboardChanged, TransferableDataHelper*, _pDataHelper ) + { + OSL_ENSURE( _pDataHelper, "OPasteClipboardDispatcher::OnClipboardChanged: ooops!" ); + m_bPastePossible = _pDataHelper->HasFormat( SOT_FORMAT_STRING ) + || _pDataHelper->HasFormat( SOT_FORMAT_RTF ); + + invalidate(); + + return 0L; + } + + //-------------------------------------------------------------------- + void OPasteClipboardDispatcher::disposing( ::osl::ClearableMutexGuard& _rClearBeforeNotify ) + { + OSL_ENSURE( getEditView() && getEditView()->GetWindow(), "OPasteClipboardDispatcher::disposing: EditView should not (yet) be disfunctional here!" ); + if ( getEditView() && getEditView()->GetWindow() && m_pClipListener ) + m_pClipListener->AddRemoveListener( getEditView()->GetWindow(), FALSE ); + m_pClipListener->release(); + m_pClipListener = NULL; + + OClipboardDispatcher::disposing( _rClearBeforeNotify ); + } + + //-------------------------------------------------------------------- + sal_Bool OPasteClipboardDispatcher::implIsEnabled( ) const + { + return m_bPastePossible && OClipboardDispatcher::implIsEnabled(); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/richtext/clipboarddispatcher.hxx b/forms/source/richtext/clipboarddispatcher.hxx new file mode 100644 index 000000000000..a9e6bd7417c1 --- /dev/null +++ b/forms/source/richtext/clipboarddispatcher.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_CLIPBOARDDISPATCHER_HXX +#define FORMS_SOURCE_RICHTEXT_CLIPBOARDDISPATCHER_HXX + +#include "featuredispatcher.hxx" +#include <tools/link.hxx> + +class TransferableClipboardListener; +class TransferableDataHelper; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OClipboardDispatcher + //==================================================================== + class OClipboardDispatcher : public ORichTextFeatureDispatcher + { + public: + enum ClipboardFunc + { + eCut, + eCopy, + ePaste + }; + + private: + ClipboardFunc m_eFunc; + sal_Bool m_bLastKnownEnabled; + + public: + OClipboardDispatcher( EditView& _rView, ClipboardFunc _eFunc ); + + protected: + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& URL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::uno::RuntimeException); + + // ORichTextFeatureDispatcher + virtual void invalidateFeatureState_Broadcast(); + virtual ::com::sun::star::frame::FeatureStateEvent + buildStatusEvent() const; + + protected: + /** determines whether our functionality is currently available + to be overridden for ePaste + */ + virtual sal_Bool implIsEnabled( ) const; + }; + + //==================================================================== + //= OPasteClipboardDispatcher + //==================================================================== + class OPasteClipboardDispatcher : public OClipboardDispatcher + { + private: + TransferableClipboardListener* m_pClipListener; + sal_Bool m_bPastePossible; + + public: + OPasteClipboardDispatcher( EditView& _rView ); + + protected: + ~OPasteClipboardDispatcher(); + + // OClipboardDispatcher + virtual sal_Bool implIsEnabled( ) const; + + // ORichTextFeatureDispatcher + virtual void disposing( ::osl::ClearableMutexGuard& _rClearBeforeNotify ); + + private: + DECL_LINK( OnClipboardChanged, TransferableDataHelper* ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_CLIPBOARDDISPATCHER_HXX + diff --git a/forms/source/richtext/featuredispatcher.cxx b/forms/source/richtext/featuredispatcher.cxx new file mode 100644 index 000000000000..d24e625e0f33 --- /dev/null +++ b/forms/source/richtext/featuredispatcher.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "featuredispatcher.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + + //==================================================================== + //= ORichTextFeatureDispatcher + //==================================================================== + //-------------------------------------------------------------------- + ORichTextFeatureDispatcher::ORichTextFeatureDispatcher( EditView& _rView, const URL& _rURL ) + :m_aFeatureURL( _rURL ) + ,m_aStatusListeners( m_aMutex ) + ,m_pEditView( &_rView ) + ,m_bDisposed( false ) + { + } + + //-------------------------------------------------------------------- + ORichTextFeatureDispatcher::~ORichTextFeatureDispatcher( ) + { + if ( !m_bDisposed ) + { + acquire(); + dispose(); + } + } + + //-------------------------------------------------------------------- + void ORichTextFeatureDispatcher::dispose() + { + EventObject aEvent( *this ); + m_aStatusListeners.disposeAndClear( aEvent ); + + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + m_bDisposed = true; + disposing( aGuard ); + } + + //-------------------------------------------------------------------- + void ORichTextFeatureDispatcher::disposing( ::osl::ClearableMutexGuard& /*_rClearBeforeNotify*/ ) + { + m_pEditView = NULL; + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextFeatureDispatcher::addStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException) + { + OSL_ENSURE( !m_bDisposed, "ORichTextFeatureDispatcher::addStatusListener: already disposed!" ); + if ( m_bDisposed ) + throw DisposedException(); + + OSL_ENSURE( _rURL.Complete == getFeatureURL().Complete, "ORichTextFeatureDispatcher::addStatusListener: invalid URL!" ); + if ( _rURL.Complete == getFeatureURL().Complete ) + if ( _rxControl.is() ) + { + m_aStatusListeners.addInterface( _rxControl ); + newStatusListener( _rxControl ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextFeatureDispatcher::removeStatusListener( const Reference< XStatusListener >& _rxControl, const URL& /*_rURL*/ ) throw (RuntimeException) + { + m_aStatusListeners.removeInterface( _rxControl ); + } + + //-------------------------------------------------------------------- + void ORichTextFeatureDispatcher::invalidate() + { + invalidateFeatureState_Broadcast(); + } + + //-------------------------------------------------------------------- + FeatureStateEvent ORichTextFeatureDispatcher::buildStatusEvent() const + { + FeatureStateEvent aEvent; + aEvent.IsEnabled = sal_False; + aEvent.Source = *const_cast< ORichTextFeatureDispatcher* >( this ); + aEvent.FeatureURL = getFeatureURL(); + aEvent.Requery = sal_False; + return aEvent; + } + + //-------------------------------------------------------------------- + void ORichTextFeatureDispatcher::invalidateFeatureState_Broadcast() + { + FeatureStateEvent aEvent( buildStatusEvent() ); + ::cppu::OInterfaceIteratorHelper aIter( getStatusListeners() ); + while ( aIter.hasMoreElements() ) + doNotify( static_cast< XStatusListener* >( aIter.next() ), aEvent ); + } + + //-------------------------------------------------------------------- + void ORichTextFeatureDispatcher::newStatusListener( const Reference< XStatusListener >& _rxListener ) + { + doNotify( _rxListener, buildStatusEvent() ); + } + + //-------------------------------------------------------------------- + void ORichTextFeatureDispatcher::doNotify( const Reference< XStatusListener >& _rxListener, const FeatureStateEvent& _rEvent ) const SAL_THROW(()) + { + OSL_PRECOND( _rxListener.is(), "ORichTextFeatureDispatcher::doNotify: invalid listener!" ); + if ( _rxListener.is() ) + { + try + { + _rxListener->statusChanged( _rEvent ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ORichTextFeatureDispatcher::doNotify: caught an exception!" ); + } + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/richtext/featuredispatcher.hxx b/forms/source/richtext/featuredispatcher.hxx new file mode 100644 index 000000000000..9a8252a21783 --- /dev/null +++ b/forms/source/richtext/featuredispatcher.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_FEATUREDISPATCHER_HXX +#define FORMS_SOURCE_RICHTEXT_FEATUREDISPATCHER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/broadcasthelper.hxx> + +class EditView; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= ORichTextFeatureDispatcher + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::frame::XDispatch + > ORichTextFeatureDispatcher_Base; + + class ORichTextFeatureDispatcher :public ::comphelper::OBaseMutex + ,public ORichTextFeatureDispatcher_Base + { + private: + ::com::sun::star::util::URL m_aFeatureURL; + ::cppu::OInterfaceContainerHelper m_aStatusListeners; + EditView* m_pEditView; + bool m_bDisposed; + + protected: + EditView* getEditView() { return m_pEditView; } + const EditView* getEditView() const { return m_pEditView; } + + protected: + inline const ::com::sun::star::util::URL& getFeatureURL() const { return m_aFeatureURL; } + inline ::cppu::OInterfaceContainerHelper& getStatusListeners() { return m_aStatusListeners; } + inline bool isDisposed() const { return m_bDisposed; } + inline void checkDisposed() const { if ( isDisposed() ) throw ::com::sun::star::lang::DisposedException(); } + + protected: + ORichTextFeatureDispatcher( EditView& _rView, const ::com::sun::star::util::URL& _rURL ); + ~ORichTextFeatureDispatcher( ); + + public: + /// clean up resources associated with this instance + void dispose(); + + // invalidate the feature, re-retrieve it's state, and broadcast changes, if necessary + void invalidate(); + + protected: + // overridables + virtual void newStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& _rxListener ); + virtual void disposing( ::osl::ClearableMutexGuard& _rClearBeforeNotify ); + virtual void invalidateFeatureState_Broadcast(); + + // to be overridden, and filled with the info special do your derived class + virtual ::com::sun::star::frame::FeatureStateEvent + buildStatusEvent() const; + + void doNotify( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& _rxListener, + const ::com::sun::star::frame::FeatureStateEvent& _rEvent + ) const SAL_THROW(()); + + protected: + // XDispatch + virtual void SAL_CALL addStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& _rxControl, const ::com::sun::star::util::URL& _rURL ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& _rxControl, const ::com::sun::star::util::URL& _rURL ) throw (::com::sun::star::uno::RuntimeException); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_FEATUREDISPATCHER_HXX + diff --git a/forms/source/richtext/makefile.mk b/forms/source/richtext/makefile.mk new file mode 100644 index 000000000000..5c62a1a9e675 --- /dev/null +++ b/forms/source/richtext/makefile.mk @@ -0,0 +1,60 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=.. +PRJNAME=forms +TARGET=richtext + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Files ------------------------------------- + +EXCEPTIONSFILES=\ + $(SLO)$/richtextunowrapper.obj \ + $(SLO)$/richtextmodel.obj \ + $(SLO)$/richtextcontrol.obj \ + $(SLO)$/featuredispatcher.obj \ + $(SLO)$/clipboarddispatcher.obj \ + $(SLO)$/attributedispatcher.obj \ + $(SLO)$/parametrizedattributedispatcher.obj \ + $(SLO)$/specialdispatchers.obj \ + $(SLO)$/richtextengine.obj \ + $(SLO)$/richtextimplcontrol.obj + +SLOFILES= $(EXCEPTIONSFILES) \ + $(SLO)$/richtextvclcontrol.obj \ + $(SLO)$/richtextviewport.obj \ + $(SLO)$/rtattributehandler.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/richtext/parametrizedattributedispatcher.cxx b/forms/source/richtext/parametrizedattributedispatcher.cxx new file mode 100644 index 000000000000..60791969c119 --- /dev/null +++ b/forms/source/richtext/parametrizedattributedispatcher.cxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "parametrizedattributedispatcher.hxx" +#include <editeng/editview.hxx> +#include <svl/itemset.hxx> +#include <svl/itempool.hxx> + +#ifndef _SVX_SVXIDS_HRC +#include <svx/svxids.hrc> +#endif +#include <sfx2/sfxuno.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::beans; + + //==================================================================== + //= OParametrizedAttributeDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OParametrizedAttributeDispatcher::OParametrizedAttributeDispatcher( EditView& _rView, AttributeId _nAttributeId, const URL& _rURL, IMultiAttributeDispatcher* _pMasterDispatcher ) + :OAttributeDispatcher( _rView, _nAttributeId, _rURL, _pMasterDispatcher ) + { + } + + //-------------------------------------------------------------------- + OParametrizedAttributeDispatcher::~OParametrizedAttributeDispatcher() + { + acquire(); + dispose(); + } + + //-------------------------------------------------------------------- + namespace + { + static SfxSlotId lcl_normalizeLatinScriptSlotId( SfxSlotId _nSlotId ) + { + switch ( _nSlotId ) + { + case SID_ATTR_CHAR_LATIN_FONT: return SID_ATTR_CHAR_FONT; + case SID_ATTR_CHAR_LATIN_LANGUAGE: return SID_ATTR_CHAR_LANGUAGE; + case SID_ATTR_CHAR_LATIN_POSTURE: return SID_ATTR_CHAR_POSTURE; + case SID_ATTR_CHAR_LATIN_WEIGHT: return SID_ATTR_CHAR_WEIGHT; + case SID_ATTR_CHAR_LATIN_FONTHEIGHT:return SID_ATTR_CHAR_FONTHEIGHT; + } + return _nSlotId; + } + } + + //-------------------------------------------------------------------- + void OParametrizedAttributeDispatcher::fillFeatureEventFromAttributeState( FeatureStateEvent& _rEvent, const AttributeState& _rState ) const + { + OSL_ENSURE( getEditView(), "OParametrizedAttributeDispatcher::notifyState: already disposed!" ); + if ( !getEditView() ) + return; + + SfxItemSet aEmptySet( const_cast< EditView* >( getEditView() )->GetEmptyItemSet() ); + Sequence< PropertyValue > aUnoStateDescription; + if ( _rState.getItem() ) + { + aEmptySet.Put( *_rState.getItem() ); + SfxSlotId nSlotId = aEmptySet.GetPool()->GetSlotId( _rState.getItem()->Which() ); + TransformItems( nSlotId, aEmptySet, aUnoStateDescription ); + _rEvent.State <<= aUnoStateDescription; + } + else + OAttributeDispatcher::fillFeatureEventFromAttributeState( _rEvent, _rState ); + } + + //-------------------------------------------------------------------- + const SfxPoolItem* OParametrizedAttributeDispatcher::convertDispatchArgsToItem( const Sequence< PropertyValue >& _rArguments ) + { + // get the real slot id. This may differ from our attribute id: for instance, both + // SID_ATTR_CHAR_HEIGHT and SID_ATTR_CHAR_LATIN_HEIGHT are mapped to the same which id + SfxSlotId nSlotId = lcl_normalizeLatinScriptSlotId( (SfxSlotId)m_nAttributeId ); + + SfxAllItemSet aParameterSet( getEditView()->GetEmptyItemSet() ); + TransformParameters( nSlotId, _rArguments, aParameterSet ); + + const SfxPoolItem* pArgument = NULL; + if ( aParameterSet.Count() ) + { + OSL_ENSURE( aParameterSet.Count() == 1, "OParametrizedAttributeDispatcher::convertDispatchArgsToItem: Arguments which form more than 1 item? How this?" ); + WhichId nAttributeWhich = aParameterSet.GetPool()->GetWhich( nSlotId ); + pArgument = aParameterSet.GetItem( nAttributeWhich ); + OSL_ENSURE( pArgument, "OParametrizedAttributeDispatcher::convertDispatchArgsToItem: suspicious: there were arguments, but they're not for my slot!" ); + } + + return pArgument; + } + + //-------------------------------------------------------------------- + void SAL_CALL OParametrizedAttributeDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( _rURL.Complete == getFeatureURL().Complete, "OParametrizedAttributeDispatcher::dispatch: invalid URL!" ); + (void)_rURL; + if ( m_pMasterDispatcher ) + { + const SfxPoolItem* pConvertedArgument = convertDispatchArgsToItem( _rArguments ); + m_pMasterDispatcher->executeAttribute( m_nAttributeId, pConvertedArgument ); + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/richtext/parametrizedattributedispatcher.hxx b/forms/source/richtext/parametrizedattributedispatcher.hxx new file mode 100644 index 000000000000..bbc73a6bd513 --- /dev/null +++ b/forms/source/richtext/parametrizedattributedispatcher.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_PARAMETRIZEDATTRIBUTEDISPATCHER_HXX +#define FORMS_SOURCE_RICHTEXT_PARAMETRIZEDATTRIBUTEDISPATCHER_HXX + +#include "attributedispatcher.hxx" + +class SfxPoolItem; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OParametrizedAttributeDispatcher + //==================================================================== + class OParametrizedAttributeDispatcher :public OAttributeDispatcher + { + public: + OParametrizedAttributeDispatcher( + EditView& _rView, + AttributeId _nAttributeId, + const ::com::sun::star::util::URL& _rURL, + IMultiAttributeDispatcher* _pMasterDispatcher + ); + + protected: + ~OParametrizedAttributeDispatcher(); + + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& URL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::uno::RuntimeException); + + // OAttributeDispatcher + virtual void fillFeatureEventFromAttributeState( ::com::sun::star::frame::FeatureStateEvent& _rEvent, const AttributeState& _rState ) const; + + protected: + // own overridables + /** convert the arguments as got in a XDispatch::dispatch call into an SfxPoolItem, which can + be used with a IMultiAttributeDispatcher::executeAttribute + */ + virtual const SfxPoolItem* convertDispatchArgsToItem( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArguments ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_PARAMETRIZEDATTRIBUTEDISPATCHER_HXX + diff --git a/forms/source/richtext/richtextcontrol.cxx b/forms/source/richtext/richtextcontrol.cxx new file mode 100644 index 000000000000..0755510cdd48 --- /dev/null +++ b/forms/source/richtext/richtextcontrol.cxx @@ -0,0 +1,766 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "richtextcontrol.hxx" +#include "frm_module.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" + +#include "richtextmodel.hxx" +#include "richtextvclcontrol.hxx" +#include "clipboarddispatcher.hxx" +#include "parametrizedattributedispatcher.hxx" +#include "specialdispatchers.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/PosSize.hpp> +/** === end UNO includes === **/ + +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> + +#include <svx/svxids.hrc> +#include <editeng/editview.hxx> +#include <svl/itemset.hxx> +#include <svl/itempool.hxx> +#include <sfx2/msgpool.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ORichTextControl() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ORichTextControl > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::frame; + +#define FORWARD_TO_PEER_1( unoInterface, method, param1 ) \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + xTypedPeer->method( param1 ); \ + } + +#define FORWARD_TO_PEER_1_RET( returnType, unoInterface, method, param1 ) \ + returnType aReturn; \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + aReturn = xTypedPeer->method( param1 ); \ + } \ + return aReturn; + +#define FORWARD_TO_PEER_3( unoInterface, method, param1, param2, param3 ) \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + xTypedPeer->method( param1, param2, param3 ); \ + } + +#define FORWARD_TO_PEER_3_RET( returnType, unoInterface, method, param1, param2, param3 ) \ + returnType aReturn; \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + aReturn = xTypedPeer->method( param1, param2, param3 ); \ + } \ + return aReturn; + + //================================================================== + // ORichTextControl + //================================================================== + DBG_NAME( ORichTextControl ) + //------------------------------------------------------------------ + ORichTextControl::ORichTextControl( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + { + DBG_CTOR( ORichTextControl, NULL ); + } + + //------------------------------------------------------------------ + ORichTextControl::~ORichTextControl() + { + DBG_DTOR( ORichTextControl, NULL ); + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextControl, UnoEditControl, ORichTextControl_Base ) + + //------------------------------------------------------------------ + Any SAL_CALL ORichTextControl::queryAggregation( const Type& _rType ) throw ( RuntimeException ) + { + Any aReturn = UnoEditControl::queryAggregation( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = ORichTextControl_Base::queryInterface( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------ + namespace + { + //.............................................................. + static void implAdjustTriStateFlag( const Reference< XPropertySet >& _rxProps, const ::rtl::OUString& _rPropertyName, + WinBits& _rAllBits, WinBits _nPositiveFlag, WinBits nNegativeFlag ) + { + sal_Bool bFlagValue = sal_False; + if ( _rxProps->getPropertyValue( _rPropertyName ) >>= bFlagValue ) + _rAllBits |= ( bFlagValue ? _nPositiveFlag : nNegativeFlag ); + } + + //.............................................................. + static void implAdjustTwoStateFlag( const Any& _rValue, WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false ) + { + sal_Bool bFlagValue = sal_False; + if ( _rValue >>= bFlagValue ) + { + if ( _bInvert ) + bFlagValue = !bFlagValue; + if ( bFlagValue ) + _rAllBits |= _nFlag; + else + _rAllBits &= ~_nFlag; + } + } + + //.............................................................. + static void implAdjustTwoStateFlag( const Reference< XPropertySet >& _rxProps, const ::rtl::OUString& _rPropertyName, + WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false ) + { + implAdjustTwoStateFlag( _rxProps->getPropertyValue( _rPropertyName ), _rAllBits, _nFlag, _bInvert ); + } + + //.............................................................. + static void adjustTwoStateWinBit( Window* _pWindow, const Any& _rValue, WinBits _nFlag, bool _bInvert = false ) + { + WinBits nBits = _pWindow->GetStyle(); + implAdjustTwoStateFlag( _rValue, nBits, _nFlag, _bInvert ); + _pWindow->SetStyle( nBits ); + } + + //.............................................................. + static WinBits getWinBits( const Reference< XControlModel >& _rxModel, WinBits nBaseBits = 0 ) + { + WinBits nBits = nBaseBits; + try + { + Reference< XPropertySet > xProps( _rxModel, UNO_QUERY ); + if ( xProps.is() ) + { + sal_Int16 nBorder = 0; + xProps->getPropertyValue( PROPERTY_BORDER ) >>= nBorder; + if ( nBorder ) + nBits |= WB_BORDER; + + implAdjustTriStateFlag( xProps, PROPERTY_TABSTOP, nBits, WB_TABSTOP, WB_NOTABSTOP ); + implAdjustTwoStateFlag( xProps, PROPERTY_HSCROLL, nBits, WB_HSCROLL ); + implAdjustTwoStateFlag( xProps, PROPERTY_VSCROLL, nBits, WB_VSCROLL ); + implAdjustTwoStateFlag( xProps, PROPERTY_HARDLINEBREAKS, nBits, WB_WORDBREAK, true ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return nBits; + } + } + + //------------------------------------------------------------------ + void SAL_CALL ORichTextControl::createPeer( const Reference< XToolkit >& _rToolkit, const Reference< XWindowPeer >& _rParentPeer ) throw( RuntimeException ) + { + sal_Bool bReallyActAsRichText = sal_False; + try + { + Reference< XPropertySet > xModelProps( getModel(), UNO_QUERY_THROW ); + xModelProps->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bReallyActAsRichText; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( !bReallyActAsRichText ) + { + UnoEditControl::createPeer( _rToolkit, _rParentPeer ); + OControl::initFormControlPeer( getPeer() ); + return; + } + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if (!getPeer().is()) + { + mbCreatingPeer = sal_True; + + // determine the VLC window for the parent + Window* pParentWin = NULL; + if ( _rParentPeer.is() ) + { + VCLXWindow* pParentXWin = VCLXWindow::GetImplementation( _rParentPeer ); + if ( pParentXWin ) + pParentWin = pParentXWin->GetWindow(); + DBG_ASSERT( pParentWin, "ORichTextControl::createPeer: could not obtain the VCL-level parent window!" ); + } + + // create the peer + Reference< XControlModel > xModel( getModel() ); + ORichTextPeer* pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) ); + DBG_ASSERT( pPeer, "ORichTextControl::createPeer: invalid peer returned!" ); + if ( pPeer ) + { + // by definition, the returned component is aquired once + pPeer->release(); + + // announce the peer to the base class + setPeer( pPeer ); + + // initialize ourself (and thus the peer) with the model properties + updateFromModel(); + + Reference< XView > xPeerView( getPeer(), UNO_QUERY ); + if ( xPeerView.is() ) + { + xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY ); + xPeerView->setGraphics( mxGraphics ); + } + + // a lot of initial settings from our component infos + setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, PosSize::POSSIZE ); + + pPeer->setVisible ( maComponentInfos.bVisible && !mbDesignMode ); + pPeer->setEnable ( maComponentInfos.bEnable ); + pPeer->setDesignMode( mbDesignMode ); + + peerCreated(); + } + + mbCreatingPeer = sal_False; + + OControl::initFormControlPeer( getPeer() ); + } + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ORichTextControl::getImplementationName() throw( RuntimeException ) + { + return getImplementationName_Static(); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ORichTextControl::getSupportedServiceNames() throw( RuntimeException ) + { + return getSupportedServiceNames_Static(); + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ORichTextControl::getImplementationName_Static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.form.ORichTextControl" ) ); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ORichTextControl::getSupportedServiceNames_Static() + { + Sequence< ::rtl::OUString > aServices( 3 ); + aServices[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) ); + aServices[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlEdit" ) ); + aServices[ 2 ] = FRM_SUN_CONTROL_RICHTEXTCONTROL; + return aServices; + } + + //------------------------------------------------------------------ + Reference< XInterface > SAL_CALL ORichTextControl::Create( const Reference< XMultiServiceFactory >& _rxFactory ) + { + return *( new ORichTextControl( _rxFactory ) ); + } + + //-------------------------------------------------------------------- + Reference< XDispatch > SAL_CALL ORichTextControl::queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& _rTargetFrameName, sal_Int32 _nSearchFlags ) throw (RuntimeException) + { + FORWARD_TO_PEER_3_RET( Reference< XDispatch >, XDispatchProvider, queryDispatch, _rURL, _rTargetFrameName, _nSearchFlags ); + } + + //-------------------------------------------------------------------- + Sequence< Reference< XDispatch > > SAL_CALL ORichTextControl::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException) + { + FORWARD_TO_PEER_1_RET( Sequence< Reference< XDispatch > >, XDispatchProvider, queryDispatches, _rRequests ); + } + + //-------------------------------------------------------------------- + sal_Bool ORichTextControl::requiresNewPeer( const ::rtl::OUString& _rPropertyName ) const + { + return UnoControl::requiresNewPeer( _rPropertyName ) || _rPropertyName.equals( PROPERTY_RICH_TEXT ); + } + + //================================================================== + // ORichTextPeer + //================================================================== + DBG_NAME( ORichTextPeer ) + //------------------------------------------------------------------ + ORichTextPeer* ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, Window* _pParentWindow, WinBits _nStyle ) + { + DBG_TESTSOLARMUTEX(); + + // the EditEngine of the model + RichTextEngine* pEngine = ORichTextModel::getEditEngine( _rxModel ); + OSL_ENSURE( pEngine, "ORichTextPeer::Create: could not obtaine the edit engine from the model!" ); + if ( !pEngine ) + return NULL; + + // the peer itself + ORichTextPeer* pPeer = new ORichTextPeer; + pPeer->acquire(); // by definition, the returned object is aquired once + + // the VCL control for the peer + RichTextControl* pRichTextControl = new RichTextControl( pEngine, _pParentWindow, _nStyle, NULL, pPeer ); + + // some knittings + pRichTextControl->SetComponentInterface( pPeer ); + + // outta here + return pPeer; + } + + //------------------------------------------------------------------ + ORichTextPeer::ORichTextPeer() + { + DBG_CTOR( ORichTextPeer, NULL ); + } + + //------------------------------------------------------------------ + ORichTextPeer::~ORichTextPeer() + { + DBG_DTOR( ORichTextPeer, NULL ); + } + + //------------------------------------------------------------------ + void ORichTextPeer::dispose( ) throw(RuntimeException) + { + { + ::vos::OGuard aGuard( GetMutex() ); + RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() ); + + if ( pRichTextControl ) + { + for ( AttributeDispatchers::iterator aDisposeLoop = m_aDispatchers.begin(); + aDisposeLoop != m_aDispatchers.end(); + ++aDisposeLoop + ) + { + pRichTextControl->disableAttributeNotification( aDisposeLoop->first ); + aDisposeLoop->second->dispose(); + } + } + + AttributeDispatchers aEmpty; + m_aDispatchers.swap( aEmpty ); + } + + VCLXWindow::dispose(); + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextPeer::draw( sal_Int32 _nX, sal_Int32 _nY ) throw(::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() ); + if ( !pControl ) + return; + + OutputDevice* pTargetDevice = VCLUnoHelper::GetOutputDevice( getGraphics() ); + OSL_ENSURE( pTargetDevice != NULL, "ORichTextPeer::draw: no graphics -> no drawing!" ); + if ( !pTargetDevice ) + return; + + ::Size aSize = pControl->GetSizePixel(); + const MapUnit eTargetUnit = pTargetDevice->GetMapMode().GetMapUnit(); + if ( eTargetUnit != MAP_PIXEL ) + aSize = pControl->PixelToLogic( aSize, eTargetUnit ); + + ::Point aPos( _nX, _nY ); + // the XView::draw API talks about pixels, always ... + if ( eTargetUnit != MAP_PIXEL ) + aPos = pTargetDevice->PixelToLogic( aPos ); + + pControl->Draw( pTargetDevice, aPos, aSize, WINDOW_DRAW_NOCONTROLS ); + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextPeer::setProperty( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (RuntimeException) + { + if ( !GetWindow() ) + { + VCLXWindow::setProperty( _rPropertyName, _rValue ); + return; + } + + if ( _rPropertyName.equals( PROPERTY_BACKGROUNDCOLOR ) ) + { + RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() ); + if ( !_rValue.hasValue() ) + { + pControl->SetBackgroundColor( ); + } + else + { + sal_Int32 nColor = COL_TRANSPARENT; + _rValue >>= nColor; + pControl->SetBackgroundColor( Color( nColor ) ); + } + } + else if ( _rPropertyName.equals( PROPERTY_HSCROLL ) ) + { + adjustTwoStateWinBit( GetWindow(), _rValue, WB_HSCROLL ); + } + else if ( _rPropertyName.equals( PROPERTY_VSCROLL ) ) + { + adjustTwoStateWinBit( GetWindow(), _rValue, WB_VSCROLL ); + } + else if ( _rPropertyName.equals( PROPERTY_HARDLINEBREAKS ) ) + { + adjustTwoStateWinBit( GetWindow(), _rValue, WB_WORDBREAK, true ); + } + else if ( _rPropertyName.equals( PROPERTY_READONLY ) ) + { + RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() ); + sal_Bool bReadOnly( pControl->IsReadOnly() ); + OSL_VERIFY( _rValue >>= bReadOnly ); + pControl->SetReadOnly( bReadOnly ); + + // update the dispatchers + for ( AttributeDispatchers::iterator aDispatcherLoop = m_aDispatchers.begin(); + aDispatcherLoop != m_aDispatchers.end(); + ++aDispatcherLoop + ) + { + aDispatcherLoop->second->invalidate(); + } + } + else if ( _rPropertyName.equals( PROPERTY_HIDEINACTIVESELECTION ) ) + { + RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() ); + sal_Bool bHide = pRichTextControl->GetHideInactiveSelection(); + OSL_VERIFY( _rValue >>= bHide ); + pRichTextControl->SetHideInactiveSelection( bHide ); + } + else + VCLXWindow::setProperty( _rPropertyName, _rValue ); + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XINTERFACE2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base ) + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base ) + + //-------------------------------------------------------------------- + namespace + { + static SfxSlotId lcl_translateConflictingSlot( SfxSlotId _nIDFromPool ) + { + // HACK HACK HACK + // unfortunately, some of our applications have some conflicting slots, + // i.e. slots which have the same UNO name as an existing other (common) + // slot. + // For instance, both the slots SID_SET_SUPER_SCRIPT (from SVX) and FN_SET_SUPER_SCRIPT + // (from SW) have the UNO name "SuperScript". + // Now, if the controls lives in a text document, and asks the SfxSlotPool for + // the id belonging to "SuperScript", it gets the FN_SET_SUPER_SCRIPT - which + // is completely unknown to the EditEngine. + // So, we need to translate such conflicting ids. + // + // Note that the real solution would be to fix the applications to + // *not* define conflicting slots. Alternatively, if SFX would provide a slot pool + // which is *static* (i.e. independent on the active application), then we + // would also never encounter such a conflict. + SfxSlotId nReturn( _nIDFromPool ); + switch ( _nIDFromPool ) + { + case 20411: /* FM_SET_SUPER_SCRIPT, originating in SW */ + nReturn = SID_SET_SUPER_SCRIPT; + break; + case 20412: /* FN_SET_SUB_SCRIPT, originating in SW */ + nReturn = SID_SET_SUB_SCRIPT; + break; + } + return nReturn; + } + } + + //-------------------------------------------------------------------- + ORichTextPeer::SingleAttributeDispatcher ORichTextPeer::implCreateDispatcher( SfxSlotId _nSlotId, const ::com::sun::star::util::URL& _rURL ) + { + RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() ); + OSL_PRECOND( pRichTextControl, "ORichTextPeer::implCreateDispatcher: invalid window!" ); + if ( !pRichTextControl ) + return SingleAttributeDispatcher( NULL ); + + ORichTextFeatureDispatcher* pDispatcher = NULL; + OAttributeDispatcher* pAttributeDispatcher = NULL; + switch ( _nSlotId ) + { + case SID_CUT: + pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCut ); + break; + + case SID_COPY: + pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCopy ); + break; + + case SID_PASTE: + pDispatcher = new OPasteClipboardDispatcher( pRichTextControl->getView() ); + break; + + case SID_SELECTALL: + pDispatcher = new OSelectAllDispatcher( pRichTextControl->getView(), _rURL ); + break; + + case SID_ATTR_PARA_LEFT_TO_RIGHT: + case SID_ATTR_PARA_RIGHT_TO_LEFT: + pAttributeDispatcher = new OParagraphDirectionDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl ); + break; + + case SID_TEXTDIRECTION_TOP_TO_BOTTOM: + case SID_TEXTDIRECTION_LEFT_TO_RIGHT: + pDispatcher = new OTextDirectionDispatcher( pRichTextControl->getView(), _rURL ); + break; + + case SID_ATTR_PARA_HANGPUNCTUATION: + case SID_ATTR_PARA_FORBIDDEN_RULES: + case SID_ATTR_PARA_SCRIPTSPACE: + pAttributeDispatcher = new OAsianFontLayoutDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl ); + break; + + default: + { + // is it a supported slot? + bool bSupportedSlot = false; + if ( !bSupportedSlot ) + { + const SfxItemPool& rPool = *pRichTextControl->getView().GetEmptyItemSet().GetPool(); + bSupportedSlot = rPool.IsInRange( rPool.GetWhich( _nSlotId ) ); + } + if ( !bSupportedSlot ) + bSupportedSlot = RichTextControl::isMappableSlot( _nSlotId ); + + if ( bSupportedSlot ) + { // it's really a slot which is supported by the EditEngine + + bool bNeedParametrizedDispatcher = true; + if ( ( _nSlotId == SID_ATTR_CHAR_POSTURE ) + || ( _nSlotId == SID_ATTR_CHAR_CJK_POSTURE ) + || ( _nSlotId == SID_ATTR_CHAR_CTL_POSTURE ) + || ( _nSlotId == SID_ATTR_CHAR_LATIN_POSTURE ) + || ( _nSlotId == SID_ATTR_CHAR_WEIGHT ) + || ( _nSlotId == SID_ATTR_CHAR_CJK_WEIGHT ) + || ( _nSlotId == SID_ATTR_CHAR_CTL_WEIGHT ) + || ( _nSlotId == SID_ATTR_CHAR_LATIN_WEIGHT ) + || ( _nSlotId == SID_ATTR_CHAR_LANGUAGE ) + || ( _nSlotId == SID_ATTR_CHAR_CJK_LANGUAGE ) + || ( _nSlotId == SID_ATTR_CHAR_CTL_LANGUAGE ) + || ( _nSlotId == SID_ATTR_CHAR_LATIN_LANGUAGE ) + || ( _nSlotId == SID_ATTR_CHAR_CONTOUR ) + || ( _nSlotId == SID_ATTR_CHAR_SHADOWED ) + || ( _nSlotId == SID_ATTR_CHAR_WORDLINEMODE ) + || ( _nSlotId == SID_ATTR_CHAR_COLOR ) + || ( _nSlotId == SID_ATTR_CHAR_RELIEF ) + || ( _nSlotId == SID_ATTR_CHAR_KERNING ) + || ( _nSlotId == SID_ATTR_CHAR_AUTOKERN ) + || ( _nSlotId == SID_ATTR_CHAR_SCALEWIDTH ) + ) + { + bNeedParametrizedDispatcher = true; + } + else if ( ( _nSlotId == SID_ATTR_PARA_HANGPUNCTUATION ) + || ( _nSlotId == SID_ATTR_PARA_FORBIDDEN_RULES ) + || ( _nSlotId == SID_ATTR_PARA_SCRIPTSPACE ) + ) + { + bNeedParametrizedDispatcher = false; + } + else + { + SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL ); + const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId ); + const SfxType* pType = pSlot ? pSlot->GetType() : NULL; + if ( pType ) + { + bNeedParametrizedDispatcher = ( pType->nAttribs > 0 ); + } + } + + if ( bNeedParametrizedDispatcher ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *parametrized* dispatcher for " ); + sTrace += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US ); + DBG_TRACE( sTrace.getStr() ); + #endif + pAttributeDispatcher = new OParametrizedAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl ); + } + else + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *normal* dispatcher for " ); + sTrace += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US ); + DBG_TRACE( sTrace.getStr() ); + #endif + pAttributeDispatcher = new OAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl ); + } + } + #if OSL_DEBUG_LEVEL > 0 + else + { + ::rtl::OString sTrace( "ORichTextPeer::implCreateDispatcher: not creating dispatcher (unsupported slot) for " ); + sTrace += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US ); + DBG_TRACE( sTrace.getStr() ); + } + #endif + } + break; + } + + SingleAttributeDispatcher xDispatcher( pDispatcher ); + if ( pAttributeDispatcher ) + { + xDispatcher = SingleAttributeDispatcher( pAttributeDispatcher ); + pRichTextControl->enableAttributeNotification( _nSlotId, pAttributeDispatcher ); + } + + return xDispatcher; + } + + //-------------------------------------------------------------------- + namespace + { + SfxSlotId lcl_getSlotFromUnoName( SfxSlotPool& _rSlotPool, const ::rtl::OUString& _rUnoSlotName ) + { + const SfxSlot* pSlot = _rSlotPool.GetUnoSlot( _rUnoSlotName ); + if ( pSlot ) + { + // okay, there's a slot with the given UNO name + return lcl_translateConflictingSlot( pSlot->GetSlotId() ); + } + + // some hard-coded slots, which do not have a UNO name at SFX level, but which + // we nevertheless need to transport via UNO mechanisms, so we need a name + if ( _rUnoSlotName.equalsAscii( "AllowHangingPunctuation" ) ) + return SID_ATTR_PARA_HANGPUNCTUATION; + if ( _rUnoSlotName.equalsAscii( "ApplyForbiddenCharacterRules" ) ) + return SID_ATTR_PARA_FORBIDDEN_RULES; + if ( _rUnoSlotName.equalsAscii( "UseScriptSpacing" ) ) + return SID_ATTR_PARA_SCRIPTSPACE; + + OSL_ENSURE( pSlot, "lcl_getSlotFromUnoName: unknown UNO slot name!" ); + return 0; + } + } + + //-------------------------------------------------------------------- + Reference< XDispatch > SAL_CALL ORichTextPeer::queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& /*_rTargetFrameName*/, sal_Int32 /*_nSearchFlags*/ ) throw (RuntimeException) + { + Reference< XDispatch > xReturn; + if ( !GetWindow() ) + { + OSL_ENSURE( sal_False, "ORichTextPeer::queryDispatch: already disposed?" ); + return xReturn; + } + + // is it an UNO slot? + ::rtl::OUString sUnoProtocolPrefix( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ) ); + if ( 0 == _rURL.Complete.compareTo( sUnoProtocolPrefix, sUnoProtocolPrefix.getLength() ) ) + { + ::rtl::OUString sUnoSlotName = _rURL.Complete.copy( sUnoProtocolPrefix.getLength() ); + SfxSlotId nSlotId = lcl_getSlotFromUnoName( SfxSlotPool::GetSlotPool( NULL ), sUnoSlotName ); + if ( nSlotId > 0 ) + { + // do we already have a dispatcher for this? + AttributeDispatchers::const_iterator aDispatcherPos = m_aDispatchers.find( nSlotId ); + if ( aDispatcherPos == m_aDispatchers.end() ) + { + SingleAttributeDispatcher pDispatcher = implCreateDispatcher( nSlotId, _rURL ); + if ( pDispatcher.is() ) + { + aDispatcherPos = m_aDispatchers.insert( AttributeDispatchers::value_type( nSlotId, pDispatcher ) ).first; + } + } + + if ( aDispatcherPos != m_aDispatchers.end() ) + xReturn = aDispatcherPos->second.getRef(); + } + } + + return xReturn; + } + + //-------------------------------------------------------------------- + Sequence< Reference< XDispatch > > SAL_CALL ORichTextPeer::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException) + { + Sequence< Reference< XDispatch > > aReturn( _rRequests.getLength() ); + Reference< XDispatch >* pReturn = aReturn.getArray(); + + const DispatchDescriptor* pRequest = _rRequests.getConstArray(); + const DispatchDescriptor* pRequestEnd = pRequest + _rRequests.getLength(); + for ( ; pRequest != pRequestEnd; ++pRequest, ++pReturn ) + { + *pReturn = queryDispatch( pRequest->FeatureURL, pRequest->FrameName, pRequest->SearchFlags ); + } + return aReturn; + } + + //-------------------------------------------------------------------- + void ORichTextPeer::onSelectionChanged( const ESelection& /*_rSelection*/ ) + { + AttributeDispatchers::iterator aDispatcherPos = m_aDispatchers.find( SID_COPY ); + if ( aDispatcherPos != m_aDispatchers.end() ) + aDispatcherPos->second.get()->invalidate(); + + aDispatcherPos = m_aDispatchers.find( SID_CUT ); + if ( aDispatcherPos != m_aDispatchers.end() ) + aDispatcherPos->second.get()->invalidate(); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/richtext/richtextcontrol.hxx b/forms/source/richtext/richtextcontrol.hxx new file mode 100644 index 000000000000..a3f0da71aca7 --- /dev/null +++ b/forms/source/richtext/richtextcontrol.hxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTCONTROL_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTCONTROL_HXX + +#include <toolkit/controls/unocontrols.hxx> +#include <toolkit/awt/vclxwindow.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XDispatchProvider.hpp> +/** === end UNO includes === **/ +#include <comphelper/uno3.hxx> +#include <comphelper/implementationreference.hxx> +#include <cppuhelper/implbase1.hxx> +#include <vcl/wintypes.hxx> +#include "rtattributes.hxx" +#include "attributedispatcher.hxx" + +#include <map> + +//......................................................................... +namespace frm +{ +//......................................................................... + + class ORichTextFeatureDispatcher; + class RichTextControl; + + //================================================================== + // ORichTextControl + //================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::frame::XDispatchProvider + > ORichTextControl_Base; + class ORichTextControl :public UnoEditControl + ,public ORichTextControl_Base + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + m_xORB; + + public: + ORichTextControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB + ); + + protected: + ~ORichTextControl(); + + public: + // XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + // UNO + DECLARE_UNO3_AGG_DEFAULTS( ORichTextControl, UnoEditControl ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw ( ::com::sun::star::uno::RuntimeException ); + + // XControl + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit >& _rToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _rParent ) throw( ::com::sun::star::uno::RuntimeException ); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XDispatchProvider + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SAL_CALL queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& _rTargetFrameName, sal_Int32 _rSearchFlags ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > > SAL_CALL queryDispatches( const ::com::sun::star::uno::Sequence< ::com::sun::star::frame::DispatchDescriptor >& Requests ) throw (::com::sun::star::uno::RuntimeException); + + // UnoControl + virtual sal_Bool requiresNewPeer( const ::rtl::OUString& _rPropertyName ) const; + }; + + //================================================================== + // ORichTextPeer + //================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::frame::XDispatchProvider + > ORichTextPeer_Base; + class ORichTextPeer :public VCLXWindow + ,public ORichTextPeer_Base + ,public ITextSelectionListener + { + private: + typedef ::comphelper::ImplementationReference< ORichTextFeatureDispatcher, ::com::sun::star::frame::XDispatch > SingleAttributeDispatcher; + typedef ::std::map< SfxSlotId, SingleAttributeDispatcher > AttributeDispatchers; + AttributeDispatchers m_aDispatchers; + + public: + /** factory method + @return + a new ORichTextPeer instance, which has been aquired once! + */ + static ORichTextPeer* Create( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& _rxModel, + Window* _pParentWindow, + WinBits _nStyle + ); + + // XInterface + DECLARE_XINTERFACE( ) + + protected: + ORichTextPeer(); + ~ORichTextPeer(); + + // XView + void SAL_CALL draw( sal_Int32 nX, sal_Int32 nY ) throw(::com::sun::star::uno::RuntimeException); + + // XVclWindowPeer + virtual void SAL_CALL setProperty( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::uno::RuntimeException); + + // XTypeProvider + DECLARE_XTYPEPROVIDER( ) + + // XComponent + virtual void SAL_CALL dispose( ) throw(::com::sun::star::uno::RuntimeException); + + // XDispatchProvider + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SAL_CALL queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& _rTargetFrameName, sal_Int32 _rSearchFlags ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > > SAL_CALL queryDispatches( const ::com::sun::star::uno::Sequence< ::com::sun::star::frame::DispatchDescriptor >& Requests ) throw (::com::sun::star::uno::RuntimeException); + + // ITextSelectionListener + virtual void onSelectionChanged( const ESelection& _rSelection ); + + private: + SingleAttributeDispatcher implCreateDispatcher( SfxSlotId _nSlotId, const ::com::sun::star::util::URL& _rURL ); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTCONTROL_HXX + diff --git a/forms/source/richtext/richtextengine.cxx b/forms/source/richtext/richtextengine.cxx new file mode 100644 index 000000000000..1105f8a51c1c --- /dev/null +++ b/forms/source/richtext/richtextengine.cxx @@ -0,0 +1,162 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "richtextengine.hxx" +#include <svl/itempool.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editobj.hxx> +#define ITEMID_FONTHEIGHT EE_CHAR_FONTHEIGHT +#include <editeng/fhgtitem.hxx> +#define ITEMID_FONT EE_CHAR_FONTHEIGHT +#include <editeng/fontitem.hxx> +#define ITEMID_LANGUAGE EE_CHAR_LANGUAGE +#include <editeng/langitem.hxx> +#include <vcl/svapp.hxx> +#include <vcl/mapunit.hxx> +#include <vcl/mapmod.hxx> +#include <vcl/outdev.hxx> +#include <unotools/lingucfg.hxx> +#include <svl/undo.hxx> +#include <vos/mutex.hxx> + +#include <algorithm> +#include <functional> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= RichTextEngine + //==================================================================== + //-------------------------------------------------------------------- + RichTextEngine* RichTextEngine::Create() + { + SfxItemPool* pPool = EditEngine::CreatePool(); + pPool->FreezeIdRanges(); + + RichTextEngine* pReturn = new RichTextEngine( pPool ); + OutputDevice* pOutputDevice = pReturn->GetRefDevice(); + MapMode aDeviceMapMode( pOutputDevice->GetMapMode() ); + + pReturn->SetStatusEventHdl( LINK( pReturn, RichTextEngine, EditEngineStatusChanged ) ); + + pPool->SetDefaultMetric( (SfxMapUnit)( aDeviceMapMode.GetMapUnit() ) ); + + // defaults + Font aFont = Application::GetSettings().GetStyleSettings().GetAppFont(); + aFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Times New Roman" ) ) ); + pPool->SetPoolDefaultItem( SvxFontItem( aFont.GetFamily(), aFont.GetName(), String(), aFont.GetPitch(), aFont.GetCharSet(), EE_CHAR_FONTINFO ) ); + + // 12 pt font size + MapMode aPointMapMode( MAP_POINT ); + Size a12PointSize( OutputDevice::LogicToLogic( Size( 12, 0 ), aPointMapMode, aDeviceMapMode ) ); + pPool->SetPoolDefaultItem( SvxFontHeightItem( a12PointSize.Width(), 100, EE_CHAR_FONTHEIGHT ) ); + + // font languages + SvtLinguOptions aLinguOpt; + pPool->SetPoolDefaultItem( SvxLanguageItem( aLinguOpt.nDefaultLanguage, EE_CHAR_LANGUAGE ) ); + pPool->SetPoolDefaultItem( SvxLanguageItem( aLinguOpt.nDefaultLanguage_CJK, EE_CHAR_LANGUAGE_CJK ) ); + pPool->SetPoolDefaultItem( SvxLanguageItem( aLinguOpt.nDefaultLanguage_CTL, EE_CHAR_LANGUAGE_CTL ) ); + + return pReturn; + } + + //-------------------------------------------------------------------- + RichTextEngine* RichTextEngine::Clone() + { + RichTextEngine* pClone( NULL ); + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + EditTextObject* pMyText = CreateTextObject(); + OSL_ENSURE( pMyText, "RichTextEngine::Clone: CreateTextObject returned nonsense!" ); + + pClone = Create(); + + if ( pMyText ) + pClone->SetText( *pMyText ); + delete pMyText; + } + + return pClone; + } + + DBG_NAME(RichTextEngine) + //-------------------------------------------------------------------- + RichTextEngine::RichTextEngine( SfxItemPool* _pPool ) + :EditEngine( _pPool ) + ,m_pEnginePool( _pPool ) + { + DBG_CTOR(RichTextEngine,NULL); + } + + //-------------------------------------------------------------------- + RichTextEngine::~RichTextEngine( ) + { + //delete m_pEnginePool; // must be done after the RichTextEngine was deleted + DBG_DTOR(RichTextEngine,NULL); + } + + //-------------------------------------------------------------------- + void RichTextEngine::registerEngineStatusListener( IEngineStatusListener* _pListener ) + { + OSL_ENSURE( _pListener, "RichTextEngine::registerEngineStatusListener: invalid listener!" ); + if ( _pListener ) + m_aStatusListeners.push_back( _pListener ); + } + + //-------------------------------------------------------------------- + void RichTextEngine::revokeEngineStatusListener( IEngineStatusListener* _pListener ) + { + ::std::vector< IEngineStatusListener* >::iterator aPos = ::std::find_if( + m_aStatusListeners.begin(), + m_aStatusListeners.end(), + ::std::bind2nd( ::std::equal_to< IEngineStatusListener* >( ), _pListener ) + ); + OSL_ENSURE( aPos != m_aStatusListeners.end(), "RichTextEngine::revokeEngineStatusListener: listener not registered!" ); + if ( aPos != m_aStatusListeners.end() ) + m_aStatusListeners.erase( aPos ); + } + + //-------------------------------------------------------------------- + IMPL_LINK( RichTextEngine, EditEngineStatusChanged, EditStatus*, _pStatus ) + { + for ( ::std::vector< IEngineStatusListener* >::const_iterator aLoop = m_aStatusListeners.begin(); + aLoop != m_aStatusListeners.end(); + ++aLoop + ) + (*aLoop)->EditEngineStatusChanged( *_pStatus ); + return 0L; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/richtext/richtextengine.hxx b/forms/source/richtext/richtextengine.hxx new file mode 100644 index 000000000000..c3a1eb36550c --- /dev/null +++ b/forms/source/richtext/richtextengine.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX + +#include <editeng/editeng.hxx> +#include <tools/link.hxx> + +#include <vector> + +class SfxItemPool; +class EditStatus; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= IEngineStatusListener + //==================================================================== + class IEngineStatusListener + { + public: + virtual void EditEngineStatusChanged( const EditStatus& _rStatus ) = 0; + }; + + //==================================================================== + //= RichTextEngine + //==================================================================== + class RichTextEngine : public EditEngine + { + private: + SfxItemPool* m_pEnginePool; + ::std::vector< IEngineStatusListener* > m_aStatusListeners; + + public: + static RichTextEngine* Create(); + RichTextEngine* Clone(); + + ~RichTextEngine( ); + + // for multiplexing the StatusChanged events of the edit engine + void registerEngineStatusListener( IEngineStatusListener* _pListener ); + void revokeEngineStatusListener( IEngineStatusListener* _pListener ); + + inline SfxItemPool* getPool() { return m_pEnginePool; } + + protected: + /** constructs a new RichTextEngine. The instances takes the ownership of the given SfxItemPool + */ + RichTextEngine( SfxItemPool* _pPool ); + + private: + RichTextEngine( ); // never implemented + RichTextEngine( const RichTextEngine& ); // never implemented + RichTextEngine& operator=( const RichTextEngine& ); // never implemented + + private: + DECL_LINK( EditEngineStatusChanged, EditStatus* ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX + diff --git a/forms/source/richtext/richtextimplcontrol.cxx b/forms/source/richtext/richtextimplcontrol.cxx new file mode 100644 index 000000000000..3a82822f6701 --- /dev/null +++ b/forms/source/richtext/richtextimplcontrol.cxx @@ -0,0 +1,680 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "richtextimplcontrol.hxx" +#include "textattributelistener.hxx" +#include "richtextengine.hxx" +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editstat.hxx> +#ifndef _SVX_SVXIDS_HRC +#include <svx/svxids.hrc> +#endif +#include <editeng/scripttypeitem.hxx> + +#include <editeng/editobj.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <vcl/mapunit.hxx> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> + +#include <memory> + +#define EMPTY_PAPER_SIZE 0x7FFFFFFF + +//........................................................................ +namespace frm +{ +//........................................................................ + //==================================================================== + //= RichTextControlImpl + //==================================================================== + //-------------------------------------------------------------------- + RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener ) + :m_pAntiImpl ( _pAntiImpl ) + ,m_pViewport ( NULL ) + ,m_pHScroll ( NULL ) + ,m_pVScroll ( NULL ) + ,m_pScrollCorner ( NULL ) + ,m_pEngine ( _pEngine ) + ,m_pView ( NULL ) + ,m_pTextAttrListener ( _pTextAttrListener ) + ,m_pSelectionListener ( _pSelectionListener ) + ,m_bHasEverBeenShown ( false ) + { + OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" ); + OSL_ENSURE( m_pEngine, "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definately* crash!" ); + + m_pViewport = new RichTextViewPort( m_pAntiImpl ); + m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) ); + m_pViewport->Show(); + + // ensure that both the window and the reference device have the same map unit + MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() ); + m_pAntiImpl->SetMapMode( aRefDeviceMapMode ); + m_pViewport->SetMapMode( aRefDeviceMapMode ); + + m_pView = new EditView( m_pEngine, m_pViewport ); + m_pEngine->InsertView( m_pView ); + m_pViewport->setView( *m_pView ); + + m_pEngine->registerEngineStatusListener( this ); + + { + ULONG nViewControlWord = m_pView->GetControlWord(); + nViewControlWord |= EV_CNTRL_AUTOSCROLL; + m_pView->SetControlWord( nViewControlWord ); + } + + // ensure that it's initially scrolled to the upper left + m_pView->SetVisArea( Rectangle( Point( ), m_pViewport->GetOutputSize() ) ); + + ensureScrollbars(); + + m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) ); + } + + //-------------------------------------------------------------------- + RichTextControlImpl::~RichTextControlImpl( ) + { + m_pEngine->RemoveView( m_pView ); + m_pEngine->revokeEngineStatusListener( this ); + delete m_pView; + delete m_pViewport; + delete m_pHScroll; + delete m_pVScroll; + delete m_pScrollCorner; + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::implUpdateAttribute( AttributeHandlerPool::const_iterator _pHandler ) + { + if ( ( _pHandler->first == SID_ATTR_CHAR_WEIGHT ) + || ( _pHandler->first == SID_ATTR_CHAR_POSTURE ) + || ( _pHandler->first == SID_ATTR_CHAR_FONT ) + || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT ) + ) + { + // these are attributes whose value depends on the current script type. + // I.e., in real, there are *three* items in the ItemSet: One for each script + // type (Latin, Asian, Complex). However, if we have an observer who is interested + // in the state of this attribute, we have to kind of *merge* the three attributes + // to only one. + // This is usefull in case the observer is for instance a toolbox which contains only + // an, e.g., "bold" slot, and thus not interested in the particular script type of the + // current selection. + SvxScriptSetItem aNormalizedSet( (WhichId)_pHandler->first, *m_pView->GetAttribs().GetPool() ); + normalizeScriptDependentAttribute( aNormalizedSet ); + + implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) ); + } + else + implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::updateAttribute( AttributeId _nAttribute ) + { + AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute ); + if ( pHandler != m_aAttributeHandlers.end() ) + implUpdateAttribute( pHandler ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::updateAllAttributes( ) + { + for ( AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin(); + pHandler != m_aAttributeHandlers.end(); + ++pHandler + ) + { + implUpdateAttribute( pHandler ); + } + + // notify changes of the selection, if necessary + if ( m_pSelectionListener && m_pView ) + { + ESelection aCurrentSelection = m_pView->GetSelection(); + if ( !aCurrentSelection.IsEqual( m_aLastKnownSelection ) ) + { + m_aLastKnownSelection = aCurrentSelection; + m_pSelectionListener->onSelectionChanged( m_aLastKnownSelection ); + } + } + } + + //-------------------------------------------------------------------- + AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const + { + StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId ); + if ( aCachedStatePos == m_aLastKnownStates.end() ) + { + OSL_ENSURE( sal_False, "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" ); + return AttributeState( eIndetermined ); + } + return aCachedStatePos->second; + } + + //-------------------------------------------------------------------- + bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, ScriptType _nForScriptType ) + { + // let's see whether we have a handler for this attribute + AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute ); + if ( aHandlerPos != m_aAttributeHandlers.end() ) + { + aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType ); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener ) + { + AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); + if ( aHandlerPos == m_aAttributeHandlers.end() ) + { + ::rtl::Reference< IAttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() ); + OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" ); + if ( !aHandler.is() ) + return; + OSL_POSTCOND( _nAttributeId == aHandler->getAttributeId(), "RichTextControlImpl::enableAttributeNotification: suspicious handler!" ); + + aHandlerPos = m_aAttributeHandlers.insert( AttributeHandlerPool::value_type( _nAttributeId , aHandler ) ).first; + } + + // remember the listener + if ( _pListener ) + m_aAttributeListeners.insert( AttributeListenerPool::value_type( _nAttributeId, _pListener ) ); + + // update (and broadcast) the state of this attribute + updateAttribute( _nAttributeId ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId ) + { + // forget the handler for this attribute + AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); + if ( aHandlerPos != m_aAttributeHandlers.end() ) + m_aAttributeHandlers.erase( aHandlerPos ); + + // as well as the listener + AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId ); + if ( aListenerPos != m_aAttributeListeners.end() ) + m_aAttributeListeners.erase( aListenerPos ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem ) + { + _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), FALSE ); + const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() ); + + WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() ); + if ( pNormalizedItem ) + { + SfxPoolItem* pProperWhich = pNormalizedItem->Clone(); + pProperWhich->SetWhich( nNormalizedWhichId ); + _rScriptSetItem.GetItemSet().Put( *pProperWhich ); + DELETEZ( pProperWhich ); + } + else + _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState ) + { + StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute ); + if ( aCachePos == m_aLastKnownStates.end() ) + { // nothing known about this attribute, yet + m_aLastKnownStates.insert( StateCache::value_type( _nAttribute, _rState ) ); + } + else + { + if ( aCachePos->second == _rState ) + { + // nothing to do + return; + } + aCachePos->second = _rState; + } + + // is there a dedicated listener for this particular attribute? + AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute ); + if ( aListenerPos != m_aAttributeListeners.end( ) ) + aListenerPos->second->onAttributeStateChanged( _nAttribute, _rState ); + + // call our global listener, if there is one + if ( m_pTextAttrListener ) + m_pTextAttrListener->onAttributeStateChanged( _nAttribute, _rState ); + } + + //-------------------------------------------------------------------- + ScriptType RichTextControlImpl::getSelectedScriptType() const + { + ScriptType nScript = m_pView->GetSelectedScriptType(); + if ( !nScript ) + nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() ); + return nScript; + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus ) + { + ULONG nStatusWord( _rStatus.GetStatusWord() ); + if ( ( nStatusWord & EE_STAT_TEXTWIDTHCHANGED ) + || ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) + ) + { + if ( ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) && windowHasAutomaticLineBreak() ) + m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) ); + + updateScrollbars(); + } + + bool bHScroll = 0 != ( nStatusWord & EE_STAT_HSCROLL ); + bool bVScroll = 0 != ( nStatusWord & EE_STAT_VSCROLL ); + + // In case of *no* automatic line breaks, we also need to check for the *range* here. + // Normally, we would do this only after a EE_STAT_TEXTWIDTHCHANGED. However, due to a bug + // in the EditEngine (I believe so) this is not fired when the engine does not have + // the AutoPaperSize bits set. + // So in order to be properly notified, we would need the AutoPaperSize. But, with + // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize, + // then the view does automatic soft line breaks at the paper end - which we definately do + // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll + // anymore in horizontal direction. + // So this is some kind of lose-lose situation ... :( + if ( !windowHasAutomaticLineBreak() && bHScroll ) + { + updateScrollbars(); + return; + } + + if ( bHScroll && m_pHScroll ) + m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() ); + if ( bVScroll && m_pVScroll ) + m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() ); + } + + //-------------------------------------------------------------------- + IMPL_LINK( RichTextControlImpl, OnInvalidateAllAttributes, void*, /*_pNotInterestedIn*/ ) + { + updateAllAttributes(); + return 0L; + } + + //-------------------------------------------------------------------- + IMPL_LINK( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar ) + { + m_pView->Scroll( -_pScrollbar->GetDelta(), 0, RGCHK_PAPERSZ1 ); + return 0L; + } + + //-------------------------------------------------------------------- + IMPL_LINK( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar ) + { + m_pView->Scroll( 0, -_pScrollbar->GetDelta(), RGCHK_PAPERSZ1 ); + return 0L; + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::ensureScrollbars() + { + bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL ); + bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL ); + + if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) ) + // nothing to do + return; + + // create or delete the scrollbars, as necessary + if ( !bNeedVScroll ) + { + delete m_pVScroll; + m_pVScroll = NULL; + } + else + { + m_pVScroll = new ScrollBar( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT ); + m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) ); + m_pVScroll->Show(); + } + + if ( !bNeedHScroll ) + { + delete m_pHScroll; + m_pHScroll = NULL; + } + else + { + m_pHScroll = new ScrollBar( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT ); + m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) ); + m_pHScroll->Show(); + } + + if ( m_pHScroll && m_pVScroll ) + { + delete m_pScrollCorner; + m_pScrollCorner = new ScrollBarBox( m_pAntiImpl ); + m_pScrollCorner->Show(); + } + else + { + delete m_pScrollCorner; + m_pScrollCorner = NULL; + } + + layoutWindow(); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::ensureLineBreakSetting() + { + if ( !windowHasAutomaticLineBreak() ) + m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) ); + + layoutWindow(); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::layoutWindow() + { + if ( !m_bHasEverBeenShown ) + // no need to do anything. Especially, no need to set the paper size on the + // EditEngine to anything .... + return; + + const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings(); + + long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0; + long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0; + + if ( m_pAntiImpl->IsZoom() ) + { + nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth ); + nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight ); + } + + // the overall size we can use + Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() ); + + // the size of the viewport - note that the viewport does *not* occupy all the place + // which is left when subtracting the scrollbar width/height + Size aViewportPlaygroundPixel( aPlaygroundSizePixel ); + aViewportPlaygroundPixel.Width() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) ); + aViewportPlaygroundPixel.Height() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) ); + Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) ); + + const long nOffset = 2; + Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset ); + Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) ); + + // position the viewport + m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel ); + // position the scrollbars + if ( m_pVScroll ) + m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) ); + if ( m_pHScroll ) + m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) ); + if ( m_pScrollCorner ) + m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) ); + + // paper size + if ( windowHasAutomaticLineBreak() ) + m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) ); + + // output area of the view + m_pView->SetOutputArea( Rectangle( Point( ), aViewportSizeLogic ) ); + m_pView->SetVisArea( Rectangle( Point( ), aViewportSizeLogic ) ); + + if ( m_pVScroll ) + { + m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() ); + + // the default height of a text line .... + long nFontHeight = m_pEngine->GetStandardFont(0).GetSize().Height(); + // ... is the scroll size for the vertical scrollbar + m_pVScroll->SetLineSize( nFontHeight ); + // the viewport width, minus one line, is the page scroll size + m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) ); + } + + // the font width + if ( m_pHScroll ) + { + m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() ); + + long nFontWidth = m_pEngine->GetStandardFont(0).GetSize().Width(); + if ( !nFontWidth ) + { + m_pViewport->Push( PUSH_FONT ); + m_pViewport->SetFont( m_pEngine->GetStandardFont(0) ); + nFontWidth = m_pViewport->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "x" ) ) ); + m_pViewport->Pop(); + } + // ... is the scroll size for the horizontal scrollbar + m_pHScroll->SetLineSize( 5 * nFontWidth ); + // the viewport height, minus one character, is the page scroll size + m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) ); + } + + // update range and position of the scrollbars + updateScrollbars(); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::updateScrollbars() + { + if ( m_pVScroll ) + { + long nOverallTextHeight = m_pEngine->GetTextHeight(); + m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) ); + m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() ); + } + + if ( m_pHScroll ) + { + Size aPaperSize( m_pEngine->GetPaperSize() ); + long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width(); + m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) ); + m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() ); + } + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::notifyInitShow() + { + if ( !m_bHasEverBeenShown ) + { + m_bHasEverBeenShown = true; + layoutWindow(); + } + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::notifyStyleChanged() + { + ensureScrollbars(); + ensureLineBreakSetting(); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::notifyZoomChanged() + { + const Fraction& rZoom = m_pAntiImpl->GetZoom(); + + MapMode aMapMode( m_pAntiImpl->GetMapMode() ); + aMapMode.SetScaleX( rZoom ); + aMapMode.SetScaleY( rZoom ); + m_pAntiImpl->SetMapMode( aMapMode ); + + m_pViewport->SetZoom( rZoom ); + m_pViewport->SetMapMode( aMapMode ); + + layoutWindow(); + } + + //-------------------------------------------------------------------- + bool RichTextControlImpl::windowHasAutomaticLineBreak() + { + return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0; + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::SetReadOnly( bool _bReadOnly ) + { + m_pView->SetReadOnly( _bReadOnly ); + } + + //-------------------------------------------------------------------- + bool RichTextControlImpl::IsReadOnly() const + { + return m_pView->IsReadOnly( ); + } + + //-------------------------------------------------------------------- + namespace + { + static void lcl_inflate( Rectangle& _rRect, long _nInflateX, long _nInflateY ) + { + _rRect.Left() -= _nInflateX; + _rRect.Right() += _nInflateX; + _rRect.Top() -= _nInflateY; + _rRect.Bottom() += _nInflateY; + } + } + //-------------------------------------------------------------------- + long RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent ) + { + if ( ( _rEvent.GetCommand() == COMMAND_WHEEL ) + || ( _rEvent.GetCommand() == COMMAND_STARTAUTOSCROLL ) + || ( _rEvent.GetCommand() == COMMAND_AUTOSCROLL ) + ) + { + m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll ); + return 1; + } + return 0; + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, ULONG /*_nFlags*/ ) + { + // need to normalize the map mode of the device - every paint operation on any device needs + // to use the same map mode + _pDev->Push( PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR ); + + // enforce our "normalize map mode" on the device + MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() ); + MapMode aOriginalMapMode( _pDev->GetMapMode() ); + MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() ); + _pDev->SetMapMode( aNormalizedMapMode ); + + // translate coordinates + Point aPos( _rPos ); + Size aSize( _rSize ); + if ( aOriginalMapMode.GetMapUnit() == MAP_PIXEL ) + { + aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode ); + aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode ); + } + else + { + aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode ); + aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode ); + } + + Rectangle aPlayground( aPos, aSize ); + Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) ); + aPlayground.Right() -= aOnePixel.Width(); + aPlayground.Bottom() -= aOnePixel.Height(); + + // background + _pDev->SetLineColor(); + _pDev->DrawRect( aPlayground ); + + // do we need to draw a border? + bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER ); + if ( bBorder ) + _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() ); + else + _pDev->SetLineColor(); + _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() ); + _pDev->DrawRect( aPlayground ); + + if ( bBorder ) + // don't draw the text over the border + lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); + + // leave a space of one pixel between the "surroundings" of the control + // and the content + lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); + lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); + + // actually draw the content + m_pEngine->Draw( _pDev, aPlayground, Point(), TRUE ); + + _pDev->Pop(); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::SetBackgroundColor( ) + { + SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::SetBackgroundColor( const Color& _rColor ) + { + Wallpaper aWallpaper( _rColor ); + m_pAntiImpl->SetBackground( aWallpaper ); + m_pViewport->SetBackground( aWallpaper ); + } + + //-------------------------------------------------------------------- + void RichTextControlImpl::SetHideInactiveSelection( bool _bHide ) + { + m_pViewport->SetHideInactiveSelection( _bHide ); + } + + //-------------------------------------------------------------------- + bool RichTextControlImpl::GetHideInactiveSelection() const + { + return m_pViewport->GetHideInactiveSelection( ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/richtext/richtextimplcontrol.hxx b/forms/source/richtext/richtextimplcontrol.hxx new file mode 100644 index 000000000000..619766bbfc4e --- /dev/null +++ b/forms/source/richtext/richtextimplcontrol.hxx @@ -0,0 +1,196 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTIMPLCONTOL_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTIMPLCONTOL_HXX + +#include "rtattributehandler.hxx" +#include "richtextviewport.hxx" +#include "richtextengine.hxx" +#include <vcl/scrbar.hxx> +#include <editeng/editdata.hxx> + +#include <map> + +class EditView; +class EditStatus; +class Window; +class SvxScriptSetItem; +//........................................................................ +namespace frm +{ +//........................................................................ + + class ITextAttributeListener; + class ITextSelectionListener; + class RichTextViewPort; + //==================================================================== + //= RichTextControlImpl + //==================================================================== + class RichTextControlImpl : public IEngineStatusListener + { + typedef ::std::map< AttributeId, AttributeState > StateCache; + typedef ::std::map< AttributeId, ::rtl::Reference< IAttributeHandler > > AttributeHandlerPool; + typedef ::std::map< AttributeId, ITextAttributeListener* > AttributeListenerPool; + + StateCache m_aLastKnownStates; + AttributeHandlerPool m_aAttributeHandlers; + AttributeListenerPool m_aAttributeListeners; + + ESelection m_aLastKnownSelection; + + Control* m_pAntiImpl; + RichTextViewPort* m_pViewport; + ScrollBar* m_pHScroll; + ScrollBar* m_pVScroll; + ScrollBarBox* m_pScrollCorner; + RichTextEngine* m_pEngine; + EditView* m_pView; + ITextAttributeListener* m_pTextAttrListener; + ITextSelectionListener* m_pSelectionListener; + bool m_bHasEverBeenShown; + + public: + struct GrantAccess { friend class RichTextControl; private: GrantAccess() { } }; + inline EditView* getView( const GrantAccess& ) const { return m_pView; } + inline RichTextEngine* getEngine( const GrantAccess& ) const { return m_pEngine; } + inline Window* getViewport( const GrantAccess& ) const { return m_pViewport; } + + public: + RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, + ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener ); + virtual ~RichTextControlImpl(); + + /** updates the cache with the state of all attribute values from the given set, notifies + the listener if the state changed + */ + void updateAllAttributes( ); + + /** updates the cache with the state of the attribute given by which id, notifies + the listener if the state changed + */ + void updateAttribute( AttributeId _nAttribute ); + + /// enables the callback for a particular attribute + void enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener = NULL ); + + /// disables the change notifications for a particular attribute + void disableAttributeNotification( AttributeId _nAttributeId ); + + /// executes a toggle of the given attribute + bool executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, ScriptType _nForScriptType ); + + /// retrieves the state of the given attribute from the cache + AttributeState getAttributeState( AttributeId _nAttributeId ) const; + + /** normalizes the given item so that the state of script dependent attributes + is correct considering the current script type + + There are some attributes which are script dependent, e.g. the CharPosture. This means + that in real, there are 3 attributes for this, one for every possible script type (latin, + asian, complex). However, to the out world, we behave as if there is only one attribute: + E.g., if the outter world asks for the state of the "CharPosture" attribute, we return + the state of either CharPostureLatin, CharPostureAsian, or CharPostureComplex, depending + on the script type of the current selection. (In real, it may be more complex since + the current selection may contain more than one script type.) + + This method normalizes a script dependent attribute, so that it's state takes into account + the currently selected script type. + */ + void normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem ); + + // gets the script type of the selection in our edit view (with fallback) + ScriptType getSelectedScriptType() const; + + /** re-arranges the view and the scrollbars + */ + void layoutWindow(); + + /** to be called when the style of our window changed + */ + void notifyStyleChanged(); + + /** to be called when the zoom of our window changed + */ + void notifyZoomChanged(); + + /** to be called when the STATE_CHANGE_INITSHOW event arrives + */ + void notifyInitShow(); + + // VCL "overrides" + void SetBackgroundColor( ); + void SetBackgroundColor( const Color& _rColor ); + + void SetReadOnly( bool _bReadOnly ); + bool IsReadOnly() const; + + void SetHideInactiveSelection( bool _bHide ); + bool GetHideInactiveSelection() const; + + /// draws the control onto a given output device + void Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, ULONG _nFlags ); + + /// handles command events arrived at the anti-impl control + long HandleCommand( const CommandEvent& _rEvent ); + + private: + // updates the cache with the state provided by the given attribut handler + void implUpdateAttribute( AttributeHandlerPool::const_iterator _pHandler ); + + // updates the cache with the given state, and calls listeners (if necessary) + void implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState ); + + // updates range and position of our scrollbars + void updateScrollbars(); + + // determines whether automatic (soft) line breaks are ON + bool windowHasAutomaticLineBreak(); + + /// hides or shows our scrollbars, according to the current WinBits of the window + void ensureScrollbars(); + + /// ensures that our "automatic line break" setting matches the current WinBits of the window + void ensureLineBreakSetting(); + + inline bool hasVScrollBar( ) const { return m_pVScroll != NULL; } + inline bool hasHScrollBar( ) const { return m_pHScroll != NULL; } + + // IEngineStatusListener overridables + virtual void EditEngineStatusChanged( const EditStatus& _rStatus ); + + private: + DECL_LINK( OnInvalidateAllAttributes, void* ); + DECL_LINK( OnHScroll, ScrollBar* ); + DECL_LINK( OnVScroll, ScrollBar* ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTIMPLCONTOL_HXX + diff --git a/forms/source/richtext/richtextmodel.cxx b/forms/source/richtext/richtextmodel.cxx new file mode 100644 index 000000000000..46a77c6dd791 --- /dev/null +++ b/forms/source/richtext/richtextmodel.cxx @@ -0,0 +1,638 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTMODEL_CXX +#include "richtextmodel.hxx" +#endif +#include "richtextengine.hxx" +#include "richtextunowrapper.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/LineEndFormat.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/guarding.hxx> +#include <toolkit/awt/vclxdevice.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <editeng/editstat.hxx> +#include <vcl/outdev.hxx> +#include <vcl/svapp.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ORichTextModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ORichTextModel > aRegisterModel; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::style; + + namespace WritingMode2 = ::com::sun::star::text::WritingMode2; + + //==================================================================== + //= ORichTextModel + //==================================================================== + DBG_NAME( ORichTextModel ) + //-------------------------------------------------------------------- + ORichTextModel::ORichTextModel( const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel ( _rxFactory, ::rtl::OUString() ) + ,FontControlModel ( true ) + ,m_pEngine ( RichTextEngine::Create() ) + ,m_bSettingEngineText( false ) + ,m_aModifyListeners ( m_aMutex ) + { + DBG_CTOR( ORichTextModel, NULL ); + m_nClassId = FormComponentType::TEXTFIELD; + + getPropertyDefaultByHandle( PROPERTY_ID_DEFAULTCONTROL ) >>= m_sDefaultControl; + getPropertyDefaultByHandle( PROPERTY_ID_BORDER ) >>= m_nBorder; + getPropertyDefaultByHandle( PROPERTY_ID_ENABLED ) >>= m_bEnabled; + getPropertyDefaultByHandle( PROPERTY_ID_ENABLEVISIBLE ) >>= m_bEnableVisible; + getPropertyDefaultByHandle( PROPERTY_ID_HARDLINEBREAKS ) >>= m_bHardLineBreaks; + getPropertyDefaultByHandle( PROPERTY_ID_HSCROLL ) >>= m_bHScroll; + getPropertyDefaultByHandle( PROPERTY_ID_VSCROLL ) >>= m_bVScroll; + getPropertyDefaultByHandle( PROPERTY_ID_READONLY ) >>= m_bReadonly; + getPropertyDefaultByHandle( PROPERTY_ID_PRINTABLE ) >>= m_bPrintable; + getPropertyDefaultByHandle( PROPERTY_ID_ALIGN ) >>= m_aAlign; + getPropertyDefaultByHandle( PROPERTY_ID_ECHO_CHAR ) >>= m_nEchoChar; + getPropertyDefaultByHandle( PROPERTY_ID_MAXTEXTLEN ) >>= m_nMaxTextLength; + getPropertyDefaultByHandle( PROPERTY_ID_MULTILINE ) >>= m_bMultiLine; + getPropertyDefaultByHandle( PROPERTY_ID_RICH_TEXT ) >>= m_bReallyActAsRichText; + getPropertyDefaultByHandle( PROPERTY_ID_HIDEINACTIVESELECTION ) >>= m_bHideInactiveSelection; + getPropertyDefaultByHandle( PROPERTY_ID_LINEEND_FORMAT ) >>= m_nLineEndFormat; + getPropertyDefaultByHandle( PROPERTY_ID_WRITING_MODE ) >>= m_nTextWritingMode; + getPropertyDefaultByHandle( PROPERTY_ID_CONTEXT_WRITING_MODE ) >>= m_nContextWritingMode; + + implInit(); + } + + //------------------------------------------------------------------ + ORichTextModel::ORichTextModel( const ORichTextModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel ( _pOriginal, _rxFactory, sal_False ) + ,FontControlModel ( _pOriginal ) + ,m_pEngine ( NULL ) + ,m_bSettingEngineText( false ) + ,m_aModifyListeners ( m_aMutex ) + { + DBG_CTOR( ORichTextModel, NULL ); + + m_aTabStop = _pOriginal->m_aTabStop; + m_aBackgroundColor = _pOriginal->m_aBackgroundColor; + m_aBorderColor = _pOriginal->m_aBorderColor; + m_aVerticalAlignment = _pOriginal->m_aVerticalAlignment; + m_sDefaultControl = _pOriginal->m_sDefaultControl; + m_sHelpText = _pOriginal->m_sHelpText; + m_sHelpURL = _pOriginal->m_sHelpURL; + m_nBorder = _pOriginal->m_nBorder; + m_bEnabled = _pOriginal->m_bEnabled; + m_bEnableVisible = _pOriginal->m_bEnableVisible; + m_bHardLineBreaks = _pOriginal->m_bHardLineBreaks; + m_bHScroll = _pOriginal->m_bHScroll; + m_bVScroll = _pOriginal->m_bVScroll; + m_bReadonly = _pOriginal->m_bReadonly; + m_bPrintable = _pOriginal->m_bPrintable; + m_bReallyActAsRichText = _pOriginal->m_bReallyActAsRichText; + m_bHideInactiveSelection = _pOriginal->m_bHideInactiveSelection; + m_nLineEndFormat = _pOriginal->m_nLineEndFormat; + m_nTextWritingMode = _pOriginal->m_nTextWritingMode; + m_nContextWritingMode = _pOriginal->m_nContextWritingMode; + + m_aAlign = _pOriginal->m_aAlign; + m_nEchoChar = _pOriginal->m_nEchoChar; + m_nMaxTextLength = _pOriginal->m_nMaxTextLength; + m_bMultiLine = _pOriginal->m_bMultiLine; + + m_pEngine.reset(_pOriginal->m_pEngine->Clone()); + m_sLastKnownEngineText = m_pEngine->GetText(); + + implInit(); + } + + //------------------------------------------------------------------ + void ORichTextModel::implInit() + { + OSL_ENSURE( m_pEngine.get(), "ORichTextModel::implInit: where's the engine?" ); + if ( m_pEngine.get() ) + { + m_pEngine->SetModifyHdl( LINK( this, ORichTextModel, OnEngineContentModified ) ); + + ULONG nEngineControlWord = m_pEngine->GetControlWord(); + nEngineControlWord = nEngineControlWord & ~EE_CNTRL_AUTOPAGESIZE; + m_pEngine->SetControlWord( nEngineControlWord ); + + VCLXDevice* pUnoRefDevice = new VCLXDevice; + pUnoRefDevice->SetOutputDevice( m_pEngine->GetRefDevice() ); + m_xReferenceDevice = pUnoRefDevice; + } + + implDoAggregation(); + implRegisterProperties(); + } + + //------------------------------------------------------------------ + void ORichTextModel::implDoAggregation() + { + increment( m_refCount ); + + { + m_xAggregate = new ORichTextUnoWrapper( *m_pEngine, this ); + setAggregation( m_xAggregate ); + doSetDelegator(); + } + + decrement( m_refCount ); + } + + //------------------------------------------------------------------ + void ORichTextModel::implRegisterProperties() + { + REGISTER_PROP_2( DEFAULTCONTROL, m_sDefaultControl, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HELPTEXT, m_sHelpText, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HELPURL, m_sHelpURL, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ENABLED, m_bEnabled, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ENABLEVISIBLE, m_bEnableVisible, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( BORDER, m_nBorder, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HARDLINEBREAKS, m_bHardLineBreaks, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HSCROLL, m_bHScroll, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( VSCROLL, m_bVScroll, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( READONLY, m_bReadonly, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( PRINTABLE, m_bPrintable, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( REFERENCE_DEVICE, m_xReferenceDevice, BOUND, TRANSIENT ); + REGISTER_PROP_2( RICH_TEXT, m_bReallyActAsRichText, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HIDEINACTIVESELECTION, m_bHideInactiveSelection, BOUND, MAYBEDEFAULT ); + + REGISTER_VOID_PROP_2( TABSTOP, m_aTabStop, sal_Bool, BOUND, MAYBEDEFAULT ); + REGISTER_VOID_PROP_2( BACKGROUNDCOLOR, m_aBackgroundColor, sal_Int32, BOUND, MAYBEDEFAULT ); + REGISTER_VOID_PROP_2( BORDERCOLOR, m_aBorderColor, sal_Int32, BOUND, MAYBEDEFAULT ); + REGISTER_VOID_PROP_2( VERTICAL_ALIGN, m_aVerticalAlignment, VerticalAlignment, BOUND, MAYBEDEFAULT ); + + // properties which exist only for compatibility with the css.swt.UnoControlEditModel, + // since we replace the default implementation for this service + REGISTER_PROP_2( ECHO_CHAR, m_nEchoChar, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( MAXTEXTLEN, m_nMaxTextLength, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( MULTILINE, m_bMultiLine, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( TEXT, m_sLastKnownEngineText, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( LINEEND_FORMAT, m_nLineEndFormat, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( WRITING_MODE, m_nTextWritingMode, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_3( CONTEXT_WRITING_MODE, m_nContextWritingMode, BOUND, MAYBEDEFAULT, TRANSIENT ); + + REGISTER_VOID_PROP_2( ALIGN, m_aAlign, sal_Int16, BOUND, MAYBEDEFAULT ); + } + + //-------------------------------------------------------------------- + ORichTextModel::~ORichTextModel( ) + { + if ( !OComponentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + if ( m_pEngine.get() ) + { + SfxItemPool* pPool = m_pEngine->getPool(); + m_pEngine.reset(); + SfxItemPool::Free(pPool); + } + + + DBG_DTOR( ORichTextModel, NULL ); + } + + //------------------------------------------------------------------ + Any SAL_CALL ORichTextModel::queryAggregation( const Type& _rType ) throw ( RuntimeException ) + { + Any aReturn = ORichTextModel_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OControlModel::queryAggregation( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextModel, OControlModel, ORichTextModel_BASE ) + + //-------------------------------------------------------------------- + IMPLEMENT_SERVICE_REGISTRATION_8( ORichTextModel, OControlModel, + FRM_SUN_COMPONENT_RICHTEXTCONTROL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextRange" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.CharacterProperties" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.ParagraphProperties" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.CharacterPropertiesAsian" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.CharacterPropertiesComplex" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.ParagraphPropertiesAsian" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.ParagraphPropertiesComplex" ) ) + ) + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( ORichTextModel ) + + //------------------------------------------------------------------------------ + void SAL_CALL ORichTextModel::disposing() + { + m_aModifyListeners.disposeAndClear( EventObject( *this ) ); + OControlModel::disposing(); + } + + //------------------------------------------------------------------------------ + namespace + { + void lcl_removeProperty( Sequence< Property >& _rSeq, const ::rtl::OUString& _rPropertyName ) + { + Property* pLoop = _rSeq.getArray(); + Property* pEnd = _rSeq.getArray() + _rSeq.getLength(); + while ( pLoop != pEnd ) + { + if ( pLoop->Name == _rPropertyName ) + { + ::std::copy( pLoop + 1, pEnd, pLoop ); + _rSeq.realloc( _rSeq.getLength() - 1 ); + break; + } + ++pLoop; + } + } + } + //------------------------------------------------------------------------------ + void ORichTextModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 1, OControlModel ) + DECL_PROP2( TABINDEX, sal_Int16, BOUND, MAYBEDEFAULT ); + END_DESCRIBE_PROPERTIES(); + + // properties which the OPropertyContainerHelper is responsible for + Sequence< Property > aContainedProperties; + describeProperties( aContainedProperties ); + + // properties which the FontControlModel is responsible for + Sequence< Property > aFontProperties; + describeFontRelatedProperties( aFontProperties ); + + _rProps = concatSequences( aContainedProperties, aFontProperties, _rProps ); + } + + //------------------------------------------------------------------------------ + void ORichTextModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const + { + OControlModel::describeAggregateProperties( _rAggregateProps ); + + // our aggregate (the SvxUnoText) declares a FontDescriptor property, as does + // our FormControlFont base class. We remove it from the base class' sequence + // here, and later on care for both instances being in sync + lcl_removeProperty( _rAggregateProps, PROPERTY_FONT ); + + // similar, the WritingMode property is declared in our aggregate, too, but we override + // it, since the aggregate does no proper PropertyState handling. + lcl_removeProperty( _rAggregateProps, PROPERTY_WRITING_MODE ); + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + if ( isRegisteredProperty( _nHandle ) ) + { + OPropertyContainerHelper::getFastPropertyValue( _rValue, _nHandle ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + FontControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + else + { + OControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL ORichTextModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw( IllegalArgumentException ) + { + sal_Bool bModified = sal_False; + + if ( isRegisteredProperty( _nHandle ) ) + { + bModified = OPropertyContainerHelper::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + bModified = FontControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + else + { + bModified = OControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + + return bModified; + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception) + { + if ( isRegisteredProperty( _nHandle ) ) + { + OPropertyContainerHelper::setFastPropertyValue( _nHandle, _rValue ); + + switch ( _nHandle ) + { + case PROPERTY_ID_REFERENCE_DEVICE: + { + #if OSL_DEBUG_LEVEL > 0 + MapMode aOldMapMode = m_pEngine->GetRefDevice()->GetMapMode(); + #endif + + OutputDevice* pRefDevice = VCLUnoHelper::GetOutputDevice( m_xReferenceDevice ); + OSL_ENSURE( pRefDevice, "ORichTextModel::setFastPropertyValue_NoBroadcast: empty reference device?" ); + m_pEngine->SetRefDevice( pRefDevice ); + + #if OSL_DEBUG_LEVEL > 0 + MapMode aNewMapMode = m_pEngine->GetRefDevice()->GetMapMode(); + OSL_ENSURE( aNewMapMode.GetMapUnit() == aOldMapMode.GetMapUnit(), + "ORichTextModel::setFastPropertyValue_NoBroadcast: You should not tamper with the MapUnit of the ref device!" ); + // if this assertion here is triggered, then we would need to adjust all + // items in all text portions in all paragraphs in the attributes of the EditEngine, + // as long as they are MapUnit-dependent. This holds at least for the FontSize. + #endif + } + break; + + case PROPERTY_ID_TEXT: + { + MutexRelease aReleaseMutex( m_aMutex ); + impl_smlock_setEngineText( m_sLastKnownEngineText ); + } + break; + } // switch ( _nHandle ) + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + FontDescriptor aOldFont( getFont() ); + + FontControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + + if ( isFontAggregateProperty( _nHandle ) ) + firePropertyChange( PROPERTY_ID_FONT, makeAny( getFont() ), makeAny( aOldFont ) ); + } + else + { + switch ( _nHandle ) + { + case PROPERTY_ID_WRITING_MODE: + { + // forward to our aggregate, so the EditEngine knows about it + if ( m_xAggregateSet.is() ) + m_xAggregateSet->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WritingMode" ) ), _rValue ); + } + break; + + default: + OControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + break; + } + } + } + + //-------------------------------------------------------------------- + Any ORichTextModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aDefault; + + switch ( _nHandle ) + { + case PROPERTY_ID_WRITING_MODE: + case PROPERTY_ID_CONTEXT_WRITING_MODE: + aDefault <<= WritingMode2::CONTEXT; + break; + + case PROPERTY_ID_LINEEND_FORMAT: + aDefault <<= (sal_Int16)LineEndFormat::LINE_FEED; + break; + + case PROPERTY_ID_ECHO_CHAR: + case PROPERTY_ID_ALIGN: + case PROPERTY_ID_MAXTEXTLEN: + aDefault <<= (sal_Int16)0; + break; + + case PROPERTY_ID_TABSTOP: + case PROPERTY_ID_BACKGROUNDCOLOR: + case PROPERTY_ID_BORDERCOLOR: + case PROPERTY_ID_VERTICAL_ALIGN: + /* void */ + break; + + case PROPERTY_ID_ENABLED: + case PROPERTY_ID_ENABLEVISIBLE: + case PROPERTY_ID_PRINTABLE: + case PROPERTY_ID_HIDEINACTIVESELECTION: + aDefault <<= (sal_Bool)sal_True; + break; + + case PROPERTY_ID_HARDLINEBREAKS: + case PROPERTY_ID_HSCROLL: + case PROPERTY_ID_VSCROLL: + case PROPERTY_ID_READONLY: + case PROPERTY_ID_MULTILINE: + case PROPERTY_ID_RICH_TEXT: + aDefault <<= (sal_Bool)sal_False; + break; + + case PROPERTY_ID_DEFAULTCONTROL: + aDefault <<= (::rtl::OUString)FRM_SUN_CONTROL_RICHTEXTCONTROL; + break; + + case PROPERTY_ID_HELPTEXT: + case PROPERTY_ID_HELPURL: + case PROPERTY_ID_TEXT: + aDefault <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_BORDER: + aDefault <<= (sal_Int16)1; + break; + + default: + if ( isFontRelatedProperty( _nHandle ) ) + aDefault = FontControlModel::getPropertyDefaultByHandle( _nHandle ); + else + aDefault = OControlModel::getPropertyDefaultByHandle( _nHandle ); + } + + return aDefault; + } + + //-------------------------------------------------------------------- + void ORichTextModel::impl_smlock_setEngineText( const ::rtl::OUString& _rText ) + { + if ( m_pEngine.get() ) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + m_bSettingEngineText = true; + m_pEngine->SetText( _rText ); + m_bSettingEngineText = false; + } + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL ORichTextModel::getServiceName() throw ( RuntimeException) + { + return FRM_SUN_COMPONENT_RICHTEXTCONTROL; + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextModel::write(const Reference< XObjectOutputStream >& _rxOutStream) throw ( IOException, RuntimeException) + { + OControlModel::write( _rxOutStream ); + // TODO: place your code here + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextModel::read(const Reference< XObjectInputStream >& _rxInStream) throw ( IOException, RuntimeException) + { + OControlModel::read( _rxInStream ); + // TODO: place your code here + } + + //-------------------------------------------------------------------- + RichTextEngine* ORichTextModel::getEditEngine( const Reference< XControlModel >& _rxModel ) + { + RichTextEngine* pEngine = NULL; + + Reference< XUnoTunnel > xTunnel( _rxModel, UNO_QUERY ); + OSL_ENSURE( xTunnel.is(), "ORichTextModel::getEditEngine: invalid model!" ); + if ( xTunnel.is() ) + { + try + { + pEngine = reinterpret_cast< RichTextEngine* >( xTunnel->getSomething( getEditEngineTunnelId() ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ORichTextModel::getEditEngine: caught an exception!" ); + } + } + return pEngine; + } + + //-------------------------------------------------------------------- + Sequence< sal_Int8 > ORichTextModel::getEditEngineTunnelId() + { + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); + } + + //-------------------------------------------------------------------- + IMPL_LINK( ORichTextModel, OnEngineContentModified, void*, /*_pNotInterestedIn*/ ) + { + if ( !m_bSettingEngineText ) + { + m_aModifyListeners.notifyEach( &XModifyListener::modified, EventObject( *this ) ); + + potentialTextChange(); + // is this a good idea? It may become expensive in case of larger texts, + // and this method here is called for every single changed character ... + // On the other hand, the API *requires* us to notify changes in the "Text" + // property immediately ... + } + + return 0L; + } + + //-------------------------------------------------------------------- + sal_Int64 SAL_CALL ORichTextModel::getSomething( const Sequence< sal_Int8 >& _rId ) throw (RuntimeException) + { + Sequence< sal_Int8 > aEditEngineAccessId( getEditEngineTunnelId() ); + if ( ( _rId.getLength() == aEditEngineAccessId.getLength() ) + && ( 0 == rtl_compareMemory( aEditEngineAccessId.getConstArray(), _rId.getConstArray(), _rId.getLength() ) ) + ) + return reinterpret_cast< sal_Int64 >( m_pEngine.get() ); + + Reference< XUnoTunnel > xAggTunnel; + if ( query_aggregation( m_xAggregate, xAggTunnel ) ) + return xAggTunnel->getSomething( _rId ); + + return 0; + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextModel::addModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException) + { + m_aModifyListeners.addInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL ORichTextModel::removeModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException) + { + m_aModifyListeners.removeInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void ORichTextModel::potentialTextChange( ) + { + ::rtl::OUString sCurrentEngineText; + if ( m_pEngine.get() ) + sCurrentEngineText = m_pEngine->GetText(); + + if ( sCurrentEngineText != m_sLastKnownEngineText ) + { + sal_Int32 nHandle = PROPERTY_ID_TEXT; + Any aOldValue; aOldValue <<= m_sLastKnownEngineText; + Any aNewValue; aNewValue <<= sCurrentEngineText; + fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False ); + + m_sLastKnownEngineText = sCurrentEngineText; + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/richtext/richtextmodel.hxx b/forms/source/richtext/richtextmodel.hxx new file mode 100644 index 000000000000..94e5523fb001 --- /dev/null +++ b/forms/source/richtext/richtextmodel.hxx @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTMODEL_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTMODEL_HXX + +#include "FormComponent.hxx" +#include "frm_module.hxx" +#include "formcontrolfont.hxx" +#include "richtextunowrapper.hxx" +#include <comphelper/propertycontainerhelper.hxx> +#include <comphelper/listenernotification.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/implbase3.hxx> +#include <tools/link.hxx> +#include <memory> + +class EditEngine; +//........................................................................ +namespace frm +{ +//........................................................................ + + class RichTextEngine; + //==================================================================== + //= ORichTextModel + //==================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::awt::XControlModel + , ::com::sun::star::lang::XUnoTunnel + , ::com::sun::star::util::XModifyBroadcaster + > ORichTextModel_BASE; + + class ORichTextModel + :public OControlModel + ,public FontControlModel + ,public IEngineTextChangeListener + ,public ::comphelper::OPropertyContainerHelper + ,public ORichTextModel_BASE + { + private: + // <properties> + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice > + m_xReferenceDevice; + ::com::sun::star::uno::Any m_aTabStop; + ::com::sun::star::uno::Any m_aBackgroundColor; + ::com::sun::star::uno::Any m_aBorderColor; + ::com::sun::star::uno::Any m_aVerticalAlignment; + ::rtl::OUString m_sDefaultControl; + ::rtl::OUString m_sHelpText; + ::rtl::OUString m_sHelpURL; + ::rtl::OUString m_sLastKnownEngineText; + sal_Int16 m_nLineEndFormat; + sal_Int16 m_nTextWritingMode; + sal_Int16 m_nContextWritingMode; + sal_Int16 m_nBorder; + sal_Bool m_bEnabled; + sal_Bool m_bEnableVisible; + sal_Bool m_bHardLineBreaks; + sal_Bool m_bHScroll; + sal_Bool m_bVScroll; + sal_Bool m_bReadonly; + sal_Bool m_bPrintable; + sal_Bool m_bReallyActAsRichText; // despite the class name, the RichTextControl later on + // will create "ordinary" text peers depending on this property + sal_Bool m_bHideInactiveSelection; + // </properties> + + // <properties_for_awt_edit_compatibility> + ::com::sun::star::uno::Any m_aAlign; + sal_Int16 m_nEchoChar; + sal_Int16 m_nMaxTextLength; + sal_Bool m_bMultiLine; + // </properties_for_awt_edit_compatibility> + + ::std::auto_ptr<RichTextEngine> + m_pEngine; + bool m_bSettingEngineText; + + ::cppu::OInterfaceContainerHelper + m_aModifyListeners; + + public: + static RichTextEngine* getEditEngine( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& _rxModel ); + + protected: + DECLARE_DEFAULT_LEAF_XTOR( ORichTextModel ); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS( ORichTextModel, OControlModel ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + DECLARE_SERVICE_REGISTRATION( ORichTextModel ) + + // XPersistObject + DECLARE_XPERSISTOBJECT() + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XCloneable + DECLARE_XCLONEABLE(); + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw (::com::sun::star::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // IEngineTextChangeListener + virtual void potentialTextChange( ); + + private: + void implInit(); + void implDoAggregation(); + void implRegisterProperties(); + + /** propagates a new text to the EditEngine + + This method needs to lock the global solar mutex, so our own mutex must not + be locked when calling. + + @precond + our mutex is not locked + */ + void impl_smlock_setEngineText( const ::rtl::OUString& _rText ); + + DECL_LINK( OnEngineContentModified, void* ); + + static ::com::sun::star::uno::Sequence< sal_Int8 > getEditEngineTunnelId(); + + private: + ORichTextModel(); // never implemented + ORichTextModel( const ORichTextModel& ); // never implemented + ORichTextModel& operator=( const ORichTextModel& ); // never implemented + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTMODEL_HXX + diff --git a/forms/source/richtext/richtextunowrapper.cxx b/forms/source/richtext/richtextunowrapper.cxx new file mode 100644 index 000000000000..1d3f98467aa7 --- /dev/null +++ b/forms/source/richtext/richtextunowrapper.cxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "richtextunowrapper.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XNameContainer.hpp> +/** === end UNO includes === **/ +#include <editeng/unofored.hxx> +#include <editeng/editview.hxx> +#include <editeng/unoipset.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdobj.hxx> +#include <editeng/unoprnms.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + + //==================================================================== + namespace + { + const SvxItemPropertySet* getTextEnginePropertySet() + { + // Propertymap fuer einen Outliner Text + static const SfxItemPropertyMapEntry aTextEnginePropertyMap[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_FONT_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + { MAP_CHAR_LEN("TextUserDefinedAttributes"), EE_CHAR_XMLATTRIBS, &::getCppuType( static_cast< const Reference< XNameContainer >* >( NULL ) ), 0, 0 }, + { MAP_CHAR_LEN("ParaUserDefinedAttributes"), EE_PARA_XMLATTRIBS, &::getCppuType( static_cast< const Reference< XNameContainer >* >( NULL ) ), 0, 0 }, + { NULL, 0, 0, NULL, 0, 0 } + }; + static SvxItemPropertySet aTextEnginePropertySet( aTextEnginePropertyMap, SdrObject::GetGlobalDrawObjectItemPool() ); + return &aTextEnginePropertySet; + } + } + + //==================================================================== + //= ORichTextUnoWrapper + //==================================================================== + //-------------------------------------------------------------------- + ORichTextUnoWrapper::ORichTextUnoWrapper( EditEngine& _rEngine, IEngineTextChangeListener* _pTextChangeListener ) + :SvxUnoText( getTextEnginePropertySet() ) + { + SetEditSource( new RichTextEditSource( _rEngine, _pTextChangeListener ) ); + } + + //-------------------------------------------------------------------- + ORichTextUnoWrapper::~ORichTextUnoWrapper() throw() + { + } + + //==================================================================== + //= RichTextEditSource + //==================================================================== + //-------------------------------------------------------------------- + RichTextEditSource::RichTextEditSource( EditEngine& _rEngine, IEngineTextChangeListener* _pTextChangeListener ) + :m_rEngine ( _rEngine ) + ,m_pTextForwarder ( new SvxEditEngineForwarder( _rEngine ) ) + ,m_pTextChangeListener ( _pTextChangeListener ) + { + } + + //-------------------------------------------------------------------- + RichTextEditSource::~RichTextEditSource() + { + delete m_pTextForwarder; + } + + //-------------------------------------------------------------------- + SvxEditSource* RichTextEditSource::Clone() const + { + return new RichTextEditSource( m_rEngine, m_pTextChangeListener ); + } + + //-------------------------------------------------------------------- + SvxTextForwarder* RichTextEditSource::GetTextForwarder() + { + return m_pTextForwarder; + } + + //-------------------------------------------------------------------- + void RichTextEditSource::UpdateData() + { + // this means that the content of the EditEngine changed via the UNO API + // to reflect this in the views, we need to update them + USHORT viewCount = m_rEngine.GetViewCount(); + for ( USHORT view = 0; view < viewCount; ++view ) + { + EditView* pView = m_rEngine.GetView( view ); + if ( pView ) + pView->ForceUpdate(); + } + + if ( m_pTextChangeListener ) + m_pTextChangeListener->potentialTextChange(); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/richtext/richtextunowrapper.hxx b/forms/source/richtext/richtextunowrapper.hxx new file mode 100644 index 000000000000..a461eb4d507e --- /dev/null +++ b/forms/source/richtext/richtextunowrapper.hxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTUNOWRAPPER_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTUNOWRAPPER_HXX + +#include <editeng/unotext.hxx> +#include <editeng/unoedsrc.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= IEngineTextChangeListener + //==================================================================== + class IEngineTextChangeListener + { + public: + virtual void potentialTextChange( ) = 0; + }; + + //==================================================================== + //= ORichTextUnoWrapper + //==================================================================== + class ORichTextUnoWrapper : public SvxUnoText + { + public: + ORichTextUnoWrapper( EditEngine& _rEngine, IEngineTextChangeListener* _pTextChangeListener ); + + protected: + ~ORichTextUnoWrapper() throw(); + + + private: + ORichTextUnoWrapper(); // never implemented + ORichTextUnoWrapper( const ORichTextUnoWrapper& ); // never implemented + ORichTextUnoWrapper& operator=( const ORichTextUnoWrapper& ); // never implemented + }; + + //==================================================================== + //= RichTextEditSource + //==================================================================== + class RichTextEditSource : public SvxEditSource + { + private: + EditEngine& m_rEngine; + SvxTextForwarder* m_pTextForwarder; + IEngineTextChangeListener* m_pTextChangeListener; + + public: + RichTextEditSource( EditEngine& _rEngine, IEngineTextChangeListener* _pTextChangeListener ); + + // SvxEditSource + virtual SvxEditSource* Clone() const; + virtual SvxTextForwarder* GetTextForwarder(); + virtual void UpdateData(); + + protected: + ~RichTextEditSource(); + + private: + RichTextEditSource( ); // never implemented + RichTextEditSource( const RichTextEditSource& _rSource ); // never implemented + RichTextEditSource& operator=( const RichTextEditSource& ); // never implemented + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTUNOWRAPPER_HXX + diff --git a/forms/source/richtext/richtextvclcontrol.cxx b/forms/source/richtext/richtextvclcontrol.cxx new file mode 100644 index 000000000000..48d458288d40 --- /dev/null +++ b/forms/source/richtext/richtextvclcontrol.cxx @@ -0,0 +1,392 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "richtextvclcontrol.hxx" +#include "richtextimplcontrol.hxx" +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <svl/languageoptions.hxx> +#if OSL_DEBUG_LEVEL > 0 + #ifndef _TOOLS_TEMPFILE_HXX + #include <tools/tempfile.hxx> + #endif + #ifndef _UNTOOLS_UCBSTREAMHELPER_HXX + #include <unotools/ucbstreamhelper.hxx> + #endif + #ifndef _SV_MSGBOX_HXX + #include <vcl/msgbox.hxx> + #endif + #ifndef _FILEDLGHELPER_HXX + #include <sfx2/filedlghelper.hxx> + #endif + #ifndef _URLOBJ_HXX + #include <tools/urlobj.hxx> + #endif + #include "com/sun/star/ui/dialogs/TemplateDescription.hpp" +#endif +#include <editeng/scripttypeitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/editids.hrc> +#include <svx/svxids.hrc> +#include <memory> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::awt; + + //==================================================================== + //= RichTextControl + //==================================================================== + //-------------------------------------------------------------------- + RichTextControl::RichTextControl( RichTextEngine* _pEngine, Window* _pParent, WinBits _nStyle, + ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener ) + :Control( _pParent, implInitStyle( _nStyle ) ) + ,m_pImpl( NULL ) + { + implInit( _pEngine, _pTextAttribListener, _pSelectionListener ); + } + + //-------------------------------------------------------------------- + void RichTextControl::implInit( RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener ) + { + m_pImpl = new RichTextControlImpl( this, _pEngine, _pTextAttribListener, _pSelectionListener ); + SetCompoundControl( TRUE ); + } + + //-------------------------------------------------------------------- + RichTextControl::~RichTextControl( ) + { + delete m_pImpl; + } + + //-------------------------------------------------------------------- + AttributeState RichTextControl::getState( AttributeId _nAttributeId ) const + { + return m_pImpl->getAttributeState( _nAttributeId ); + } + + //-------------------------------------------------------------------- + void RichTextControl::executeAttribute( AttributeId _nAttributeId, const SfxPoolItem* _pArgument ) + { + SfxItemSet aToApplyAttributes( getView().GetEmptyItemSet() ); + if ( !m_pImpl->executeAttribute( getView().GetAttribs(), aToApplyAttributes, _nAttributeId, _pArgument, m_pImpl->getSelectedScriptType() ) ) + { + OSL_ENSURE( sal_False, "RichTextControl::executeAttribute: cannot handle the given attribute!" ); + return; + } + + applyAttributes( aToApplyAttributes ); + } + + //-------------------------------------------------------------------- + void RichTextControl::applyAttributes( const SfxItemSet& _rAttributesToApply ) + { + // apply + if ( HasChildPathFocus() ) + getView().HideCursor(); + + BOOL bOldUpdateMode = getEngine().GetUpdateMode(); // TODO: guard? + getEngine().SetUpdateMode( FALSE ); + + getView().SetAttribs( _rAttributesToApply ); + + getEngine().SetUpdateMode( bOldUpdateMode ); + getView().Invalidate(); + + if ( HasChildPathFocus() ) + getView().ShowCursor(); + + m_pImpl->updateAllAttributes(); + // TODO: maybe we should have a list of attributes which need to be updated + // (the handler for the just executed attribute should know) + } + + //-------------------------------------------------------------------- + void RichTextControl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener ) + { + m_pImpl->enableAttributeNotification( _nAttributeId, _pListener ); + } + + //-------------------------------------------------------------------- + void RichTextControl::disableAttributeNotification( AttributeId _nAttributeId ) + { + m_pImpl->disableAttributeNotification( _nAttributeId ); + } + + //-------------------------------------------------------------------- + bool RichTextControl::isMappableSlot( SfxSlotId _nSlotId ) + { + switch ( _nSlotId ) + { + case SID_ATTR_PARA_ADJUST_LEFT: + case SID_ATTR_PARA_ADJUST_CENTER: + case SID_ATTR_PARA_ADJUST_RIGHT: + case SID_ATTR_PARA_ADJUST_BLOCK: + case SID_SET_SUPER_SCRIPT: + case SID_SET_SUB_SCRIPT: + case SID_ATTR_PARA_LINESPACE_10: + case SID_ATTR_PARA_LINESPACE_15: + case SID_ATTR_PARA_LINESPACE_20: + case SID_ATTR_PARA_LEFT_TO_RIGHT: + case SID_ATTR_PARA_RIGHT_TO_LEFT: + case SID_TEXTDIRECTION_TOP_TO_BOTTOM: + case SID_TEXTDIRECTION_LEFT_TO_RIGHT: + case SID_ATTR_CHAR_LATIN_FONT: + case SID_ATTR_CHAR_LATIN_FONTHEIGHT: + case SID_ATTR_CHAR_LATIN_LANGUAGE: + case SID_ATTR_CHAR_LATIN_POSTURE: + case SID_ATTR_CHAR_LATIN_WEIGHT: + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void RichTextControl::Resize() + { + m_pImpl->layoutWindow(); + Invalidate(); + } + + //-------------------------------------------------------------------- + void RichTextControl::GetFocus() + { + getViewport().GrabFocus(); + } + + //-------------------------------------------------------------------- + WinBits RichTextControl::implInitStyle( WinBits nStyle ) + { + if ( !( nStyle & WB_NOTABSTOP ) ) + nStyle |= WB_TABSTOP; + return nStyle; + } + + //-------------------------------------------------------------------- + void RichTextControl::StateChanged( StateChangedType _nStateChange ) + { + if ( _nStateChange == STATE_CHANGE_STYLE ) + { + SetStyle( implInitStyle( GetStyle() ) ); + m_pImpl->notifyStyleChanged(); + } + else if ( _nStateChange == STATE_CHANGE_ZOOM ) + { + m_pImpl->notifyZoomChanged(); + } + else if ( _nStateChange == STATE_CHANGE_INITSHOW ) + { + m_pImpl->notifyInitShow(); + } + Control::StateChanged( _nStateChange ); + } + + //-------------------------------------------------------------------- + long RichTextControl::PreNotify( NotifyEvent& _rNEvt ) + { + if ( IsWindowOrChild( _rNEvt.GetWindow() ) ) + { + if ( EVENT_KEYINPUT == _rNEvt.GetType() ) + { + const ::KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent(); + + sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode(); + sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift(); + sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1(); + sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2(); + if ( ( KEY_TAB == nCode ) && bCtrl && !bAlt ) + { + // Ctrl-Tab is used to step out of the control + // -> build a new key event without the Ctrl-key, and let the very base class handle it + KeyCode aNewCode( KEY_TAB, bShift, sal_False, sal_False, sal_False ); + ::KeyEvent aNewEvent( pKeyEvent->GetCharCode(), aNewCode ); + Control::KeyInput( aNewEvent ); + return 1; // handled + } + +#if OSL_DEBUG_LEVEL > 0 + if ( ( ( KEY_F12 == nCode ) + || ( KEY_F11 == nCode ) + ) + && bCtrl + && bAlt + ) + { + bool bLoad = KEY_F11 == nCode; + struct + { + const sal_Char* pDescription; + const sal_Char* pExtension; + EETextFormat eFormat; + } aExportFormats[] = + { + { "OASIS OpenDocument (*.xml)", "*.xml", EE_FORMAT_XML }, + { "HyperText Markup Language (*.html)", "*.html", EE_FORMAT_HTML }, + { "Rich Text format (*.rtf)", "*.rtf", EE_FORMAT_RTF }, + { "Text (*.txt)", "*.txt", EE_FORMAT_TEXT } + }; + + ::sfx2::FileDialogHelper aFP( bLoad ? com::sun::star::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE : com::sun::star::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, 0, this ); + + for ( size_t i = 0; i < sizeof( aExportFormats ) / sizeof( aExportFormats[ 0 ] ); ++i ) + { + aFP.AddFilter( + String::CreateFromAscii( aExportFormats[i].pDescription ), + String::CreateFromAscii( aExportFormats[i].pExtension ) ); + } + ErrCode nResult = aFP.Execute(); + if ( nResult == 0 ) + { + String sFileName = aFP.GetPath(); + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( + sFileName, ( bLoad ? STREAM_READ : STREAM_WRITE | STREAM_TRUNC ) | STREAM_SHARE_DENYALL + ); + if ( pStream ) + { + EETextFormat eFormat = EE_FORMAT_XML; + String sFilter = aFP.GetCurrentFilter(); + for ( size_t i = 0; i < sizeof( aExportFormats ) / sizeof( aExportFormats[ 0 ] ); ++i ) + { + if ( sFilter.EqualsAscii( aExportFormats[i].pDescription ) ) + { + eFormat = aExportFormats[i].eFormat; + break; + } + } + if ( bLoad ) + { + INetURLObject aURL( sFileName ); + aURL.removeSegment(); + getEngine().Read( *pStream, aURL.GetMainURL( INetURLObject::NO_DECODE ), eFormat ); + } + else + { + getEngine().Write( *pStream, eFormat ); + } + } + DELETEZ( pStream ); + } + return 1; // handled + } +#endif + } + } + return Control::PreNotify( _rNEvt ); + } + + //-------------------------------------------------------------------- + long RichTextControl::Notify( NotifyEvent& _rNEvt ) + { + long nDone = 0; + if ( _rNEvt.GetType() == EVENT_COMMAND ) + { + const CommandEvent& rEvent = *_rNEvt.GetCommandEvent(); + nDone = m_pImpl->HandleCommand( rEvent ); + } + return nDone ? nDone : Control::Notify( _rNEvt ); + } + + //-------------------------------------------------------------------- + void RichTextControl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, ULONG _nFlags ) + { + m_pImpl->Draw( _pDev, _rPos, _rSize, _nFlags ); + } + + //-------------------------------------------------------------------- + EditView& RichTextControl::getView() + { + return *m_pImpl->getView( RichTextControlImpl::GrantAccess() ); + } + + //-------------------------------------------------------------------- + const EditView& RichTextControl::getView() const + { + return *m_pImpl->getView( RichTextControlImpl::GrantAccess() ); + } + + //-------------------------------------------------------------------- + EditEngine& RichTextControl::getEngine() const + { + return *m_pImpl->getEngine( RichTextControlImpl::GrantAccess() ); + } + + //-------------------------------------------------------------------- + Window& RichTextControl::getViewport() const + { + return *m_pImpl->getViewport( RichTextControlImpl::GrantAccess() ); + } + + //-------------------------------------------------------------------- + void RichTextControl::SetReadOnly( bool _bReadOnly ) + { + m_pImpl->SetReadOnly( _bReadOnly ); + } + + //-------------------------------------------------------------------- + bool RichTextControl::IsReadOnly() const + { + return m_pImpl->IsReadOnly(); + } + + //-------------------------------------------------------------------- + void RichTextControl::SetBackgroundColor( ) + { + m_pImpl->SetBackgroundColor( ); + } + + //-------------------------------------------------------------------- + void RichTextControl::SetBackgroundColor( const Color& _rColor ) + { + m_pImpl->SetBackgroundColor( _rColor ); + } + + //-------------------------------------------------------------------- + void RichTextControl::SetHideInactiveSelection( bool _bHide ) + { + m_pImpl->SetHideInactiveSelection( _bHide ); + } + + //-------------------------------------------------------------------- + bool RichTextControl::GetHideInactiveSelection() const + { + return m_pImpl->GetHideInactiveSelection( ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + + diff --git a/forms/source/richtext/richtextvclcontrol.hxx b/forms/source/richtext/richtextvclcontrol.hxx new file mode 100644 index 000000000000..54f59569984f --- /dev/null +++ b/forms/source/richtext/richtextvclcontrol.hxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTVCLCONTROL_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTVCLCONTROL_HXX + +#include <vcl/dialog.hxx> +#include <vcl/fixed.hxx> +#ifndef _SV_BUTTON_HXX +#include <vcl/button.hxx> +#endif +#include <vcl/toolbox.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include "rtattributes.hxx" +#include "textattributelistener.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +class EditView; +class EditEngine; +class SfxItemSet; +//........................................................................ +namespace frm +{ +//........................................................................ + + class RichTextControlImpl; + class RichTextEngine; + //==================================================================== + //= RichTextControl + //==================================================================== + class RichTextControl : public Control, public IMultiAttributeDispatcher + { + private: + RichTextControlImpl* m_pImpl; + + public: + RichTextControl( + RichTextEngine* _pEngine, + Window* _pParent, + WinBits _nStyle, + ITextAttributeListener* _pTextAttribListener, + ITextSelectionListener* _pSelectionListener + ); + + ~RichTextControl( ); + + /* enables the change notifications for a particular attribute + + If you want to be notified of any changes in the state of an attribute, you need to call enableAttributeNotification. + + If you provide a dedicated listener for this attribute, this listener is called for every change in the state of + the attribute. + + No matter whether you provide such a dedicated listener, the "global" listener which you specified + in the constructor of the control is also called for all changes in the attribute state. + + If you previously already enabled the notification for this attribute, and specified a different listener, + then the previous listener will be replaced with the new listener, provided the latter is not <NULL/>. + */ + void enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener = NULL ); + + /** disables the change notifications for a particular attribute + + If there was a listener dedicated to this attribute, it will not be referenced and used anymore + after this method had been called + */ + void disableAttributeNotification( AttributeId _nAttributeId ); + + /** determines whether a given slot can be mapped to an aspect of an attribute of the EditEngine + + E.g. SID_ATTR_PARA_ADJUST_LEFT can, though it's not part of the EditEngine pool, be mapped + to the SID_ATTR_PARA_ADJUST slot, which in fact *is* usable with the EditEngine. + */ + static bool isMappableSlot( SfxSlotId _nSlotId ); + + // IMultiAttributeDispatcher + virtual AttributeState getState( AttributeId _nAttributeId ) const; + virtual void executeAttribute( AttributeId _nAttributeId, const SfxPoolItem* _pArgument ); + + void SetBackgroundColor( ); + void SetBackgroundColor( const Color& _rColor ); + + void SetReadOnly( bool _bReadOnly ); + bool IsReadOnly() const; + + void SetHideInactiveSelection( bool _bHide ); + bool GetHideInactiveSelection() const; + + const EditView& getView() const; + EditView& getView(); + + // Window overridables + virtual void Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, ULONG _nFlags ); + + protected: + // Window overridables + virtual void Resize(); + virtual void GetFocus(); + virtual void StateChanged( StateChangedType nStateChange ); + virtual long PreNotify( NotifyEvent& _rNEvt ); + virtual long Notify( NotifyEvent& _rNEvt ); + + private: + void applyAttributes( const SfxItemSet& _rAttributesToApply ); + void implInit( RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener ); + static WinBits implInitStyle( WinBits nStyle ); + + private: + EditEngine& getEngine() const; + Window& getViewport() const; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTVCLCONTROL_HXX + diff --git a/forms/source/richtext/richtextviewport.cxx b/forms/source/richtext/richtextviewport.cxx new file mode 100644 index 000000000000..ffeda61e6b0c --- /dev/null +++ b/forms/source/richtext/richtextviewport.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "richtextviewport.hxx" +#include <editeng/editview.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= RichTextViewPort + //==================================================================== + //-------------------------------------------------------------------- + RichTextViewPort::RichTextViewPort( Window* _pParent ) + :Control ( _pParent ) + ,m_bHideInactiveSelection( true ) + { + } + + //-------------------------------------------------------------------- + void RichTextViewPort::setView( EditView& _rView ) + { + m_pView = &_rView; + SetPointer( _rView.GetPointer() ); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::Paint( const Rectangle& _rRect ) + { + m_pView->Paint( _rRect ); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::GetFocus() + { + Control::GetFocus(); + m_pView->SetSelectionMode( EE_SELMODE_STD ); + m_pView->ShowCursor( TRUE ); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::LoseFocus() + { + m_pView->HideCursor(); + m_pView->SetSelectionMode( m_bHideInactiveSelection ? EE_SELMODE_HIDDEN : EE_SELMODE_STD ); + Control::LoseFocus(); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::KeyInput( const KeyEvent& _rKEvt ) + { + if ( !m_pView->PostKeyEvent( _rKEvt ) ) + Control::KeyInput( _rKEvt ); + else + implInvalidateAttributes(); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::MouseMove( const MouseEvent& _rMEvt ) + { + Control::MouseMove( _rMEvt ); + m_pView->MouseMove( _rMEvt ); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::MouseButtonDown( const MouseEvent& _rMEvt ) + { + Control::MouseButtonDown( _rMEvt ); + m_pView->MouseButtonDown( _rMEvt ); + GrabFocus(); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::MouseButtonUp( const MouseEvent& _rMEvt ) + { + Control::MouseButtonUp( _rMEvt ); + m_pView->MouseButtonUp( _rMEvt ); + implInvalidateAttributes(); + } + + //-------------------------------------------------------------------- + void RichTextViewPort::SetHideInactiveSelection( bool _bHide ) + { + if ( m_bHideInactiveSelection == _bHide ) + return; + m_bHideInactiveSelection = _bHide; + if ( !HasFocus() ) + m_pView->SetSelectionMode( m_bHideInactiveSelection ? EE_SELMODE_HIDDEN : EE_SELMODE_STD ); + } + + //-------------------------------------------------------------------- + bool RichTextViewPort::GetHideInactiveSelection() const + { + return m_bHideInactiveSelection; + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/richtext/richtextviewport.hxx b/forms/source/richtext/richtextviewport.hxx new file mode 100644 index 000000000000..70ae75a346f6 --- /dev/null +++ b/forms/source/richtext/richtextviewport.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTVIEWPORT_HXX +#define FORMS_SOURCE_RICHTEXT_RICHTEXTVIEWPORT_HXX + +#include <vcl/ctrl.hxx> + +class EditView; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= RichTextViewPort + //==================================================================== + class RichTextViewPort : public Control + { + private: + EditView* m_pView; + Link m_aInvalidationHandler; + bool m_bHideInactiveSelection; + + public: + RichTextViewPort( Window* _pParent ); + + void setView( EditView& _rView ); + + inline void setAttributeInvalidationHandler( const Link& _rHandler ) { m_aInvalidationHandler = _rHandler; } + + void SetHideInactiveSelection( bool _bHide ); + bool GetHideInactiveSelection() const; + + protected: + virtual void Paint( const Rectangle& rRect ); + virtual void GetFocus(); + virtual void LoseFocus(); + virtual void KeyInput( const KeyEvent& _rKEvt ); + virtual void MouseMove( const MouseEvent& _rMEvt ); + virtual void MouseButtonDown( const MouseEvent& _rMEvt ); + virtual void MouseButtonUp( const MouseEvent& _rMEvt ); + + private: + inline void implInvalidateAttributes() const + { + if ( m_aInvalidationHandler.IsSet() ) + m_aInvalidationHandler.Call( NULL ); + } + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTVIEWPORT_HXX + diff --git a/forms/source/richtext/rtattributehandler.cxx b/forms/source/richtext/rtattributehandler.cxx new file mode 100644 index 000000000000..c19fe516beb2 --- /dev/null +++ b/forms/source/richtext/rtattributehandler.cxx @@ -0,0 +1,532 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "rtattributehandler.hxx" + +#ifndef _SVX_SVXIDS_HRC +#include <svx/svxids.hrc> +#endif +#include <editeng/eeitem.hxx> +#include <svl/itemset.hxx> +#include <svl/itempool.hxx> +#include <vcl/mapunit.hxx> +#include <vcl/mapmod.hxx> +#include <vcl/outdev.hxx> + +#define ITEMID_ADJUST EE_PARA_JUST +#include <editeng/adjitem.hxx> +#define ITEMID_WEIGHT EE_CHAR_WEIGHT +#include <editeng/wghtitem.hxx> +#define ITEMID_ESCAPEMENT EE_CHAR_ESCAPEMENT +#include <editeng/escpitem.hxx> +#define ITEMID_LINESPACING EE_PARA_SBL +#include <editeng/lspcitem.hxx> +#define ITEMID_FONTHEIGHT EE_CHAR_FONTHEIGHT +#include <editeng/fhgtitem.hxx> +#define ITEMID_FRAMEDIR EE_PARA_WRITINGDIR +#include <editeng/frmdiritem.hxx> +#include <editeng/scripttypeitem.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + //==================================================================== + //= ReferenceBase + //==================================================================== + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL ReferenceBase::acquire() + { + return osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL ReferenceBase::release() + { + return osl_decrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + ReferenceBase::~ReferenceBase() + { + } + + //==================================================================== + //= AttributeHandler + //==================================================================== + //-------------------------------------------------------------------- + AttributeHandler::AttributeHandler( AttributeId _nAttributeId, WhichId _nWhichId ) + :m_nAttribute( _nAttributeId ) + ,m_nWhich ( _nWhichId ) + { + } + + //-------------------------------------------------------------------- + AttributeHandler::~AttributeHandler() + { + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AttributeHandler::acquire() + { + return ReferenceBase::acquire(); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AttributeHandler::release() + { + return ReferenceBase::release(); + } + + //-------------------------------------------------------------------- + AttributeId AttributeHandler::getAttributeId( ) const + { + return getAttribute(); + } + + //-------------------------------------------------------------------- + AttributeCheckState AttributeHandler::implGetCheckState( const SfxPoolItem& /*_rItem*/ ) const + { + OSL_ENSURE( sal_False, "AttributeHandler::implGetCheckState: not to be called!" ); + return eIndetermined; + } + + //-------------------------------------------------------------------- + void AttributeHandler::putItemForScript( SfxItemSet& _rAttribs, const SfxPoolItem& _rItem, ScriptType _nForScriptType ) const + { + SvxScriptSetItem aSetItem( (WhichId)getAttributeId(), *_rAttribs.GetPool() ); + aSetItem.PutItemForScriptType( _nForScriptType, _rItem ); + _rAttribs.Put( aSetItem.GetItemSet(), FALSE ); + } + + //-------------------------------------------------------------------- + AttributeCheckState AttributeHandler::getCheckState( const SfxItemSet& _rAttribs ) const + { + AttributeCheckState eSimpleState( eIndetermined ); + const SfxPoolItem* pItem = _rAttribs.GetItem( getWhich() ); + if ( pItem ) + eSimpleState = implGetCheckState( *pItem ); + return eSimpleState; + } + + //-------------------------------------------------------------------- + AttributeState AttributeHandler::getState( const SfxItemSet& _rAttribs ) const + { + AttributeState aState( eIndetermined ); + aState.eSimpleState = getCheckState( _rAttribs ); + return aState; + } + + //==================================================================== + //= AttributeHandlerFactory + //==================================================================== + //-------------------------------------------------------------------- + namespace + { + static WhichId lcl_implGetWhich( const SfxItemPool& _rPool, AttributeId _nAttributeId ) + { + WhichId nWhich = 0; + switch ( _nAttributeId ) + { + case SID_ATTR_CHAR_LATIN_FONTHEIGHT:nWhich = EE_CHAR_FONTHEIGHT;break; + case SID_ATTR_CHAR_LATIN_FONT: nWhich = EE_CHAR_FONTINFO; break; + case SID_ATTR_CHAR_LATIN_LANGUAGE: nWhich = EE_CHAR_LANGUAGE; break; + case SID_ATTR_CHAR_LATIN_POSTURE: nWhich = EE_CHAR_ITALIC; break; + case SID_ATTR_CHAR_LATIN_WEIGHT: nWhich = EE_CHAR_WEIGHT; break; + + default: + nWhich = _rPool.GetWhich( (SfxSlotId)_nAttributeId ); + } + return nWhich; + } + } + //-------------------------------------------------------------------- + ::rtl::Reference< IAttributeHandler > AttributeHandlerFactory::getHandlerFor( AttributeId _nAttributeId, const SfxItemPool& _rEditEnginePool ) + { + ::rtl::Reference< IAttributeHandler > pReturn; + switch ( _nAttributeId ) + { + case SID_ATTR_PARA_ADJUST_LEFT : + case SID_ATTR_PARA_ADJUST_CENTER: + case SID_ATTR_PARA_ADJUST_RIGHT : + case SID_ATTR_PARA_ADJUST_BLOCK : + pReturn = new ParaAlignmentHandler( _nAttributeId ); + break; + + case SID_ATTR_PARA_LINESPACE_10: + case SID_ATTR_PARA_LINESPACE_15: + case SID_ATTR_PARA_LINESPACE_20: + pReturn = new LineSpacingHandler( _nAttributeId ); + break; + + case SID_SET_SUPER_SCRIPT: + case SID_SET_SUB_SCRIPT: + pReturn = new EscapementHandler( _nAttributeId ); + break; + + case SID_ATTR_CHAR_FONTHEIGHT: + case SID_ATTR_CHAR_CTL_FONTHEIGHT: + case SID_ATTR_CHAR_CJK_FONTHEIGHT: + case SID_ATTR_CHAR_LATIN_FONTHEIGHT: + pReturn = new FontSizeHandler( _nAttributeId, lcl_implGetWhich( _rEditEnginePool, _nAttributeId ) ); + break; + + case SID_ATTR_PARA_LEFT_TO_RIGHT: + case SID_ATTR_PARA_RIGHT_TO_LEFT: + pReturn = new ParagraphDirectionHandler( _nAttributeId ); + break; + + case SID_ATTR_PARA_HANGPUNCTUATION: + case SID_ATTR_PARA_FORBIDDEN_RULES: + case SID_ATTR_PARA_SCRIPTSPACE: + pReturn = new BooleanHandler( _nAttributeId, lcl_implGetWhich( _rEditEnginePool, _nAttributeId ) ); + break; + + default: + pReturn = new SlotHandler( (SfxSlotId)_nAttributeId, lcl_implGetWhich( _rEditEnginePool, _nAttributeId ) ); + break; + + } + + return pReturn; + } + + //==================================================================== + //= ParaAlignmentHandler + //==================================================================== + //-------------------------------------------------------------------- + ParaAlignmentHandler::ParaAlignmentHandler( AttributeId _nAttributeId ) + :AttributeHandler( _nAttributeId, EE_PARA_JUST ) + ,m_eAdjust( SVX_ADJUST_CENTER ) + { + switch ( getAttribute() ) + { + case SID_ATTR_PARA_ADJUST_LEFT : m_eAdjust = SVX_ADJUST_LEFT; break; + case SID_ATTR_PARA_ADJUST_CENTER: m_eAdjust = SVX_ADJUST_CENTER; break; + case SID_ATTR_PARA_ADJUST_RIGHT : m_eAdjust = SVX_ADJUST_RIGHT; break; + case SID_ATTR_PARA_ADJUST_BLOCK : m_eAdjust = SVX_ADJUST_BLOCK; break; + default: + OSL_ENSURE( sal_False, "ParaAlignmentHandler::ParaAlignmentHandler: invalid slot!" ); + break; + } + } + + //-------------------------------------------------------------------- + AttributeCheckState ParaAlignmentHandler::implGetCheckState( const SfxPoolItem& _rItem ) const + { + OSL_ENSURE( _rItem.ISA( SvxAdjustItem ), "ParaAlignmentHandler::implGetCheckState: invalid pool item!" ); + SvxAdjust eAdjust = static_cast< const SvxAdjustItem& >( _rItem ).GetAdjust(); + return ( eAdjust == m_eAdjust ) ? eChecked : eUnchecked; + } + + //-------------------------------------------------------------------- + void ParaAlignmentHandler::executeAttribute( const SfxItemSet& /*_rCurrentAttribs*/, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType /*_nForScriptType*/ ) const + { + OSL_ENSURE( !_pAdditionalArg, "ParaAlignmentHandler::executeAttribute: this is a simple toggle attribute - no args possible!" ); + (void)_pAdditionalArg; + _rNewAttribs.Put( SvxAdjustItem( m_eAdjust, getWhich() ) ); + } + + //==================================================================== + //= LineSpacingHandler + //==================================================================== + //-------------------------------------------------------------------- + LineSpacingHandler::LineSpacingHandler( AttributeId _nAttributeId ) + :AttributeHandler( _nAttributeId, EE_PARA_SBL ) + ,m_nLineSpace( 100 ) + { + switch ( getAttribute() ) + { + case SID_ATTR_PARA_LINESPACE_10: m_nLineSpace = 100; break; + case SID_ATTR_PARA_LINESPACE_15: m_nLineSpace = 150; break; + case SID_ATTR_PARA_LINESPACE_20: m_nLineSpace = 200; break; + default: + OSL_ENSURE( sal_False, "LineSpacingHandler::LineSpacingHandler: invalid slot!" ); + break; + } + } + + //-------------------------------------------------------------------- + AttributeCheckState LineSpacingHandler::implGetCheckState( const SfxPoolItem& _rItem ) const + { + OSL_ENSURE( _rItem.ISA( SvxLineSpacingItem ), "LineSpacingHandler::implGetCheckState: invalid pool item!" ); + USHORT nLineSpace = static_cast< const SvxLineSpacingItem& >( _rItem ).GetPropLineSpace(); + return ( nLineSpace == m_nLineSpace ) ? eChecked : eUnchecked; + } + + //-------------------------------------------------------------------- + void LineSpacingHandler::executeAttribute( const SfxItemSet& /*_rCurrentAttribs*/, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType /*_nForScriptType*/ ) const + { + OSL_ENSURE( !_pAdditionalArg, "LineSpacingHandler::executeAttribute: this is a simple toggle attribute - no args possible!" ); + (void)_pAdditionalArg; + + SvxLineSpacingItem aLineSpacing( m_nLineSpace, getWhich() ); + aLineSpacing.GetLineSpaceRule() = SVX_LINE_SPACE_AUTO; + if ( 100 == m_nLineSpace ) + aLineSpacing.GetInterLineSpaceRule() = SVX_INTER_LINE_SPACE_OFF; + else + aLineSpacing.SetPropLineSpace( (BYTE)m_nLineSpace ); + + _rNewAttribs.Put( aLineSpacing ); + } + + //==================================================================== + //= EscapementHandler + //==================================================================== + //-------------------------------------------------------------------- + EscapementHandler::EscapementHandler( AttributeId _nAttributeId ) + :AttributeHandler( _nAttributeId, EE_CHAR_ESCAPEMENT ) + ,m_eEscapement( SVX_ESCAPEMENT_OFF ) + { + switch ( getAttribute() ) + { + case SID_SET_SUPER_SCRIPT : m_eEscapement = SVX_ESCAPEMENT_SUPERSCRIPT; break; + case SID_SET_SUB_SCRIPT : m_eEscapement = SVX_ESCAPEMENT_SUBSCRIPT; break; + default: + OSL_ENSURE( sal_False, "EscapementHandler::EscapementHandler: invalid slot!" ); + break; + } + } + + //-------------------------------------------------------------------- + AttributeCheckState EscapementHandler::implGetCheckState( const SfxPoolItem& _rItem ) const + { + OSL_ENSURE( _rItem.ISA( SvxEscapementItem ), "EscapementHandler::getState: invalid pool item!" ); + SvxEscapement eEscapement = static_cast< const SvxEscapementItem& >( _rItem ).GetEscapement(); + return ( eEscapement == m_eEscapement ) ? eChecked : eUnchecked; + } + + //-------------------------------------------------------------------- + void EscapementHandler::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType /*_nForScriptType*/ ) const + { + OSL_ENSURE( !_pAdditionalArg, "EscapementHandler::executeAttribute: this is a simple toggle attribute - no args possible!" ); + // well, in theory we could allow an SvxEscapementItem here, but this is not needed + (void)_pAdditionalArg; + + bool bIsChecked = getCheckState( _rCurrentAttribs ) == eChecked; + _rNewAttribs.Put( SvxEscapementItem( bIsChecked ? SVX_ESCAPEMENT_OFF : m_eEscapement, getWhich() ) ); + } + + //==================================================================== + //= SlotHandler + //==================================================================== + //-------------------------------------------------------------------- + SlotHandler::SlotHandler( AttributeId _nAttributeId, WhichId _nWhichId ) + :AttributeHandler( _nAttributeId, _nWhichId ) + ,m_bScriptDependent( false ) + { + m_bScriptDependent = ( SID_ATTR_CHAR_WEIGHT == _nAttributeId ) + || ( SID_ATTR_CHAR_POSTURE == _nAttributeId ) + || ( SID_ATTR_CHAR_FONT == _nAttributeId ); + } + + //-------------------------------------------------------------------- + AttributeState SlotHandler::getState( const SfxItemSet& _rAttribs ) const + { + AttributeState aState( eIndetermined ); + + const SfxPoolItem* pItem = _rAttribs.GetItem( getWhich() ); + if ( pItem ) + aState.setItem( pItem->Clone() ); + + return aState; + } + + //-------------------------------------------------------------------- + void SlotHandler::executeAttribute( const SfxItemSet& /*_rCurrentAttribs*/, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const + { + if ( _pAdditionalArg ) + { + SfxPoolItem* pCorrectWich = _pAdditionalArg->Clone(); + pCorrectWich->SetWhich( getWhich() ); + + if ( m_bScriptDependent ) + putItemForScript( _rNewAttribs, *pCorrectWich, _nForScriptType ); + else + _rNewAttribs.Put( *pCorrectWich ); + DELETEZ( pCorrectWich ); + } + else + OSL_ENSURE( sal_False, "SlotHandler::executeAttribute: need attributes to do something!" ); + } + + //==================================================================== + //= FontSizeHandler + //==================================================================== + //-------------------------------------------------------------------- + FontSizeHandler::FontSizeHandler( AttributeId _nAttributeId, WhichId _nWhichId ) + :AttributeHandler( _nAttributeId, _nWhichId ) + { + OSL_ENSURE( ( _nAttributeId == SID_ATTR_CHAR_FONTHEIGHT ) || ( _nAttributeId == SID_ATTR_CHAR_CTL_FONTHEIGHT ) + || ( _nAttributeId == SID_ATTR_CHAR_CJK_FONTHEIGHT ) || ( _nAttributeId == SID_ATTR_CHAR_LATIN_FONTHEIGHT ), + "FontSizeHandler::FontSizeHandler: invalid attribute id!" ); + } + + //-------------------------------------------------------------------- + AttributeState FontSizeHandler::getState( const SfxItemSet& _rAttribs ) const + { + AttributeState aState( eIndetermined ); + + const SfxPoolItem* pItem = _rAttribs.GetItem( getWhich() ); + const SvxFontHeightItem* pFontHeightItem = PTR_CAST( SvxFontHeightItem, pItem ); + OSL_ENSURE( pFontHeightItem || !pItem, "FontSizeHandler::getState: invalid item!" ); + if ( pFontHeightItem ) + { + // by definition, the item should have the unit twip + ULONG nHeight = pFontHeightItem->GetHeight(); + if ( _rAttribs.GetPool()->GetMetric( getWhich() ) != SFX_MAPUNIT_TWIP ) + { + nHeight = OutputDevice::LogicToLogic( + Size( 0, nHeight ), + MapMode( (MapUnit)( _rAttribs.GetPool()->GetMetric( getWhich() ) ) ), + MapMode( MAP_TWIP ) + ).Height(); + } + + SvxFontHeightItem* pNewItem = new SvxFontHeightItem( nHeight, 100, getWhich() ); + pNewItem->SetProp( pFontHeightItem->GetProp(), pFontHeightItem->GetPropUnit() ); + aState.setItem( pNewItem ); + } + + return aState; + } + + //-------------------------------------------------------------------- + void FontSizeHandler::executeAttribute( const SfxItemSet& /*_rCurrentAttribs*/, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const + { + const SvxFontHeightItem* pFontHeightItem = PTR_CAST( SvxFontHeightItem, _pAdditionalArg ); + OSL_ENSURE( pFontHeightItem, "FontSizeHandler::executeAttribute: need a FontHeightItem!" ); + + if ( pFontHeightItem ) + { + // corect measurement units + SfxMapUnit eItemMapUnit = pFontHeightItem->GetPropUnit(); (void)eItemMapUnit; + ULONG nHeight = pFontHeightItem->GetHeight(); + if ( _rNewAttribs.GetPool()->GetMetric( getWhich() ) != SFX_MAPUNIT_TWIP ) + { + nHeight = OutputDevice::LogicToLogic( + Size( 0, nHeight ), + MapMode( (MapUnit)( SFX_MAPUNIT_TWIP ) ), + MapMode( (MapUnit)( _rNewAttribs.GetPool()->GetMetric( getWhich() ) ) ) + ).Height(); + } + + SvxFontHeightItem aNewItem( nHeight, 100, getWhich() ); + aNewItem.SetProp( pFontHeightItem->GetProp(), pFontHeightItem->GetPropUnit() ); + + if ( ( getAttributeId() == SID_ATTR_CHAR_FONTHEIGHT ) && _nForScriptType ) + putItemForScript( _rNewAttribs, aNewItem, _nForScriptType ); + else + _rNewAttribs.Put( aNewItem ); + } + } + + //==================================================================== + //= ParagraphDirectionHandler + //==================================================================== + //-------------------------------------------------------------------- + ParagraphDirectionHandler::ParagraphDirectionHandler( AttributeId _nAttributeId ) + :AttributeHandler( _nAttributeId, EE_PARA_WRITINGDIR ) + ,m_eParagraphDirection( FRMDIR_HORI_LEFT_TOP ) + ,m_eDefaultAdjustment( SVX_ADJUST_RIGHT ) + ,m_eOppositeDefaultAdjustment( SVX_ADJUST_LEFT ) + { + switch ( getAttributeId() ) + { + case SID_ATTR_PARA_LEFT_TO_RIGHT: m_eParagraphDirection = FRMDIR_HORI_LEFT_TOP; m_eDefaultAdjustment = SVX_ADJUST_LEFT; break; + case SID_ATTR_PARA_RIGHT_TO_LEFT: m_eParagraphDirection = FRMDIR_HORI_RIGHT_TOP; m_eDefaultAdjustment = SVX_ADJUST_RIGHT; break; + default: + OSL_ENSURE( sal_False, "ParagraphDirectionHandler::ParagraphDirectionHandler: invalid attribute id!" ); + } + + if ( SVX_ADJUST_RIGHT == m_eDefaultAdjustment ) + m_eOppositeDefaultAdjustment = SVX_ADJUST_LEFT; + else + m_eOppositeDefaultAdjustment = SVX_ADJUST_RIGHT; + } + + //-------------------------------------------------------------------- + AttributeCheckState ParagraphDirectionHandler::implGetCheckState( const SfxPoolItem& _rItem ) const + { + OSL_ENSURE( _rItem.ISA( SvxFrameDirectionItem ), "ParagraphDirectionHandler::implGetCheckState: invalid pool item!" ); + SvxFrameDirection eDirection = static_cast< SvxFrameDirection >( static_cast< const SvxFrameDirectionItem& >( _rItem ).GetValue() ); + return ( eDirection == m_eParagraphDirection ) ? eChecked : eUnchecked; + } + + //-------------------------------------------------------------------- + void ParagraphDirectionHandler::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* /*_pAdditionalArg*/, ScriptType /*_nForScriptType*/ ) const + { + _rNewAttribs.Put( SvxFrameDirectionItem( m_eParagraphDirection, getWhich() ) ); + + // if the current adjustment of the was the default adjustment for the *previous* text direction, + // then we toggle the adjustment, too + SvxAdjust eCurrentAdjustment = SVX_ADJUST_LEFT; + const SfxPoolItem* pCurrentAdjustment = NULL; + if ( SFX_ITEM_ON == _rCurrentAttribs.GetItemState( EE_PARA_JUST, TRUE, &pCurrentAdjustment ) ) + eCurrentAdjustment = static_cast< const SvxAdjustItem* >( pCurrentAdjustment )->GetAdjust(); + + if ( eCurrentAdjustment == m_eOppositeDefaultAdjustment ) + _rNewAttribs.Put( SvxAdjustItem( m_eDefaultAdjustment, EE_PARA_JUST ) ); + } + + //==================================================================== + //= BooleanHandler + //==================================================================== + //-------------------------------------------------------------------- + BooleanHandler::BooleanHandler( AttributeId _nAttributeId, WhichId _nWhichId ) + :AttributeHandler( _nAttributeId, _nWhichId ) + { + } + + //-------------------------------------------------------------------- + AttributeCheckState BooleanHandler::implGetCheckState( const SfxPoolItem& _rItem ) const + { + OSL_ENSURE( _rItem.ISA( SfxBoolItem ), "BooleanHandler::implGetCheckState: invalid item!" ); + if ( _rItem.ISA( SfxBoolItem ) ) + return static_cast< const SfxBoolItem& >( _rItem ).GetValue() ? eChecked : eUnchecked; + + return eIndetermined; + } + + //-------------------------------------------------------------------- + void BooleanHandler::executeAttribute( const SfxItemSet& /*_rCurrentAttribs*/, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType /*_nForScriptType*/ ) const + { + OSL_ENSURE( _pAdditionalArg && _pAdditionalArg->ISA( SfxBoolItem ), "BooleanHandler::executeAttribute: invalid argument!" ); + if ( _pAdditionalArg ) + { + SfxPoolItem* pCorrectWich = _pAdditionalArg->Clone(); + pCorrectWich->SetWhich( getWhich() ); + _rNewAttribs.Put( *pCorrectWich ); + DELETEZ( pCorrectWich ); + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/richtext/rtattributehandler.hxx b/forms/source/richtext/rtattributehandler.hxx new file mode 100644 index 000000000000..4e15cbc44050 --- /dev/null +++ b/forms/source/richtext/rtattributehandler.hxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_COMPONENT_RTATTRIBUTEHANDLER_HXX +#define FORMS_SOURCE_COMPONENT_RTATTRIBUTEHANDLER_HXX + +#include "rtattributes.hxx" +#include <rtl/ref.hxx> +#include <editeng/svxenum.hxx> +#include <editeng/frmdir.hxx> + +class SfxItemSet; +class SfxPoolItem; +class SfxItemPool; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= ReferenceBase + //==================================================================== + class ReferenceBase : public ::rtl::IReference + { + protected: + oslInterlockedCount m_refCount; + + public: + // IReference + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + protected: + virtual ~ReferenceBase(); + }; + + //==================================================================== + //= IAttributeHandler + //==================================================================== + class IAttributeHandler : public ::rtl::IReference + { + public: + virtual AttributeId getAttributeId( ) const = 0; + virtual AttributeState getState( const SfxItemSet& _rAttribs ) const = 0; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const = 0; + }; + + //==================================================================== + //= AttributeHandler + //==================================================================== + class AttributeHandler :public ReferenceBase + ,public IAttributeHandler + { + private: + AttributeId m_nAttribute; + WhichId m_nWhich; + + protected: + AttributeId getAttribute() const { return m_nAttribute; } + WhichId getWhich() const { return m_nWhich; } + + public: + AttributeHandler( AttributeId _nAttributeId, WhichId _nWhichId ); + + // IAttributeHandler + virtual AttributeId getAttributeId( ) const; + virtual AttributeState getState( const SfxItemSet& _rAttribs ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const = 0; + + protected: + /// helper method calling implGetCheckState + AttributeCheckState getCheckState( const SfxItemSet& _rAttribs ) const; + + /// helper method putting an item into a set, respecting a script type + void putItemForScript( SfxItemSet& _rAttribs, const SfxPoolItem& _rItem, ScriptType _nForScriptType ) const; + + // pseudo-abstract + virtual AttributeCheckState implGetCheckState( const SfxPoolItem& _rItem ) const; + + // disambiguate IReference + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + protected: + virtual ~AttributeHandler(); + }; + + //==================================================================== + //= AttributeHandlerFactory + //==================================================================== + class AttributeHandlerFactory + { + public: + static ::rtl::Reference< IAttributeHandler > getHandlerFor( AttributeId _nAttributeId, const SfxItemPool& _rEditEnginePool ); + + private: + AttributeHandlerFactory(); // never implemented + AttributeHandlerFactory( const AttributeHandlerFactory& ); // never implemented + AttributeHandlerFactory& operator=( const AttributeHandlerFactory& ); // never implemented + ~AttributeHandlerFactory(); // never implemented + }; + + //==================================================================== + //= ParaAlignmentHandler + //==================================================================== + class ParaAlignmentHandler : public AttributeHandler + { + private: + SvxAdjust m_eAdjust; + + public: + ParaAlignmentHandler( AttributeId _nAttributeId ); + + public: + virtual AttributeCheckState implGetCheckState( const SfxPoolItem& _rItem ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + + //==================================================================== + //= LineSpacingHandler + //==================================================================== + class LineSpacingHandler : public AttributeHandler + { + private: + USHORT m_nLineSpace; + + public: + LineSpacingHandler( AttributeId _nAttributeId ); + + public: + virtual AttributeCheckState implGetCheckState( const SfxPoolItem& _rItem ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + + //==================================================================== + //= EscapementHandler + //==================================================================== + class EscapementHandler : public AttributeHandler + { + private: + SvxEscapement m_eEscapement; + + public: + EscapementHandler( AttributeId _nAttributeId ); + + public: + virtual AttributeCheckState implGetCheckState( const SfxPoolItem& _rItem ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + + //==================================================================== + //= SlotHandler + //==================================================================== + class SlotHandler : public AttributeHandler + { + private: + bool m_bScriptDependent; + + public: + SlotHandler( AttributeId _nAttributeId, WhichId _nWhichId ); + + public: + virtual AttributeState getState( const SfxItemSet& _rAttribs ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + + //==================================================================== + //= BooleanHandler + //==================================================================== + class BooleanHandler : public AttributeHandler + { + public: + BooleanHandler( AttributeId _nAttributeId, WhichId _nWhichId ); + + public: + virtual AttributeCheckState implGetCheckState( const SfxPoolItem& _rItem ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + + //==================================================================== + //= FontSizeHandler + //==================================================================== + class FontSizeHandler : public AttributeHandler + { + public: + FontSizeHandler( AttributeId _nAttributeId, WhichId _nWhichId ); + + public: + virtual AttributeState getState( const SfxItemSet& _rAttribs ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + + //==================================================================== + //= ParagraphDirectionHandler + //==================================================================== + class ParagraphDirectionHandler : public AttributeHandler + { + private: + SvxFrameDirection m_eParagraphDirection; + SvxAdjust m_eDefaultAdjustment; + SvxAdjust m_eOppositeDefaultAdjustment; + + public: + ParagraphDirectionHandler( AttributeId _nAttributeId ); + + public: + virtual AttributeCheckState implGetCheckState( const SfxPoolItem& _rItem ) const; + virtual void executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rNewAttribs, const SfxPoolItem* _pAdditionalArg, ScriptType _nForScriptType ) const; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_RTATTRIBUTEHANDLER_HXX + diff --git a/forms/source/richtext/rtattributes.hxx b/forms/source/richtext/rtattributes.hxx new file mode 100644 index 000000000000..2506dbcb5186 --- /dev/null +++ b/forms/source/richtext/rtattributes.hxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_RTATTRIBUTES_HXX +#define FORMS_SOURCE_RICHTEXT_RTATTRIBUTES_HXX + +#include <tools/solar.h> +#include <sal/types.h> +#include <svl/poolitem.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= misc + //==================================================================== + /// the id of an attribute + typedef sal_Int32 AttributeId; + /// the "which id" of an item in an SfxItemSet + typedef USHORT WhichId; + /// a SFX slot id + typedef USHORT SfxSlotId; + /// a script type + typedef USHORT ScriptType; + + //==================================================================== + //= AttributeCheckState + //==================================================================== + enum AttributeCheckState + { + eChecked, + eUnchecked, + eIndetermined + }; + + //==================================================================== + //= AttributeState + //==================================================================== + struct AttributeState + { + private: + SfxItemHandle* pItemHandle; + + public: + AttributeCheckState eSimpleState; + + //................................................................ + inline AttributeState( ); + inline explicit AttributeState( AttributeCheckState _eCheckState ); + inline AttributeState( const AttributeState& _rSource ); + + inline AttributeState& operator=( const AttributeState& _rSource ); + + inline bool operator==( const AttributeState& _rRHS ); + + inline const SfxPoolItem* getItem() const; + inline void setItem( const SfxPoolItem* _pItem ); + }; + + //==================================================================== + //= AttributeState (inline implementation) + //==================================================================== + //................................................................ + inline AttributeState::AttributeState( ) + :pItemHandle( NULL ) + ,eSimpleState( eIndetermined ) + { + } + + //................................................................ + inline AttributeState::AttributeState( AttributeCheckState _eCheckState ) + :pItemHandle( NULL ) + ,eSimpleState( _eCheckState ) + { + } + + //................................................................ + inline AttributeState::AttributeState( const AttributeState& _rSource ) + :pItemHandle( NULL ) + ,eSimpleState( eIndetermined ) + { + operator=( _rSource ); + } + + //................................................................ + inline AttributeState& AttributeState::operator=( const AttributeState& _rSource ) + { + if ( &_rSource == this ) + return *this; + + eSimpleState = _rSource.eSimpleState; + setItem( _rSource.getItem() ); + return *this; + } + + //................................................................ + inline const SfxPoolItem* AttributeState::getItem() const + { + return pItemHandle ? &pItemHandle->GetItem() : NULL; + } + + //................................................................ + inline void AttributeState::setItem( const SfxPoolItem* _pItem ) + { + if ( pItemHandle ) + delete pItemHandle; + if ( _pItem ) + pItemHandle = new SfxItemHandle( *const_cast< SfxPoolItem* >( _pItem ) ); + else + pItemHandle = NULL; + } + + //................................................................ + inline bool AttributeState::operator==( const AttributeState& _rRHS ) + { + if ( eSimpleState != _rRHS.eSimpleState ) + return false; + + if ( pItemHandle && !_rRHS.pItemHandle ) + return false; + + if ( !pItemHandle && _rRHS.pItemHandle ) + return false; + + if ( !pItemHandle && !_rRHS.pItemHandle ) + return true; + + return ( pItemHandle->GetItem() == _rRHS.pItemHandle->GetItem() ); + } + + //==================================================================== + //= IMultiAttributeDispatcher + //==================================================================== + class IMultiAttributeDispatcher + { + public: + virtual AttributeState getState( AttributeId _nAttributeId ) const = 0; + virtual void executeAttribute( AttributeId _nAttributeId, const SfxPoolItem* _pArgument ) = 0; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_RTATTRIBUTES_HXX + diff --git a/forms/source/richtext/specialdispatchers.cxx b/forms/source/richtext/specialdispatchers.cxx new file mode 100644 index 000000000000..2540c9d797f2 --- /dev/null +++ b/forms/source/richtext/specialdispatchers.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "specialdispatchers.hxx" +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#ifndef _SVX_SVXIDS_HRC +#include <svx/svxids.hrc> +#endif +#define ITEMID_SCRIPTSPACE SID_ATTR_PARA_SCRIPTSPACE +#include <editeng/scriptspaceitem.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::beans; + + //==================================================================== + //= OSelectAllDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OSelectAllDispatcher::OSelectAllDispatcher( EditView& _rView, const URL& _rURL ) + :ORichTextFeatureDispatcher( _rView, _rURL ) + { + } + + //-------------------------------------------------------------------- + OSelectAllDispatcher::~OSelectAllDispatcher( ) + { + if ( !isDisposed() ) + { + acquire(); + dispose(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OSelectAllDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& /*_rArguments*/ ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( _rURL.Complete == getFeatureURL().Complete, "OSelectAllDispatcher::dispatch: invalid URL!" ); + (void)_rURL; + + checkDisposed(); + + EditEngine* pEngine = getEditView() ? getEditView()->GetEditEngine() : NULL; + OSL_ENSURE( pEngine, "OSelectAllDispatcher::dispatch: no edit engine - but not yet disposed?" ); + if ( !pEngine ) + return; + + USHORT nParagraphs = pEngine->GetParagraphCount(); + if ( nParagraphs ) + { + USHORT nLastParaNumber = nParagraphs - 1; + xub_StrLen nParaLen = pEngine->GetTextLen( nLastParaNumber ); + getEditView()->SetSelection( ESelection( 0, 0, nLastParaNumber, nParaLen ) ); + } + } + + //-------------------------------------------------------------------- + FeatureStateEvent OSelectAllDispatcher::buildStatusEvent() const + { + FeatureStateEvent aEvent( ORichTextFeatureDispatcher::buildStatusEvent() ); + aEvent.IsEnabled = sal_True; + return aEvent; + } + + //==================================================================== + //= OParagraphDirectionDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OParagraphDirectionDispatcher::OParagraphDirectionDispatcher( EditView& _rView, AttributeId _nAttributeId, const URL& _rURL, + IMultiAttributeDispatcher* _pMasterDispatcher ) + :OAttributeDispatcher( _rView, _nAttributeId, _rURL, _pMasterDispatcher ) + { + } + + //-------------------------------------------------------------------- + FeatureStateEvent OParagraphDirectionDispatcher::buildStatusEvent() const + { + FeatureStateEvent aEvent( OAttributeDispatcher::buildStatusEvent() ); + + EditEngine* pEngine = getEditView() ? getEditView()->GetEditEngine() : NULL; + OSL_ENSURE( pEngine, "OParagraphDirectionDispatcher::dispatch: no edit engine - but not yet disposed?" ); + if ( pEngine && pEngine->IsVertical() ) + aEvent.IsEnabled = sal_False; + + return aEvent; + } + + //==================================================================== + //= OTextDirectionDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OTextDirectionDispatcher::OTextDirectionDispatcher( EditView& _rView, const URL& _rURL ) + :ORichTextFeatureDispatcher( _rView, _rURL ) + { + } + + //-------------------------------------------------------------------- + void SAL_CALL OTextDirectionDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& /*_rArguments*/ ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( _rURL.Complete == getFeatureURL().Complete, "OTextDirectionDispatcher::dispatch: invalid URL!" ); + (void)_rURL; + + checkDisposed(); + + EditEngine* pEngine = getEditView() ? getEditView()->GetEditEngine() : NULL; + OSL_ENSURE( pEngine, "OTextDirectionDispatcher::dispatch: no edit engine - but not yet disposed?" ); + if ( !pEngine ) + return; + + pEngine->SetVertical( !pEngine->IsVertical() ); + } + + //-------------------------------------------------------------------- + FeatureStateEvent OTextDirectionDispatcher::buildStatusEvent() const + { + FeatureStateEvent aEvent( ORichTextFeatureDispatcher::buildStatusEvent() ); + + EditEngine* pEngine = getEditView() ? getEditView()->GetEditEngine() : NULL; + OSL_ENSURE( pEngine, "OTextDirectionDispatcher::dispatch: no edit engine - but not yet disposed?" ); + + aEvent.IsEnabled = sal_True; + aEvent.State <<= (sal_Bool)( pEngine && pEngine->IsVertical() ); + + return aEvent; + } + + //==================================================================== + //= OAsianFontLayoutDispatcher + //==================================================================== + //-------------------------------------------------------------------- + OAsianFontLayoutDispatcher::OAsianFontLayoutDispatcher( EditView& _rView, AttributeId _nAttributeId, const URL& _rURL, IMultiAttributeDispatcher* _pMasterDispatcher ) + :OParametrizedAttributeDispatcher( _rView, _nAttributeId, _rURL, _pMasterDispatcher ) + { + } + + //-------------------------------------------------------------------- + const SfxPoolItem* OAsianFontLayoutDispatcher::convertDispatchArgsToItem( const Sequence< PropertyValue >& _rArguments ) + { + // look for the "Enable" parameter + const PropertyValue* pLookup = _rArguments.getConstArray(); + const PropertyValue* pLookupEnd = _rArguments.getConstArray() + _rArguments.getLength(); + while ( pLookup != pLookupEnd ) + { + if ( pLookup->Name.equalsAscii( "Enable" ) ) + break; + ++pLookup; + } + if ( pLookup != pLookupEnd ) + { + sal_Bool bEnable = sal_True; + OSL_VERIFY( pLookup->Value >>= bEnable ); + if ( m_nAttributeId == SID_ATTR_PARA_SCRIPTSPACE ) + return new SvxScriptSpaceItem( bEnable, (WhichId)m_nAttributeId ); + return new SfxBoolItem( (WhichId)m_nAttributeId, bEnable ); + } + + OSL_ENSURE( sal_False, "OAsianFontLayoutDispatcher::convertDispatchArgsToItem: did not find the one and only argument!" ); + return NULL; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/richtext/specialdispatchers.hxx b/forms/source/richtext/specialdispatchers.hxx new file mode 100644 index 000000000000..7b6c7b98ea24 --- /dev/null +++ b/forms/source/richtext/specialdispatchers.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_RICHTEXT_SPECIALDISPATCHERS_HXX +#define FORMS_SOURCE_RICHTEXT_SPECIALDISPATCHERS_HXX + +#include "parametrizedattributedispatcher.hxx" + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OSelectAllDispatcher + //==================================================================== + class OSelectAllDispatcher : public ORichTextFeatureDispatcher + { + public: + OSelectAllDispatcher( EditView& _rView, const ::com::sun::star::util::URL& _rURL ); + + protected: + ~OSelectAllDispatcher(); + + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& URL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::uno::RuntimeException); + + // ORichTextFeatureDispatcher + virtual ::com::sun::star::frame::FeatureStateEvent buildStatusEvent() const; + }; + + //==================================================================== + //= OParagraphDirectionDispatcher + //==================================================================== + class OParagraphDirectionDispatcher : public OAttributeDispatcher + { + public: + OParagraphDirectionDispatcher( + EditView& _rView, + AttributeId _nAttributeId, + const ::com::sun::star::util::URL& _rURL, + IMultiAttributeDispatcher* _pMasterDispatcher + ); + + protected: + // ORichTextFeatureDispatcher + virtual ::com::sun::star::frame::FeatureStateEvent buildStatusEvent() const; + }; + + //==================================================================== + //= OTextDirectionDispatcher + //==================================================================== + class OTextDirectionDispatcher : public ORichTextFeatureDispatcher + { + public: + OTextDirectionDispatcher( EditView& _rView, const ::com::sun::star::util::URL& _rURL ); + + protected: + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& URL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::uno::RuntimeException); + + // ORichTextFeatureDispatcher + virtual ::com::sun::star::frame::FeatureStateEvent buildStatusEvent() const; + }; + + //==================================================================== + //= OAsianFontLayoutDispatcher + //==================================================================== + class OAsianFontLayoutDispatcher : public OParametrizedAttributeDispatcher + { + public: + OAsianFontLayoutDispatcher( + EditView& _rView, + AttributeId _nAttributeId, + const ::com::sun::star::util::URL& _rURL, + IMultiAttributeDispatcher* _pMasterDispatcher + ); + + protected: + // OParametrizedAttributeDispatcher + virtual const SfxPoolItem* convertDispatchArgsToItem( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArguments ); + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_SPECIALDISPATCHERS_HXX diff --git a/forms/source/richtext/textattributelistener.hxx b/forms/source/richtext/textattributelistener.hxx new file mode 100644 index 000000000000..3b7b29ee19f9 --- /dev/null +++ b/forms/source/richtext/textattributelistener.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef FORMS_SOURCE_RICHTEXT_TEXTATTRIBUTELISTENER_HXX +#define FORMS_SOURCE_RICHTEXT_TEXTATTRIBUTELISTENER_HXX + +#include "rtattributes.hxx" + +struct ESelection; +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= ITextAttributeListener + //==================================================================== + class ITextAttributeListener + { + public: + virtual void onAttributeStateChanged( AttributeId _nAttributeId, const AttributeState& _rState ) = 0; + }; + + //==================================================================== + //= ITextAttributeListener + //==================================================================== + class ITextSelectionListener + { + public: + virtual void onSelectionChanged( const ESelection& _rSelection ) = 0; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_RICHTEXT_TEXTATTRIBUTELISTENER_HXX + diff --git a/forms/source/runtime/formoperations.cxx b/forms/source/runtime/formoperations.cxx new file mode 100644 index 000000000000..48e6159585ab --- /dev/null +++ b/forms/source/runtime/formoperations.cxx @@ -0,0 +1,1719 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "formoperations.hxx" +#include "frm_strings.hxx" +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "frm_module.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ucb/AlreadyInitializedException.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/form/runtime/FormFeature.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/form/XGrid.hpp> +#include <com/sun/star/form/XBoundControl.hpp> +#include <com/sun/star/form/XBoundComponent.hpp> +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <com/sun/star/form/XConfirmDeleteListener.hpp> +#include <com/sun/star/sdb/RowChangeEvent.hpp> +#include <com/sun/star/sdb/RowChangeAction.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +/** === end UNO includes === **/ + +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <vcl/svapp.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/waitobj.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/container.hxx> +#include <comphelper/property.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <vos/mutex.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_FormOperations() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using ::dbtools::SQLExceptionInfo; + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::sdbc::XRowSet; + using ::com::sun::star::sdbc::XResultSetUpdate; + using ::com::sun::star::form::runtime::XFormController; + using ::com::sun::star::form::runtime::XFeatureInvalidation; + using ::com::sun::star::form::runtime::FeatureState; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::form::XForm; + using ::com::sun::star::ucb::AlreadyInitializedException; + using ::com::sun::star::util::XModifyBroadcaster; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::beans::PropertyChangeEvent; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::awt::XControl; + using ::com::sun::star::form::XGrid; + using ::com::sun::star::container::XIndexAccess; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::form::XBoundControl; + using ::com::sun::star::form::XBoundComponent; + using ::com::sun::star::sdbcx::XRowLocate; + using ::com::sun::star::form::XConfirmDeleteListener; + using ::com::sun::star::sdb::RowChangeEvent; + using ::com::sun::star::form::XReset; + using ::com::sun::star::beans::XMultiPropertySet; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::ui::dialogs::XExecutableDialog; + using ::com::sun::star::beans::NamedValue; + + using ::com::sun::star::util::XRefreshable; + using ::com::sun::star::awt::XControlModel; + /** === end UNO using === **/ + namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; + namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction; + + //==================================================================== + //= FormOperations + //==================================================================== + //-------------------------------------------------------------------- + FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext ) + :FormOperations_Base( m_aMutex ) + ,m_aContext( _rxContext ) + ,m_bInitializedParser( false ) + ,m_bActiveControlModified( false ) + ,m_bConstructed( false ) + #ifdef DBG_UTIL + ,m_nMethodNestingLevel( false ) + #endif + { + } + + //-------------------------------------------------------------------- + FormOperations::~FormOperations() + { + } + + //-------------------------------------------------------------------- + ::rtl::OUString FormOperations::getImplementationName_Static( ) throw(RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.FormOperations" ) ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException) + { + Sequence< ::rtl::OUString > aNames(1); + aNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.runtime.FormOperations" ) ); + return aNames; + } + + //-------------------------------------------------------------------- + Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory ) + { + return *new FormOperations( _rxFactory ); + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException) + { + if ( m_bConstructed ) + throw AlreadyInitializedException(); + + if ( _arguments.getLength() == 1 ) + { + Reference< XFormController > xController; + Reference< XForm > xForm; + if ( _arguments[0] >>= xController ) + createWithFormController( xController ); + else if ( _arguments[0] >>= xForm ) + createWithForm( xForm ); + else + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + return; + } + + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL FormOperations::getImplementationName( ) throw (RuntimeException) + { + return getImplementationName_Static(); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::supportsService( const ::rtl::OUString& _ServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupportedServiceNames( getSupportedServiceNames() ); + const ::rtl::OUString* pBegin = aSupportedServiceNames.getConstArray(); + const ::rtl::OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength(); + return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL FormOperations::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_Static(); + } + + //-------------------------------------------------------------------- + Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xCursor; + } + + //-------------------------------------------------------------------- + Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xUpdateCursor; + } + + //-------------------------------------------------------------------- + Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xController; + } + + //-------------------------------------------------------------------- + Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xFeatureInvalidation; + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + m_xFeatureInvalidation = _rxFeatureInvalidation; + } + + //-------------------------------------------------------------------- + FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + + FeatureState aState; + aState.Enabled = sal_False; + + try + { + // some checks for basic pre-requisites + if ( !m_xLoadableForm.is() + || !m_xLoadableForm->isLoaded() + || !m_xCursorProperties.is() + ) + { + return aState; + } + + switch ( _nFeature ) + { + case FormFeature::MoveToFirst: + case FormFeature::MoveToPrevious: + aState.Enabled = impl_canMoveLeft_throw( ); + break; + + case FormFeature::MoveToNext: + aState.Enabled = impl_canMoveRight_throw(); + break; + + case FormFeature::MoveToLast: + aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() ); + break; + + case FormFeature::DeleteRecord: + // already deleted ? + if ( m_xCursor->rowDeleted() ) + aState.Enabled = sal_False; + else + { + // allowed to delete the row ? + aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties ); + } + break; + + case FormFeature::MoveToInsertRow: + // if we are inserting we can move to the next row if the current record or control is modified + aState.Enabled = impl_isInsertionRow_throw() + ? impl_isModifiedRow_throw() || m_bActiveControlModified + : ::dbtools::canInsert( m_xCursorProperties ); + break; + + case FormFeature::ReloadForm: + { + // there must be an active connection + Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY ); + aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is(); + + // and an active command + ::rtl::OUString sActiveCommand; + m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand; + aState.Enabled &= sActiveCommand.getLength() > 0; + } + break; + + case FormFeature::RefreshCurrentControl: + { + Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY ); + aState.Enabled = xControlModelRefresh.is(); + } + break; + + case FormFeature::SaveRecordChanges: + case FormFeature::UndoRecordChanges: + aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified; + break; + + case FormFeature::RemoveFilterAndSort: + if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() ) + aState.Enabled = !impl_isInsertOnlyForm_throw(); + break; + + case FormFeature::SortAscending: + case FormFeature::SortDescending: + case FormFeature::AutoFilter: + if ( m_xController.is() && impl_isParseable_throw() ) + { + sal_Bool bIsDeleted = m_xCursor->rowDeleted(); + + if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() ) + { + Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( ); + if ( xBoundField.is() ) + xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled; + } + } + break; + + case FormFeature::InteractiveSort: + case FormFeature::InteractiveFilter: + if ( impl_isParseable_throw() ) + aState.Enabled = !impl_isInsertOnlyForm_throw(); + break; + + case FormFeature::ToggleApplyFilter: + { + ::rtl::OUString sFilter; + m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter; + if ( sFilter.getLength() ) + { + aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ); + aState.Enabled = !impl_isInsertOnlyForm_throw(); + } + else + aState.State <<= (sal_Bool)sal_False; + } + break; + + case FormFeature::MoveAbsolute: + { + sal_Int32 nPosition = m_xCursor->getRow(); + sal_Bool bIsNew = impl_isInsertionRow_throw(); + sal_Int32 nCount = impl_getRowCount_throw(); + sal_Bool bFinalCount = impl_isRowCountFinal_throw(); + + if ( ( nPosition >= 0 ) || bIsNew ) + { + if ( bFinalCount ) + { + // special case: there are no records at all, and we + // can't insert records -> disabled + if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) ) + { + aState.Enabled = sal_False; + } + else + { + if ( bIsNew ) + nPosition = ++nCount; + aState.State <<= (sal_Int32)nPosition; + aState.Enabled = sal_True; + } + } + else + { + aState.State <<= (sal_Int32)nPosition; + aState.Enabled = sal_True; + } + } + } + break; + + case FormFeature::TotalRecords: + { + sal_Bool bIsNew = impl_isInsertionRow_throw(); + sal_Int32 nCount = impl_getRowCount_throw(); + sal_Bool bFinalCount = impl_isRowCountFinal_throw(); + + if ( bIsNew ) + ++nCount; + + ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) ); + if ( !bFinalCount ) + sValue += ::rtl::OUString::createFromAscii( " *" ); + + aState.State <<= sValue; + aState.Enabled = sal_True; + } + break; + + default: + OSL_ENSURE( sal_False, "FormOperations::getState: unknown feature id!" ); + break; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::getState: caught an exception!" ); + } + + return aState; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + + FeatureState aState( getState( _nFeature ) ); + return aState.Enabled; + } + + //-------------------------------------------------------------------- + namespace + { + static bool lcl_needConfirmCommit( sal_Int32 _nFeature ) + { + return ( ( _nFeature == FormFeature::ReloadForm ) + || ( _nFeature == FormFeature::RemoveFilterAndSort ) + || ( _nFeature == FormFeature::ToggleApplyFilter ) + || ( _nFeature == FormFeature::SortAscending ) + || ( _nFeature == FormFeature::SortDescending ) + || ( _nFeature == FormFeature::AutoFilter ) + || ( _nFeature == FormFeature::InteractiveSort ) + || ( _nFeature == FormFeature::InteractiveFilter ) + ); + } + static bool lcl_requiresArguments( sal_Int32 _nFeature ) + { + return ( _nFeature == FormFeature::MoveAbsolute ); + } + static bool lcl_isExecutableFeature( sal_Int32 _nFeature ) + { + return ( _nFeature != FormFeature::TotalRecords ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + MethodGuard aGuard( *this ); + + if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) ) + { + // if we have a controller, commit the current control + if ( m_xController.is() ) + if ( !impl_commitCurrentControl_throw() ) + return; + + // commit the current record + bool bCommitCurrentRecord = true; + // (but before, let the user confirm if necessary) + if ( impl_isModifiedRow_throw() ) + { + if ( lcl_needConfirmCommit( _nFeature ) ) + { + // TODO: shouldn't this be done with an interaction handler? + QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) ); + switch ( aQuery.Execute() ) + { + case RET_NO: bCommitCurrentRecord = false; break; + case RET_CANCEL: return; + } + } + } + + if ( bCommitCurrentRecord && !impl_commitCurrentRecord_throw() ) + return; + } + + try + { + switch ( _nFeature ) + { + case FormFeature::MoveToFirst: + m_xCursor->first(); + break; + + case FormFeature::MoveToNext: + impl_moveRight_throw( ); + break; + + case FormFeature::MoveToPrevious: + impl_moveLeft_throw( ); + break; + + case FormFeature::MoveToLast: + { +/* + // TODO: re-implement this ..... + // run in an own thread if ... + // ... the data source is thread safe ... + sal_Bool bAllowOwnThread = sal_False; + if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) ) + m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread; + + // ... the record count is unknown + sal_Bool bNeedOwnThread sal_False; + if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) ) + m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread; + + if ( bNeedOwnThread && bAllowOwnThread ) + ; + else +*/ + m_xCursor->last(); + } + break; + + case FormFeature::ReloadForm: + if ( m_xLoadableForm.is() ) + { + WaitObject aWO( NULL ); + m_xLoadableForm->reload(); + + // refresh all controls in the form (and sub forms) which can be refreshed + // #i90914# / 2008-07-02 / frank.schoenheit@sun.com + ::comphelper::IndexAccessIterator aIter( m_xLoadableForm ); + Reference< XInterface > xElement( aIter.Next() ); + while ( xElement.is() ) + { + Reference< XRefreshable > xRefresh( xElement, UNO_QUERY ); + if ( xRefresh.is() ) + xRefresh->refresh(); + xElement = aIter.Next(); + } + } + break; + + case FormFeature::RefreshCurrentControl: + { + Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY ); + OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" ); + if ( xControlModelRefresh.is() ) + xControlModelRefresh->refresh(); + } + break; + + case FormFeature::DeleteRecord: + { + sal_uInt32 nCount = impl_getRowCount_throw(); + + // next position + sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 ); + sal_Bool bRight= !m_xCursor->isLast(); + sal_Bool bSuccess = sal_False; + try + { + // ask for confirmation + Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY ); + + if ( xConfirmDelete.is() ) + { + RowChangeEvent aEvent; + aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY ); + aEvent.Action = RowChangeAction::DELETE; + aEvent.Rows = 1; + bSuccess = xConfirmDelete->confirmDelete( aEvent ); + } + + // delete it + if ( bSuccess ) + m_xUpdateCursor->deleteRow(); + } + catch( const Exception& ) + { + bSuccess = sal_False; + } + + if ( bSuccess ) + { + if ( bLeft || bRight ) + m_xCursor->relative( bRight ? 1 : -1 ); + else + { + sal_Bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties ); + // is it possible to insert another record? + if ( bCanInsert ) + m_xUpdateCursor->moveToInsertRow(); + else + // move record to update stati + m_xCursor->first(); + } + } + } + break; + + case FormFeature::SaveRecordChanges: + case FormFeature::UndoRecordChanges: + { + sal_Bool bInserting = impl_isInsertionRow_throw(); + + if ( FormFeature::UndoRecordChanges == _nFeature ) + { + if ( !bInserting ) + m_xUpdateCursor->cancelRowUpdates(); + + // reset all controls for this form + impl_resetAllControls_nothrow( ); + + if ( bInserting ) // back to insertion mode for this form + m_xUpdateCursor->moveToInsertRow(); + } + else + { + if ( bInserting ) + { + m_xUpdateCursor->insertRow(); + m_xCursor->last(); + } + else + m_xUpdateCursor->updateRow(); + } + } + break; + + case FormFeature::MoveToInsertRow: + // move to the last row before moving to the insert row + // 21.01.2002 - 96480 - fs@openoffice.org + m_xCursor->last(); + m_xUpdateCursor->moveToInsertRow(); + break; + + case FormFeature::RemoveFilterAndSort: + { + // simultaneously reset Filter and Order property + Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY ); + OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" ); + if ( xProperties.is() ) + { + Sequence< ::rtl::OUString > aNames( 2 ); + aNames[0] = PROPERTY_FILTER; + aNames[1] = PROPERTY_SORT; + + Sequence< Any> aValues( 2 ); + aValues[0] <<= ::rtl::OUString(); + aValues[1] <<= ::rtl::OUString(); + + WaitObject aWO( NULL ); + xProperties->setPropertyValues( aNames, aValues ); + + if ( m_xLoadableForm.is() ) + m_xLoadableForm->reload(); + } + } + break; + + case FormFeature::ToggleApplyFilter: + if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() ) + { + // simply toggle the value + sal_Bool bApplied = sal_False; + m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied; + m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) ); + + // and reload + WaitObject aWO( NULL ); + m_xLoadableForm->reload(); + } + break; + + case FormFeature::SortAscending: + impl_executeAutoSort_throw( true ); + break; + + case FormFeature::SortDescending: + impl_executeAutoSort_throw( false ); + break; + + case FormFeature::AutoFilter: + impl_executeAutoFilter_throw(); + break; + + case FormFeature::InteractiveSort: + impl_executeFilterOrSort_throw( false ); + break; + + case FormFeature::InteractiveFilter: + impl_executeFilterOrSort_throw( true ); + break; + + default: + { + sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN; + if ( lcl_requiresArguments( _nFeature ) ) + nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS; + else if ( !lcl_isExecutableFeature( _nFeature ) ) + nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE; + throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 ); + } + } // switch + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const IllegalArgumentException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException) + { + if ( !lcl_requiresArguments( _nFeature ) ) + { + execute( _nFeature ); + return; + } + + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + MethodGuard aGuard( *this ); + + // at the moment we have only one feature which supports execution parameters + if ( !lcl_isExecutableFeature( _nFeature ) ) + throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 ); + + switch ( _nFeature ) + { + case FormFeature::MoveAbsolute: + { + sal_Int32 nPosition = -1; + + ::comphelper::NamedValueCollection aArguments( _rArguments ); + aArguments.get_ensureType( "Position", nPosition ); + + if ( nPosition < 1 ) + nPosition = 1; + + try + { + // commit before doing anything else + if ( m_xController.is() && !impl_commitCurrentControl_throw() ) + return; + if ( !impl_commitCurrentRecord_throw() ) + return; + + sal_Int32 nCount = impl_getRowCount_throw(); + sal_Bool bFinalCount = impl_isRowCountFinal_throw(); + + if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) ) + nPosition = nCount; + + m_xCursor->absolute( nPosition ); + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + } + break; + default: + throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 ); + } // switch + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException) + { + MethodGuard aGuard( *this ); + _out_rRecordInserted = sal_False; + + return impl_commitCurrentRecord_throw( &_out_rRecordInserted ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const + { + DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" ); + + if ( !impl_hasCursor_nothrow() ) + return false; + + // nothing to do if the record is not modified + sal_Bool bResult = !impl_isModifiedRow_throw(); + if ( !bResult ) + { + // insert respectively update the row + if ( impl_isInsertionRow_throw() ) + { + m_xUpdateCursor->insertRow(); + if ( _pRecordInserted ) + *_pRecordInserted = sal_True; + } + else + m_xUpdateCursor->updateRow(); + bResult = true; + } + return bResult; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException) + { + MethodGuard aGuard( *this ); + return impl_commitCurrentControl_throw(); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_commitCurrentControl_throw() const + { + DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" ); + OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" ); + if ( !m_xController.is() ) + return false; + + bool bSuccess = false; + try + { + Reference< XControl > xCurrentControl( m_xController->getCurrentControl() ); + + // check whether the control is locked + Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY ); + sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock(); + + // commit if necessary + bSuccess = true; + if ( xCurrentControl.is() && !bControlIsLocked ) + { + // both the control and it's model can be committable, so try both + Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY ); + if ( !xBound.is() ) + xBound = xBound.query( xCurrentControl->getModel() ); + // and now really commit + if ( xBound.is() ) + bSuccess = xBound->commit(); + } + + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + bSuccess = false; + } + + return bSuccess; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException) + { + sal_Bool bIs = sal_False; + try + { + bIs = impl_isInsertionRow_throw(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + return bIs; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException) + { + sal_Bool bIs = sal_False; + try + { + bIs = impl_isModifiedRow_throw(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + return bIs; + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + m_bActiveControlModified = sal_False; + + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException ) + { + MethodGuard aGuard( *this ); + + OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" ); + if ( !m_bActiveControlModified ) + { + m_bActiveControlModified = sal_True; + impl_invalidateModifyDependentFeatures_nothrow( aGuard ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + + if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) ) + { + sal_Bool bIs = sal_False; + if ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED ) + || ( _rEvent.PropertyName == PROPERTY_ISNEW ) + ) + { + if ( ( _rEvent.NewValue >>= bIs ) && !bIs ) + m_bActiveControlModified = sal_False; + } + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + + if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) ) + { + try + { + ::rtl::OUString sNewValue; + _rEvent.NewValue >>= sNewValue; + if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND ) + { + m_xParser->setElementaryQuery( sNewValue ); + } + else if ( _rEvent.PropertyName == PROPERTY_FILTER ) + { + if ( m_xParser->getFilter() != sNewValue ) + m_xParser->setFilter( sNewValue ); + } + else if ( _rEvent.PropertyName == PROPERTY_SORT ) + { + _rEvent.NewValue >>= sNewValue; + if ( m_xParser->getOrder() != sNewValue ) + m_xParser->setOrder( sNewValue ); + } + } + catch( Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::propertyChange: caught an exception while updating the parser!" ); + } + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException) + { + // TODO: should we react on this? Or is this the responsibility of our owner to dispose us? + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::disposing() + { + ::osl::MutexGuard aGuard( m_aMutex ); + + impl_disposeParser_nothrow(); + + try + { + // revoke various listeners + if ( m_xCursor.is() ) + m_xCursor->removeRowSetListener( this ); + + if ( m_xCursorProperties.is() ) + { + m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this ); + m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this ); + } + + Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->removeModifyListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_xController.clear(); + m_xCursor.clear(); + m_xUpdateCursor.clear(); + m_xCursorProperties.clear(); + m_xLoadableForm.clear(); + m_xFeatureInvalidation.clear(); + + m_bActiveControlModified = true; + } + + //-------------------------------------------------------------------- + void FormOperations::impl_checkDisposed_throw() const + { + if ( impl_isDisposed_nothrow() ) + throw DisposedException( ::rtl::OUString(), *const_cast< FormOperations* >( this ) ); + } + + //-------------------------------------------------------------------- + void FormOperations::impl_initFromController_throw() + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" ); + m_xCursor = m_xCursor.query( m_xController->getModel() ); + if ( !m_xCursor.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + impl_initFromForm_throw(); + + Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->addModifyListener( this ); + } + + //-------------------------------------------------------------------- + void FormOperations::impl_initFromForm_throw() + { + OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" ); + m_xCursorProperties = m_xCursorProperties.query ( m_xCursor ); + m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor ); + m_xLoadableForm = m_xLoadableForm.query ( m_xCursor ); + + if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + m_xCursor->addRowSetListener( this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this ); + } + + //-------------------------------------------------------------------- + void FormOperations::createWithFormController( const Reference< XFormController >& _rxController ) + { + m_xController = _rxController; + if ( !m_xController.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + impl_initFromController_throw(); + + m_bConstructed = true; + } + + //-------------------------------------------------------------------- + void FormOperations::createWithForm( const Reference< XForm >& _rxForm ) + { + m_xCursor = m_xCursor.query( _rxForm ); + if ( !m_xCursor.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + impl_initFromForm_throw(); + + m_bConstructed = true; + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const + { + if ( !m_xFeatureInvalidation.is() ) + // nobody's interested in ... + return; + + Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation; + _rClearForCallback.clear(); + xInvalidation->invalidateAllFeatures(); + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const + { + if ( !m_xFeatureInvalidation.is() ) + // nobody's interested in ... + return; + + static Sequence< sal_Int16 > s_aModifyDependentFeatures; + if ( s_aModifyDependentFeatures.getLength() == 0 ) + { + sal_Int16 pModifyDependentFeatures[] = + { + FormFeature::MoveToNext, + FormFeature::MoveToInsertRow, + FormFeature::SaveRecordChanges, + FormFeature::UndoRecordChanges + }; + size_t nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] ); + s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount ); + } + + Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation; + _rClearForCallback.clear(); + + xInvalidation->invalidateFeatures( s_aModifyDependentFeatures ); + } + + //-------------------------------------------------------------------- + void FormOperations::impl_ensureInitializedParser_nothrow() + { + OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" ); + if ( m_bInitializedParser ) + return; + + try + { + sal_Bool bUseEscapeProcessing = sal_False; + m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing; + if ( bUseEscapeProcessing ) + { + Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY ); + if ( xFactory.is() ) + { + m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY ); + OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" ); + } + } + + if ( m_xParser.is() ) + { + if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() ) + { + ::rtl::OUString sStatement; + ::rtl::OUString sFilter; + ::rtl::OUString sSort; + + m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sStatement; + m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter; + m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sSort; + + m_xParser->setElementaryQuery( sStatement ); + m_xParser->setFilter ( sFilter ); + m_xParser->setOrder ( sSort ); + } + + // start listening at the order/sort properties at the form, so + // we can keep our parser in sync + m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" ); + } + + m_bInitializedParser = true; + } + + //-------------------------------------------------------------------- + void FormOperations::impl_disposeParser_nothrow() + { + try + { + // if we have a parser (and a cursor), then we're listening at the cursor's + // properties to keep the parser in sync with the cursor + if ( m_xParser.is() && m_xCursorProperties.is() ) + { + m_xCursorProperties->removePropertyChangeListener( PROPERTY_FILTER, this ); + m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this ); + m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this ); + } + + Reference< XComponent > xParserComp( m_xParser, UNO_QUERY ); + if ( xParserComp.is() ) + xParserComp->dispose(); + m_xParser.clear(); + + m_bInitializedParser = false; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_disposeParser_nothrow: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_canMoveLeft_throw( ) const + { + if ( !impl_hasCursor_nothrow() ) + return false; + + return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_canMoveRight_throw( ) const + { + if ( !impl_hasCursor_nothrow() ) + return false; + + bool bIsNew = impl_isInsertionRow_throw(); + + if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew ) + return true; + + if ( ::dbtools::canInsert( m_xCursorProperties ) ) + if ( !bIsNew || impl_isModifiedRow_throw() ) + return true; + + if ( bIsNew && m_bActiveControlModified ) + return true; + + return false; + } + + //-------------------------------------------------------------------- + namespace + { + template < typename TYPE > + TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const ::rtl::OUString& _rPropertyName, TYPE _Default ) + { + TYPE value( _Default ); + OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" ); + if ( _rxProperties.is() ) + OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value ); + return value; + } + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isInsertionRow_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false ); + } + + //-------------------------------------------------------------------- + sal_Int32 FormOperations::impl_getRowCount_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 ); + } + //-------------------------------------------------------------------- + bool FormOperations::impl_isRowCountFinal_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isModifiedRow_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isParseable_throw() const + { + const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow(); + return m_xParser.is() && m_xParser->getQuery().getLength(); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_hasFilterOrOrder_throw() const + { + return impl_isParseable_throw() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isInsertOnlyForm_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true ); + } + + //------------------------------------------------------------------------------ + Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const + { + Reference< XControl > xControl( m_xController->getCurrentControl() ); + + // special handling for grid controls + Reference< XGrid > xGrid( xControl, UNO_QUERY ); + Reference< XControlModel > xControlModel; + + if ( xGrid.is() ) + { + Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW ); + sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition(); + nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos ); + + if ( nCurrentPos != (sal_Int16)-1 ) + xColumns->getByIndex( nCurrentPos ) >>= xControlModel; + } + else if ( xControl.is() ) + { + xControlModel = xControl->getModel(); + } + return xControlModel; + } + + //------------------------------------------------------------------------------ + Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" ); + if ( !m_xController.is() ) + return NULL; + + Reference< XPropertySet > xField; + try + { + Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY ); + + if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) ) + xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField; + + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return xField; + } + + //------------------------------------------------------------------------------ + sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const + { + OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" ); + try + { + // loop through all columns + sal_Int16 col = 0; + Reference< XPropertySet > xCol; + bool bHidden( false ); + for ( col = 0; col < _rxColumns->getCount(); ++col ) + { + _rxColumns->getByIndex( col ) >>= xCol; + OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden ); + if ( bHidden ) + continue; + + // for every visible col : if nViewPos is greater zero, decrement it, else we + // have found the model position + if ( !_nViewPos ) + break; + else + --_nViewPos; + } + if ( col < _rxColumns->getCount() ) + return col; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return (sal_Int16)-1; + } + + //------------------------------------------------------------------------------ + bool FormOperations::impl_moveLeft_throw( ) const + { + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" ); + if ( !impl_hasCursor_nothrow() ) + return false; + + sal_Bool bRecordInserted = sal_False; + sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted ); + + if ( !bSuccess ) + return false; + + if ( bRecordInserted ) + { + // retrieve the bookmark of the new record and move to the record preceding this bookmark + Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY ); + OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" ); + if ( xLocate.is() ) + xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 ); + } + else + { + if ( impl_isInsertionRow_throw() ) + { + // we assume that the inserted record is now the last record in the + // result set + m_xCursor->last(); + } + else + m_xCursor->previous(); + } + + return true; + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_moveRight_throw( ) const + { + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" ); + if ( !impl_hasCursor_nothrow() ) + return false; + + sal_Bool bRecordInserted = sal_False; + sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted ); + + if ( !bSuccess ) + return false; + + if ( bRecordInserted ) + { + // go to insert row + m_xUpdateCursor->moveToInsertRow(); + } + else + { + if ( m_xCursor->isLast() ) + m_xUpdateCursor->moveToInsertRow(); + else + m_xCursor->next(); + } + + return true; + } + + //-------------------------------------------------------------------- + void FormOperations::impl_resetAllControls_nothrow() const + { + Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY ); + if ( !xContainer.is() ) + return; + + try + { + Reference< XReset > xReset; + sal_Int32 nCount( xContainer->getCount() ); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + if ( xContainer->getByIndex( i ) >>= xReset ) + { + // no resets on sub forms + Reference< XForm > xAsForm( xReset, UNO_QUERY ); + if ( !xAsForm.is() ) + xReset->reset(); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" ); + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" ); + OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" ); + if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) + return; + + try + { + Reference< XControl > xControl = m_xController->getCurrentControl(); + if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) + return; + + Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() ); + if ( !xBoundField.is() ) + return; + + ::rtl::OUString sOriginalSort; + m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort; + + // automatic sort by field is expected to always resets the previous sort order + m_xParser->setOrder( ::rtl::OUString() ); + + param_appendOrderByColumn aParam; + aParam.xField = xBoundField; + aParam.bUp = _bUp; + impl_doActionInSQLContext_throw( + (Action)&FormOperations::impl_appendOrderByColumn_throw, + static_cast< const void* >( &aParam ), + (sal_uInt16)RID_STR_COULD_NOT_SET_ORDER + ); + + WaitObject aWO( NULL ); + try + { + m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" ); + } + + + if ( !m_xLoadableForm->isLoaded() ) + { // something went wrong -> restore the original state + try + { + m_xParser->setOrder( sOriginalSort ); + m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" ); + } + + } + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_executeAutoFilter_throw( ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" ); + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" ); + OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" ); + if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) + return; + + try + { + Reference< XControl > xControl = m_xController->getCurrentControl(); + if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) + return; + + Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() ); + if ( !xBoundField.is() ) + return; + + ::rtl::OUString sOriginalFilter; + m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter; + sal_Bool bApplied = sal_True; + m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied; + + // if we have a filter, but it's not applied, then we have to overwrite it, else append one + if ( !bApplied ) + m_xParser->setFilter( ::rtl::OUString() ); + + param_appendFilterByColumn aParam; + aParam.xField = xBoundField; + impl_doActionInSQLContext_throw( + (Action)&FormOperations::impl_appendFilterByColumn_throw, + static_cast< const void* >( &aParam ), + (sal_uInt16)RID_STR_COULD_NOT_SET_FILTER + ); + + WaitObject aWO( NULL ); + try + { + m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); + m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) ); + + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" ); + } + + + if ( !m_xLoadableForm->isLoaded() ) + { // something went wrong -> restore the original state + try + { + m_xParser->setOrder( sOriginalFilter ); + m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) ); + m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" ); + } + + } + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + + //-------------------------------------------------------------------- + void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" ); + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" ); + OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" ); + if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) + return; + + if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) + return; + try + { + PropertyValue aFirst; + aFirst.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "QueryComposer" ) ); + aFirst.Value <<= m_xParser; + + PropertyValue aSecond; + aSecond.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowSet" ) ); + aSecond.Value <<= m_xCursorProperties; + + Sequence<Any> aInit(2); + aInit[0] <<= aFirst; + aInit[1] <<= aSecond; + + ::rtl::OUString sDialogServiceName; + if ( _bFilter ) + sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FilterDialog" ) ); + else + sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.OrderDialog" ) ); + + Reference< XExecutableDialog> xDialog; + m_aContext.createComponentWithArguments( sDialogServiceName, aInit, xDialog ); + + if ( !xDialog.is() ) + { + ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True ); + return; + } + + if ( RET_OK == xDialog->execute() ) + { + WaitObject aWO( NULL ); + if ( _bFilter ) + m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); + else + m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); + m_xLoadableForm->reload(); + } + + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_appendOrderByColumn_throw( const void* _pActionParam ) const + { + const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam ); + m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp ); + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_appendFilterByColumn_throw( const void* _pActionParam ) const + { + const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam ); + m_xParser->appendFilterByColumn( pParam->xField, sal_True ); + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const + { + try + { + (this->*_pAction)( _pParam ); + } + catch( const SQLException& e ) + { + (void)e; + if ( !_nErrorResourceId ) + // no information to prepend + throw; + + SQLExceptionInfo aInfo( ::cppu::getCaughtException() ); + ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) ); + aInfo.prepend( sAdditionalError ); + aInfo.doThrow(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) ); + throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/runtime/formoperations.hxx b/forms/source/runtime/formoperations.hxx new file mode 100644 index 000000000000..374df8c2165c --- /dev/null +++ b/forms/source/runtime/formoperations.hxx @@ -0,0 +1,379 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_FORMOPERATIONS_HXX +#define FORMS_FORMOPERATIONS_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/form/runtime/XFormOperations.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase6.hxx> + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= FormOperations + //==================================================================== + typedef ::cppu::WeakComponentImplHelper6 < ::com::sun::star::form::runtime::XFormOperations + , ::com::sun::star::lang::XInitialization + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::beans::XPropertyChangeListener + , ::com::sun::star::util::XModifyListener + , ::com::sun::star::sdbc::XRowSetListener + > FormOperations_Base; + + class FormOperations :public ::cppu::BaseMutex + ,public FormOperations_Base + { + public: + class MethodGuard; + + private: + ::comphelper::ComponentContext m_aContext; + ::com::sun::star::uno::Reference< ::com::sun::star::form::runtime::XFormController > m_xController; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > m_xCursor; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetUpdate > m_xUpdateCursor; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xCursorProperties; + ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadable > m_xLoadableForm; + ::com::sun::star::uno::Reference< ::com::sun::star::form::runtime::XFeatureInvalidation > + m_xFeatureInvalidation; + mutable ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer > + m_xParser; + + bool m_bInitializedParser; + bool m_bActiveControlModified; + bool m_bConstructed; + #ifdef DBG_UTIL + mutable long + m_nMethodNestingLevel; + #endif + + public: + FormOperations( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxContext ); + + // XServiceInfo - static versions + static ::rtl::OUString getImplementationName_Static( ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static( ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&); + + struct MethodAccess { friend class MethodGuard; private: MethodAccess() { } }; + + inline void enterMethod( MethodAccess ) const + { + m_aMutex.acquire(); + impl_checkDisposed_throw(); + #ifdef DBG_UTIL + ++m_nMethodNestingLevel; + #endif + } + + inline void leaveMethod( MethodAccess ) const + { + m_aMutex.release(); + #ifdef DBG_UTIL + --m_nMethodNestingLevel; + #endif + } + + protected: + virtual ~FormOperations(); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XFormOperations + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > SAL_CALL getCursor() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetUpdate > SAL_CALL getUpdateCursor() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::runtime::XFormController > SAL_CALL getController() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::runtime::XFeatureInvalidation > SAL_CALL getFeatureInvalidation() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFeatureInvalidation(const ::com::sun::star::uno::Reference< ::com::sun::star::form::runtime::XFeatureInvalidation > & the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::form::runtime::FeatureState SAL_CALL getState(::sal_Int16 Feature) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isEnabled(::sal_Int16 Feature) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL execute(::sal_Int16 Feature) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::sdbc::SQLException, ::com::sun::star::lang::WrappedTargetException); + virtual void SAL_CALL executeWithArguments(::sal_Int16 Feature, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::sdbc::SQLException, ::com::sun::star::lang::WrappedTargetException); + virtual ::sal_Bool SAL_CALL commitCurrentRecord(::sal_Bool & RecordInserted) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::sdbc::SQLException); + virtual ::sal_Bool SAL_CALL commitCurrentControl() throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::sdbc::SQLException); + virtual ::sal_Bool SAL_CALL isInsertionRow() throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::WrappedTargetException); + virtual ::sal_Bool SAL_CALL isModifiedRow() throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::WrappedTargetException); + + // XRowSetListener + virtual void SAL_CALL cursorMoved( const ::com::sun::star::lang::EventObject& event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowChanged( const ::com::sun::star::lang::EventObject& event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowSetChanged( const ::com::sun::star::lang::EventObject& event ) throw (::com::sun::star::uno::RuntimeException); + + // XModifyListener + virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& _rSource ) throw( ::com::sun::star::uno::RuntimeException ); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // XComponent/OComponentHelper + virtual void SAL_CALL disposing(); + + private: + // service constructors + void createWithFormController( const ::com::sun::star::uno::Reference< ::com::sun::star::form::runtime::XFormController >& _rxController ); + void createWithForm( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm >& _rxForm ); + + /** determines whether or not we're already disposed + */ + inline bool impl_isDisposed_nothrow() const { return !m_xCursor.is(); } + + /** checks whether the instance is already disposed, and throws an exception if so + */ + void impl_checkDisposed_throw() const; + + /** initializes the instance after m_xController has been set + @precond + m_xController is not <NULL/> + */ + void impl_initFromController_throw(); + + /** initializes the instance after m_xCursor has been set + @precond + m_xCursor is not <NULL/> + */ + void impl_initFromForm_throw(); + + /// invalidate the full palette of features which we know + void impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const; + + /** invalidate the features which depend on the "modified" state of the current control + of our controller + */ + void impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const; + + /** ensures that our parse is initialized, or at least that we attempted to do so + @precond + we're not disposed + */ + void impl_ensureInitializedParser_nothrow(); + + /// disposes our parser, if we have one + void impl_disposeParser_nothrow(); + + /** determines whether our cursor can be moved left + @precond hasCursor() + */ + bool impl_canMoveLeft_throw() const; + + /** determines whether our cursor can be moved right + @precond hasCursor() + */ + bool impl_canMoveRight_throw() const; + + /// determines whether we're positioned on the insertion row + bool impl_isInsertionRow_throw() const; + + /// retrieves the RowCount property of the form + sal_Int32 impl_getRowCount_throw() const; + + /// retrieves the RowCountFinal property of the form + bool impl_isRowCountFinal_throw() const; + + /// retrieves the IsModified property of the form + bool impl_isModifiedRow_throw() const; + + /// determines whether we can parse the query of our form + bool impl_isParseable_throw() const; + + /// determines if we have an active filter or order condition + bool impl_hasFilterOrOrder_throw() const; + + /// determines whether our form is in "insert-only" mode + bool impl_isInsertOnlyForm_throw() const; + + /** retrieces the column to which the current control of our controller is bound + @precond + m_xController.is() + */ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + impl_getCurrentBoundField_nothrow( ) const; + + /** returns the control model of the current control + + If the current control is a grid control, then the returned model is the + model of the current <em>column</em> in the grid. + + @precond + m_xController.is() + */ + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > + impl_getCurrentControlModel_throw() const; + + /// determines if we have a valid cursor + inline bool impl_hasCursor_nothrow() const { return m_xCursorProperties.is(); } + + /** determines the model position from a grid control column's view position + + A grid control can have columns which are currently hidden, so the index of a + column in the view is not necessarily the same as its index in the model. + */ + sal_Int16 impl_gridView2ModelPos_nothrow( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const; + + /** moves our cursor one position to the left, caring for different possible + cursor states. + + Before the movement is done, the current row is saved, if necessary. + + @precond + canMoveLeft() + */ + bool impl_moveLeft_throw() const; + + /** moves our cursor one position to the right, caring for different possible + cursor states. + + Before the movement is done, the current row is saved, if necessary. + + @precond + canMoveRight() + */ + bool impl_moveRight_throw( ) const; + + /** impl-version of commitCurrentRecord, which can be called without caring for + an output parameter, and within const-contexts + + @precond + our mutex is locked + */ + bool impl_commitCurrentRecord_throw( sal_Bool* _pRecordInserted = NULL ) const; + + /** impl-version of commitCurrentControl, which can be called in const-contexts + + @precond + our mutex is locked + */ + bool impl_commitCurrentControl_throw() const; + + /// resets all control models in our own form + void impl_resetAllControls_nothrow() const; + + /// executes the "auto sort ascending" and "auto sort descending" features + void impl_executeAutoSort_throw( bool _bUp ) const; + + /// executes the "auto filter" feature + void impl_executeAutoFilter_throw( ) const; + + /// executes the interactive sort resp. filter feature + void impl_executeFilterOrSort_throw( bool _bFilter ) const; + + private: + /// typedef for member method of this class + typedef void (FormOperations::*Action)( const void* ) const; + + /** calls a member function, catches SQLExceptions, extends them with additional context information, + and rethrows them + + @param _pAction + the member function to call + @param _pParam + the parameters to pass to the member function + @param _nErrorResourceId + the id of the resources string to use as error message + */ + void impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const; + + // parameter structure for appendOrderByColumn + struct param_appendOrderByColumn + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + xField; + bool bUp; + }; + void impl_appendOrderByColumn_throw( const void* _pActionParam ) const; + + // parameter structure for appendFilterByColumn + struct param_appendFilterByColumn + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + xField; + }; + void impl_appendFilterByColumn_throw( const void* _pActionParam ) const; + + private: + FormOperations(); // never implemented + FormOperations( const FormOperations& ); // never implemented + FormOperations& operator=( const FormOperations& ); // never implemented + + public: + class MethodGuard + { + FormOperations& m_rOwner; + bool m_bCleared; + + public: + inline MethodGuard( FormOperations& _rOwner ) + :m_rOwner( _rOwner ) + ,m_bCleared( false ) + { + m_rOwner.enterMethod( FormOperations::MethodAccess() ); + } + + inline ~MethodGuard() + { + clear(); + } + + inline void clear() + { + if ( !m_bCleared ) + m_rOwner.leaveMethod( FormOperations::MethodAccess() ); + m_bCleared = true; + } + }; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_FORMOPERATIONS_HXX diff --git a/forms/source/runtime/makefile.mk b/forms/source/runtime/makefile.mk new file mode 100644 index 000000000000..90e3750378af --- /dev/null +++ b/forms/source/runtime/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=.. +PRJNAME=forms +TARGET=runtime + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/formoperations.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/solar/component/makefile.mk b/forms/source/solar/component/makefile.mk new file mode 100644 index 000000000000..06471405a3e2 --- /dev/null +++ b/forms/source/solar/component/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=forms +TARGET=solarcomponent + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Types ------------------------------------- + +INCPRE+=$(SOLARINCDIR)$/offuh + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/navbarcontrol.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/solar/component/navbarcontrol.cxx b/forms/source/solar/component/navbarcontrol.cxx new file mode 100644 index 000000000000..d31727cff125 --- /dev/null +++ b/forms/source/solar/component/navbarcontrol.cxx @@ -0,0 +1,564 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "navbarcontrol.hxx" +#include "frm_strings.hxx" +#include "frm_module.hxx" +#include "FormComponent.hxx" +#include "componenttools.hxx" +#include "navtoolbar.hxx" +#include "commandimageprovider.hxx" +#include "commanddescriptionprovider.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XView.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/form/runtime/FormFeature.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +/** === end UNO includes === **/ + +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ONavigationBarControl() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ONavigationBarControl > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::graphic; + namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; + +#define FORWARD_TO_PEER_1( unoInterface, method, param1 ) \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + xTypedPeer->method( param1 ); \ + } + +#define FORWARD_TO_PEER_1_RET( returnType, unoInterface, method, param1 ) \ + returnType aReturn; \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + aReturn = xTypedPeer->method( param1 ); \ + } \ + return aReturn; + +#define FORWARD_TO_PEER_3( unoInterface, method, param1, param2, param3 ) \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + xTypedPeer->method( param1, param2, param3 ); \ + } + +#define FORWARD_TO_PEER_3_RET( returnType, unoInterface, method, param1, param2, param3 ) \ + returnType aReturn; \ + Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \ + if ( xTypedPeer.is() ) \ + { \ + aReturn = xTypedPeer->method( param1, param2, param3 ); \ + } \ + return aReturn; + + //================================================================== + // ONavigationBarControl + //================================================================== + DBG_NAME( ONavigationBarControl ) + //------------------------------------------------------------------ + ONavigationBarControl::ONavigationBarControl( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + { + DBG_CTOR( ONavigationBarControl, NULL ); + } + + //------------------------------------------------------------------ + ONavigationBarControl::~ONavigationBarControl() + { + DBG_DTOR( ONavigationBarControl, NULL ); + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ONavigationBarControl, UnoControl, ONavigationBarControl_Base ) + + //------------------------------------------------------------------ + Any SAL_CALL ONavigationBarControl::queryAggregation( const Type& _rType ) throw ( RuntimeException ) + { + Any aReturn = UnoControl::queryAggregation( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = ONavigationBarControl_Base::queryInterface( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------ + namespace + { + //.............................................................. + static WinBits lcl_getWinBits_nothrow( const Reference< XControlModel >& _rxModel ) + { + WinBits nBits = 0; + try + { + Reference< XPropertySet > xProps( _rxModel, UNO_QUERY ); + if ( xProps.is() ) + { + sal_Int16 nBorder = 0; + xProps->getPropertyValue( PROPERTY_BORDER ) >>= nBorder; + if ( nBorder ) + nBits |= WB_BORDER; + + sal_Bool bTabStop = sal_False; + if ( xProps->getPropertyValue( PROPERTY_TABSTOP ) >>= bTabStop ) + nBits |= ( bTabStop ? WB_TABSTOP : WB_NOTABSTOP ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return nBits; + } + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarControl::createPeer( const Reference< XToolkit >& /*_rToolkit*/, const Reference< XWindowPeer >& _rParentPeer ) throw( RuntimeException ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if (!getPeer().is()) + { + mbCreatingPeer = sal_True; + + // determine the VLC window for the parent + Window* pParentWin = NULL; + if ( _rParentPeer.is() ) + { + VCLXWindow* pParentXWin = VCLXWindow::GetImplementation( _rParentPeer ); + if ( pParentXWin ) + pParentWin = pParentXWin->GetWindow(); + DBG_ASSERT( pParentWin, "ONavigationBarControl::createPeer: could not obtain the VCL-level parent window!" ); + } + + // create the peer + ONavigationBarPeer* pPeer = ONavigationBarPeer::Create( m_xORB, pParentWin, getModel() ); + DBG_ASSERT( pPeer, "ONavigationBarControl::createPeer: invalid peer returned!" ); + if ( pPeer ) + // by definition, the returned component is aquired once + pPeer->release(); + + // announce the peer to the base class + setPeer( pPeer ); + + // initialize ourself (and thus the peer) with the model properties + updateFromModel(); + + Reference< XView > xPeerView( getPeer(), UNO_QUERY ); + if ( xPeerView.is() ) + { + xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY ); + xPeerView->setGraphics( mxGraphics ); + } + + // a lot of initial settings from our component infos + setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, PosSize::POSSIZE ); + + pPeer->setVisible ( maComponentInfos.bVisible && !mbDesignMode ); + pPeer->setEnable ( maComponentInfos.bEnable ); + pPeer->setDesignMode( mbDesignMode ); + + peerCreated(); + + mbCreatingPeer = sal_False; + + OControl::initFormControlPeer( getPeer() ); + } + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarControl::getImplementationName() throw( RuntimeException ) + { + return getImplementationName_Static(); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ONavigationBarControl::getSupportedServiceNames() throw( RuntimeException ) + { + return getSupportedServiceNames_Static(); + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarControl::getImplementationName_Static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.form.ONavigationBarControl" ) ); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ONavigationBarControl::getSupportedServiceNames_Static() + { + Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) ); + aServices[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.NavigationToolBar" ) ); + return aServices; + } + + //------------------------------------------------------------------ + Reference< XInterface > SAL_CALL ONavigationBarControl::Create( const Reference< XMultiServiceFactory >& _rxFactory ) + { + return *( new ONavigationBarControl( _rxFactory ) ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + FORWARD_TO_PEER_1( XDispatchProviderInterception, registerDispatchProviderInterceptor, _rxInterceptor ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + FORWARD_TO_PEER_1( XDispatchProviderInterception, releaseDispatchProviderInterceptor, _rxInterceptor ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarControl::setDesignMode( sal_Bool _bOn ) throw( RuntimeException ) + { + UnoControl::setDesignMode( _bOn ); + FORWARD_TO_PEER_1( XVclWindowPeer, setDesignMode, _bOn ); + } + + //================================================================== + // ONavigationBarPeer + //================================================================== + DBG_NAME( ONavigationBarPeer ) + //------------------------------------------------------------------ + ONavigationBarPeer* ONavigationBarPeer::Create( const Reference< XMultiServiceFactory >& _rxORB, + Window* _pParentWindow, const Reference< XControlModel >& _rxModel ) + { + DBG_TESTSOLARMUTEX(); + + // the peer itself + ONavigationBarPeer* pPeer = new ONavigationBarPeer( _rxORB ); + pPeer->acquire(); // by definition, the returned object is aquired once + + // the VCL control for the peer + Reference< XModel > xContextDocument( getXModel( _rxModel ) ); + NavigationToolBar* pNavBar = new NavigationToolBar( + _pParentWindow, + lcl_getWinBits_nothrow( _rxModel ), + createDocumentCommandImageProvider( _rxORB, xContextDocument ), + createDocumentCommandDescriptionProvider( _rxORB, xContextDocument ) + ); + + // some knittings + pNavBar->setDispatcher( pPeer ); + pNavBar->SetComponentInterface( pPeer ); + + // we want a faster repeating rate for the slots in this + // toolbox + AllSettings aSettings = pNavBar->GetSettings(); + MouseSettings aMouseSettings = aSettings.GetMouseSettings(); + aMouseSettings.SetButtonRepeat( 10 ); + aSettings.SetMouseSettings( aMouseSettings ); + pNavBar->SetSettings( aSettings, TRUE ); + + // outta here + return pPeer; + } + + //------------------------------------------------------------------ + ONavigationBarPeer::ONavigationBarPeer( const Reference< XMultiServiceFactory >& _rxORB ) + :OFormNavigationHelper( _rxORB ) + { + DBG_CTOR( ONavigationBarPeer, NULL ); + } + + //------------------------------------------------------------------ + ONavigationBarPeer::~ONavigationBarPeer() + { + DBG_DTOR( ONavigationBarPeer, NULL ); + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XINTERFACE2( ONavigationBarPeer, VCLXWindow, OFormNavigationHelper ) + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ONavigationBarPeer, VCLXWindow, OFormNavigationHelper ) + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarPeer::dispose( ) throw( RuntimeException ) + { + VCLXWindow::dispose(); + OFormNavigationHelper::dispose(); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarPeer::setProperty( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw( RuntimeException ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + NavigationToolBar* pNavBar = static_cast< NavigationToolBar* >( GetWindow() ); + if ( !pNavBar ) + { + VCLXWindow::setProperty( _rPropertyName, _rValue ); + return; + } + + bool bVoid = !_rValue.hasValue(); + + sal_Bool bBoolValue = sal_False; + sal_Int32 nColor = COL_TRANSPARENT; + + // TODO: more generic mechanisms for this (the grid control implementation, + // when used herein, will do the same stuff for lot of these) + + if ( _rPropertyName.equals( PROPERTY_BACKGROUNDCOLOR ) ) + { + Wallpaper aTest = pNavBar->GetBackground(); + if ( bVoid ) + { + pNavBar->SetBackground( pNavBar->GetSettings().GetStyleSettings().GetFaceColor() ); + pNavBar->SetControlBackground(); + } + else + { + OSL_VERIFY( _rValue >>= nColor ); + Color aColor( nColor ); + pNavBar->SetBackground( aColor ); + pNavBar->SetControlBackground( aColor ); + } + } + else if ( _rPropertyName.equals( PROPERTY_TEXTLINECOLOR ) ) + { + if ( bVoid ) + { + pNavBar->SetTextLineColor(); + } + else + { + OSL_VERIFY( _rValue >>= nColor ); + Color aColor( nColor ); + pNavBar->SetTextLineColor( nColor ); + } + } + else if ( _rPropertyName.equals( PROPERTY_ICONSIZE ) ) + { + sal_Int16 nInt16Value = 0; + OSL_VERIFY( _rValue >>= nInt16Value ); + pNavBar->SetImageSize( nInt16Value ? NavigationToolBar::eLarge : NavigationToolBar::eSmall ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_POSITION ) ) + { + OSL_VERIFY( _rValue >>= bBoolValue ); + pNavBar->ShowFunctionGroup( NavigationToolBar::ePosition, bBoolValue ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_NAVIGATION ) ) + { + OSL_VERIFY( _rValue >>= bBoolValue ); + pNavBar->ShowFunctionGroup( NavigationToolBar::eNavigation, bBoolValue ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_RECORDACTIONS ) ) + { + OSL_VERIFY( _rValue >>= bBoolValue ); + pNavBar->ShowFunctionGroup( NavigationToolBar::eRecordActions, bBoolValue ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_FILTERSORT ) ) + { + OSL_VERIFY( _rValue >>= bBoolValue ); + pNavBar->ShowFunctionGroup( NavigationToolBar::eFilterSort, bBoolValue ); + } + else + { + VCLXWindow::setProperty( _rPropertyName, _rValue ); + } + } + + //------------------------------------------------------------------ + Any SAL_CALL ONavigationBarPeer::getProperty( const ::rtl::OUString& _rPropertyName ) throw( RuntimeException ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + Any aReturn; + NavigationToolBar* pNavBar = static_cast< NavigationToolBar* >( GetWindow() ); + + if ( _rPropertyName.equals( PROPERTY_BACKGROUNDCOLOR ) ) + { + aReturn <<= (sal_Int32)pNavBar->GetControlBackground().GetColor(); + } + else if ( _rPropertyName.equals( PROPERTY_TEXTLINECOLOR ) ) + { + aReturn <<= (sal_Int32)pNavBar->GetTextLineColor().GetColor(); + } + else if ( _rPropertyName.equals( PROPERTY_ICONSIZE ) ) + { + sal_Int16 nIconType = ( NavigationToolBar::eLarge == pNavBar->GetImageSize() ) + ? 1 : 0; + aReturn <<= nIconType; + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_POSITION ) ) + { + aReturn <<= (sal_Bool)( pNavBar->IsFunctionGroupVisible( NavigationToolBar::ePosition ) ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_NAVIGATION ) ) + { + aReturn <<= (sal_Bool)( pNavBar->IsFunctionGroupVisible( NavigationToolBar::eNavigation ) ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_RECORDACTIONS ) ) + { + aReturn <<= (sal_Bool)( pNavBar->IsFunctionGroupVisible( NavigationToolBar::eRecordActions ) ); + } + else if ( _rPropertyName.equals( PROPERTY_SHOW_FILTERSORT ) ) + { + aReturn <<= (sal_Bool)( pNavBar->IsFunctionGroupVisible( NavigationToolBar::eFilterSort ) ); + } + else + aReturn = VCLXWindow::getProperty( _rPropertyName ); + + return aReturn; + } + + //------------------------------------------------------------------ + void ONavigationBarPeer::interceptorsChanged( ) + { + if ( isDesignMode() ) + // not interested in if we're in design mode + return; + + OFormNavigationHelper::interceptorsChanged(); + } + + //------------------------------------------------------------------ + void ONavigationBarPeer::featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ) + { + // enable this button on the toolbox + NavigationToolBar* pNavBar = static_cast< NavigationToolBar* >( GetWindow() ); + if ( pNavBar ) + { + pNavBar->enableFeature( _nFeatureId, _bEnabled ); + + // is it a feature with additional state information? + if ( _nFeatureId == FormFeature::ToggleApplyFilter ) + { // additional boolean state + pNavBar->checkFeature( _nFeatureId, getBooleanState( _nFeatureId ) ); + } + else if ( _nFeatureId == FormFeature::TotalRecords ) + { + pNavBar->setFeatureText( _nFeatureId, getStringState( _nFeatureId ) ); + } + else if ( _nFeatureId == FormFeature::MoveAbsolute ) + { + pNavBar->setFeatureText( _nFeatureId, String::CreateFromInt32( getIntegerState( _nFeatureId ) ) ); + } + } + + // base class + OFormNavigationHelper::featureStateChanged( _nFeatureId, _bEnabled ); + } + + //------------------------------------------------------------------ + void ONavigationBarPeer::allFeatureStatesChanged( ) + { + // force the control to update it's states + NavigationToolBar* pNavBar = static_cast< NavigationToolBar* >( GetWindow() ); + if ( pNavBar ) + pNavBar->setDispatcher( this ); + + // base class + OFormNavigationHelper::allFeatureStatesChanged( ); + } + + //------------------------------------------------------------------ + bool ONavigationBarPeer::isEnabled( sal_Int16 _nFeatureId ) const + { + if ( const_cast< ONavigationBarPeer* >( this )->isDesignMode() ) + return false; + + return OFormNavigationHelper::isEnabled( _nFeatureId ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarPeer::setDesignMode( sal_Bool _bOn ) throw( RuntimeException ) + { + VCLXWindow::setDesignMode( _bOn ); + + if ( _bOn ) + disconnectDispatchers(); + else + connectDispatchers(); + // this will connect if not already connected and just update else + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarPeer::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + VCLXWindow::disposing( _rSource ); + OFormNavigationHelper::disposing( _rSource ); + } + + //------------------------------------------------------------------ + void ONavigationBarPeer::getSupportedFeatures( ::std::vector< sal_Int16 >& _rFeatureIds ) + { + _rFeatureIds.push_back( FormFeature::MoveAbsolute ); + _rFeatureIds.push_back( FormFeature::TotalRecords ); + _rFeatureIds.push_back( FormFeature::MoveToFirst ); + _rFeatureIds.push_back( FormFeature::MoveToPrevious ); + _rFeatureIds.push_back( FormFeature::MoveToNext ); + _rFeatureIds.push_back( FormFeature::MoveToLast ); + _rFeatureIds.push_back( FormFeature::SaveRecordChanges ); + _rFeatureIds.push_back( FormFeature::UndoRecordChanges ); + _rFeatureIds.push_back( FormFeature::MoveToInsertRow ); + _rFeatureIds.push_back( FormFeature::DeleteRecord ); + _rFeatureIds.push_back( FormFeature::ReloadForm ); + _rFeatureIds.push_back( FormFeature::RefreshCurrentControl ); + _rFeatureIds.push_back( FormFeature::SortAscending ); + _rFeatureIds.push_back( FormFeature::SortDescending ); + _rFeatureIds.push_back( FormFeature::InteractiveSort ); + _rFeatureIds.push_back( FormFeature::AutoFilter ); + _rFeatureIds.push_back( FormFeature::InteractiveFilter ); + _rFeatureIds.push_back( FormFeature::ToggleApplyFilter ); + _rFeatureIds.push_back( FormFeature::RemoveFilterAndSort ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/solar/component/navbarcontrol.hxx b/forms/source/solar/component/navbarcontrol.hxx new file mode 100644 index 000000000000..1e7c6cd8b854 --- /dev/null +++ b/forms/source/solar/component/navbarcontrol.hxx @@ -0,0 +1,162 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_NAVBARCONTROL_HXX +#define FORMS_NAVBARCONTROL_HXX + +#include "formnavigation.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> +/** === end UNO includes === **/ + +#include <toolkit/controls/unocontrol.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/implbase1.hxx> +#include <vcl/wintypes.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //================================================================== + // ONavigationBarControl + //================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::frame::XDispatchProviderInterception + > ONavigationBarControl_Base; + + class ONavigationBarControl + :public UnoControl + ,public ONavigationBarControl_Base + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + m_xORB; + + public: + ONavigationBarControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB + ); + + protected: + ~ONavigationBarControl(); + + public: + // XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + // UNO + DECLARE_UNO3_AGG_DEFAULTS( ONavigationBarControl, UnoControl ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw ( ::com::sun::star::uno::RuntimeException ); + + // XControl + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit >& _rToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _rParent ) throw( ::com::sun::star::uno::RuntimeException ); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XVclWindowPeer + virtual void SAL_CALL setDesignMode( sal_Bool _bOn ) throw( ::com::sun::star::uno::RuntimeException ); + + // XDispatchProviderInterception + virtual void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + }; + + //================================================================== + // ONavigationBarPeer + //================================================================== + class ONavigationBarPeer + :public VCLXWindow + ,public OFormNavigationHelper + { + public: + /** factory method + @return + a new ONavigationBarPeer instance, which has been aquired once! + */ + static ONavigationBarPeer* Create( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + Window* _pParentWindow, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& _rxModel + ); + + protected: + ONavigationBarPeer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB + ); + ~ONavigationBarPeer(); + + public: + // XInterface + DECLARE_XINTERFACE( ) + + // XVclWindowPeer + virtual void SAL_CALL setDesignMode( sal_Bool _bOn ) throw( ::com::sun::star::uno::RuntimeException ); + + // XWindow2 + using VCLXWindow::isEnabled; + + protected: + // XTypeProvider + DECLARE_XTYPEPROVIDER( ) + + // XComponent + void SAL_CALL dispose( ) throw( ::com::sun::star::uno::RuntimeException ); + + // XVclWindowPeer + void SAL_CALL setProperty( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rValue ) throw( ::com::sun::star::uno::RuntimeException ); + ::com::sun::star::uno::Any SAL_CALL getProperty( const ::rtl::OUString& _rPropertyName ) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // OFormNavigationHelper overriables + virtual void interceptorsChanged( ); + virtual void featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ); + virtual void allFeatureStatesChanged( ); + virtual void getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ); + + // IFeatureDispatcher overriables + virtual bool isEnabled( sal_Int16 _nFeatureId ) const; + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_NAVBARCONTROL_HXX diff --git a/forms/source/solar/control/makefile.mk b/forms/source/solar/control/makefile.mk new file mode 100644 index 000000000000..906f5938d596 --- /dev/null +++ b/forms/source/solar/control/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=forms +TARGET=solarcontrol + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Types ------------------------------------- + +INCPRE+=$(SOLARINCDIR)$/offuh + +# --- Files ------------------------------------- + +CXXFILES= navtoolbar.cxx \ + +SLOFILES= $(SLO)$/navtoolbar.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/solar/control/navtoolbar.cxx b/forms/source/solar/control/navtoolbar.cxx new file mode 100644 index 000000000000..128bc112adee --- /dev/null +++ b/forms/source/solar/control/navtoolbar.cxx @@ -0,0 +1,736 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "navtoolbar.hxx" +#include "frm_resource.hxx" +#include "featuredispatcher.hxx" +#include "frm_resource.hrc" +#include "commandimageprovider.hxx" +#include "commanddescriptionprovider.hxx" + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/form/runtime/FormFeature.hpp> + +#include <sfx2/imgmgr.hxx> +#include <vcl/fixed.hxx> + +#include <memory> + +#define LID_RECORD_LABEL 1000 +#define LID_RECORD_FILLER 1001 + +//......................................................................... +namespace frm +{ +//......................................................................... + + using ::com::sun::star::uno::makeAny; + namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; + + //===================================================================== + //..................................................................... + namespace + { + static bool isArtificialItem( sal_Int16 _nFeatureId ) + { + return ( _nFeatureId == LID_RECORD_LABEL ) + || ( _nFeatureId == LID_RECORD_FILLER ); + } + + static String getLabelString( USHORT _nResId ) + { + String sLabel = String::CreateFromAscii( " " ); + sLabel += String( FRM_RES_STRING( _nResId ) ); + sLabel += String::CreateFromAscii( " " ); + return sLabel; + } + + ::rtl::OUString lcl_getCommandURL( const sal_Int16 _nFormFeature ) + { + const sal_Char* pAsciiCommandName = NULL; + switch ( _nFormFeature ) + { + case FormFeature::MoveAbsolute : pAsciiCommandName = "AbsoluteRecord"; break; + case FormFeature::TotalRecords : pAsciiCommandName = "RecTotal"; break; + case FormFeature::MoveToFirst : pAsciiCommandName = "FirstRecord"; break; + case FormFeature::MoveToPrevious : pAsciiCommandName = "PrevRecord"; break; + case FormFeature::MoveToNext : pAsciiCommandName = "NextRecord"; break; + case FormFeature::MoveToLast : pAsciiCommandName = "LastRecord"; break; + case FormFeature::SaveRecordChanges : pAsciiCommandName = "RecSave"; break; + case FormFeature::UndoRecordChanges : pAsciiCommandName = "RecUndo"; break; + case FormFeature::MoveToInsertRow : pAsciiCommandName = "NewRecord"; break; + case FormFeature::DeleteRecord : pAsciiCommandName = "DeleteRecord"; break; + case FormFeature::ReloadForm : pAsciiCommandName = "Refresh"; break; + case FormFeature::RefreshCurrentControl : pAsciiCommandName = "RefreshFormControl"; break; + case FormFeature::SortAscending : pAsciiCommandName = "Sortup"; break; + case FormFeature::SortDescending : pAsciiCommandName = "SortDown"; break; + case FormFeature::InteractiveSort : pAsciiCommandName = "OrderCrit"; break; + case FormFeature::AutoFilter : pAsciiCommandName = "AutoFilter"; break; + case FormFeature::InteractiveFilter : pAsciiCommandName = "FilterCrit"; break; + case FormFeature::ToggleApplyFilter : pAsciiCommandName = "FormFiltered"; break; + case FormFeature::RemoveFilterAndSort : pAsciiCommandName = "RemoveFilterSort"; break; + } + if ( pAsciiCommandName != NULL ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ) ) + ::rtl::OUString::createFromAscii( pAsciiCommandName ); + + OSL_ENSURE( false, "lcl_getCommandURL: unknown FormFeature!" ); + return ::rtl::OUString(); + } + } + + //===================================================================== + //= ImplNavToolBar + //===================================================================== + class ImplNavToolBar : public ToolBox + { + protected: + const IFeatureDispatcher* m_pDispatcher; + + public: + ImplNavToolBar( Window* _pParent ) + :ToolBox( _pParent, WB_3DLOOK ) + ,m_pDispatcher( NULL ) + { + } + + void setDispatcher( const IFeatureDispatcher* _pDispatcher ) + { + m_pDispatcher = _pDispatcher; + } + + protected: + // ToolBox overridables + virtual void Select(); + + }; + + //--------------------------------------------------------------------- + void ImplNavToolBar::Select() + { + if ( m_pDispatcher ) + { + if ( !m_pDispatcher->isEnabled( GetCurItemId() ) ) + // the toolbox is a little bit buggy: With TIB_REPEAT, it sometimes + // happens that a select is reported, even though the respective + // item has just been disabled. + return; + m_pDispatcher->dispatch( GetCurItemId() ); + } + } + + //===================================================================== + //= NavigationToolBar + //===================================================================== + DBG_NAME( NavigationToolBar ) + //--------------------------------------------------------------------- + NavigationToolBar::NavigationToolBar( Window* _pParent, WinBits _nStyle, const PCommandImageProvider& _pImageProvider, + const PCommandDescriptionProvider& _pDescriptionProvider ) + :Window( _pParent, _nStyle ) + ,m_pDispatcher( NULL ) + ,m_pImageProvider( _pImageProvider ) + ,m_pDescriptionProvider( _pDescriptionProvider ) + ,m_eImageSize( eSmall ) + ,m_pToolbar( NULL ) + { + DBG_CTOR( NavigationToolBar, NULL ); + implInit( ); + } + + //--------------------------------------------------------------------- + NavigationToolBar::~NavigationToolBar( ) + { + for ( ::std::vector< Window* >::iterator loopChildWins = m_aChildWins.begin(); + loopChildWins != m_aChildWins.end(); + ++loopChildWins + ) + { + delete *loopChildWins; + } + delete m_pToolbar; + DBG_DTOR( NavigationToolBar, NULL ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::setDispatcher( const IFeatureDispatcher* _pDispatcher ) + { + m_pDispatcher = _pDispatcher; + + m_pToolbar->setDispatcher( _pDispatcher ); + + RecordPositionInput* pPositionWindow = static_cast< RecordPositionInput* >( m_pToolbar->GetItemWindow( FormFeature::MoveAbsolute ) ); + OSL_ENSURE( pPositionWindow, "NavigationToolBar::setDispatcher: can't forward the dispatcher to the position window!" ); + if ( pPositionWindow ) + pPositionWindow->setDispatcher( _pDispatcher ); + + updateFeatureStates( ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::updateFeatureStates( ) + { + for ( USHORT nPos = 0; nPos < m_pToolbar->GetItemCount(); ++nPos ) + { + USHORT nItemId = m_pToolbar->GetItemId( nPos ); + + if ( ( nItemId == LID_RECORD_LABEL ) || ( nItemId == LID_RECORD_FILLER ) ) + continue; + + // is this item enabled? + bool bEnabled = m_pDispatcher ? m_pDispatcher->isEnabled( nItemId ) : false; + implEnableItem( nItemId, bEnabled ); + } + } + + //--------------------------------------------------------------------- + void NavigationToolBar::implEnableItem( USHORT _nItemId, bool _bEnabled ) + { + m_pToolbar->EnableItem( _nItemId, _bEnabled ); + + if ( _nItemId == FormFeature::MoveAbsolute ) + m_pToolbar->EnableItem( LID_RECORD_LABEL, _bEnabled ); + + if ( _nItemId == FormFeature::TotalRecords ) + m_pToolbar->EnableItem( LID_RECORD_FILLER, _bEnabled ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::enableFeature( sal_Int16 _nFeatureId, bool _bEnabled ) + { + DBG_ASSERT( m_pToolbar->GetItemPos( (USHORT)_nFeatureId ) != TOOLBOX_ITEM_NOTFOUND, + "NavigationToolBar::enableFeature: invalid id!" ); + + implEnableItem( (USHORT)_nFeatureId, _bEnabled ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::checkFeature( sal_Int16 _nFeatureId, bool _bEnabled ) + { + DBG_ASSERT( m_pToolbar->GetItemPos( (USHORT)_nFeatureId ) != TOOLBOX_ITEM_NOTFOUND, + "NavigationToolBar::checkFeature: invalid id!" ); + + m_pToolbar->CheckItem( (USHORT)_nFeatureId, _bEnabled ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::setFeatureText( sal_Int16 _nFeatureId, const ::rtl::OUString& _rText ) + { + DBG_ASSERT( m_pToolbar->GetItemPos( (USHORT)_nFeatureId ) != TOOLBOX_ITEM_NOTFOUND, + "NavigationToolBar::checkFeature: invalid id!" ); + + Window* pItemWindow = m_pToolbar->GetItemWindow( (USHORT)_nFeatureId ); + if ( pItemWindow ) + pItemWindow->SetText( _rText ); + else + m_pToolbar->SetItemText( (USHORT)_nFeatureId, _rText ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::implInit( ) + { + m_pToolbar = new ImplNavToolBar( this ); + m_pToolbar->SetOutStyle( TOOLBOX_STYLE_FLAT ); + m_pToolbar->Show(); + + // need the SfxApplication for retrieving informations about our + // items. We could duplicate all the information here in our lib + // (such as the item text and the image), but why should we? + + struct FeatureDescription + { + USHORT nId; + bool bRepeat; + bool bItemWindow; + } aSupportedFeatures[] = + { + { LID_RECORD_LABEL, false, true }, + { FormFeature::MoveAbsolute, false, true }, + { LID_RECORD_FILLER, false, true }, + { FormFeature::TotalRecords, false, true }, + { FormFeature::MoveToFirst, true, false }, + { FormFeature::MoveToPrevious, true, false }, + { FormFeature::MoveToNext, true, false }, + { FormFeature::MoveToLast, true, false }, + { FormFeature::MoveToInsertRow, false, false }, + { 0, false, false }, + { FormFeature::SaveRecordChanges, false, false }, + { FormFeature::UndoRecordChanges, false, false }, + { FormFeature::DeleteRecord, false, false }, + { FormFeature::ReloadForm, false, false }, + { FormFeature::RefreshCurrentControl, false, false }, + { 0, false, false }, + { FormFeature::SortAscending, false, false }, + { FormFeature::SortDescending, false, false }, + { FormFeature::InteractiveSort, false, false }, + { FormFeature::AutoFilter, false, false }, + { FormFeature::InteractiveFilter, false, false }, + { FormFeature::ToggleApplyFilter, false, false }, + { FormFeature::RemoveFilterAndSort, false, false }, + }; + + size_t nSupportedFeatures = sizeof( aSupportedFeatures ) / sizeof( aSupportedFeatures[0] ); + FeatureDescription* pSupportedFeatures = aSupportedFeatures; + FeatureDescription* pSupportedFeaturesEnd = aSupportedFeatures + nSupportedFeatures; + for ( ; pSupportedFeatures < pSupportedFeaturesEnd; ++pSupportedFeatures ) + { + if ( pSupportedFeatures->nId ) + { // it's _not_ a separator + + // insert the entry + m_pToolbar->InsertItem( pSupportedFeatures->nId, String(), pSupportedFeatures->bRepeat ? TIB_REPEAT : 0 ); + m_pToolbar->SetQuickHelpText( pSupportedFeatures->nId, String() ); // TODO + + if ( !isArtificialItem( pSupportedFeatures->nId ) ) + { + ::rtl::OUString sCommandURL( lcl_getCommandURL( pSupportedFeatures->nId ) ); + m_pToolbar->SetItemCommand( pSupportedFeatures->nId, sCommandURL ); + if ( m_pDescriptionProvider ) + m_pToolbar->SetQuickHelpText( pSupportedFeatures->nId, m_pDescriptionProvider->getCommandDescription( sCommandURL ) ); + } + + if ( pSupportedFeatures->bItemWindow ) + { + Window* pItemWindow = NULL; + if ( FormFeature::MoveAbsolute == pSupportedFeatures->nId ) + { + pItemWindow = new RecordPositionInput( m_pToolbar ); + static_cast< RecordPositionInput* >( pItemWindow )->setDispatcher( m_pDispatcher ); + } + else if ( LID_RECORD_FILLER == pSupportedFeatures->nId ) + { + pItemWindow = new FixedText( m_pToolbar, WB_CENTER | WB_VCENTER ); + pItemWindow->SetBackground(Wallpaper(Color(COL_TRANSPARENT))); + } + else + { + pItemWindow = new FixedText( m_pToolbar, WB_VCENTER ); + pItemWindow->SetBackground(); + pItemWindow->SetPaintTransparent(TRUE); + } + m_aChildWins.push_back( pItemWindow ); + + switch ( pSupportedFeatures->nId ) + { + case LID_RECORD_LABEL: + pItemWindow->SetText( getLabelString( RID_STR_LABEL_RECORD ) ); + break; + + case LID_RECORD_FILLER: + pItemWindow->SetText( getLabelString( RID_STR_LABEL_OF ) ); + break; + } + + m_pToolbar->SetItemWindow( pSupportedFeatures->nId, pItemWindow ); + } + } + else + { // a separator + m_pToolbar->InsertSeparator( ); + } + } + + forEachItemWindow( &NavigationToolBar::adjustItemWindowWidth, NULL ); + + implUpdateImages(); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::implUpdateImages() + { + OSL_ENSURE( m_pImageProvider, "NavigationToolBar::implUpdateImages: no image provider => no images!" ); + if ( !m_pImageProvider ) + return; + + const bool bIsHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode(); + + const USHORT nItemCount = m_pToolbar->GetItemCount(); + + // collect the FormFeatures in the toolbar + typedef ::std::vector< sal_Int16 > FormFeatures; + FormFeatures aFormFeatures; + aFormFeatures.reserve( nItemCount ); + + for ( USHORT i=0; i<nItemCount; ++i ) + { + USHORT nId = m_pToolbar->GetItemId( i ); + if ( ( TOOLBOXITEM_BUTTON == m_pToolbar->GetItemType( i ) ) && !isArtificialItem( nId ) ) + aFormFeatures.push_back( nId ); + } + + // translate them into command URLs + CommandURLs aCommandURLs( aFormFeatures.size() ); + for ( FormFeatures::const_iterator formFeature = aFormFeatures.begin(); + formFeature != aFormFeatures.end(); + ++formFeature + ) + { + aCommandURLs[ formFeature - aFormFeatures.begin() ] = lcl_getCommandURL( *formFeature ); + } + + // retrieve the images for the command URLs + CommandImages aCommandImages = m_pImageProvider->getCommandImages( aCommandURLs, m_eImageSize == eLarge, bIsHighContrast ); + + // and set them at the toolbar + CommandImages::const_iterator commandImage = aCommandImages.begin(); + for ( FormFeatures::const_iterator formFeature = aFormFeatures.begin(); + formFeature != aFormFeatures.end(); + ++formFeature, ++commandImage + ) + { + m_pToolbar->SetItemImage( *formFeature, *commandImage ); + } + + // parts of our layout is dependent on the size of our icons + Resize(); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::implSetImageSize( ImageSize _eSize ) + { + if ( _eSize != m_eImageSize ) + { + m_eImageSize = _eSize; + implUpdateImages(); + } + } + + //--------------------------------------------------------------------- + void NavigationToolBar::SetImageSize( ImageSize _eSize ) + { + implSetImageSize( _eSize ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::ShowFunctionGroup( FunctionGroup _eGroup, bool _bShow ) + { + const USHORT* pGroupIds = NULL; + + switch ( _eGroup ) + { + case ePosition: + { + static const USHORT aPositionIds[] = { + LID_RECORD_LABEL, FormFeature::MoveAbsolute, LID_RECORD_FILLER, FormFeature::TotalRecords, 0 + }; + pGroupIds = aPositionIds; + } + break; + case eNavigation: + { + static const USHORT aNavigationIds[] = { + FormFeature::MoveToFirst, FormFeature::MoveToPrevious, FormFeature::MoveToNext, FormFeature::MoveToLast, FormFeature::MoveToInsertRow, 0 + }; + pGroupIds = aNavigationIds; + } + break; + case eRecordActions: + { + static const USHORT aActionIds[] = { + FormFeature::SaveRecordChanges, FormFeature::UndoRecordChanges, FormFeature::DeleteRecord, FormFeature::ReloadForm, FormFeature::RefreshCurrentControl, 0 + }; + pGroupIds = aActionIds; + } + break; + case eFilterSort: + { + static const USHORT aFilterSortIds[] = { + FormFeature::SortAscending, FormFeature::SortDescending, FormFeature::InteractiveSort, FormFeature::AutoFilter, FormFeature::InteractiveFilter, FormFeature::ToggleApplyFilter, FormFeature::RemoveFilterAndSort, 0 + }; + pGroupIds = aFilterSortIds; + } + break; + default: + OSL_ENSURE( sal_False, "NavigationToolBar::ShowFunctionGroup: invalid group id!" ); + } + + if ( pGroupIds ) + while ( *pGroupIds ) + m_pToolbar->ShowItem( *pGroupIds++, _bShow ); + } + + //--------------------------------------------------------------------- + bool NavigationToolBar::IsFunctionGroupVisible( FunctionGroup _eGroup ) + { + USHORT nIndicatorItem = 0; + switch ( _eGroup ) + { + case ePosition : nIndicatorItem = LID_RECORD_LABEL; break; + case eNavigation : nIndicatorItem = FormFeature::MoveToFirst; break; + case eRecordActions : nIndicatorItem = FormFeature::SaveRecordChanges; break; + case eFilterSort : nIndicatorItem = FormFeature::SortAscending; break; + default: + OSL_ENSURE( sal_False, "NavigationToolBar::IsFunctionGroupVisible: invalid group id!" ); + } + + return m_pToolbar->IsItemVisible( nIndicatorItem ); + } + + //------------------------------------------------------------------------------ + void NavigationToolBar::StateChanged( StateChangedType nType ) + { + Window::StateChanged( nType ); + + switch ( nType ) + { + case STATE_CHANGE_ZOOM: +// m_pToolbar->SetZoom( GetZoom() ); +// forEachItemWindow( setItemWindowZoom, NULL ); + // the ToolBox class is not zoomable at the moment, so + // we better have no zoom at all instead of only half a zoom ... + break; + + case STATE_CHANGE_CONTROLFONT: + forEachItemWindow( &NavigationToolBar::setItemControlFont, NULL ); + forEachItemWindow( &NavigationToolBar::adjustItemWindowWidth, NULL ); + break; + + case STATE_CHANGE_CONTROLFOREGROUND: + forEachItemWindow( &NavigationToolBar::setItemControlForeground, NULL ); + break; + + case STATE_CHANGE_MIRRORING: + { + BOOL bIsRTLEnabled( IsRTLEnabled() ); + m_pToolbar->EnableRTL( bIsRTLEnabled ); + forEachItemWindow( &NavigationToolBar::enableItemRTL, &bIsRTLEnabled ); + Resize(); + } + break; + } + } + + //--------------------------------------------------------------------- + void NavigationToolBar::Resize() + { + // resize/position the toolbox as a whole + sal_Int32 nToolbarHeight = m_pToolbar->CalcWindowSizePixel().Height(); + + sal_Int32 nMyHeight = GetOutputSizePixel().Height(); + m_pToolbar->SetPosSizePixel( Point( 0, ( nMyHeight - nToolbarHeight ) / 2 ), + Size( GetSizePixel().Width(), nToolbarHeight ) ); + + Window::Resize(); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::SetControlBackground() + { + Window::SetControlBackground(); + m_pToolbar->SetControlBackground(); + forEachItemWindow( &NavigationToolBar::setItemBackground, NULL ); + + // the contrast of the background color may have changed, so force + // the images to be rebuild (high contrast requires a possibly different + // image set) + implUpdateImages(); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::SetControlBackground( const Color& _rColor ) + { + Window::SetControlBackground( _rColor ); + m_pToolbar->SetControlBackground( _rColor ); + forEachItemWindow( &NavigationToolBar::setItemBackground, &_rColor ); + + // the contrast of the background color may have changed, so force + // the images to be rebuild (high contrast requires a possibly different + // image set) + implUpdateImages(); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::SetTextLineColor( ) + { + Window::SetTextLineColor( ); + m_pToolbar->SetTextLineColor( ); + forEachItemWindow( &NavigationToolBar::setTextLineColor, NULL ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::SetTextLineColor( const Color& _rColor ) + { + Window::SetTextLineColor( _rColor ); + m_pToolbar->SetTextLineColor( _rColor ); + forEachItemWindow( &NavigationToolBar::setTextLineColor, &_rColor ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::forEachItemWindow( ItemWindowHandler _handler, const void* _pParam ) + { + for ( USHORT item = 0; item < m_pToolbar->GetItemCount(); ++item ) + { + USHORT nItemId = m_pToolbar->GetItemId( item ); + Window* pItemWindow = m_pToolbar->GetItemWindow( nItemId ); + if ( pItemWindow ) + (this->*_handler)( nItemId, pItemWindow, _pParam ); + } + } + + //--------------------------------------------------------------------- + void NavigationToolBar::setItemBackground( USHORT /* _nItemId */, Window* _pItemWindow, const void* _pColor ) const + { + if ( _pColor ) + _pItemWindow->SetControlBackground( *static_cast< const Color* >( _pColor ) ); + else + _pItemWindow->SetControlBackground(); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::setTextLineColor( USHORT /* _nItemId */, Window* _pItemWindow, const void* _pColor ) const + { + if ( _pColor ) + _pItemWindow->SetTextLineColor( *static_cast< const Color* >( _pColor ) ); + else + _pItemWindow->SetTextLineColor(); + } +#if 0 + //--------------------------------------------------------------------- + void NavigationToolBar::setItemWindowZoom( USHORT /* _nItemId */, Window* _pItemWindow, const void* /* _pParam */ ) const + { + _pItemWindow->SetZoom( GetZoom() ); + _pItemWindow->SetZoomedPointFont( IsControlFont() ? GetControlFont() : GetPointFont() ); + } +#endif + //--------------------------------------------------------------------- + void NavigationToolBar::setItemControlFont( USHORT /* _nItemId */, Window* _pItemWindow, const void* /* _pParam */ ) const + { + if ( IsControlFont() ) + _pItemWindow->SetControlFont( GetControlFont() ); + else + _pItemWindow->SetControlFont( ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::setItemControlForeground( USHORT /* _nItemId */, Window* _pItemWindow, const void* /* _pParam */ ) const + { + if ( IsControlForeground() ) + _pItemWindow->SetControlForeground( GetControlForeground() ); + else + _pItemWindow->SetControlForeground( ); + _pItemWindow->SetTextColor( GetTextColor() ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::adjustItemWindowWidth( USHORT _nItemId, Window* _pItemWindow, const void* /* _pParam */ ) const + { + String sItemText; + switch ( _nItemId ) + { + case LID_RECORD_LABEL: + sItemText = getLabelString( RID_STR_LABEL_RECORD ); + break; + + case LID_RECORD_FILLER: + sItemText = getLabelString( RID_STR_LABEL_OF ); + break; + + case FormFeature::MoveAbsolute: + sItemText = String::CreateFromAscii( "12345678" ); + break; + + case FormFeature::TotalRecords: + sItemText = String::CreateFromAscii( "123456" ); + break; + } + + Size aSize( _pItemWindow->GetTextWidth( sItemText ), /* _pItemWindow->GetSizePixel( ).Height() */ _pItemWindow->GetTextHeight() + 4 ); + aSize.Width() += 6; + _pItemWindow->SetSizePixel( aSize ); + + m_pToolbar->SetItemWindow( _nItemId, _pItemWindow ); + } + + //--------------------------------------------------------------------- + void NavigationToolBar::enableItemRTL( USHORT /*_nItemId*/, Window* _pItemWindow, const void* _pIsRTLEnabled ) const + { + _pItemWindow->EnableRTL( *static_cast< const BOOL* >( _pIsRTLEnabled ) ); + } + + //===================================================================== + //= RecordPositionInput + //===================================================================== + //--------------------------------------------------------------------- + RecordPositionInput::RecordPositionInput( Window* _pParent ) + :NumericField( _pParent, WB_BORDER | WB_VCENTER ) + ,m_pDispatcher( NULL ) + { + SetMin( 1 ); + SetFirst( 1 ); + SetSpinSize( 1 ); + SetDecimalDigits( 0 ); + SetStrictFormat( TRUE ); + SetBorderStyle( WINDOW_BORDER_MONO ); + } + + //--------------------------------------------------------------------- + RecordPositionInput::~RecordPositionInput() + { + } + + //--------------------------------------------------------------------- + void RecordPositionInput::setDispatcher( const IFeatureDispatcher* _pDispatcher ) + { + m_pDispatcher = _pDispatcher; + } + + //--------------------------------------------------------------------- + void RecordPositionInput::FirePosition( sal_Bool _bForce ) + { + if ( _bForce || ( GetText() != GetSavedValue() ) ) + { + sal_Int64 nRecord = GetValue(); + if ( nRecord < GetMin() || nRecord > GetMax() ) + return; + + if ( m_pDispatcher ) + m_pDispatcher->dispatchWithArgument( FormFeature::MoveAbsolute, "Position", makeAny( (sal_Int32)nRecord ) ); + + SaveValue(); + } + } + + //--------------------------------------------------------------------- + void RecordPositionInput::LoseFocus() + { + FirePosition( sal_False ); + } + + //--------------------------------------------------------------------- + void RecordPositionInput::KeyInput( const KeyEvent& rKeyEvent ) + { + if( rKeyEvent.GetKeyCode() == KEY_RETURN && GetText().Len() ) + FirePosition( sal_True ); + else + NumericField::KeyInput( rKeyEvent ); + } + + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/solar/inc/navtoolbar.hxx b/forms/source/solar/inc/navtoolbar.hxx new file mode 100644 index 000000000000..5ace33765262 --- /dev/null +++ b/forms/source/solar/inc/navtoolbar.hxx @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOLAR_CONTROL_NAVTOOLBAR_HXX +#define FORMS_SOLAR_CONTROL_NAVTOOLBAR_HXX + +#include <vcl/toolbox.hxx> +#include <vcl/field.hxx> + +#include <boost/shared_ptr.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + class IFeatureDispatcher; + class ICommandImageProvider; + class ICommandDescriptionProvider; + + class ImplNavToolBar; + + //===================================================================== + //= NavigationToolBar + //===================================================================== + class NavigationToolBar : public Window + { + public: + enum ImageSize + { + eSmall, + eLarge + }; + + enum FunctionGroup + { + ePosition, + eNavigation, + eRecordActions, + eFilterSort + }; + + private: + const IFeatureDispatcher* m_pDispatcher; + const ::boost::shared_ptr< const ICommandImageProvider > + m_pImageProvider; + const ::boost::shared_ptr< const ICommandDescriptionProvider > + m_pDescriptionProvider; + ImageSize m_eImageSize; + ImplNavToolBar* m_pToolbar; + ::std::vector< Window* > m_aChildWins; + + public: + NavigationToolBar( + Window* _pParent, + WinBits _nStyle, + const ::boost::shared_ptr< const ICommandImageProvider >& _pImageProvider, + const ::boost::shared_ptr< const ICommandDescriptionProvider >& _pDescriptionProvider + ); + ~NavigationToolBar( ); + + /** sets the dispatcher which is to be used for the features + + If the dispatcher is the same as the one which is currently set, + then the states of the features are updated + + @param _pDispatcher + the new (or old) dispatcher. The caller is reponsible for + ensuring the life time of the object does exceed the life time + of the tool bar instance. + */ + void setDispatcher( const IFeatureDispatcher* _pDispatcher ); + + /// enables or disables a given feature + void enableFeature( sal_Int16 _nFeatureId, bool _bEnabled ); + + /// checks or unchecks a given feature + void checkFeature( sal_Int16 _nFeatureId, bool _bEnabled ); + + /// sets the text of a given feature + void setFeatureText( sal_Int16 _nFeatureId, const ::rtl::OUString& _rText ); + + /** retrieves the current image size + */ + inline ImageSize GetImageSize( ) const { return m_eImageSize; } + + /** sets the size of the images + */ + void SetImageSize( ImageSize _eSize ); + + /** shows or hides a function group + */ + void ShowFunctionGroup( FunctionGroup _eGroup, bool _bShow ); + + /** determines whether or not a given function group is currently visible + */ + bool IsFunctionGroupVisible( FunctionGroup _eGroup ); + + // Window "overridables" (hiding the respective Window methods) + void SetControlBackground(); + void SetControlBackground( const Color& rColor ); + void SetTextLineColor( ); + void SetTextLineColor( const Color& rColor ); + + protected: + // Window overridables + virtual void Resize(); + virtual void StateChanged( StateChangedType nType ); + + /// ctor implementation + void implInit( ); + + /// impl version of SetImageSize + void implSetImageSize( ImageSize _eSize ); + + /// updates the images of our items + void implUpdateImages(); + + /// enables or disables an item, plus possible dependent items + void implEnableItem( USHORT _nItemId, bool _bEnabled ); + + /** update the states of all features, using the callback + */ + void updateFeatureStates( ); + + // iterating through item windows + typedef void (NavigationToolBar::*ItemWindowHandler) (USHORT, Window*, const void*) const; + void forEachItemWindow( ItemWindowHandler _handler, const void* _pParam ); + + void setItemBackground( USHORT /* _nItemId */, Window* _pItemWindow, const void* _pColor ) const; + void setTextLineColor( USHORT /* _nItemId */, Window* _pItemWindow, const void* _pColor ) const; +#if 0 + void setItemWindowZoom( USHORT /* _nItemId */, Window* _pItemWindow, const void* /* _pParam */ ) const; +#endif + void setItemControlFont( USHORT /* _nItemId */, Window* _pItemWindow, const void* /* _pParam */ ) const; + void setItemControlForeground( USHORT /* _nItemId */, Window* _pItemWindow, const void* /* _pParam */ ) const; + void adjustItemWindowWidth( USHORT _nItemId, Window* _pItemWindow, const void* /* _pParam */ ) const; + void enableItemRTL( USHORT /*_nItemId*/, Window* _pItemWindow, const void* _pIsRTLEnabled ) const; + }; + + //===================================================================== + //= RecordPositionInput + //===================================================================== + class RecordPositionInput : public NumericField + { + private: + const IFeatureDispatcher* m_pDispatcher; + + public: + RecordPositionInput( Window* _pParent ); + ~RecordPositionInput(); + + /** sets the dispatcher which is to be used for the features + */ + void setDispatcher( const IFeatureDispatcher* _pDispatcher ); + + protected: + // Window overridables + virtual void LoseFocus(); + virtual void KeyInput( const KeyEvent& rKeyEvent ); + + private: + void FirePosition( sal_Bool _bForce ); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_SOLAR_CONTROL_NAVTOOLBAR_HXX diff --git a/forms/source/xforms/NameContainer.hxx b/forms/source/xforms/NameContainer.hxx new file mode 100644 index 000000000000..3cab033f605e --- /dev/null +++ b/forms/source/xforms/NameContainer.hxx @@ -0,0 +1,221 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _NAMECONTAINER_HXX +#define _NAMECONTAINER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <map> + +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Type.hxx> + +typedef cppu::WeakImplHelper1< + com::sun::star::container::XNameContainer +> NameContainer_t; + +template<class T> +class NameContainer : public NameContainer_t +{ +protected: + typedef std::map<rtl::OUString,T> map_t; + map_t maItems; + + + bool hasItems() + { + return ! maItems.empty(); + } + + typename map_t::const_iterator findItem( const rtl::OUString& rName ) + { + return maItems.find( rName ); + } + + bool hasItem( const rtl::OUString& rName ) + { + return findItem( rName ) != maItems.end(); + } + + T getItem( const rtl::OUString& rName ) + { + OSL_ENSURE( hasItem( rName ), "can't get non-existant item" ); + return maItems[ rName ]; + } + + + void replace( const rtl::OUString& rName, + const T& aElement ) + { + OSL_ENSURE( hasItem( rName ), "unknown item" ); + maItems[ rName ] = aElement; + } + + void insert( const rtl::OUString& rName, + const T& aElement ) + { + OSL_ENSURE( ! hasItem( rName ), "item already in set" ); + maItems[ rName ] = aElement; + } + + void remove( const rtl::OUString& rName ) + { + OSL_ENSURE( hasItem( rName ), "item not in set" ); + maItems.erase( rName ); + } + + +public: + + NameContainer() {} + virtual ~NameContainer() {} + + // + // methods for XElementAccess + // + + virtual com::sun::star::uno::Type SAL_CALL getElementType() + throw( com::sun::star::uno::RuntimeException ) + { + return getCppuType( static_cast<T*>( NULL ) ); + } + + virtual sal_Bool SAL_CALL hasElements() + throw( com::sun::star::uno::RuntimeException ) + { + return hasItems(); + } + + + // + // methods for XNameAccess (inherits XElementAccess) + // + + virtual com::sun::star::uno::Any SAL_CALL getByName( + const rtl::OUString& rName ) + throw( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ) + { + typename map_t::const_iterator aIter = findItem( rName ); + if( aIter == maItems.end() ) + throw com::sun::star::container::NoSuchElementException(); + else + return com::sun::star::uno::makeAny( aIter->second ); + } + + virtual com::sun::star::uno::Sequence<rtl::OUString> SAL_CALL getElementNames() + throw( com::sun::star::uno::RuntimeException ) + { + com::sun::star::uno::Sequence<rtl::OUString> aSequence( maItems.size() ); + typename map_t::const_iterator aIter = maItems.begin(); + rtl::OUString* pStrings = aSequence.getArray(); + while( aIter != maItems.end() ) + { + *pStrings = aIter->first; + ++aIter; + ++pStrings; + } + OSL_ENSURE( pStrings == aSequence.getArray() + aSequence.getLength(), + "sequence not of right size; possible buffer overflow" ); + return aSequence; + } + + virtual sal_Bool SAL_CALL hasByName( + const rtl::OUString& rName ) + throw( com::sun::star::uno::RuntimeException ) + { + return hasItem( rName ); + } + + + // + // methods for XNameReplace (inherits XNameAccess) + // + + virtual void SAL_CALL replaceByName( + const rtl::OUString& rName, + const com::sun::star::uno::Any& aElement ) + throw( com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException) + { + T aItem; + if( aElement >>= aItem ) + if( hasByName( rName ) ) + replace( rName, aItem ); + else + throw com::sun::star::container::NoSuchElementException(); + else + throw com::sun::star::lang::IllegalArgumentException(); + } + + + // + // methods for XNameContainer (inherits XNameReplace) + // + + virtual void SAL_CALL insertByName( + const rtl::OUString& rName, + const com::sun::star::uno::Any& aElement ) + throw( com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::ElementExistException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ) + { + T aItem; + if( aElement >>= aItem ) + if( ! hasByName( rName ) ) + insert( rName, aItem ); + else + throw com::sun::star::container::ElementExistException(); + else + throw com::sun::star::lang::IllegalArgumentException(); + } + + virtual void SAL_CALL removeByName( + const rtl::OUString& rName ) + throw( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException) + { + if( hasByName( rName ) ) + remove( rName ); + else + throw com::sun::star::container::NoSuchElementException(); + } + +}; + +#endif diff --git a/forms/source/xforms/binding.cxx b/forms/source/xforms/binding.cxx new file mode 100644 index 000000000000..3df2385796f0 --- /dev/null +++ b/forms/source/xforms/binding.cxx @@ -0,0 +1,1409 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "binding.hxx" + +#include "model.hxx" +#include "unohelper.hxx" +#include "NameContainer.hxx" +#include "evaluationcontext.hxx" +#include "convert.hxx" +#include "resourcehelper.hxx" +#include "xmlhelper.hxx" +#include "xformsevent.hxx" + +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> + +#include <tools/diagnose_ex.h> + +#include <algorithm> +#include <functional> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XElement.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/xml/dom/events/XEventTarget.hpp> +#include <com/sun/star/xml/dom/events/XEventListener.hpp> +#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/container/XNameContainer.hpp> + +#include <comphelper/propertysetinfo.hxx> +#include <unotools/textsearch.hxx> +#include <cppuhelper/typeprovider.hxx> + +using namespace com::sun::star::xml::xpath; +using namespace com::sun::star::xml::dom::events; + +using rtl::OUString; +using rtl::OUStringBuffer; +using std::vector; +using xforms::Binding; +using xforms::MIP; +using xforms::Model; +using xforms::getResource; +using xforms::EvaluationContext; +using com::sun::star::beans::PropertyVetoException; +using com::sun::star::beans::UnknownPropertyException; +using com::sun::star::beans::XPropertySet; +using com::sun::star::container::XSet; +using com::sun::star::container::XNameAccess; +using com::sun::star::form::binding::IncompatibleTypesException; +using com::sun::star::form::binding::InvalidBindingStateException; +using com::sun::star::form::binding::XValueBinding; +using com::sun::star::lang::EventObject; +using com::sun::star::lang::IllegalArgumentException; +using com::sun::star::lang::IndexOutOfBoundsException; +using com::sun::star::lang::NoSupportException; +using com::sun::star::lang::NullPointerException; +using com::sun::star::lang::WrappedTargetException; +using com::sun::star::lang::XUnoTunnel; +using com::sun::star::uno::Any; +using com::sun::star::uno::Reference; +using com::sun::star::uno::RuntimeException; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::UNO_QUERY_THROW; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::makeAny; +using com::sun::star::util::XModifyListener; +using com::sun::star::xforms::XDataTypeRepository; +using com::sun::star::xml::dom::NodeType_ATTRIBUTE_NODE; +using com::sun::star::xml::dom::NodeType_TEXT_NODE; +using com::sun::star::xml::dom::XNode; +using com::sun::star::xml::dom::XNodeList; +using com::sun::star::xml::dom::events::XEventListener; +using com::sun::star::xml::dom::events::XEventTarget; +using com::sun::star::xsd::XDataType; + + + + +#define EXCEPT(msg) OUSTRING(msg),static_cast<XValueBinding*>(this) + +#define HANDLE_BindingID 0 +#define HANDLE_BindingExpression 1 +#define HANDLE_Model 2 +#define HANDLE_ModelID 3 +#define HANDLE_BindingNamespaces 4 +#define HANDLE_ReadonlyExpression 5 +#define HANDLE_RelevantExpression 6 +#define HANDLE_RequiredExpression 7 +#define HANDLE_ConstraintExpression 8 +#define HANDLE_CalculateExpression 9 +#define HANDLE_Type 10 +#define HANDLE_ReadOnly 11 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control +#define HANDLE_Relevant 12 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control +#define HANDLE_ModelNamespaces 13 +#define HANDLE_ExternalData 14 + + +Binding::Binding() : + mxModel(), + msBindingID(), + maBindingExpression(), + maReadonly(), + mxNamespaces( new NameContainer<OUString>() ), + mbInCalculate( false ), + mnDeferModifyNotifications( 0 ), + mbValueModified( false ), + mbBindingModified( false ) + +{ + initializePropertySet(); +} + +Binding::~Binding() throw() +{ + _setModel(NULL); +} + + +Binding::Model_t Binding::getModel() const +{ + return mxModel; +} + +void Binding::_setModel( const Model_t& xModel ) +{ + PropertyChangeNotifier aNotifyModelChange( *this, HANDLE_Model ); + PropertyChangeNotifier aNotifyModelIDChange( *this, HANDLE_ModelID ); + + // prepare binding for removal of old model + clear(); // remove all cached data (e.g. XPath evaluation results) + XNameContainer_t xNamespaces = getModelNamespaces(); // save namespaces + + mxModel = xModel; + + // set namespaces (and move to model, if appropriate) + setBindingNamespaces( xNamespaces ); + _checkBindingID(); + + notifyAndCachePropertyValue( HANDLE_ExternalData ); +} + + +OUString Binding::getModelID() const +{ + Model* pModel = getModelImpl(); + return ( pModel == NULL ) ? OUString() : pModel->getID(); +} + + +Binding::XNodeList_t Binding::getXNodeList() +{ + // first make sure we are bound + if( ! maBindingExpression.hasValue() ) + bind( sal_False ); + + return maBindingExpression.getXNodeList(); +} + +bool Binding::isSimpleBinding() const +{ + return maBindingExpression.isSimpleExpression() + && maReadonly.isSimpleExpression() + && maRelevant.isSimpleExpression() + && maRequired.isSimpleExpression() + && maConstraint.isSimpleExpression() + && maCalculate.isSimpleExpression(); +} + +bool Binding::isSimpleBindingExpression() const +{ + return maBindingExpression.isSimpleExpression(); +} + +void Binding::update() +{ + // clear all expressions (to remove cached node references) + maBindingExpression.clear(); + maReadonly.clear(); + maRelevant.clear(); + maRequired.clear(); + maConstraint.clear(); + maCalculate.clear(); + + // let's just pretend the binding has been modified -> full rebind() + bindingModified(); +} + +void Binding::deferNotifications( bool bDefer ) +{ + mnDeferModifyNotifications += ( bDefer ? 1 : -1 ); + OSL_ENSURE( mnDeferModifyNotifications >= 0, "you're deferring too much" ); + + if( mnDeferModifyNotifications == 0 ) + { + if( mbBindingModified ) + bindingModified(); + if( mbValueModified ) + valueModified(); + } + + OSL_ENSURE( ( mnDeferModifyNotifications > 0 ) + || ( ! mbBindingModified && ! mbValueModified ), + "deferred modifications not delivered?" ); +} + +bool Binding::isValid() +{ + // TODO: determine whether node is suitable, not just whether it exists + return maBindingExpression.getNode().is() && + isValid_DataType() && + maMIP.isConstraint() && + ( ! maMIP.isRequired() || + ( maBindingExpression.hasValue() && + maBindingExpression.getString().getLength() > 0 ) ); +} + +bool Binding::isUseful() +{ + // we are useful, if + // 0) we don't have a model + // (at least, in this case we shouldn't be removed from the model) + // 1) we have a proper name + // 2) we have some MIPs, + // 3) we are bound to some control + // (this can be assumed if some listeners are set) + bool bUseful = + getModelImpl() == NULL +// || msBindingID.getLength() > 0 + || msTypeName.getLength() > 0 + || ! maReadonly.isEmptyExpression() + || ! maRelevant.isEmptyExpression() + || ! maRequired.isEmptyExpression() + || ! maConstraint.isEmptyExpression() + || ! maCalculate.isEmptyExpression() + || ! maModifyListeners.empty() + || ! maListEntryListeners.empty() + || ! maValidityListeners.empty(); + + return bUseful; +} + +OUString Binding::explainInvalid() +{ + OUString sReason; + if( ! maBindingExpression.getNode().is() ) + { + sReason = ( maBindingExpression.getExpression().getLength() == 0 ) + ? getResource( RID_STR_XFORMS_NO_BINDING_EXPRESSION ) + : getResource( RID_STR_XFORMS_INVALID_BINDING_EXPRESSION ); + } + else if( ! isValid_DataType() ) + { + sReason = explainInvalid_DataType(); + if( sReason.getLength() == 0 ) + { + // no explanation given by data type? Then give generic message + sReason = getResource( RID_STR_XFORMS_INVALID_VALUE, + maMIP.getTypeName() ); + } + } + else if( ! maMIP.isConstraint() ) + { + sReason = maMIP.getConstraintExplanation(); + } + else if( maMIP.isRequired() && maBindingExpression.hasValue() && + ( maBindingExpression.getString().getLength() == 0 ) ) + { + sReason = getResource( RID_STR_XFORMS_REQUIRED ); + } + // else: no explanation given; should only happen if data is valid + + OSL_ENSURE( ( sReason.getLength() == 0 ) == isValid(), + "invalid data should have an explanation!" ); + + return sReason; +} + + + +EvaluationContext Binding::getEvaluationContext() const +{ + OSL_ENSURE( getModelImpl() != NULL, "need model impl" ); + EvaluationContext aContext = getModelImpl()->getEvaluationContext(); + aContext.mxNamespaces = getBindingNamespaces(); + return aContext; +} + +::std::vector<EvaluationContext> Binding::getMIPEvaluationContexts() +{ + OSL_ENSURE( getModelImpl() != NULL, "need model impl" ); + + // bind (in case we were not bound before) + bind( sal_False ); + return _getMIPEvaluationContexts(); +} + + +Binding::IntSequence_t Binding::getUnoTunnelID() +{ + static cppu::OImplementationId aImplementationId; + return aImplementationId.getImplementationId(); +} + +Binding* SAL_CALL Binding::getBinding( const Reference<XPropertySet>& xPropertySet ) +{ + Reference<XUnoTunnel> xTunnel( xPropertySet, UNO_QUERY ); + return xTunnel.is() + ? reinterpret_cast<Binding*>( xTunnel->getSomething(getUnoTunnelID())) + : NULL; +} + + + + +OUString Binding::getBindingID() const +{ + return msBindingID; +} + +void Binding::setBindingID( const OUString& sBindingID ) +{ + msBindingID = sBindingID; +} + +OUString Binding::getBindingExpression() const +{ + return maBindingExpression.getExpression(); +} + +void Binding::setBindingExpression( const OUString& sBindingExpression) +{ + maBindingExpression.setExpression( sBindingExpression ); + bindingModified(); +} + +OUString Binding::getReadonlyExpression() const +{ + return maReadonly.getExpression(); +} + +void Binding::setReadonlyExpression( const OUString& sReadonly) +{ + maReadonly.setExpression( sReadonly ); + bindingModified(); +} + +OUString Binding::getRelevantExpression() const +{ + return maRelevant.getExpression(); +} + +void Binding::setRelevantExpression( const OUString& sRelevant ) +{ + maRelevant.setExpression( sRelevant ); + bindingModified(); +} + +OUString Binding::getRequiredExpression() const +{ + return maRequired.getExpression(); +} + +void Binding::setRequiredExpression( const OUString& sRequired ) +{ + maRequired.setExpression( sRequired ); + bindingModified(); +} + +OUString Binding::getConstraintExpression() const +{ + return maConstraint.getExpression(); +} + +void Binding::setConstraintExpression( const OUString& sConstraint ) +{ + maConstraint.setExpression( sConstraint ); + msExplainConstraint = getResource( RID_STR_XFORMS_INVALID_CONSTRAINT, + sConstraint ); + + // TODO: This should only re-evaluate the constraint, and notify + // the validity constraint listeners; instead we currently pretend + // the entire binding was notified, which does a little too much. + bindingModified(); +} + +OUString Binding::getCalculateExpression() const +{ + return maCalculate.getExpression(); +} + +void Binding::setCalculateExpression( const OUString& sCalculate ) +{ + maCalculate.setExpression( sCalculate ); + bindingModified(); +} + +OUString Binding::getType() const +{ + return msTypeName; +} + +void Binding::setType( const OUString& sTypeName ) +{ + msTypeName = sTypeName; + bindingModified(); +} + +Binding::XNameContainer_t Binding::getBindingNamespaces() const +{ + // return _getNamespaces(); + return mxNamespaces; +} + +void Binding::setBindingNamespaces( const XNameContainer_t& rNamespaces ) +{ + _setNamespaces( rNamespaces, true ); +} + +Binding::XNameContainer_t Binding::getModelNamespaces() const +{ + return _getNamespaces(); +} + +void Binding::setModelNamespaces( const XNameContainer_t& rNamespaces ) +{ + _setNamespaces( rNamespaces, false ); +} + +bool Binding::getReadOnly() const +{ + return maMIP.isReadonly(); +} + +bool Binding::getRelevant() const +{ + return maMIP.isRelevant(); +} + +bool Binding::getExternalData() const +{ + bool bExternalData = true; + if ( !mxModel.is() ) + return bExternalData; + + try + { + Reference< XPropertySet > xModelProps( mxModel, UNO_QUERY_THROW ); + OSL_VERIFY( + xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ) ) >>= bExternalData ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bExternalData; +} + + +void Binding::checkLive() + throw( RuntimeException ) +{ + if( ! isLive() ) + throw RuntimeException( EXCEPT("Binding not initialized") ); +} + +void Binding::checkModel() + throw( RuntimeException ) +{ + if( ! mxModel.is() ) + throw RuntimeException( EXCEPT("Binding has no Model") ); +} + +bool Binding::isLive() const +{ + const Model* pModel = getModelImpl(); + return ( pModel != NULL ) ? pModel->isInitialized() : false; +} + +Model* Binding::getModelImpl() const +{ + return getModelImpl( mxModel ); +} + +Model* Binding::getModelImpl( const Model_t& xModel ) const +{ + Reference<XUnoTunnel> xTunnel( xModel, UNO_QUERY ); + Model* pModel = xTunnel.is() + ? reinterpret_cast<Model*>( + xTunnel->getSomething( Model::getUnoTunnelID() ) ) + : NULL; + return pModel; +} + +void lcl_addListenerToNode( Reference<XNode> xNode, + Reference<XEventListener> xListener ) +{ + Reference<XEventTarget> xTarget( xNode, UNO_QUERY ); + if( xTarget.is() ) + { + xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"), + xListener, false ); + xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"), + xListener, true ); + xTarget->addEventListener( OUSTRING("DOMAttrModified"), + xListener, false ); + xTarget->addEventListener( OUSTRING("DOMAttrModified"), + xListener, true ); + xTarget->addEventListener( OUSTRING("DOMAttrModified"), + xListener, true ); + xTarget->addEventListener( OUSTRING("xforms-generic"), + xListener, true ); + } +} + +void lcl_removeListenerFromNode( Reference<XNode> xNode, + Reference<XEventListener> xListener ) +{ + Reference<XEventTarget> xTarget( xNode, UNO_QUERY ); + if( xTarget.is() ) + { + xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"), + xListener, false ); + xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"), + xListener, true ); + xTarget->removeEventListener( OUSTRING("DOMAttrModified"), + xListener, false ); + xTarget->removeEventListener( OUSTRING("DOMAttrModified"), + xListener, true ); + xTarget->removeEventListener( OUSTRING("xforms-generic"), + xListener, true ); + } +} + +::std::vector<EvaluationContext> Binding::_getMIPEvaluationContexts() const +{ + OSL_ENSURE( getModelImpl() != NULL, "need model impl" ); + + // iterate over nodes of bind expression and create + // EvaluationContext for each + PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); + ::std::vector<EvaluationContext> aVector; + sal_Int32 nCount = 0; // count nodes for context position + for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin(); + aIter != aNodes.end(); + aIter++, nCount++ ) + { + OSL_ENSURE( aIter->is(), "no node?" ); + + // create proper evaluation context for this MIP + aVector.push_back( EvaluationContext( *aIter, getModel(), + getBindingNamespaces(), + nCount, aNodes.size() ) ); + } + return aVector; +} + +void Binding::bind( bool bForceRebind ) +{ + checkModel(); + + // bind() will evaluate this binding as follows: + // 1) evaluate the binding expression + // 1b) if necessary, create node according to 'lazy author' rules + // 2) register suitable listeners on the instance (and remove old ones) + // 3) remove old MIPs defined by this binding + // 4) for every node in the binding nodeset do: + // 1) create proper evaluation context for this MIP + // 2) evaluate calculate expression (and push value into instance) + // 3) evaluate remaining MIPs + // 4) evaluate the locally defined MIPs, and push them to the model + + + // 1) evaluate the binding expression + EvaluationContext aContext = getEvaluationContext(); + maBindingExpression.evaluate( aContext ); + if( ! maBindingExpression.getNode().is() ) + { + // 1b) create node (if valid element name) + if( isValidQName( maBindingExpression.getExpression(), + aContext.mxNamespaces ) ) + { + aContext.mxContextNode->appendChild( + Reference<XNode>( + aContext.mxContextNode->getOwnerDocument()->createElement( + maBindingExpression.getExpression() ), + UNO_QUERY ) ); + maBindingExpression.evaluate( aContext ); + OSL_ENSURE( maBindingExpression.getNode().is(), + "we should bind to the newly inserted node!" ); + } + } + PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); + + // 2) register suitable listeners on the instance (and remove old ones) + if( maEventNodes.empty() || bForceRebind ) + { + for( XNodes_t::iterator aIter = maEventNodes.begin(); + aIter != maEventNodes.end(); + aIter ++ ) + lcl_removeListenerFromNode( *aIter, this ); + maEventNodes.clear(); + if( isSimpleBinding() ) + for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin(); + aIter != aNodes.end(); + aIter++ ) + maEventNodes.push_back( *aIter ); + else + maEventNodes.push_back( + Reference<XNode>( aContext.mxContextNode->getOwnerDocument(), + UNO_QUERY_THROW ) ); + for( PathExpression::NodeVector_t::iterator aIter2 = maEventNodes.begin(); + aIter2 != maEventNodes.end(); + aIter2 ++ ) + lcl_addListenerToNode( *aIter2, this ); + } + + // 3) remove old MIPs defined by this binding + Model* pModel = getModelImpl(); + OSL_ENSURE( pModel != NULL, "need model" ); + pModel->removeMIPs( this ); + + // 4) calculate all MIPs + ::std::vector<EvaluationContext> aMIPContexts = _getMIPEvaluationContexts(); + for( ::std::vector<EvaluationContext>::iterator aIter = aMIPContexts.begin(); + aIter != aMIPContexts.end(); + aIter++ ) + { + EvaluationContext& rContext = *aIter; + + // evaluate calculate expression (and push value into instance) + // (prevent recursion using mbInCalculate + if( ! maCalculate.isEmptyExpression() ) + { + if( ! mbInCalculate ) + { + mbInCalculate = true; + maCalculate.evaluate( rContext ); + pModel->setSimpleContent( rContext.mxContextNode, + maCalculate.getString() ); + mbInCalculate = false; + } + } + + // now evaluate remaining MIPs in the apropriate context + maReadonly.evaluate( rContext ); + maRelevant.evaluate( rContext ); + maRequired.evaluate( rContext ); + maConstraint.evaluate( rContext ); + // type is static; does not need updating + + // evaluate the locally defined MIPs, and push them to the model + pModel->addMIP( this, rContext.mxContextNode, getLocalMIP() ); + } +} + + +// helper for Binding::valueModified +void lcl_modified( const Binding::XModifyListener_t xListener, + const Reference<XInterface> xSource ) +{ + OSL_ENSURE( xListener.is(), "no listener?" ); + xListener->modified( EventObject( xSource ) ); +} + +// helper for Binding::valueModified +void lcl_listentry( const Binding::XListEntryListener_t xListener, + const Reference<XInterface> xSource ) +{ + OSL_ENSURE( xListener.is(), "no listener?" ); + // TODO: send fine granular events + xListener->allEntriesChanged( EventObject( xSource ) ); +} + +// helper for Binding::valueModified +void lcl_validate( const Binding::XValidityConstraintListener_t xListener, + const Reference<XInterface> xSource ) +{ + OSL_ENSURE( xListener.is(), "no listener?" ); + xListener->validityConstraintChanged( EventObject( xSource ) ); +} + + +void Binding::valueModified() +{ + // defer notifications, if so desired + if( mnDeferModifyNotifications > 0 ) + { + mbValueModified = true; + return; + } + mbValueModified = false; + + // query MIP used by our first node (also note validity) + Reference<XNode> xNode = maBindingExpression.getNode(); + maMIP = getModelImpl()->queryMIP( xNode ); + + // distribute MIPs _used_ by this binding + if( xNode.is() ) + { + notifyAndCachePropertyValue( HANDLE_ReadOnly ); + notifyAndCachePropertyValue( HANDLE_Relevant ); + } + + // iterate over _value_ listeners and send each a modified signal, + // using this object as source (will also update validity, because + // control will query once the value has changed) + Reference<XInterface> xSource = static_cast<XPropertySet*>( this ); + ::std::for_each( maModifyListeners.begin(), + maModifyListeners.end(), + ::std::bind2nd( ::std::ptr_fun( lcl_modified ), xSource ) ); + ::std::for_each( maListEntryListeners.begin(), + maListEntryListeners.end(), + ::std::bind2nd( ::std::ptr_fun( lcl_listentry ), xSource ) ); + ::std::for_each( maValidityListeners.begin(), + maValidityListeners.end(), + ::std::bind2nd( ::std::ptr_fun( lcl_validate ), xSource ) ); + + // now distribute MIPs to childs + if( xNode.is() ) + distributeMIP( xNode->getFirstChild() ); +} + +void Binding::distributeMIP( const XNode_t & rxNode ) { + + typedef com::sun::star::xforms::XFormsEventConcrete XFormsEvent_t; + OUString sEventName( RTL_CONSTASCII_USTRINGPARAM("xforms-generic") ); + XFormsEvent_t *pEvent = new XFormsEvent_t; + pEvent->initXFormsEvent(sEventName, sal_True, sal_False); + Reference<XEvent> xEvent(pEvent); + + // naive depth-first traversal + XNode_t xNode( rxNode ); + while(xNode.is()) { + + // notifications should be triggered at the + // leaf nodes first, bubbling upwards the hierarchy. + XNode_t child(xNode->getFirstChild()); + if(child.is()) + distributeMIP(child); + + // we're standing at a particular node somewhere + // below the one which changed a property (MIP). + // bindings which are listening at this node will receive + // a notification message about what exactly happened. + Reference< XEventTarget > target(xNode,UNO_QUERY); + target->dispatchEvent(xEvent); + + xNode = xNode->getNextSibling(); + }; +} + +void Binding::bindingModified() +{ + // defer notifications, if so desired + if( mnDeferModifyNotifications > 0 ) + { + mbBindingModified = true; + return; + } + mbBindingModified = false; + + // rebind (if live); then call valueModified + // A binding should be inert until its model is fully constructed. + if( isLive() ) + { + bind( true ); + valueModified(); + } +} + + +MIP Binding::getLocalMIP() const +{ + MIP aMIP; + + if( maReadonly.hasValue() ) + aMIP.setReadonly( maReadonly.getBool( false ) ); + if( maRelevant.hasValue() ) + aMIP.setRelevant( maRelevant.getBool( true ) ); + if( maRequired.hasValue() ) + aMIP.setRequired( maRequired.getBool( false ) ); + if( maConstraint.hasValue() ) + { + aMIP.setConstraint( maConstraint.getBool( true ) ); + if( ! aMIP.isConstraint() ) + aMIP.setConstraintExplanation( msExplainConstraint ); + } + if( msTypeName.getLength() > 0 ) + aMIP.setTypeName( msTypeName ); + + // calculate: only handle presence of calculate; value set elsewhere + aMIP.setHasCalculate( !maCalculate.isEmptyExpression() ); + + return aMIP; +} + +Binding::XDataType_t Binding::getDataType() +{ + OSL_ENSURE( getModel().is(), "need model" ); + OSL_ENSURE( getModel()->getDataTypeRepository().is(), "need types" ); + + Reference<XDataTypeRepository> xRepository( + getModel()->getDataTypeRepository(), UNO_QUERY ); + OUString sTypeName = maMIP.getTypeName(); + + return ( xRepository.is() && xRepository->hasByName( sTypeName ) ) + ? Reference<XDataType>( xRepository->getByName( sTypeName ), UNO_QUERY) + : Reference<XDataType>( NULL ); +} + +bool Binding::isValid_DataType() +{ + Reference<XDataType> xDataType = getDataType(); + return xDataType.is() + ? xDataType->validate( maBindingExpression.getString() ) + : true; +} + +rtl::OUString Binding::explainInvalid_DataType() +{ + Reference<XDataType> xDataType = getDataType(); + return xDataType.is() + ? xDataType->explainInvalid( maBindingExpression.getString() ) + : OUString(); +} + +void Binding::clear() +{ + // remove MIPs contributed by this binding + Model* pModel = getModelImpl(); + if( pModel != NULL ) + pModel->removeMIPs( this ); + + // remove all references + for( XNodes_t::iterator aIter = maEventNodes.begin(); + aIter != maEventNodes.end(); + aIter ++ ) + lcl_removeListenerFromNode( *aIter, this ); + maEventNodes.clear(); + + // clear expressions + maBindingExpression.clear(); + maReadonly.clear(); + maRelevant.clear(); + maRequired.clear(); + maConstraint.clear(); + maCalculate.clear(); + + // TODO: what about our listeners? +} + + +void lcl_removeOtherNamespaces( const Binding::XNameContainer_t& xFrom, + Binding::XNameContainer_t& xTo ) +{ + OSL_ENSURE( xFrom.is(), "no source" ); + OSL_ENSURE( xTo.is(), "no target" ); + + // iterate over name in source + Sequence<OUString> aNames = xTo->getElementNames(); + sal_Int32 nNames = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + for( sal_Int32 i = 0; i < nNames; i++ ) + { + const OUString& rName = pNames[i]; + + if( ! xFrom->hasByName( rName ) ) + xTo->removeByName( rName ); + } +} + +/** copy namespaces from one namespace container into another + * @param bOverwrite true: overwrite namespaces in target + * false: do not overwrite namespaces in target + * @param bMove true: move namespaces (i.e., delete in source) + * false: copy namespaces (do not modify source) + * @param bFromSource true: use elements from source + * false: use only elements from target + */ +void lcl_copyNamespaces( const Binding::XNameContainer_t& xFrom, + Binding::XNameContainer_t& xTo, + bool bOverwrite ) +{ + OSL_ENSURE( xFrom.is(), "no source" ); + OSL_ENSURE( xTo.is(), "no target" ); + + // iterate over name in source + Sequence<OUString> aNames = xFrom->getElementNames(); + sal_Int32 nNames = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + for( sal_Int32 i = 0; i < nNames; i++ ) + { + const OUString& rName = pNames[i]; + + // determine whether to copy the value, and whether to delete + // it in the source: + + bool bInTarget = xTo->hasByName( rName ); + + // we copy: if property is in target, and + // if bOverwrite is set, or when the namespace prefix is free + bool bCopy = bOverwrite || ! bInTarget; + + // and now... ACTION! + if( bCopy ) + { + if( bInTarget ) + xTo->replaceByName( rName, xFrom->getByName( rName ) ); + else + xTo->insertByName( rName, xFrom->getByName( rName ) ); + } + } +} + +// implement get*Namespaces() +// (identical for both variants) +Binding::XNameContainer_t Binding::_getNamespaces() const +{ + XNameContainer_t xNamespaces = new NameContainer<OUString>(); + lcl_copyNamespaces( mxNamespaces, xNamespaces, true ); + + // merge model's with binding's own namespaces + Model* pModel = getModelImpl(); + if( pModel != NULL ) + lcl_copyNamespaces( pModel->getNamespaces(), xNamespaces, false ); + + return xNamespaces; +} + +// implement set*Namespaces() +// bBinding = true: setBindingNamespaces, otherwise: setModelNamespaces +void Binding::_setNamespaces( const XNameContainer_t& rNamespaces, + bool bBinding ) +{ + Model* pModel = getModelImpl(); + XNameContainer_t xModelNamespaces = ( pModel != NULL ) + ? pModel->getNamespaces() + : NULL; + OSL_ENSURE( ( pModel != NULL ) == xModelNamespaces.is(), "no model nmsp?"); + + // remove deleted namespaces + lcl_removeOtherNamespaces( rNamespaces, mxNamespaces ); + if( !bBinding && xModelNamespaces.is() ) + lcl_removeOtherNamespaces( rNamespaces, xModelNamespaces ); + + // copy namespaces as appropriate + Sequence<OUString> aNames = rNamespaces->getElementNames(); + sal_Int32 nNames = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + for( sal_Int32 i = 0; i < nNames; i++ ) + { + const OUString& rName = pNames[i]; + Any aValue = rNamespaces->getByName( rName ); + + // determine whether the namespace should go into model's or + // into binding's namespaces + bool bLocal = + ! xModelNamespaces.is() + || mxNamespaces->hasByName( rName ) + || ( bBinding + && xModelNamespaces.is() + && xModelNamespaces->hasByName( rName ) ); + + // write namespace into the appropriate namespace container + XNameContainer_t& rWhich = bLocal ? mxNamespaces : xModelNamespaces; + OSL_ENSURE( rWhich.is(), "whoops" ); + if( rWhich->hasByName( rName ) ) + rWhich->replaceByName( rName, aValue ); + else + rWhich->insertByName( rName, aValue ); + + // always 'promote' namespaces from binding to model, if equal + if( xModelNamespaces.is() + && xModelNamespaces->hasByName( rName ) + && mxNamespaces->hasByName( rName ) + && xModelNamespaces->getByName( rName ) == mxNamespaces->getByName( rName ) ) + { + mxNamespaces->removeByName( rName ); + } + } + + // ... done. But we modified the binding! + bindingModified(); +} + +void Binding::_checkBindingID() +{ + if( getModel().is() ) + { + Reference<XNameAccess> xBindings( getModel()->getBindings(), UNO_QUERY_THROW ); + if( msBindingID.getLength() == 0 ) + { + // no binding ID? then make one up! + OUString sIDPrefix = getResource( RID_STR_XFORMS_BINDING_UI_NAME ); + sIDPrefix += String::CreateFromAscii( " " ); + sal_Int32 nNumber = 0; + OUString sName; + do + { + nNumber++; + sName = sIDPrefix + OUString::valueOf( nNumber ); + } + while( xBindings->hasByName( sName ) ); + setBindingID( sName ); + } + } +} + + + + +// +// XValueBinding +// + +Binding::Sequence_Type_t Binding::getSupportedValueTypes() + throw( RuntimeException ) +{ + return Convert::get().getTypes(); +} + +sal_Bool Binding::supportsType( const Type_t& rType ) + throw( RuntimeException ) +{ + return Convert::get().hasType( rType ); +} + +Binding::Any_t Binding::getValue( const Type_t& rType ) + throw( IncompatibleTypesException, + RuntimeException ) +{ + // first, check for model + checkLive(); + + // second, check for type + if( ! supportsType( rType ) ) + throw IncompatibleTypesException( EXCEPT( "type unsupported" ) ); + + // return string value (if present; else return empty Any) + Binding::Any_t result = Any(); + if(maBindingExpression.hasValue()) { + rtl::OUString pathExpr(maBindingExpression.getString()); + Convert &rConvert = Convert::get(); + result = rConvert.toAny(pathExpr,rType); + } + +// return maBindingExpression.hasValue() + // ? Convert::get().toAny( maBindingExpression.getString(), rType ) + // : Any(); + + return result; +} + +void Binding::setValue( const Any_t& aValue ) + throw( IncompatibleTypesException, + InvalidBindingStateException, + NoSupportException, + RuntimeException ) +{ + // first, check for model + checkLive(); + + // check for supported type + if( ! supportsType( aValue.getValueType() ) ) + throw IncompatibleTypesException( EXCEPT( "type unsupported" ) ); + + if( maBindingExpression.hasValue() ) + { + Binding::XNode_t xNode = maBindingExpression.getNode(); + if( xNode.is() ) + { + OUString sValue = Convert::get().toXSD( aValue ); + bool bSuccess = getModelImpl()->setSimpleContent( xNode, sValue ); + if( ! bSuccess ) + throw InvalidBindingStateException( EXCEPT( "can't set value" ) ); + } + else + throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) ); + } + else + throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) ); +} + + +// +// XListEntry Source +// + +sal_Int32 Binding::getListEntryCount() + throw( RuntimeException ) +{ + // first, check for model + checkLive(); + + // return size of node list + return maBindingExpression.getNodeList().size(); +} + +void lcl_getString( const Reference<XNode>& xNode, OUStringBuffer& rBuffer ) +{ + if( xNode->getNodeType() == NodeType_TEXT_NODE + || xNode->getNodeType() == NodeType_ATTRIBUTE_NODE ) + { + rBuffer.append( xNode->getNodeValue() ); + } + else + { + for( Reference<XNode> xChild = xNode->getFirstChild(); + xChild.is(); + xChild = xChild->getNextSibling() ) + { + lcl_getString( xChild, rBuffer ); + } + } +} + +OUString lcl_getString( const Reference<XNode>& xNode ) +{ + OUStringBuffer aBuffer; + lcl_getString( xNode, aBuffer ); + return aBuffer.makeStringAndClear(); +} + +OUString Binding::getListEntry( sal_Int32 nPosition ) + throw( IndexOutOfBoundsException, + RuntimeException ) +{ + // first, check for model + checkLive(); + + // check bounds and return proper item + PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); + if( nPosition < 0 || nPosition >= static_cast<sal_Int32>( aNodes.size() ) ) + throw IndexOutOfBoundsException( EXCEPT("") ); + return lcl_getString( aNodes[ nPosition ] ); +} + +Sequence<OUString> Binding::getAllListEntries() + throw( RuntimeException ) +{ + // first, check for model + checkLive(); + + // create sequence of string values + PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); + Sequence<OUString> aSequence( aNodes.size() ); + OUString* pSequence = aSequence.getArray(); + for( sal_Int32 n = 0; n < aSequence.getLength(); n++ ) + { + pSequence[n] = lcl_getString( aNodes[n] ); + } + + return aSequence; +} + +void Binding::addListEntryListener( const XListEntryListener_t& xListener ) + throw( NullPointerException, + RuntimeException ) +{ + OSL_ENSURE( xListener.is(), "need listener!" ); + if( ::std::find( maListEntryListeners.begin(), + maListEntryListeners.end(), + xListener) + == maListEntryListeners.end() ) + maListEntryListeners.push_back( xListener ); +} + +void Binding::removeListEntryListener( const XListEntryListener_t& xListener ) + throw( NullPointerException, + RuntimeException ) +{ + XListEntryListeners_t::iterator aIter = + ::std::find( maListEntryListeners.begin(), maListEntryListeners.end(), + xListener ); + if( aIter != maListEntryListeners.end() ) + maListEntryListeners.erase( aIter ); +} + + +// +// XValidator +// + +sal_Bool Binding::isValid( const Any_t& ) + throw( RuntimeException ) +{ + // first, check for model + checkLive(); + + // ignore value; determine validate only on current data + return isValid(); +} + +rtl::OUString Binding::explainInvalid( + const Any_t& /*Value*/ ) + throw( RuntimeException ) +{ + // first, check for model + checkLive(); + + // ignore value; determine explanation only on current data + return explainInvalid(); +} + +void Binding::addValidityConstraintListener( + const XValidityConstraintListener_t& xListener ) + throw( NullPointerException, + RuntimeException ) +{ + OSL_ENSURE( xListener.is(), "need listener!" ); + if( ::std::find(maValidityListeners.begin(), maValidityListeners.end(), xListener) + == maValidityListeners.end() ) + maValidityListeners.push_back( xListener ); +} + +void Binding::removeValidityConstraintListener( + const XValidityConstraintListener_t& xListener ) + throw( NullPointerException, + RuntimeException ) +{ + XValidityConstraintListeners_t::iterator aIter = + ::std::find( maValidityListeners.begin(), maValidityListeners.end(), + xListener ); + if( aIter != maValidityListeners.end() ) + maValidityListeners.erase( aIter ); +} + + + +// +// xml::dom::event::XEventListener +// + +void Binding::handleEvent( const XEvent_t& xEvent ) + throw( RuntimeException ) +{ + OUString sType(xEvent->getType()); + //OUString sEventMIPChanged(RTL_CONSTASCII_USTRINGPARAM("xforms-generic")); + //if(sType.equals(sEventMIPChanged)) { + if(!sType.compareToAscii("xforms-generic")) { + + // the modification of the 'mnDeferModifyNotifications'-member + // is necessary to prevent infinite notication looping. + // This can happend in case the binding which caused + // the notification chain is listening to those events + // as well... + bool bPreserveValueModified = mbValueModified; + mnDeferModifyNotifications++; + valueModified(); + --mnDeferModifyNotifications; + mbValueModified = bPreserveValueModified; + return; + } + + // if we're a dynamic binding, we better re-bind, too! + bind( false ); + + // our value was maybe modified + valueModified(); +} + + +// +// lang::XUnoTunnel +// + +sal_Int64 Binding::getSomething( const IntSequence_t& xId ) + throw( RuntimeException ) +{ + return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL ); +} + +// +// XCloneable +// + +Binding::XCloneable_t SAL_CALL Binding::createClone() + throw( RuntimeException ) +{ + Reference< XPropertySet > xClone; + + Model* pModel = getModelImpl(); + if ( pModel ) + xClone = pModel->cloneBinding( this ); + else + { + xClone = new Binding; + copy( this, xClone ); + } + return XCloneable_t( xClone, UNO_QUERY ); +} + +// +// property set implementations +// + +#define REGISTER_PROPERTY( property, type ) \ + registerProperty( PROPERTY( property, type ), \ + new DirectPropertyAccessor< Binding, type >( this, &Binding::set##property, &Binding::get##property ) ); + +#define REGISTER_PROPERTY_RO( property, type ) \ + registerProperty( PROPERTY_RO( property, type ), \ + new DirectPropertyAccessor< Binding, type >( this, NULL, &Binding::get##property ) ); + +#define REGISTER_BOOL_PROPERTY_RO( property ) \ + registerProperty( PROPERTY_RO( property, sal_Bool ), \ + new BooleanPropertyAccessor< Binding, bool >( this, NULL, &Binding::get##property ) ); + +void Binding::initializePropertySet() +{ + REGISTER_PROPERTY ( BindingID, OUString ); + REGISTER_PROPERTY ( BindingExpression, OUString ); + REGISTER_PROPERTY_RO ( Model, Model_t ); + REGISTER_PROPERTY ( BindingNamespaces, XNameContainer_t ); + REGISTER_PROPERTY ( ModelNamespaces, XNameContainer_t ); + REGISTER_PROPERTY_RO ( ModelID, OUString ); + REGISTER_PROPERTY ( ReadonlyExpression, OUString ); + REGISTER_PROPERTY ( RelevantExpression, OUString ); + REGISTER_PROPERTY ( RequiredExpression, OUString ); + REGISTER_PROPERTY ( ConstraintExpression, OUString ); + REGISTER_PROPERTY ( CalculateExpression, OUString ); + REGISTER_PROPERTY ( Type, OUString ); + REGISTER_PROPERTY_RO ( ReadOnly, bool ); + REGISTER_PROPERTY_RO ( Relevant, bool ); + REGISTER_BOOL_PROPERTY_RO( ExternalData ); + + initializePropertyValueCache( HANDLE_ReadOnly ); + initializePropertyValueCache( HANDLE_Relevant ); + initializePropertyValueCache( HANDLE_ExternalData ); +} + +void Binding::addModifyListener( + const XModifyListener_t& xListener ) + throw( RuntimeException ) +{ + OSL_ENSURE( xListener.is(), "need listener!" ); + if( ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener ) + == maModifyListeners.end() ) + maModifyListeners.push_back( xListener ); + + // HACK: currently, we have to 'push' some MIPs to the control + // (read-only, relevant, etc.) To enable this, we need to update + // the control at least once when it registers here. + valueModified(); +} + +void Binding::removeModifyListener( + const XModifyListener_t& xListener ) + throw( RuntimeException ) +{ + ModifyListeners_t::iterator aIter = + ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener ); + if( aIter != maModifyListeners.end() ) + maModifyListeners.erase( aIter ); +} + + + + +rtl::OUString Binding::getName() + throw( RuntimeException ) +{ + return getBindingID(); +} + +void SAL_CALL Binding::setName( const rtl::OUString& rName ) + throw( RuntimeException ) +{ + // use the XPropertySet methods, so the change in the name is notified to the + // property listeners + setFastPropertyValue( HANDLE_BindingID, makeAny( rName ) ); +} diff --git a/forms/source/xforms/binding.hxx b/forms/source/xforms/binding.hxx new file mode 100644 index 000000000000..7a69b1547418 --- /dev/null +++ b/forms/source/xforms/binding.hxx @@ -0,0 +1,527 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BINDING_HXX +#define _BINDING_HXX + +#include <com/sun/star/uno/Reference.hxx> + +// forward declaractions +namespace xforms +{ + class Model; + class EvaluationContext; +} +namespace com { namespace sun { namespace star { + namespace xml { + namespace xpath { class XXPathAPI; } + namespace dom + { + class XNode; + class XNodeList; + } + } + namespace container { class XNameContainer; } + namespace xforms { class XModel; } + namespace xsd { class XDataType; } +} } } + +// includes for parent classes +#include <cppuhelper/implbase8.hxx> +#include <propertysetbase.hxx> +#include <com/sun/star/form/binding/XValueBinding.hpp> +#include <com/sun/star/form/binding/XListEntrySource.hpp> +#include <com/sun/star/form/validation/XValidator.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/xml/dom/events/XEventListener.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +// includes for member variables +#include "pathexpression.hxx" +#include "boolexpression.hxx" +#include "mip.hxx" +#include <rtl/ustring.hxx> +#include <vector> +#include <memory> // auto_ptr + + + +namespace xforms +{ + +/** An XForms Binding. Contains: + * # a connection to its model + * # an ID + * # an binding expression + * # model item properties + * # (NOT YET IMPLEMENTED) child bindings (sequence of) + * + * See http://www.w3.org/TR/xforms/ for more information. + */ + +typedef cppu::ImplInheritanceHelper8< + PropertySetBase, + com::sun::star::form::binding::XValueBinding, + com::sun::star::form::binding::XListEntrySource, + com::sun::star::form::validation::XValidator, + com::sun::star::util::XModifyBroadcaster, + com::sun::star::container::XNamed, + com::sun::star::xml::dom::events::XEventListener, + com::sun::star::lang::XUnoTunnel, + com::sun::star::util::XCloneable +> Binding_t; + +class Binding : public Binding_t +{ +public: + typedef com::sun::star::uno::Reference<com::sun::star::xforms::XModel> Model_t; + typedef com::sun::star::uno::Reference<com::sun::star::util::XModifyListener> XModifyListener_t; + typedef std::vector<XModifyListener_t> ModifyListeners_t; + typedef com::sun::star::uno::Reference<com::sun::star::form::validation::XValidityConstraintListener> XValidityConstraintListener_t; + typedef std::vector<XValidityConstraintListener_t> XValidityConstraintListeners_t; + typedef com::sun::star::uno::Reference<com::sun::star::form::binding::XListEntryListener> XListEntryListener_t; + typedef std::vector<XListEntryListener_t> XListEntryListeners_t; + typedef com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> XNameContainer_t; + typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> XNode_t; + typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNodeList> XNodeList_t; + typedef com::sun::star::uno::Reference<com::sun::star::util::XCloneable> XCloneable_t; + typedef com::sun::star::uno::Sequence<sal_Int8> IntSequence_t; + typedef com::sun::star::uno::Sequence<rtl::OUString> StringSequence_t; + typedef std::vector<MIP> MIPs_t; + typedef std::vector<XNode_t> XNodes_t; + + + +private: + + /// the Model to which this Binding belongs; may be NULL + Model_t mxModel; + + /// binding-ID. A document-wide unique ID for this binding element. + rtl::OUString msBindingID; + + /// an XPath-expression to be instantiated on the data instance + PathExpression maBindingExpression; + + /// an XPath-expression to determine read-only status + BoolExpression maReadonly; + + /// an XPath-expression to determine relevance + BoolExpression maRelevant; + + /// an XPath-expression to determine if item is required + BoolExpression maRequired; + + /// an XPath-expression to determine if item is valid + BoolExpression maConstraint; + + /// user-readable explanation of the constraint + rtl::OUString msExplainConstraint; + + /// an XPath-expression to calculate values + ComputedExpression maCalculate; + + /// the XML namespaces used for XML names/XPath-expressions in this binding + XNameContainer_t mxNamespaces; + + /// a type name + rtl::OUString msTypeName; + + /// modify listeners + ModifyListeners_t maModifyListeners; + + /// list entry listener + XListEntryListeners_t maListEntryListeners; + + /// validity listeners; + XValidityConstraintListeners_t maValidityListeners; + + /// nodes on which we are listening for events + XNodes_t maEventNodes; + + /// the current MIP object for the first node we are bound to + MIP maMIP; + + /// flag to detect recursions in calculate + bool mbInCalculate; + + // flags to manage deferred notifications: + /// if >0, valueModified() and bindingModified() will only set flags + sal_Int32 mnDeferModifyNotifications; + bool mbValueModified; /// if true, valueModified needs to be called + bool mbBindingModified; /// if true, bindingModified needs to be called + + + void initializePropertySet(); + + +public: + Binding(); + virtual ~Binding() throw(); + + // + // property methods: get/set value + // + + Model_t getModel() const; /// get XForms model + void _setModel( const Model_t& ); /// set XForms model (only called by Model) + + + rtl::OUString getModelID() const; /// get ID of XForms model + + rtl::OUString getBindingID() const; /// get ID for this binding + void setBindingID( const rtl::OUString& ); /// set ID for this binding + + rtl::OUString getBindingExpression() const; /// get binding expression + void setBindingExpression( const rtl::OUString& ); /// set binding exp. + + // MIPs (model item properties) + + rtl::OUString getReadonlyExpression() const; /// get read-only MIP + void setReadonlyExpression( const rtl::OUString& ); /// set read-only MIP + + rtl::OUString getRelevantExpression() const; /// get relevant MIP + void setRelevantExpression( const rtl::OUString& ); /// set relevant MIP + + rtl::OUString getRequiredExpression() const; /// get required MIP + void setRequiredExpression( const rtl::OUString& ); /// set required MIP + + rtl::OUString getConstraintExpression() const; /// get constraint MIP + void setConstraintExpression( const rtl::OUString& );/// set constraint MIP + + rtl::OUString getCalculateExpression() const; /// get calculate MIP + void setCalculateExpression( const rtl::OUString& ); /// set calculate MIP + + rtl::OUString getType() const; /// get type name MIP (static) + void setType( const rtl::OUString& ); /// set type name MIP (static) + + // a binding expression can only be interpreted with respect to + // suitable namespace declarations. We collect those in the model and in a binding. + + // access to a binding's namespace + // (set-method only changes local namespaces (but may add to model)) + XNameContainer_t getBindingNamespaces() const; /// set binding namespaces + void setBindingNamespaces( const XNameContainer_t& ); /// get binding nmsp. + + // access to the model's namespaces + // (set-method changes model's namespaces (unless a local one is present)) + XNameContainer_t getModelNamespaces() const; /// set model namespaces + void setModelNamespaces( const XNameContainer_t& ); /// get model nmsp. + + + // read-only properties that map MIPs to control data source properties + bool getReadOnly() const; // MIP readonly + bool getRelevant() const; // MIP relevant + bool getExternalData() const; // mapped from model's ExternalData property + + + // missing binding properties: + // - type (static; default: xsd:string) + // - minOccurs/maxOccurs (computed XPath; default: 0/inf) + // - p3ptype (static; no default) + + + + + /// get this binding's context node + xforms::EvaluationContext getEvaluationContext() const; + + /// get evalation contexts for this binding's MIPs + std::vector<xforms::EvaluationContext> getMIPEvaluationContexts(); + + /// get nodeset the bind is bound to + XNodeList_t getXNodeList(); + + /// heuristically determine whether this binding is simple binding + /// (here: simple binding == does not depend on other parts of the + /// instance, it's not a 'dynamic' binding) + bool isSimpleBinding() const; + + /// heuristically determine whether this binding's binding + /// expression is simple + bool isSimpleBindingExpression() const; + + /// update this binding (e.g. called by model for refresh ) + void update(); + + /// prevent change notifications being sent to controls + void deferNotifications( bool ); + + /// is this binding valid? (are constraint, type and required MIPs ok?) + bool isValid(); + + /// determine whether this binding currently performs a useful + /// function, r whether is may be discarded + bool isUseful(); + + /// explain why binding is invalid + rtl::OUString explainInvalid(); + + + // the ID for XUnoTunnel calls + static IntSequence_t getUnoTunnelID(); + static Binding* getBinding( const com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& ); + + // + // class-scoped typedef for easy-to-read UNO interfaces + // + + // basic types + typedef com::sun::star::uno::Any Any_t; + typedef com::sun::star::uno::Sequence<com::sun::star::uno::Type> Sequence_Type_t; + typedef com::sun::star::uno::Type Type_t; + + // reference types + typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertyChangeListener> XPropertyChangeListener_t; + typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertySetInfo> XPropertySetInfo_t; + typedef com::sun::star::uno::Reference<com::sun::star::beans::XVetoableChangeListener> XVetoableChangeListener_t; + typedef com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathAPI> XXPathAPI_t; + typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::events::XEvent> XEvent_t; + typedef com::sun::star::uno::Reference<com::sun::star::xsd::XDataType> XDataType_t; + + // exceptions + typedef com::sun::star::beans::PropertyVetoException PropertyVetoException_t; + typedef com::sun::star::beans::UnknownPropertyException UnknownPropertyException_t; + typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t; + typedef com::sun::star::lang::NoSupportException NoSupportException_t; + typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t; + typedef com::sun::star::uno::RuntimeException RuntimeException_t; + typedef com::sun::star::form::binding::IncompatibleTypesException IncompatibleTypesException_t; + typedef com::sun::star::form::binding::InvalidBindingStateException InvalidBindingStateException_t; + typedef com::sun::star::lang::NullPointerException NullPointerException_t; + typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t; + + + +private: + /// check whether object is live, and throw suitable exception if not + /// (to be used be API methods before acting on the object) + void checkLive() throw( RuntimeException_t ); + + /// check whether binding has a model, and throw exception if not + /// (to be used be API methods before acting on the object) + void checkModel() throw( RuntimeException_t ); + + /// determine whether object is live + /// live: has model, and model has been initialized + bool isLive() const; + + /// get the model implementation + xforms::Model* getModelImpl() const; + xforms::Model* getModelImpl( const Model_t& xModel ) const; + + /// get MIP evaluation contexts + /// (only valid if control has already been bound) + std::vector<xforms::EvaluationContext> _getMIPEvaluationContexts() const; + + /// bind this binding, and pre-compute the affected nodes + void bind( bool bForceRebind = false ); + + /// the binding value has been changed: + /// trigger a modified event on all modified listeners + void valueModified(); + + /// the binding itself has changed: + /// force rebind, then call valueModified() + void bindingModified(); + + + /// register the event listeners for + void registerListeners(); + + /// set MIPs defined by this binding on MIP item + MIP getLocalMIP() const; + + /// get the data type that applies to this binding + XDataType_t getDataType(); + + /// determine whether binding is valid according to the given data type + bool isValid_DataType(); + + /// explain validity of binding with respect to the given data type + rtl::OUString explainInvalid_DataType(); + + /// 'clear' this binding - remove all listeners, etc. + void clear(); + + /// distribute MIPs from current node recursively to childs + void distributeMIP( const XNode_t &rxNode ); + + /// implement get*Namespaces() + XNameContainer_t _getNamespaces() const; + + /// implement set*Namespaces() + void _setNamespaces( const XNameContainer_t&, bool bBinding ); + + /// set a useful default binding ID (if none is set) + void _checkBindingID(); + +public: + /// for debugging purposes only: get the MIPs defined by this binding + const MIP* _getMIP(); + + + + + + // + // XValueBinding: + // + +public: + + virtual Sequence_Type_t SAL_CALL getSupportedValueTypes() + throw( RuntimeException_t ); + + virtual sal_Bool SAL_CALL supportsType( const Type_t& aType ) + throw( RuntimeException_t ); + + virtual Any_t SAL_CALL getValue( const Type_t& aType ) + throw( IncompatibleTypesException_t, + RuntimeException_t ); + + virtual void SAL_CALL setValue( const Any_t& aValue ) + throw( IncompatibleTypesException_t, + InvalidBindingStateException_t, + NoSupportException_t, + RuntimeException_t ); + + + + // + // XListEntry Source + // + + virtual sal_Int32 SAL_CALL getListEntryCount() + throw( RuntimeException_t ); + + virtual rtl::OUString SAL_CALL getListEntry( sal_Int32 nPosition ) + throw( IndexOutOfBoundsException_t, + RuntimeException_t ); + + virtual StringSequence_t SAL_CALL getAllListEntries() + throw( RuntimeException_t ); + + virtual void SAL_CALL addListEntryListener( const XListEntryListener_t& ) + throw( NullPointerException_t, + RuntimeException_t ); + + virtual void SAL_CALL removeListEntryListener( const XListEntryListener_t&) + throw( NullPointerException_t, + RuntimeException_t ); + + + + // + // XValidator: + // + + virtual sal_Bool SAL_CALL isValid( + const Any_t& ) + throw( RuntimeException_t ); + + virtual rtl::OUString SAL_CALL explainInvalid( + const Any_t& ) + throw( RuntimeException_t ); + + virtual void SAL_CALL addValidityConstraintListener( + const XValidityConstraintListener_t& xListener ) + throw( NullPointerException_t, + RuntimeException_t ); + + virtual void SAL_CALL removeValidityConstraintListener( + const XValidityConstraintListener_t& xListener ) + throw( NullPointerException_t, + RuntimeException_t ); + + + // + // XModifyBroadcaster & friends: + // inform listeners about changes in our values + // + +public: + + virtual void SAL_CALL addModifyListener( + const XModifyListener_t& xListener ) + throw( RuntimeException_t ); + + virtual void SAL_CALL removeModifyListener( + const XModifyListener_t& xListener ) + throw( RuntimeException_t ); + + + + + // + // XNamed: + // get/set name + // + +public: + + virtual rtl::OUString SAL_CALL getName() + throw( RuntimeException_t ); + + virtual void SAL_CALL setName( const rtl::OUString& ) + throw( RuntimeException_t ); + + + + // + // xml::dom::event::XEventListener + // receive an event if our node changed + // + + virtual void SAL_CALL handleEvent( + const XEvent_t& xEvent ) + throw( RuntimeException_t ); + + + + // + // XUnoTunnel + // + + virtual sal_Int64 SAL_CALL getSomething( const IntSequence_t& ) + throw( RuntimeException_t ); + + + // + // XCloneable + // + + virtual XCloneable_t SAL_CALL createClone() + throw( RuntimeException_t ); +}; + + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/boolexpression.cxx b/forms/source/xforms/boolexpression.cxx new file mode 100644 index 000000000000..c8d7572b5f56 --- /dev/null +++ b/forms/source/xforms/boolexpression.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "boolexpression.hxx" + + +namespace xforms +{ + +/** BoolExpression represents a computed XPath expression that returns + * a bool value and caches the results. + * + * As this class has no virtual methods, it should never be used + * polymorphically. */ + +BoolExpression::BoolExpression() : ComputedExpression() +{ +} + +BoolExpression::~BoolExpression() +{ +} + +void BoolExpression::setExpression( const rtl::OUString& rExpression ) +{ + ComputedExpression::setExpression( rExpression ); + mbIsSimple = _checkExpression( " *(true)|(false) *\\( *\\) *" ); +} + + +} // namespace xforms + diff --git a/forms/source/xforms/boolexpression.hxx b/forms/source/xforms/boolexpression.hxx new file mode 100644 index 000000000000..2c34a98b4fed --- /dev/null +++ b/forms/source/xforms/boolexpression.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BOOLEXPRESSION_HXX +#define _BOOLEXPRESSION_HXX + +// include for parent class +#include "computedexpression.hxx" + +namespace xforms +{ + +/** BoolExpression represents a computed XPath expression that returns + * a bool value and caches the results. + * + * As this class has no virtual methods, it should never be used + * polymorphically. */ +class BoolExpression : public ComputedExpression +{ +public: + BoolExpression(); + ~BoolExpression(); + + /// set the expression string + /// (overridden for new definition of a simple expression) + void setExpression( const rtl::OUString& rExpression ); +}; + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/collection.hxx b/forms/source/xforms/collection.hxx new file mode 100644 index 000000000000..2c083a969306 --- /dev/null +++ b/forms/source/xforms/collection.hxx @@ -0,0 +1,337 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _COLLECTION_HXX +#define _COLLECTION_HXX + +#include "enumeration.hxx" + +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/container/ElementExistException.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XIndexReplace.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Type.hxx> +#include <vector> +#include <algorithm> + + +typedef cppu::WeakImplHelper3< + com::sun::star::container::XIndexReplace, + com::sun::star::container::XSet, + com::sun::star::container::XContainer> +Collection_t; + +template<class ELEMENT_TYPE> +class Collection : public Collection_t +{ +public: + typedef ELEMENT_TYPE T; + typedef com::sun::star::uno::Reference<com::sun::star::container::XContainerListener> XContainerListener_t; + typedef std::vector<XContainerListener_t> Listeners_t; + +protected: + std::vector<T> maItems; + Listeners_t maListeners; + +public: + + Collection() {} + virtual ~Collection() {} + + const T& getItem( sal_Int32 n ) const + { + OSL_ENSURE( isValidIndex(n), "invalid index" ); + OSL_ENSURE( isValid( maItems[n] ), "invalid item found" ); + return maItems[n]; + } + + void setItem( sal_Int32 n, const T& t) + { + OSL_ENSURE( isValidIndex(n), "invalid index" ); + OSL_ENSURE( isValid ( t ), "invalid item" ); + + T& aRef = maItems[ n ]; + _elementReplaced( n, t ); + _remove( aRef ); + aRef = t; + _insert( t ); + } + + bool hasItem( const T& t ) const + { + return maItems.end() != std::find( maItems.begin(), maItems.end(), t ); + } + + sal_Int32 addItem( const T& t ) + { + OSL_ENSURE( !hasItem( t ), "item to be added already present" ); + OSL_ENSURE( isValid( t ), "invalid item" ); + + maItems.push_back( t ); + _insert( t ); + _elementInserted( maItems.size() - 1 ); + return ( maItems.size() - 1 ); + } + + void removeItem( const T& t ) + { + OSL_ENSURE( hasItem( t ), "item to be removed not present" ); + OSL_ENSURE( isValid( t ), "an invalid item, funny that!" ); + + _elementRemoved( t ); + _remove( t ); + maItems.erase( std::find( maItems.begin(), maItems.end(), t ) ); + } + + bool hasItems() const + { + return maItems.size() != 0; + } + + sal_Int32 countItems() const + { + return static_cast<sal_Int32>( maItems.size() ); + } + + bool isValidIndex( sal_Int32 n ) const + { + return n >= 0 && n < static_cast<sal_Int32>( maItems.size() ); + } + + + // the following method may be overriden by sub-classes for + // customized behaviour + + /// called before insertion to determine whether item is valid + virtual bool isValid( const T& ) const { return true; } + + +protected: + + // the following methods may be overriden by sub-classes for + // customized behaviour + + /// called after item has been inserted into the collection + virtual void _insert( const T& ) { } + + /// called before item is removed from the collection + virtual void _remove( const T& ) { } + +public: + + typedef com::sun::star::uno::Type Type_t; + typedef com::sun::star::uno::Any Any_t; + typedef com::sun::star::uno::RuntimeException RuntimeException_t; + typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t; + typedef com::sun::star::container::NoSuchElementException NoSuchElementException_t; + typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t; + typedef com::sun::star::uno::Reference<com::sun::star::container::XEnumeration> XEnumeration_t; + typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t; + typedef com::sun::star::container::ElementExistException ElementExistException_t; + + + // XElementAccess + virtual Type_t SAL_CALL getElementType() + throw( RuntimeException_t ) + { + return getCppuType( static_cast<T*>( NULL ) ); + } + + virtual sal_Bool SAL_CALL hasElements() + throw( RuntimeException_t ) + { + return hasItems(); + } + + // XIndexAccess : XElementAccess + virtual sal_Int32 SAL_CALL getCount() + throw( RuntimeException_t ) + { + return countItems(); + } + + virtual Any_t SAL_CALL getByIndex( sal_Int32 nIndex ) + throw( IndexOutOfBoundsException_t, + WrappedTargetException_t, + RuntimeException_t) + { + if( isValidIndex( nIndex ) ) + return com::sun::star::uno::makeAny( getItem( nIndex ) ); + else + throw IndexOutOfBoundsException_t(); + } + + // XIndexReplace : XIndexAccess + virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex, + const Any_t& aElement ) + throw( IllegalArgumentException_t, + IndexOutOfBoundsException_t, + WrappedTargetException_t, + RuntimeException_t) + { + T t; + if( isValidIndex( nIndex) ) + if( ( aElement >>= t ) && isValid( t ) ) + setItem( nIndex, t ); + else + throw IllegalArgumentException_t(); + else + throw IndexOutOfBoundsException_t(); + } + + // XEnumerationAccess : XElementAccess + virtual XEnumeration_t SAL_CALL createEnumeration() + throw( RuntimeException_t ) + { + return new Enumeration( this ); + } + + + // XSet : XEnumerationAccess + virtual sal_Bool SAL_CALL has( const Any_t& aElement ) + throw( RuntimeException_t ) + { + T t; + return ( aElement >>= t ) ? hasItem( t ) : sal_False; + } + + virtual void SAL_CALL insert( const Any_t& aElement ) + throw( IllegalArgumentException_t, + ElementExistException_t, + RuntimeException_t ) + { + T t; + if( ( aElement >>= t ) && isValid( t ) ) + if( ! hasItem( t ) ) + addItem( t ); + else + throw ElementExistException_t(); + else + throw IllegalArgumentException_t(); + } + + virtual void SAL_CALL remove( const Any_t& aElement ) + throw( IllegalArgumentException_t, + NoSuchElementException_t, + RuntimeException_t ) + { + T t; + if( aElement >>= t ) + if( hasItem( t ) ) + removeItem( t ); + else + throw NoSuchElementException_t(); + else + throw IllegalArgumentException_t(); + } + + + // XContainer + virtual void SAL_CALL addContainerListener( + const XContainerListener_t& xListener ) + throw( RuntimeException_t ) + { + OSL_ENSURE( xListener.is(), "need listener!" ); + if( std::find( maListeners.begin(), maListeners.end(), xListener) + == maListeners.end() ) + maListeners.push_back( xListener ); + } + + virtual void SAL_CALL removeContainerListener( + const XContainerListener_t& xListener ) + throw( RuntimeException_t ) + { + OSL_ENSURE( xListener.is(), "need listener!" ); + Listeners_t::iterator aIter = + std::find( maListeners.begin(), maListeners.end(), xListener ); + if( aIter != maListeners.end() ) + maListeners.erase( aIter ); + } + +protected: + + // call listeners: + void _elementInserted( sal_Int32 nPos ) + { + OSL_ENSURE( isValidIndex(nPos), "invalid index" ); + com::sun::star::container::ContainerEvent aEvent( + static_cast<com::sun::star::container::XIndexReplace*>( this ), + com::sun::star::uno::makeAny( nPos ), + com::sun::star::uno::makeAny( getItem( nPos ) ), + com::sun::star::uno::Any() ); + for( Listeners_t::iterator aIter = maListeners.begin(); + aIter != maListeners.end(); + aIter++ ) + { + (*aIter)->elementInserted( aEvent ); + } + } + + void _elementRemoved( const T& aOld ) + { + com::sun::star::container::ContainerEvent aEvent( + static_cast<com::sun::star::container::XIndexReplace*>( this ), + com::sun::star::uno::Any(), + com::sun::star::uno::makeAny( aOld ), + com::sun::star::uno::Any() ); + for( Listeners_t::iterator aIter = maListeners.begin(); + aIter != maListeners.end(); + aIter++ ) + { + (*aIter)->elementRemoved( aEvent ); + } + } + + void _elementReplaced( const sal_Int32 nPos, const T& aNew ) + { + OSL_ENSURE( isValidIndex(nPos), "invalid index" ); + com::sun::star::container::ContainerEvent aEvent( + static_cast<com::sun::star::container::XIndexReplace*>( this ), + com::sun::star::uno::makeAny( nPos ), + com::sun::star::uno::makeAny( getItem( nPos ) ), + com::sun::star::uno::makeAny( aNew ) ); + for( Listeners_t::iterator aIter = maListeners.begin(); + aIter != maListeners.end(); + aIter++ ) + { + (*aIter)->elementReplaced( aEvent ); + } + } + +}; + +#endif diff --git a/forms/source/xforms/computedexpression.cxx b/forms/source/xforms/computedexpression.cxx new file mode 100644 index 000000000000..540cfd2f6d5b --- /dev/null +++ b/forms/source/xforms/computedexpression.cxx @@ -0,0 +1,246 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "computedexpression.hxx" +#include "unohelper.hxx" +#include "evaluationcontext.hxx" +#include "NameContainer.hxx" + +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/xpath/XXPathAPI.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xml/xpath/XXPathExtension.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/SearchAlgorithms.hpp> + +#include <unotools/textsearch.hxx> +#include <comphelper/processfactory.hxx> + +using rtl::OUString; +using com::sun::star::beans::NamedValue; +using com::sun::star::uno::Any; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Sequence; +using com::sun::star::lang::XInitialization; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::xml::dom::XNode; +using com::sun::star::container::XNameContainer; +using com::sun::star::xml::xpath::XXPathAPI; +using com::sun::star::xml::xpath::XXPathExtension; +using com::sun::star::xml::xpath::XXPathObject; +using com::sun::star::uno::RuntimeException; +using com::sun::star::uno::Exception; +using com::sun::star::uno::UNO_QUERY_THROW; +using com::sun::star::xml::xpath::XPathObjectType_XPATH_UNDEFINED; +using com::sun::star::util::SearchOptions; +using com::sun::star::util::SearchAlgorithms_REGEXP; + + +namespace xforms +{ + +ComputedExpression::ComputedExpression() + : msExpression(), + mbIsEmpty( true ), + mbIsSimple( true ), + mxResult() +{ +} + +ComputedExpression::~ComputedExpression() +{ +} + + +OUString ComputedExpression::getExpression() const +{ + return msExpression; +} + +void ComputedExpression::setExpression( const OUString& rExpression ) +{ + // set new expression, and clear pre-computed results + msExpression = rExpression; + mbIsEmpty = _checkExpression( " *" ); + mbIsSimple = false; + mxResult.clear(); +} + + +bool ComputedExpression::_checkExpression( const sal_Char* pExpression ) const +{ + OSL_ENSURE( pExpression != NULL, "no expression?" ); + + // call RegExp engine + SearchOptions aSearchOptions; + aSearchOptions.algorithmType = SearchAlgorithms_REGEXP; + aSearchOptions.searchString = String( pExpression, RTL_TEXTENCODING_ASCII_US ); + utl::TextSearch aTextSearch( aSearchOptions ); + + xub_StrLen nLength = + static_cast<xub_StrLen>( msExpression.getLength() ); + xub_StrLen nStart = 0; + xub_StrLen nEnd = nLength; + int nSearch = aTextSearch.SearchFrwrd( msExpression, &nStart, &nEnd ); + + // our expression is static only if 1) we found our regexp, and 2) + // the regexp goes from beginning to end. + return ( nLength == 0 || nSearch != 0 ) + && ( nStart == 0 && nEnd == nLength ); +} + +/// do we have an actual expression? +bool ComputedExpression::isEmptyExpression() const +{ + return mbIsEmpty; +} + +bool ComputedExpression::isSimpleExpression() const +{ + // actual work is done by setExpression + return mbIsEmpty || mbIsSimple; +} + + +const OUString ComputedExpression::_getExpressionForEvaluation() const +{ + // the default implementation is to do nothing... + return msExpression; +} + +bool ComputedExpression::_evaluate( + const xforms::EvaluationContext& rContext, + const OUString& sExpression ) +{ + OSL_ENSURE( rContext.mxContextNode.is(), "no context node in context" ); + + // obtain value by evaluating XPath expression + mxResult.clear(); + try + { + mxResult = _getXPathAPI(rContext)->eval( rContext.mxContextNode, + sExpression ); + } + catch( const Exception& ) + { + ; // ignore exception -> mxResult will be empty + } + + return hasValue(); +} + +bool ComputedExpression::evaluate( const EvaluationContext& rContext ) +{ + // for simple expression we don't need to re-evaluate (if we have + // an older result); neither for empty expressions + if( mbIsEmpty || (mxResult.is() && mbIsSimple) ) + return true; + + return _evaluate( rContext, _getExpressionForEvaluation() ); +} + + +bool ComputedExpression::hasValue() const +{ + return mxResult.is() && + mxResult->getObjectType() != XPathObjectType_XPATH_UNDEFINED; +} + +void ComputedExpression::clear() +{ + mxResult.clear(); +} + +Reference<XXPathObject> ComputedExpression::getXPath() +{ + return mxResult; +} + +OUString ComputedExpression::getString( const rtl::OUString& rDefault ) const +{ + return mxResult.is() ? mxResult->getString() : rDefault; +} + +bool ComputedExpression::getBool( bool bDefault ) const +{ + return mxResult.is() ? mxResult->getBoolean() : bDefault; +} + + + + +Reference<XXPathAPI> ComputedExpression::_getXPathAPI(const xforms::EvaluationContext& aContext) +{ + // create XPath API, then register namespaces + Reference<XXPathAPI> xXPath( createInstance( + OUSTRING( "com.sun.star.xml.xpath.XPathAPI" ) ), + UNO_QUERY_THROW ); + OSL_ENSURE( xXPath.is(), "cannot get XPath API" ); + + // register xforms extension# + Sequence< Any > aSequence(2); + NamedValue aValue; + aValue.Name = OUSTRING("Model"); + aValue.Value <<= aContext.mxModel; + aSequence[0] <<= aValue; + aValue.Name = OUSTRING("ContextNode"); + aValue.Value <<= aContext.mxContextNode; + aSequence[1] <<= aValue; + Reference<XMultiServiceFactory> aFactory = comphelper::getProcessServiceFactory(); + Reference< XXPathExtension > aExtension( aFactory->createInstanceWithArguments( + OUSTRING( "com.sun.star.comp.xml.xpath.XFormsExtension"), aSequence), UNO_QUERY_THROW); + xXPath->registerExtensionInstance(aExtension); + + // register namespaces + if( aContext.mxNamespaces.is() ) + { + Sequence<OUString> aPrefixes =aContext.mxNamespaces->getElementNames(); + sal_Int32 nCount = aPrefixes.getLength(); + const OUString* pPrefixes = aPrefixes.getConstArray(); + for( sal_Int32 i = 0; i < nCount; i++ ) + { + const OUString* pNamePrefix = &pPrefixes[i]; + OUString sNameURL; + aContext.mxNamespaces->getByName( *pNamePrefix ) >>= sNameURL; + xXPath->registerNS( *pNamePrefix, sNameURL ); + } + } + + // done, so return xXPath-object + return xXPath; +} + + +} // namespace xforms diff --git a/forms/source/xforms/computedexpression.hxx b/forms/source/xforms/computedexpression.hxx new file mode 100644 index 000000000000..6a1581cc8d0b --- /dev/null +++ b/forms/source/xforms/computedexpression.hxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _COMPUTEDEXPRESSION_HXX +#define _COMPUTEDEXPRESSION_HXX + + +// includes for member variables +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Reference.hxx> + +// forward declaractions +namespace com { namespace sun { namespace star +{ + namespace xml + { + namespace dom { class XNode; } + namespace dom { class XNodeset; } + namespace xpath { class XXPathAPI; } + namespace xpath { class XXPathObject; } + } + namespace container { class XNameContainer; } +} } } +namespace xforms { class EvaluationContext; } + + + +namespace xforms +{ + +/** ComputedExpression represents an XPath Expression and caches results. + * + * As this class has no virtual methods, it should never be used + * polymorphically. */ +class ComputedExpression +{ + /// the expression string + rtl::OUString msExpression; + + /// is msExpression empty? + bool mbIsEmpty; + +protected: + /// is msExpression a simple expression? + bool mbIsSimple; + + /// the result from the last bind + com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathObject> mxResult; + + + /// implementation of isSimpleExpression + bool _checkExpression( const sal_Char* pExpression ) const; + + /// allow manipulation of the expression before it is evaluated + const rtl::OUString _getExpressionForEvaluation() const; + + /// obtain a (suitable) XPathAPI implementation + com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathAPI> _getXPathAPI(const xforms::EvaluationContext& aContext); + + /// evaluate the expression relative to the content node. + bool _evaluate( const xforms::EvaluationContext& rContext, + const rtl::OUString& sExpression ); + + +public: + ComputedExpression(); + ~ComputedExpression(); + + + /// get the expression string + rtl::OUString getExpression() const; + + /// set a new expression string + void setExpression( const rtl::OUString& rExpression ); + + /// get the namespaces that are used to interpret the expression string + com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> getNamespaces() const; + + /// set the namespaces that are used to interpret the expression string + void setNamespaces( const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& ); + + /// do we have an actual expression? + bool isEmptyExpression() const; + + /// heuristically determine whether this expression is 'simple', + /// i.e. whether its value will change depending on the values + /// of other nodes + bool isSimpleExpression() const; + + + /// evaluate the expression relative to the content node. + bool evaluate( const xforms::EvaluationContext& rContext ); + + + /// does this expression have a value? + bool hasValue() const; + + + /// remove value/evaluate results + void clear(); + + + // get the result of this expression as string/bool/... + // (Results will be based on the last call of evaluate(..). The caller + // must call evaluate to ensure current results.) + com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathObject> getXPath(); + bool getBool( bool bDefault = false ) const; + rtl::OUString getString( const rtl::OUString& rDefault = rtl::OUString() ) const; + +}; + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/convert.cxx b/forms/source/xforms/convert.cxx new file mode 100644 index 000000000000..7ea6e35a5284 --- /dev/null +++ b/forms/source/xforms/convert.cxx @@ -0,0 +1,627 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "convert.hxx" + +#include "unohelper.hxx" +#include <memory> +#include <algorithm> +#include <functional> +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/date.hxx> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/util/Time.hpp> + +using xforms::Convert; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using com::sun::star::uno::Any; +using com::sun::star::uno::makeAny; +using com::sun::star::util::Time; +using namespace std; + +typedef com::sun::star::util::Date UNODate; +typedef com::sun::star::util::Time UNOTime; +typedef com::sun::star::util::DateTime UNODateTime; + +Convert::Convert() + : maMap() +{ + init(); +} + +#define ADD_ENTRY(XCONVERT,TYPE) XCONVERT->maMap[ getCppuType( static_cast<TYPE*>( NULL ) ) ] = Convert_t( &lcl_toXSD_##TYPE, &lcl_toAny_##TYPE ) + +namespace +{ + // ======================================================================== + struct StringToken + { + private: + ::rtl::OUString m_sString; + sal_Int32 m_nTokenStart; + sal_Int32 m_nTokenEnd; + + public: + StringToken() : m_sString(), m_nTokenStart( 0 ), m_nTokenEnd( 0 ) { } + StringToken( const ::rtl::OUString& _rString, sal_Int32 _nTokenStart, sal_Int32 _nTokenEnd ); + StringToken( const StringToken& ); + StringToken& operator=( const StringToken& ); + + inline bool isEmpty() const { return m_nTokenEnd <= m_nTokenStart; } + inline sal_Int32 getLength() const { return isEmpty() ? 0 : m_nTokenEnd - m_nTokenStart - 1; } + inline const sal_Unicode* begin() const { return m_sString.getStr() + m_nTokenStart; } + inline const sal_Unicode* end() const { return m_sString.getStr() + m_nTokenEnd; } + + bool toInt32( sal_Int32& _rValue ) const; + }; + + // ------------------------------------------------------------------------ + StringToken::StringToken( const ::rtl::OUString& _rString, sal_Int32 _nTokenStart, sal_Int32 _nTokenEnd ) + :m_sString( _rString ) + ,m_nTokenStart( _nTokenStart ) + ,m_nTokenEnd( _nTokenEnd ) + { + OSL_ENSURE( ( m_nTokenStart >= 0 ) && ( m_nTokenStart <= m_sString.getLength() ), "StringToken::StringToken: invalid token start!" ); + OSL_ENSURE( ( m_nTokenEnd >= 0 ) && ( m_nTokenEnd <= m_sString.getLength() ), "StringToken::StringToken: invalid token end!" ); + } + + // ------------------------------------------------------------------------ + StringToken::StringToken( const StringToken& _rRHS ) + { + *this = _rRHS; + } + + // ------------------------------------------------------------------------ + StringToken& StringToken::operator=( const StringToken& _rRHS ) + { + if ( this == &_rRHS ) + return *this; + + m_sString = _rRHS.m_sString; + m_nTokenStart = _rRHS.m_nTokenStart; + m_nTokenEnd = _rRHS.m_nTokenEnd; + + return *this; + } + + // ------------------------------------------------------------------------ + bool StringToken::toInt32( sal_Int32& _rValue ) const + { + if ( isEmpty() ) + return false; + + _rValue = 0; + const sal_Unicode* pStr = begin(); + while ( pStr < end() ) + { + if ( ( *pStr < '0' ) || ( *pStr > '9' ) ) + return false; + + _rValue *= 10; + _rValue += ( *pStr - '0' ); + + ++pStr; + } + + return true; + } + + // ======================================================================== + class StringTokenizer + { + private: + ::rtl::OUString m_sString; + const sal_Unicode m_nTokenSeparator; + sal_Int32 m_nTokenStart; + + public: + /** constructs a tokenizer + @param _rString the string to tokenize + @param _nTokenSeparator the token value. May be 0, in this case the tokenizer + will recognize exactly one token, being the whole string. + This may make sense if you want to apply <type>StringToken</type> + methods to a whole string. + */ + StringTokenizer( const ::rtl::OUString& _rString, sal_Unicode _nTokenSeparator = ';' ); + + /// resets the tokenizer to the beginning of the string + void reset(); + + /// determines whether there is a next token + bool hasNextToken() const; + + /// retrieves the next token + StringToken + getNextToken(); + }; + + // ------------------------------------------------------------------------ + StringTokenizer::StringTokenizer( const ::rtl::OUString& _rString, sal_Unicode _nTokenSeparator ) + :m_sString( _rString ) + ,m_nTokenSeparator( _nTokenSeparator ) + { + reset(); + } + + // ------------------------------------------------------------------------ + void StringTokenizer::reset() + { + m_nTokenStart = 0; + } + + // ------------------------------------------------------------------------ + bool StringTokenizer::hasNextToken() const + { + return ( m_nTokenStart < m_sString.getLength() ); + } + + // ------------------------------------------------------------------------ + StringToken StringTokenizer::getNextToken() + { + OSL_PRECOND( hasNextToken(), "StringTokenizer::getNextToken: there is no next token!" ); + if ( !hasNextToken() ) + return StringToken(); + + // determine the end of the current token + sal_Int32 nTokenEnd = m_nTokenSeparator ? m_sString.indexOf( m_nTokenSeparator, m_nTokenStart ) : m_sString.getLength(); + bool bLastToken = !m_nTokenSeparator || ( nTokenEnd == -1 ); + + // construct a new token + StringToken aToken( m_sString, m_nTokenStart, bLastToken ? m_sString.getLength() : nTokenEnd ); + // advance + m_nTokenStart = bLastToken ? m_sString.getLength() : nTokenEnd + 1; + // outta here + return aToken; + } + + // ======================================================================== + // ------------------------------------------------------------------------ + OUString lcl_toXSD_OUString( const Any& rAny ) + { OUString sStr; rAny >>= sStr; return sStr; } + + // ------------------------------------------------------------------------ + Any lcl_toAny_OUString( const OUString& rStr ) + { Any aAny; aAny <<= rStr; return aAny; } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_bool( const Any& rAny ) + { bool b = false; rAny >>= b; return b ? OUSTRING("true") : OUSTRING("false"); } + + // ------------------------------------------------------------------------ + Any lcl_toAny_bool( const OUString& rStr ) + { + bool b = ( rStr == OUSTRING("true") || rStr == OUSTRING("1") ); + return makeAny( b ); + } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_double( const Any& rAny ) + { + double f = 0.0; + rAny >>= f; + + return rtl::math::isFinite( f ) + ? rtl::math::doubleToUString( f, rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', + sal_True ) + : OUString(); + } + + // ------------------------------------------------------------------------ + Any lcl_toAny_double( const OUString& rString ) + { + rtl_math_ConversionStatus eStatus; + double f = rtl::math::stringToDouble( + rString, sal_Unicode('.'), sal_Unicode(','), &eStatus, NULL ); + return ( eStatus == rtl_math_ConversionStatus_Ok ) ? makeAny( f ) : Any(); + } + + // ------------------------------------------------------------------------ + void lcl_appendInt32ToBuffer( const sal_Int32 _nValue, ::rtl::OUStringBuffer& _rBuffer, sal_Int16 _nMinDigits ) + { + if ( ( _nMinDigits >= 4 ) && ( _nValue < 1000 ) ) + _rBuffer.append( (sal_Unicode)'0' ); + if ( ( _nMinDigits >= 3 ) && ( _nValue < 100 ) ) + _rBuffer.append( (sal_Unicode)'0' ); + if ( ( _nMinDigits >= 2 ) && ( _nValue < 10 ) ) + _rBuffer.append( (sal_Unicode)'0' ); + _rBuffer.append( _nValue ); + } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_UNODate_typed( const UNODate& rDate ) + { + + ::rtl::OUStringBuffer sInfo; + lcl_appendInt32ToBuffer( rDate.Year, sInfo, 4 ); + sInfo.appendAscii( "-" ); + lcl_appendInt32ToBuffer( rDate.Month, sInfo, 2 ); + sInfo.appendAscii( "-" ); + lcl_appendInt32ToBuffer( rDate.Day, sInfo, 2 ); + + return sInfo.makeStringAndClear(); + } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_UNODate( const Any& rAny ) + { + UNODate aDate; + OSL_VERIFY( rAny >>= aDate ); + return lcl_toXSD_UNODate_typed( aDate ); + } + + // ------------------------------------------------------------------------ + UNODate lcl_toUNODate( const OUString& rString ) + { + bool bWellformed = true; + + UNODate aDate( 1, 1, 1900 ); + + sal_Int32 nToken = 0; + StringTokenizer aTokenizer( rString, '-' ); + while ( aTokenizer.hasNextToken() ) + { + sal_Int32 nTokenValue = 0; + if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) ) + { + bWellformed = false; + break; + } + + if ( nToken == 0 ) + aDate.Year = (sal_uInt16)nTokenValue; + else if ( nToken == 1 ) + aDate.Month = (sal_uInt16)nTokenValue; + else if ( nToken == 2 ) + aDate.Day = (sal_uInt16)nTokenValue; + else + { + bWellformed = false; + break; + } + ++nToken; + } + + // sanity checks + if ( ( aDate.Year > 9999 ) || ( aDate.Month < 1 ) || ( aDate.Month > 12 ) || ( aDate.Day < 1 ) || ( aDate.Day > 31 ) ) + bWellformed = false; + else + { + ::Date aDateCheck( 1, aDate.Month, aDate.Year ); + if ( aDate.Day > aDateCheck.GetDaysInMonth() ) + bWellformed = false; + } + + // all okay? + if ( !bWellformed ) + return UNODate( 1, 1, 1900 ); + + return aDate; + } + + // ------------------------------------------------------------------------ + Any lcl_toAny_UNODate( const OUString& rString ) + { + return makeAny( lcl_toUNODate( rString ) ); + } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_UNOTime_typed( const UNOTime& rTime ) + { + + ::rtl::OUStringBuffer sInfo; + lcl_appendInt32ToBuffer( rTime.Hours, sInfo, 2 ); + sInfo.appendAscii( ":" ); + lcl_appendInt32ToBuffer( rTime.Minutes, sInfo, 2 ); + sInfo.appendAscii( ":" ); + lcl_appendInt32ToBuffer( rTime.Seconds, sInfo, 2 ); + if ( rTime.HundredthSeconds ) + { + sInfo.appendAscii( "." ); + lcl_appendInt32ToBuffer( rTime.HundredthSeconds, sInfo, 2 ); + } + + return sInfo.makeStringAndClear(); + } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_UNOTime( const Any& rAny ) + { + UNOTime aTime; + OSL_VERIFY( rAny >>= aTime ); + return lcl_toXSD_UNOTime_typed( aTime ); + } + + // ------------------------------------------------------------------------ + UNOTime lcl_toUNOTime( const OUString& rString ) + { + bool bWellformed = true; + + UNOTime aTime( 0, 0, 0, 0 ); + + ::rtl::OUString sString( rString ); + // see if there's a decimal separator for the seconds, + // and if so, handle it separately + sal_Int32 nDecimalSepPos = rString.indexOf( '.' ); + if ( nDecimalSepPos == -1 ) + // ISO 8601 allows for both a comma and a dot + nDecimalSepPos = rString.indexOf( ',' ); + if ( nDecimalSepPos != -1 ) + { + // handle fractional seconds + ::rtl::OUString sFractional = sString.copy( nDecimalSepPos + 1 ); + if ( sFractional.getLength() > 2 ) + // our precision is HundrethSeconds - it's all a css.util.Time can hold + sFractional = sFractional.copy( 0, 2 ); + sal_Int32 nFractional = 0; + if ( sFractional.getLength() ) + { + if ( StringTokenizer( sFractional, 0 ).getNextToken().toInt32( nFractional ) ) + { + aTime.HundredthSeconds = (sal_uInt16)nFractional; + if ( nFractional < 10 ) + aTime.HundredthSeconds *= 10; + } + else + bWellformed = false; + } + + // strip the fraction before further processing + sString = sString.copy( 0, nDecimalSepPos ); + } + + // split into the tokens which are separated by colon + sal_Int32 nToken = 0; + StringTokenizer aTokenizer( sString, ':' ); + while ( aTokenizer.hasNextToken() ) + { + sal_Int32 nTokenValue = 0; + if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) ) + { + bWellformed = false; + break; + } + + if ( nToken == 0 ) + aTime.Hours = (sal_uInt16)nTokenValue; + else if ( nToken == 1 ) + aTime.Minutes = (sal_uInt16)nTokenValue; + else if ( nToken == 2 ) + aTime.Seconds = (sal_uInt16)nTokenValue; + else + { + bWellformed = false; + break; + } + ++nToken; + } + + // sanity checks + // note that Seconds == 60 denotes leap seconds. Normally, they're not allowed everywhere, + // but we accept them all the time for simplicity reasons + if ( ( aTime.Hours > 24 ) + || ( aTime.Minutes > 59 ) + || ( aTime.Seconds > 60 ) + ) + bWellformed = false; + + if ( bWellformed + && ( aTime.Hours == 24 ) + && ( ( aTime.Minutes != 0 ) + || ( aTime.Seconds != 0 ) + || ( aTime.HundredthSeconds != 0 ) + ) + ) + bWellformed = false; + + // all okay? + if ( !bWellformed ) + return UNOTime( 0, 0, 0, 0 ); + + return aTime; + } + + // ------------------------------------------------------------------------ + Any lcl_toAny_UNOTime( const OUString& rString ) + { + return makeAny( lcl_toUNOTime( rString ) ); + } + + // ------------------------------------------------------------------------ + OUString lcl_toXSD_UNODateTime( const Any& rAny ) + { + UNODateTime aDateTime; + OSL_VERIFY( rAny >>= aDateTime ); + + UNODate aDate( aDateTime.Day, aDateTime.Month, aDateTime.Year ); + ::rtl::OUString sDate = lcl_toXSD_UNODate_typed( aDate ); + + UNOTime aTime( aDateTime.HundredthSeconds, aDateTime.Seconds, aDateTime.Minutes, aDateTime.Hours ); + ::rtl::OUString sTime = lcl_toXSD_UNOTime_typed( aTime ); + + ::rtl::OUStringBuffer sInfo; + sInfo.append( sDate ); + sInfo.append( (sal_Unicode) 'T' ); + sInfo.append( sTime ); + return sInfo.makeStringAndClear(); + } + + // ------------------------------------------------------------------------ + Any lcl_toAny_UNODateTime( const OUString& rString ) + { + // separate the date from the time part + sal_Int32 nDateTimeSep = rString.indexOf( 'T' ); + if ( nDateTimeSep == -1 ) + nDateTimeSep = rString.indexOf( 't' ); + + UNODate aDate; + UNOTime aTime; + if ( nDateTimeSep == -1 ) + { // no time part + aDate = lcl_toUNODate( rString ); + aTime = UNOTime( 0, 0, 0, 0 ); + } + else + { + aDate = lcl_toUNODate( rString.copy( 0, nDateTimeSep ) ); + aTime = lcl_toUNOTime( rString.copy( nDateTimeSep + 1 ) ); + } + UNODateTime aDateTime( + aTime.HundredthSeconds, aTime.Seconds, aTime.Minutes, aTime.Hours, + aDate.Day, aDate.Month, aDate.Year + ); + return makeAny( aDateTime ); + } +} + +// ============================================================================ +void Convert::init() +{ + ADD_ENTRY( this, OUString ); + ADD_ENTRY( this, bool ); + ADD_ENTRY( this, double ); + ADD_ENTRY( this, UNODate ); + ADD_ENTRY( this, UNOTime ); + ADD_ENTRY( this, UNODateTime ); +} + + +Convert& Convert::get() +{ + // create our Singleton instance on demand + static Convert* pConvert = NULL; + if( pConvert == NULL ) + pConvert = new Convert(); + + OSL_ENSURE( pConvert != NULL, "no converter?" ); + return *pConvert; +} + +bool Convert::hasType( const Type_t& rType ) +{ + return maMap.find( rType ) != maMap.end(); +} + +Convert::Types_t Convert::getTypes() +{ + Types_t aTypes( maMap.size() ); + transform( maMap.begin(), maMap.end(), aTypes.getArray(), + select1st<Map_t::value_type>() ); + return aTypes; +} + +rtl::OUString Convert::toXSD( const Any_t& rAny ) +{ + Map_t::iterator aIter = maMap.find( rAny.getValueType() ); + return aIter != maMap.end() ? aIter->second.first( rAny ) : OUString(); +} + +Convert::Any_t Convert::toAny( const rtl::OUString& rValue, + const Type_t& rType ) +{ + Map_t::iterator aIter = maMap.find( rType ); + return aIter != maMap.end() ? aIter->second.second( rValue ) : Any_t(); +} + +//------------------------------------------------------------------------ +::rtl::OUString Convert::convertWhitespace( const ::rtl::OUString& _rString, sal_Int16 _nWhitespaceTreatment ) +{ + ::rtl::OUString sConverted; + switch( _nWhitespaceTreatment ) + { + default: + OSL_ENSURE( sal_False, "Convert::convertWhitespace: invalid whitespace treatment constant!" ); + // NO break + case com::sun::star::xsd::WhiteSpaceTreatment::Preserve: + sConverted = _rString; + break; + case com::sun::star::xsd::WhiteSpaceTreatment::Replace: + sConverted = replaceWhitespace( _rString ); + break; + case com::sun::star::xsd::WhiteSpaceTreatment::Collapse: + sConverted = collapseWhitespace( _rString ); + break; + } + return sConverted; +} + +//------------------------------------------------------------------------ +::rtl::OUString Convert::replaceWhitespace( const ::rtl::OUString& _rString ) +{ + OUStringBuffer aBuffer( _rString ); + sal_Int32 nLength = aBuffer.getLength(); + const sal_Unicode* pBuffer = aBuffer.getStr(); + for( sal_Int32 i = 0; i < nLength; i++ ) + { + sal_Unicode c = pBuffer[i]; + if( c == sal_Unicode(0x08) || + c == sal_Unicode(0x0A) || + c == sal_Unicode(0x0D) ) + aBuffer.setCharAt( i, sal_Unicode(0x20) ); + } + return aBuffer.makeStringAndClear(); +} + +//------------------------------------------------------------------------ +::rtl::OUString Convert::collapseWhitespace( const ::rtl::OUString& _rString ) +{ + sal_Int32 nLength = _rString.getLength(); + OUStringBuffer aBuffer( nLength ); + const sal_Unicode* pStr = _rString.getStr(); + bool bStrip = true; + for( sal_Int32 i = 0; i < nLength; i++ ) + { + sal_Unicode c = pStr[i]; + if( c == sal_Unicode(0x08) || + c == sal_Unicode(0x0A) || + c == sal_Unicode(0x0D) || + c == sal_Unicode(0x20) ) + { + if( ! bStrip ) + { + aBuffer.append( sal_Unicode(0x20) ); + bStrip = true; + } + } + else + { + bStrip = false; + aBuffer.append( c ); + } + } + if( aBuffer[ aBuffer.getLength() - 1 ] == sal_Unicode( 0x20 ) ) + aBuffer.setLength( aBuffer.getLength() - 1 ); + return aBuffer.makeStringAndClear(); +} diff --git a/forms/source/xforms/convert.hxx b/forms/source/xforms/convert.hxx new file mode 100644 index 000000000000..750399879ee0 --- /dev/null +++ b/forms/source/xforms/convert.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CONVERT_HXX +#define _CONVERT_HXX + +#include <com/sun/star/uno/Sequence.hxx> +#include <map> + +namespace com { namespace sun { namespace star { namespace uno +{ + class Any; + class Type; +} } } } +namespace rtl { class OUString; } +class ConvertImpl; + +namespace xforms +{ + +struct TypeLess +{ + bool operator()( const com::sun::star::uno::Type& rType1, + const com::sun::star::uno::Type& rType2 ) const + { return rType1.getTypeName() < rType2.getTypeName(); } +}; + +class Convert +{ + typedef com::sun::star::uno::Type Type_t; + typedef com::sun::star::uno::Sequence<com::sun::star::uno::Type> Types_t; + typedef com::sun::star::uno::Any Any_t; + + // hold conversion objects + typedef rtl::OUString (*fn_toXSD)( const Any_t& ); + typedef Any_t (*fn_toAny)( const rtl::OUString& ); + typedef std::pair<fn_toXSD,fn_toAny> Convert_t; + typedef std::map<Type_t,Convert_t,TypeLess> Map_t; + Map_t maMap; + + Convert(); + + void init(); + +public: + /** get/create Singleton class */ + static Convert& get(); + + /// can we convert this type? + bool hasType( const Type_t& ); + + /// get list of convertable types + Types_t getTypes(); + + /// convert any to XML representation + rtl::OUString toXSD( const Any_t& rAny ); + + /// convert XML representation to Any of given type + Any_t toAny( const rtl::OUString&, const Type_t& ); + + /** translates the whitespaces in a given string, according + to a given <type scope="com::sun::star::xsd">WhiteSpaceTreatment</type>. + + @param _rString + the string to convert + @param _nWhitespaceTreatment + a constant from the <type scope="com::sun::star::xsd">WhiteSpaceTreatment</type> group, specifying + how to handle whitespaces + @return + the converted string + */ + static ::rtl::OUString convertWhitespace( + const ::rtl::OUString& _rString, + sal_Int16 _nWhitespaceTreatment + ); + + /** replace all occurences 0x08, 0x0A, 0x0D with 0x20 + */ + static ::rtl::OUString replaceWhitespace( const ::rtl::OUString& _rString ); + + /** replace all sequences of 0x08, 0x0A, 0x0D, 0x20 with a single 0x20. + also strip leading/trailing whitespace. + */ + static ::rtl::OUString collapseWhitespace( const ::rtl::OUString& _rString ); +}; + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/datatyperepository.cxx b/forms/source/xforms/datatyperepository.cxx new file mode 100644 index 000000000000..8a9a4847af62 --- /dev/null +++ b/forms/source/xforms/datatyperepository.cxx @@ -0,0 +1,298 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#ifndef FORMS_SOURCE_XFORMS_DATATYPEREPOSITORY_HXX +#include "datatyperepository.hxx" +#endif +#include "datatypes.hxx" +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif +#include "frm_resource.hxx" +#include "frm_strings.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <tools/debug.hxx> +#include <comphelper/enumhelper.hxx> + +#include <functional> +#include <algorithm> + +//........................................................................ +namespace xforms +{ +//........................................................................ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::Type; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::util::VetoException; + using ::com::sun::star::container::NoSuchElementException; + using ::com::sun::star::container::ElementExistException; + using ::com::sun::star::container::XEnumeration; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::xsd::XDataType; + using namespace frm; + + //==================================================================== + //= ODataTypeRepository + //==================================================================== + DBG_NAME( ODataTypeRepository ) + //-------------------------------------------------------------------- + ODataTypeRepository::ODataTypeRepository( ) + { + DBG_CTOR( ODataTypeRepository, NULL ); + + // insert some basic types + ::rtl::OUString sName( FRM_RES_STRING( RID_STR_DATATYPE_STRING ) ); + m_aRepository[ sName ] = new OStringType( sName, ::com::sun::star::xsd::DataTypeClass::STRING ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_URL ); + m_aRepository[ sName ] = new OStringType( sName, ::com::sun::star::xsd::DataTypeClass::anyURI ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_BOOLEAN ); + m_aRepository[ sName ] = new OBooleanType( sName ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_DECIMAL ); + m_aRepository[ sName ] = new ODecimalType( sName, ::com::sun::star::xsd::DataTypeClass::DECIMAL ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_FLOAT ); + m_aRepository[ sName ] = new ODecimalType( sName, ::com::sun::star::xsd::DataTypeClass::FLOAT ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_DOUBLE ); + m_aRepository[ sName ] = new ODecimalType( sName, ::com::sun::star::xsd::DataTypeClass::DOUBLE ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_DATE ); + m_aRepository[ sName ] = new ODateType( sName ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_TIME ); + m_aRepository[ sName ] = new OTimeType( sName ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_DATETIME ); + m_aRepository[ sName ] = new ODateTimeType( sName ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_YEAR ); + m_aRepository[ sName ] = new OShortIntegerType( sName, ::com::sun::star::xsd::DataTypeClass::gYear ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_MONTH ); + m_aRepository[ sName ] = new OShortIntegerType( sName, ::com::sun::star::xsd::DataTypeClass::gMonth ); + + sName = FRM_RES_STRING( RID_STR_DATATYPE_DAY ); + m_aRepository[ sName ] = new OShortIntegerType( sName, ::com::sun::star::xsd::DataTypeClass::gDay ); + } + + //-------------------------------------------------------------------- + ODataTypeRepository::~ODataTypeRepository( ) + { + DBG_DTOR( ODataTypeRepository, NULL ); + } + + //-------------------------------------------------------------------- + ODataTypeRepository::Repository::iterator ODataTypeRepository::implLocate( const ::rtl::OUString& _rName, bool _bAllowMiss ) SAL_THROW( ( NoSuchElementException ) ) + { + Repository::iterator aTypePos = m_aRepository.find( _rName ); + if ( aTypePos == m_aRepository.end() && !_bAllowMiss ) + throw NoSuchElementException( ::rtl::OUString(), *this ); + + return aTypePos; + } + + //-------------------------------------------------------------------- + Reference< XDataType > SAL_CALL ODataTypeRepository::getBasicDataType( sal_Int16 dataTypeClass ) throw (NoSuchElementException, RuntimeException) + { + Reference< XDataType > xReturn; + + for ( Repository::const_iterator lookup = m_aRepository.begin(); + ( lookup != m_aRepository.end() ) && ! xReturn.is(); + ++lookup + ) + { + if ( lookup->second->getIsBasic() && ( lookup->second->getTypeClass() == dataTypeClass ) ) + xReturn = lookup->second.get(); + } + + if ( !xReturn.is() ) + throw NoSuchElementException( ::rtl::OUString(), *this ); + + return xReturn; + } + + //-------------------------------------------------------------------- + Reference< XDataType > SAL_CALL ODataTypeRepository::cloneDataType( const ::rtl::OUString& sourceName, const ::rtl::OUString& newName ) throw (NoSuchElementException, ElementExistException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Repository::iterator aTypePos = implLocate( newName, true ); + if ( aTypePos != m_aRepository.end() ) + throw ElementExistException( ::rtl::OUString(), *this ); + + aTypePos = implLocate( sourceName ); + OXSDDataType* pClone = aTypePos->second->clone( newName ); + m_aRepository[ newName ] = pClone; + + return pClone; + } + + //-------------------------------------------------------------------- + void SAL_CALL ODataTypeRepository::revokeDataType( const ::rtl::OUString& typeName ) throw (NoSuchElementException, VetoException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Repository::iterator aTypePos = implLocate( typeName ); + if ( aTypePos->second->getIsBasic() ) + throw VetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "This is a built-in type and cannot be removed." ) ), *this ); + // TODO: localize this error message + + m_aRepository.erase( aTypePos ); + } + + //-------------------------------------------------------------------- + Reference< XDataType > SAL_CALL ODataTypeRepository::getDataType( const ::rtl::OUString& typeName ) throw (NoSuchElementException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return implLocate( typeName, false )->second.get(); + } + + + //-------------------------------------------------------------------- + Reference< XEnumeration > SAL_CALL ODataTypeRepository::createEnumeration( ) throw (RuntimeException) + { + return new ::comphelper::OEnumerationByName( this ); + } + + //-------------------------------------------------------------------- + Any SAL_CALL ODataTypeRepository::getByName( const ::rtl::OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) + { + return makeAny( getDataType( aName ) ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL ODataTypeRepository::getElementNames( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Sequence< ::rtl::OUString > aNames( m_aRepository.size() ); + ::std::transform( + m_aRepository.begin(), + m_aRepository.end(), + aNames.getArray(), + ::std::select1st< Repository::value_type >() + ); + return aNames; + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL ODataTypeRepository::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_aRepository.find( aName ) != m_aRepository.end(); + } + + //-------------------------------------------------------------------- + Type SAL_CALL ODataTypeRepository::getElementType( ) throw (RuntimeException) + { + return ::getCppuType( static_cast< Reference< XDataType >* >( NULL ) ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL ODataTypeRepository::hasElements( ) throw (RuntimeException) + { + return !m_aRepository.empty(); + } + + //-------------------------------------------------------------------- + // type specific implementation of registerProperties, using explicit + // template instantiations + + template<> + void OValueLimitedType<com::sun::star::util::Date>::registerProperties() + { + OValueLimitedType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_DATE, m_aMaxInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_DATE, m_aMaxExclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_DATE, m_aMinInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_DATE, m_aMinExclusive, ValueType ); + } + + template<> + void OValueLimitedType<com::sun::star::util::Time>::registerProperties() + { + OValueLimitedType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_TIME, m_aMaxInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_TIME, m_aMaxExclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_TIME, m_aMinInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_TIME, m_aMinExclusive, ValueType ); + } + + template<> + void OValueLimitedType<com::sun::star::util::DateTime>::registerProperties() + { + OValueLimitedType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_DATE_TIME, m_aMaxInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_DATE_TIME, m_aMaxExclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_DATE_TIME, m_aMinInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_DATE_TIME, m_aMinExclusive, ValueType ); + } + + template<> + void OValueLimitedType<double>::registerProperties() + { + OValueLimitedType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_DOUBLE, m_aMaxInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_DOUBLE, m_aMaxExclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_DOUBLE, m_aMinInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_DOUBLE, m_aMinExclusive, ValueType ); + } + + template<> + void OValueLimitedType<sal_Int16>::registerProperties() + { + OValueLimitedType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_INT, m_aMaxInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_INT, m_aMaxExclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_INT, m_aMinInclusive, ValueType ); + REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_INT, m_aMinExclusive, ValueType ); + } +//........................................................................ +} // namespace xforms +//........................................................................ + diff --git a/forms/source/xforms/datatyperepository.hxx b/forms/source/xforms/datatyperepository.hxx new file mode 100644 index 000000000000..f680079ebf4b --- /dev/null +++ b/forms/source/xforms/datatyperepository.hxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef OFFAPI_COM_SUN_STAR_XFORMS_DATATYPEREPOSITORY_HXX +#define OFFAPI_COM_SUN_STAR_XFORMS_DATATYPEREPOSITORY_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/xforms/XDataTypeRepository.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + +#include <map> + +//........................................................................ +namespace xforms +{ +//........................................................................ + + class OXSDDataType; + //==================================================================== + //= ODataTypeRepository + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::xforms::XDataTypeRepository + > ODataTypeRepository_Base; + class ODataTypeRepository : public ODataTypeRepository_Base + { + private: + typedef ::rtl::Reference< OXSDDataType > DataType; + typedef ::std::map< ::rtl::OUString, DataType > Repository; + + ::osl::Mutex m_aMutex; + Repository m_aRepository; + + public: + ODataTypeRepository( ); + + protected: + ~ODataTypeRepository( ); + + // XDataTypeRepository + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xsd::XDataType > SAL_CALL getBasicDataType( sal_Int16 dataTypeClass ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xsd::XDataType > SAL_CALL cloneDataType( const ::rtl::OUString& sourceName, const ::rtl::OUString& newName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL revokeDataType( const ::rtl::OUString& typeName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::util::VetoException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xsd::XDataType > SAL_CALL getDataType( const ::rtl::OUString& typeName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + + // XEnumerationAccess (base of XDataTypeRepository) + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration( ) throw (::com::sun::star::uno::RuntimeException); + + // XNameAccess (base of XDataTypeRepository) + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException); + + // XElementAccess (base of XEnumerationAccess and XNameAccess) + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException); + + private: + ODataTypeRepository( const ODataTypeRepository& ); // never implemented + ODataTypeRepository& operator=( const ODataTypeRepository& ); // never implemented + + private: + /** locates the type with the given name in our repository, or throws an exception if there is no such type + */ + Repository::iterator implLocate( const ::rtl::OUString& _rName, bool _bAllowMiss = false ) SAL_THROW( ( ::com::sun::star::container::NoSuchElementException ) ); + }; + +//........................................................................ +} // namespace xforms +//........................................................................ + +#endif // OFFAPI_COM_SUN_STAR_XFORMS_DATATYPEREPOSITORY_HXX + diff --git a/forms/source/xforms/datatypes.cxx b/forms/source/xforms/datatypes.cxx new file mode 100644 index 000000000000..212b5f721e67 --- /dev/null +++ b/forms/source/xforms/datatypes.cxx @@ -0,0 +1,995 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "datatypes.hxx" +#include "resourcehelper.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "convert.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp> +/** === end UNO includes === **/ +#include <tools/debug.hxx> +#include <tools/datetime.hxx> +#include <rtl/math.hxx> + +//........................................................................ +namespace xforms +{ +//........................................................................ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Type; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::util::VetoException; + using ::com::sun::star::util::Date; + using ::com::sun::star::util::Time; + using ::com::sun::star::util::DateTime; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::beans::UnknownPropertyException; + using ::com::sun::star::beans::PropertyVetoException; + using ::com::sun::star::beans::XPropertyChangeListener; + using ::com::sun::star::beans::XVetoableChangeListener; + + using ::com::sun::star::beans::PropertyAttribute::BOUND; + using ::com::sun::star::beans::PropertyAttribute::READONLY; + + using namespace ::com::sun::star::xsd; + using namespace ::frm; + U_NAMESPACE_USE + + //==================================================================== + //= OXSDDataType + //==================================================================== + //-------------------------------------------------------------------- + OXSDDataType::OXSDDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :OXSDDataType_PBase( m_aBHelper ) + ,m_bIsBasic( sal_True ) + ,m_nTypeClass( _nTypeClass ) + ,m_sName( _rName ) + ,m_nWST( WhiteSpaceTreatment::Preserve ) + ,m_bPatternMatcherDirty( true ) + { + } + + //-------------------------------------------------------------------- + OXSDDataType::~OXSDDataType() + { + } + + //-------------------------------------------------------------------- + void OXSDDataType::registerProperties() + { + registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, BOUND, &m_sName, ::getCppuType( &m_sName ) ); + registerProperty( PROPERTY_XSD_WHITESPACE, PROPERTY_ID_XSD_WHITESPACE, BOUND, &m_nWST, ::getCppuType( &m_nWST ) ); + registerProperty( PROPERTY_XSD_PATTERN, PROPERTY_ID_XSD_PATTERN, BOUND, &m_sPattern, ::getCppuType( &m_sPattern ) ); + + registerProperty( PROPERTY_XSD_IS_BASIC, PROPERTY_ID_XSD_IS_BASIC, READONLY, &m_bIsBasic, ::getCppuType( &m_bIsBasic ) ); + registerProperty( PROPERTY_XSD_TYPE_CLASS, PROPERTY_ID_XSD_TYPE_CLASS, READONLY, &m_nTypeClass, ::getCppuType( &m_nTypeClass ) ); + } + + //-------------------------------------------------------------------- + void OXSDDataType::initializeClone( const OXSDDataType& _rCloneSource ) + { + m_bIsBasic = sal_False; + m_nTypeClass = _rCloneSource.m_nTypeClass; + m_sPattern = _rCloneSource.m_sPattern; + m_nWST = _rCloneSource.m_nWST; + } + + //-------------------------------------------------------------------- + OXSDDataType* OXSDDataType::clone( const ::rtl::OUString& _rNewName ) const + { + OXSDDataType* pClone = createClone( _rNewName ); + pClone->initializeClone( *this ); + return pClone; + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer ) + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer ) + +#define SET_PROPERTY( propertyid, value, member ) \ + setFastPropertyValue( PROPERTY_ID_##propertyid, makeAny( value ) ); \ + OSL_POSTCOND( member == value, "OXSDDataType::setFoo: inconsistency!" ); + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OXSDDataType::getName( ) throw (RuntimeException) + { + return m_sName; + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::setName( const ::rtl::OUString& aName ) throw (RuntimeException, VetoException) + { + // TODO: check the name for conflicts in the repository + SET_PROPERTY( NAME, aName, m_sName ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OXSDDataType::getPattern() throw (RuntimeException) + { + return m_sPattern; + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::setPattern( const ::rtl::OUString& _pattern ) throw (RuntimeException) + { + SET_PROPERTY( XSD_PATTERN, _pattern, m_sPattern ); + } + + //-------------------------------------------------------------------- + sal_Int16 SAL_CALL OXSDDataType::getWhiteSpaceTreatment() throw (RuntimeException) + { + return m_nWST; + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::setWhiteSpaceTreatment( sal_Int16 _whitespacetreatment ) throw (RuntimeException, IllegalArgumentException) + { + SET_PROPERTY( XSD_WHITESPACE, _whitespacetreatment, m_nWST ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OXSDDataType::getIsBasic() throw (RuntimeException) + { + return m_bIsBasic; + } + + + //-------------------------------------------------------------------- + sal_Int16 SAL_CALL OXSDDataType::getTypeClass() throw (RuntimeException) + { + return m_nTypeClass; + } + + //-------------------------------------------------------------------- + sal_Bool OXSDDataType::validate( const ::rtl::OUString& sValue ) throw( RuntimeException ) + { + return ( _validate( sValue ) == 0 ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString OXSDDataType::explainInvalid( const ::rtl::OUString& sValue ) throw( RuntimeException ) + { + // get reason + sal_uInt16 nReason = _validate( sValue ); + + // get resource and return localized string + return ( nReason == 0 ) + ? ::rtl::OUString() + : getResource( nReason, sValue, + _explainInvalid( nReason ) ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString OXSDDataType::_explainInvalid( sal_uInt16 nReason ) + { + if ( RID_STR_XFORMS_PATTERN_DOESNT_MATCH == nReason ) + { + OSL_ENSURE( m_sPattern.getLength(), "OXSDDataType::_explainInvalid: how can this error occur without a regular expression?" ); + return m_sPattern; + } + return ::rtl::OUString(); + } + + //-------------------------------------------------------------------- + namespace + { + static void lcl_initializePatternMatcher( ::std::auto_ptr< RegexMatcher >& _rpMatcher, const ::rtl::OUString& _rPattern ) + { + UErrorCode nMatchStatus = U_ZERO_ERROR; + UnicodeString aIcuPattern( reinterpret_cast<const UChar *>(_rPattern.getStr()), _rPattern.getLength() ); // UChar != sal_Unicode in MinGW + _rpMatcher.reset( new RegexMatcher( aIcuPattern, 0, nMatchStatus ) ); + OSL_ENSURE( U_SUCCESS( nMatchStatus ), "lcl_initializePatternMatcher: invalid pattern property!" ); + // if asserts, then something changed our pattern without going to convertFastPropertyValue/checkPropertySanity + } + + static bool lcl_matchString( RegexMatcher& _rMatcher, const ::rtl::OUString& _rText ) + { + UErrorCode nMatchStatus = U_ZERO_ERROR; + UnicodeString aInput( reinterpret_cast<const UChar *>(_rText.getStr()), _rText.getLength() ); // UChar != sal_Unicode in MinGW + _rMatcher.reset( aInput ); + if ( _rMatcher.matches( nMatchStatus ) ) + { + int32_t nStart = _rMatcher.start( nMatchStatus ); + int32_t nEnd = _rMatcher.end ( nMatchStatus ); + if ( ( nStart == 0 ) && ( nEnd == _rText.getLength() ) ) + return true; + } + + return false; + } + } + + //-------------------------------------------------------------------- + sal_uInt16 OXSDDataType::_validate( const ::rtl::OUString& _rValue ) + { + // care for the whitespaces + ::rtl::OUString sConverted = Convert::convertWhitespace( _rValue, m_nWST ); + + // care for the regular expression + if ( m_sPattern.getLength() ) + { + // ensure our pattern matcher is up to date + if ( m_bPatternMatcherDirty ) + { + lcl_initializePatternMatcher( m_pPatternMatcher, m_sPattern ); + m_bPatternMatcherDirty = false; + } + + // let it match the string + if ( !lcl_matchString( *m_pPatternMatcher.get(), _rValue ) ) + return RID_STR_XFORMS_PATTERN_DOESNT_MATCH; + } + + return 0; + } + + //-------------------------------------------------------------------- + sal_Bool OXSDDataType::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException) + { + // let the base class do the conversion + if ( !OXSDDataType_PBase::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ) ) + return sal_False; + + // sanity checks + ::rtl::OUString sErrorMessage; + if ( !checkPropertySanity( _nHandle, _rConvertedValue, sErrorMessage ) ) + { + IllegalArgumentException aException; + aException.Message = sErrorMessage; + aException.Context = *this; + throw IllegalArgumentException( aException ); + } + + return sal_True; + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) + { + OXSDDataType_PBase::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + if ( _nHandle == PROPERTY_ID_XSD_PATTERN ) + m_bPatternMatcherDirty = true; + } + + //-------------------------------------------------------------------- + bool OXSDDataType::checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::rtl::OUString& _rErrorMessage ) + { + if ( _nHandle == PROPERTY_ID_XSD_PATTERN ) + { + ::rtl::OUString sPattern; + OSL_VERIFY( _rNewValue >>= sPattern ); + + UnicodeString aIcuPattern( reinterpret_cast<const UChar *>(sPattern.getStr()), sPattern.getLength() ); // UChar != sal_Unicode in MinGW + UErrorCode nMatchStatus = U_ZERO_ERROR; + RegexMatcher aMatcher( aIcuPattern, 0, nMatchStatus ); + if ( U_FAILURE( nMatchStatus ) ) + { + _rErrorMessage = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "This is no valid pattern." ) ); + return false; + } + } + return true; + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::setPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) + { + OXSDDataType_PBase::setPropertyValue( aPropertyName, aValue ); + } + + //-------------------------------------------------------------------- + Any SAL_CALL OXSDDataType::getPropertyValue( const ::rtl::OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + return OXSDDataType_PBase::getPropertyValue( PropertyName ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OXSDDataType_PBase::addPropertyChangeListener( aPropertyName, xListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OXSDDataType_PBase::removePropertyChangeListener( aPropertyName, aListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::addVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OXSDDataType_PBase::addVetoableChangeListener( PropertyName, aListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OXSDDataType::removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OXSDDataType_PBase::removeVetoableChangeListener( PropertyName, aListener ); + } + + //==================================================================== + //= OValueLimitedType_Base + //==================================================================== + OValueLimitedType_Base::OValueLimitedType_Base( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :OXSDDataType( _rName, _nTypeClass ) + ,m_fCachedMaxInclusive( 0 ) + ,m_fCachedMaxExclusive( 0 ) + ,m_fCachedMinInclusive( 0 ) + ,m_fCachedMinExclusive( 0 ) + { + } + + //-------------------------------------------------------------------- + void OValueLimitedType_Base::initializeClone( const OXSDDataType& _rCloneSource ) + { + OXSDDataType::initializeClone( _rCloneSource ); + initializeTypedClone( static_cast< const OValueLimitedType_Base& >( _rCloneSource ) ); + } + + //-------------------------------------------------------------------- + void OValueLimitedType_Base::initializeTypedClone( const OValueLimitedType_Base& _rCloneSource ) + { + m_aMaxInclusive = _rCloneSource.m_aMaxInclusive; + m_aMaxExclusive = _rCloneSource.m_aMaxExclusive; + m_aMinInclusive = _rCloneSource.m_aMinInclusive; + m_aMinExclusive = _rCloneSource.m_aMinExclusive; + m_fCachedMaxInclusive = _rCloneSource.m_fCachedMaxInclusive; + m_fCachedMaxExclusive = _rCloneSource.m_fCachedMaxExclusive; + m_fCachedMinInclusive = _rCloneSource.m_fCachedMinInclusive; + m_fCachedMinExclusive = _rCloneSource.m_fCachedMinExclusive; + } + + //-------------------------------------------------------------------- + void SAL_CALL OValueLimitedType_Base::setFastPropertyValue_NoBroadcast( + sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::uno::Exception) + { + OXSDDataType::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + + // if one of our limit properties has been set, translate it into a double + // value, for later efficient validation + switch ( _nHandle ) + { + case PROPERTY_ID_XSD_MAX_INCLUSIVE_INT: + case PROPERTY_ID_XSD_MAX_INCLUSIVE_DOUBLE: + case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE: + case PROPERTY_ID_XSD_MAX_INCLUSIVE_TIME: + case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE_TIME: + if ( m_aMaxInclusive.hasValue() ) + normalizeValue( m_aMaxInclusive, m_fCachedMaxInclusive ); + else + m_fCachedMaxInclusive = 0; + break; + case PROPERTY_ID_XSD_MAX_EXCLUSIVE_INT: + case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DOUBLE: + case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE: + case PROPERTY_ID_XSD_MAX_EXCLUSIVE_TIME: + case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE_TIME: + if ( m_aMaxExclusive.hasValue() ) + normalizeValue( m_aMaxExclusive, m_fCachedMaxExclusive ); + else + m_fCachedMaxExclusive = 0; + break; + case PROPERTY_ID_XSD_MIN_INCLUSIVE_INT: + case PROPERTY_ID_XSD_MIN_INCLUSIVE_DOUBLE: + case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE: + case PROPERTY_ID_XSD_MIN_INCLUSIVE_TIME: + case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE_TIME: + if ( m_aMinInclusive.hasValue() ) + normalizeValue( m_aMinInclusive, m_fCachedMinInclusive ); + else + m_fCachedMinInclusive = 0; + break; + case PROPERTY_ID_XSD_MIN_EXCLUSIVE_INT: + case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DOUBLE: + case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE: + case PROPERTY_ID_XSD_MIN_EXCLUSIVE_TIME: + case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE_TIME: + if ( m_aMinExclusive.hasValue() ) + normalizeValue( m_aMinExclusive, m_fCachedMinExclusive ); + else + m_fCachedMinExclusive = 0; + break; + } + } + + //-------------------------------------------------------------------- + bool OValueLimitedType_Base::_getValue( const ::rtl::OUString& rValue, double& fValue ) + { + // convert to double + rtl_math_ConversionStatus eStatus; + sal_Int32 nEnd; + double f = ::rtl::math::stringToDouble( + rValue, sal_Unicode('.'), sal_Unicode(0), &eStatus, &nEnd ); + + // error checking... + bool bReturn = false; + if( eStatus == rtl_math_ConversionStatus_Ok + && nEnd == rValue.getLength() ) + { + bReturn = true; + fValue = f; + } + return bReturn; + } + + //-------------------------------------------------------------------- + sal_uInt16 OValueLimitedType_Base::_validate( const ::rtl::OUString& rValue ) + { + sal_uInt16 nReason = OXSDDataType::_validate( rValue ); + if( nReason == 0 ) + { + + // convert value and check format + double f; + if( ! _getValue( rValue, f ) ) + nReason = RID_STR_XFORMS_VALUE_IS_NOT_A; + + // check range + else if( ( m_aMaxInclusive.hasValue() ) && f > m_fCachedMaxInclusive ) + nReason = RID_STR_XFORMS_VALUE_MAX_INCL; + else if( ( m_aMaxExclusive.hasValue() ) && f >= m_fCachedMaxExclusive ) + nReason = RID_STR_XFORMS_VALUE_MAX_EXCL; + else if( ( m_aMinInclusive.hasValue() ) && f < m_fCachedMinInclusive ) + nReason = RID_STR_XFORMS_VALUE_MIN_INCL; + else if( ( m_aMinExclusive.hasValue() ) && f <= m_fCachedMinExclusive ) + nReason = RID_STR_XFORMS_VALUE_MIN_EXCL; + } + return nReason; + } + + //-------------------------------------------------------------------- + ::rtl::OUString OValueLimitedType_Base::_explainInvalid( sal_uInt16 nReason ) + { + ::rtl::OUStringBuffer sInfo; + switch( nReason ) + { + case 0: + // nothing to do! + break; + + case RID_STR_XFORMS_VALUE_IS_NOT_A: + sInfo.append( getName() ); + break; + + case RID_STR_XFORMS_VALUE_MAX_INCL: + sInfo.append( typedValueAsHumanReadableString( m_aMaxInclusive ) ); + break; + + case RID_STR_XFORMS_VALUE_MAX_EXCL: + sInfo.append( typedValueAsHumanReadableString( m_aMaxExclusive ) ); + break; + + case RID_STR_XFORMS_VALUE_MIN_INCL: + sInfo.append( typedValueAsHumanReadableString( m_aMinInclusive ) ); + break; + + case RID_STR_XFORMS_VALUE_MIN_EXCL: + sInfo.append( typedValueAsHumanReadableString( m_aMinExclusive ) ); + break; + + default: + OSL_ENSURE( false, "OValueLimitedType::_explainInvalid: unknown reason!" ); + break; + } + + return sInfo.makeStringAndClear(); + } + + //==================================================================== + //= OStringType + //==================================================================== + //-------------------------------------------------------------------- + OStringType::OStringType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :OStringType_Base( _rName, _nTypeClass ) + { + } + + //-------------------------------------------------------------------- + void OStringType::registerProperties() + { + OStringType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_LENGTH, m_aLength, sal_Int32 ); + REGISTER_VOID_PROP( XSD_MIN_LENGTH, m_aMinLength, sal_Int32 ); + REGISTER_VOID_PROP( XSD_MAX_LENGTH, m_aMaxLength, sal_Int32 ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_DEFAULT_TYPED_CLONING( OStringType, OStringType_Base ) + + //-------------------------------------------------------------------- + void OStringType::initializeTypedClone( const OStringType& _rCloneSource ) + { + m_aLength = _rCloneSource.m_aLength; + m_aMinLength = _rCloneSource.m_aMinLength; + m_aMaxLength = _rCloneSource.m_aMaxLength; + } + + //-------------------------------------------------------------------- + bool OStringType::checkPropertySanity( sal_Int32 _nHandle, const Any& _rNewValue, ::rtl::OUString& _rErrorMessage ) + { + // let the base class do the conversion + if ( !OStringType_Base::checkPropertySanity( _nHandle, _rNewValue, _rErrorMessage ) ) + return false; + + _rErrorMessage = ::rtl::OUString(); + switch ( _nHandle ) + { + case PROPERTY_ID_XSD_LENGTH: + case PROPERTY_ID_XSD_MIN_LENGTH: + case PROPERTY_ID_XSD_MAX_LENGTH: + { + sal_Int32 nValue( 0 ); + OSL_VERIFY( _rNewValue >>= nValue ); + if ( nValue <= 0 ) + _rErrorMessage = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Length limits must denote positive integer values." ) ); + // TODO/eforms: localize the error message + } + break; + } + + return _rErrorMessage.getLength() == 0; + } + + //-------------------------------------------------------------------- + sal_uInt16 OStringType::_validate( const ::rtl::OUString& rValue ) + { + // check regexp, whitespace etc. in parent class + sal_uInt16 nReason = OStringType_Base::_validate( rValue ); + + if( nReason == 0 ) + { + // check string constraints + sal_Int32 nLength = rValue.getLength(); + sal_Int32 nLimit = 0; + if ( m_aLength >>= nLimit ) + { + if ( nLimit != nLength ) + nReason = RID_STR_XFORMS_VALUE_LENGTH; + } + else + { + if ( ( m_aMaxLength >>= nLimit ) && ( nLength > nLimit ) ) + nReason = RID_STR_XFORMS_VALUE_MAX_LENGTH; + else if ( ( m_aMinLength >>= nLimit ) && ( nLength < nLimit ) ) + nReason = RID_STR_XFORMS_VALUE_MIN_LENGTH; + } + } + return nReason; + } + + //-------------------------------------------------------------------- + ::rtl::OUString OStringType::_explainInvalid( sal_uInt16 nReason ) + { + sal_Int32 nValue = 0; + ::rtl::OUStringBuffer sInfo; + switch( nReason ) + { + case 0: + // nothing to do! + break; + + case RID_STR_XFORMS_VALUE_LENGTH: + if( m_aLength >>= nValue ) + sInfo.append( nValue ); + break; + + case RID_STR_XFORMS_VALUE_MAX_LENGTH: + if( m_aMaxLength >>= nValue ) + sInfo.append( nValue ); + break; + + case RID_STR_XFORMS_VALUE_MIN_LENGTH: + if( m_aMinLength >>= nValue ) + sInfo.append( nValue ); + break; + + default: + sInfo.append( OStringType_Base::_explainInvalid( nReason ) ); + break; + } + return sInfo.makeStringAndClear(); + } + + //==================================================================== + //= OBooleanType + //==================================================================== + //-------------------------------------------------------------------- + OBooleanType::OBooleanType( const ::rtl::OUString& _rName ) + :OBooleanType_Base( _rName, DataTypeClass::BOOLEAN ) + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_DEFAULT_CLONING( OBooleanType, OBooleanType_Base ) + + //-------------------------------------------------------------------- + void OBooleanType::initializeTypedClone( const OBooleanType& /*_rCloneSource*/ ) + { + } + + //-------------------------------------------------------------------- + sal_uInt16 OBooleanType::_validate( const ::rtl::OUString& sValue ) + { + sal_uInt16 nInvalidityReason = OBooleanType_Base::_validate( sValue ); + if ( nInvalidityReason ) + return nInvalidityReason; + + bool bValid = + sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("0")) || + sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("1")) || + sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("true")) || + sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("false")); + return bValid ? 0 : RID_STR_XFORMS_INVALID_VALUE; + } + + //-------------------------------------------------------------------- + ::rtl::OUString OBooleanType::_explainInvalid( sal_uInt16 nReason ) + { + return ( nReason == 0 ) ? ::rtl::OUString() : getName(); + } + + //==================================================================== + //= ODecimalType + //==================================================================== + //-------------------------------------------------------------------- + ODecimalType::ODecimalType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :ODecimalType_Base( _rName, _nTypeClass ) + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_DEFAULT_TYPED_CLONING( ODecimalType, ODecimalType_Base ) + + //-------------------------------------------------------------------- + void ODecimalType::initializeTypedClone( const ODecimalType& _rCloneSource ) + { + m_aTotalDigits = _rCloneSource.m_aTotalDigits; + m_aFractionDigits = _rCloneSource.m_aFractionDigits; + } + + //-------------------------------------------------------------------- + void ODecimalType::registerProperties() + { + ODecimalType_Base::registerProperties(); + + REGISTER_VOID_PROP( XSD_TOTAL_DIGITS, m_aTotalDigits, sal_Int32 ); + REGISTER_VOID_PROP( XSD_FRACTION_DIGITS, m_aFractionDigits, sal_Int32 ); + } + + //-------------------------------------------------------------------- + + // validate decimals and return code for which facets failed + // to be used by: ODecimalType::validate and ODecimalType::explainInvalid + sal_uInt16 ODecimalType::_validate( const ::rtl::OUString& rValue ) + { + sal_Int16 nReason = ODecimalType_Base::_validate( rValue ); + + // check digits (if no other cause is available so far) + if( nReason == 0 ) + { + sal_Int32 nLength = rValue.getLength(); + sal_Int32 n = 0; + sal_Int32 nTotalDigits = 0; + sal_Int32 nFractionDigits = 0; + const sal_Unicode* pValue = rValue.getStr(); + for( ; pValue[n] != sal_Unicode('.') && n < nLength; n++ ) + if( pValue[n] >= sal_Unicode('0') + && pValue[n] <= sal_Unicode('9')) + nTotalDigits++; + for( ; n < nLength; n++ ) + if( pValue[n] >= sal_Unicode('0') + && pValue[n] <= sal_Unicode('9')) + nFractionDigits++; + nTotalDigits += nFractionDigits; + + sal_Int32 nValue = 0; + if( ( m_aTotalDigits >>= nValue ) && nTotalDigits > nValue ) + nReason = RID_STR_XFORMS_VALUE_TOTAL_DIGITS; + else if( ( m_aFractionDigits >>= nValue ) && + ( nFractionDigits > nValue ) ) + nReason = RID_STR_XFORMS_VALUE_FRACTION_DIGITS; + } + + return nReason; + } + + //-------------------------------------------------------------------- + ::rtl::OUString ODecimalType::_explainInvalid( sal_uInt16 nReason ) + { + sal_Int32 nValue = 0; + ::rtl::OUStringBuffer sInfo; + switch( nReason ) + { + case RID_STR_XFORMS_VALUE_TOTAL_DIGITS: + if( m_aTotalDigits >>= nValue ) + sInfo.append( nValue ); + break; + + case RID_STR_XFORMS_VALUE_FRACTION_DIGITS: + if( m_aFractionDigits >>= nValue ) + sInfo.append( nValue ); + break; + + default: + sInfo.append( ODecimalType_Base::_explainInvalid( nReason ) ); + break; + } + return sInfo.makeStringAndClear(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString ODecimalType::typedValueAsHumanReadableString( const Any& _rValue ) const + { + double fValue( 0 ); + normalizeValue( _rValue, fValue ); + return ::rtl::OUString::valueOf( fValue ); + } + + //-------------------------------------------------------------------- + void ODecimalType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const + { + OSL_VERIFY( _rValue >>= _rDoubleValue ); + } + + //==================================================================== + //= + //==================================================================== +#define DEFAULT_IMPLEMNENT_SUBTYPE( classname, typeclass ) \ + classname::classname( const ::rtl::OUString& _rName ) \ + :classname##_Base( _rName, DataTypeClass::typeclass ) \ + { \ + } \ + \ + IMPLEMENT_DEFAULT_CLONING( classname, classname##_Base ) \ + \ + void classname::initializeTypedClone( const classname& /*_rCloneSource*/ ) \ + { \ + } \ + + + //==================================================================== + //= ODateType + //==================================================================== + //-------------------------------------------------------------------- + DEFAULT_IMPLEMNENT_SUBTYPE( ODateType, DATE ) + + //-------------------------------------------------------------------- + sal_uInt16 ODateType::_validate( const ::rtl::OUString& _rValue ) + { + return ODateType_Base::_validate( _rValue ); + } + + //-------------------------------------------------------------------- + bool ODateType::_getValue( const ::rtl::OUString& value, double& fValue ) + { + Any aTypeValue = Convert::get().toAny( value, getCppuType() ); + + Date aValue; + if ( !( aTypeValue >>= aValue ) ) + return false; + + ::Date aToolsDate( aValue.Day, aValue.Month, aValue.Year ); + fValue = aToolsDate.GetDate(); + return true; + } + + //-------------------------------------------------------------------- + ::rtl::OUString ODateType::typedValueAsHumanReadableString( const Any& _rValue ) const + { + OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "ODateType::typedValueAsHumanReadableString: unexpected type" ); + return Convert::get().toXSD( _rValue ); + } + + //-------------------------------------------------------------------- + void ODateType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const + { + Date aValue; + OSL_VERIFY( _rValue >>= aValue ); + ::Date aToolsDate( aValue.Day, aValue.Month, aValue.Year ); + _rDoubleValue = aToolsDate.GetDate(); + } + + //==================================================================== + //= OTimeType + //==================================================================== + //-------------------------------------------------------------------- + DEFAULT_IMPLEMNENT_SUBTYPE( OTimeType, TIME ) + + //-------------------------------------------------------------------- + sal_uInt16 OTimeType::_validate( const ::rtl::OUString& _rValue ) + { + return OTimeType_Base::_validate( _rValue ); + } + + //-------------------------------------------------------------------- + bool OTimeType::_getValue( const ::rtl::OUString& value, double& fValue ) + { + Any aTypedValue = Convert::get().toAny( value, getCppuType() ); + + Time aValue; + if ( !( aTypedValue >>= aValue ) ) + return false; + + ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.HundredthSeconds ); + fValue = aToolsTime.GetTime(); + return true; + } + + //-------------------------------------------------------------------- + ::rtl::OUString OTimeType::typedValueAsHumanReadableString( const Any& _rValue ) const + { + OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "OTimeType::typedValueAsHumanReadableString: unexpected type" ); + return Convert::get().toXSD( _rValue ); + } + + //-------------------------------------------------------------------- + void OTimeType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const + { + Time aValue; + OSL_VERIFY( _rValue >>= aValue ); + ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.HundredthSeconds ); + _rDoubleValue = aToolsTime.GetTime(); + } + + //==================================================================== + //= ODateTimeType + //==================================================================== + //-------------------------------------------------------------------- + DEFAULT_IMPLEMNENT_SUBTYPE( ODateTimeType, DATETIME ) + + //-------------------------------------------------------------------- + sal_uInt16 ODateTimeType::_validate( const ::rtl::OUString& _rValue ) + { + return ODateTimeType_Base::_validate( _rValue ); + } + + //-------------------------------------------------------------------- + namespace + { + double lcl_normalizeDateTime( const DateTime& _rValue ) + { + ::DateTime aToolsValue( + ::Date( _rValue.Day, _rValue.Month, _rValue.Year ), + ::Time( _rValue.Hours, _rValue.Minutes, _rValue.Seconds, _rValue.HundredthSeconds ) + ); + + double fValue = 0; + // days since 1.1.1900 (which is relatively arbitrary but fixed date) + fValue += ::Date( aToolsValue ) - ::Date( 1, 1, 1900 ); + // time + fValue += aToolsValue.GetTimeInDays(); + return fValue; + } + } + + //-------------------------------------------------------------------- + bool ODateTimeType::_getValue( const ::rtl::OUString& value, double& fValue ) + { + Any aTypedValue = Convert::get().toAny( value, getCppuType() ); + + DateTime aValue; + if ( !( aTypedValue >>= aValue ) ) + return false; + + fValue = lcl_normalizeDateTime( aValue ); + return true; + } + + //-------------------------------------------------------------------- + ::rtl::OUString ODateTimeType::typedValueAsHumanReadableString( const Any& _rValue ) const + { + OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "OTimeType::typedValueAsHumanReadableString: unexpected type" ); + ::rtl::OUString sString = Convert::get().toXSD( _rValue ); + + // ISO 8601 notation has a "T" to separate between date and time. Our only concession + // to the "human readable" in the method name is to replace this T with a whitespace. + OSL_ENSURE( sString.indexOf( 'T' ) != -1, "ODateTimeType::typedValueAsHumanReadableString: hmm - no ISO notation?" ); + return sString.replace( 'T', ' ' ); + } + + //-------------------------------------------------------------------- + void ODateTimeType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const + { + DateTime aValue; + OSL_VERIFY( _rValue >>= aValue ); + _rDoubleValue = lcl_normalizeDateTime( aValue ); + } + + //==================================================================== + //= OShortIntegerType + //==================================================================== + //-------------------------------------------------------------------- + OShortIntegerType::OShortIntegerType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :OShortIntegerType_Base( _rName, _nTypeClass ) + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_DEFAULT_TYPED_CLONING( OShortIntegerType, OShortIntegerType_Base ) + + //-------------------------------------------------------------------- + void OShortIntegerType::initializeTypedClone( const OShortIntegerType& /*_rCloneSource*/ ) + { + } + + //-------------------------------------------------------------------- + bool OShortIntegerType::_getValue( const ::rtl::OUString& value, double& fValue ) + { + fValue = (double)(sal_Int16)value.toInt32(); + // TODO/eforms + // this does not care for values which do not fit into a sal_Int16, but simply + // cuts them down. A better implementation here should probably return <FALSE/> + // for those values. + // Else, we may have a situation where the UI claims an input to be valid + // (say "12345678"), while internally, and at submission time, this is cut to + // some smaller value. + // + // Additionally, this of course does not care for strings which are no numers ... + return true; + } + + //-------------------------------------------------------------------- + ::rtl::OUString OShortIntegerType::typedValueAsHumanReadableString( const Any& _rValue ) const + { + sal_Int16 nValue( 0 ); + OSL_VERIFY( _rValue >>= nValue ); + return ::rtl::OUString::valueOf( (sal_Int32)nValue ); + } + + //-------------------------------------------------------------------- + void OShortIntegerType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const + { + sal_Int16 nValue( 0 ); + OSL_VERIFY( _rValue >>= nValue ); + _rDoubleValue = nValue; + } + //==================================================================== + //==================================================================== + +#define DATATYPES_INCLUDED_BY_MASTER_HEADER +#include "datatypes_impl.hxx" +#undef DATATYPES_INCLUDED_BY_MASTER_HEADER + +//........................................................................ +} // namespace xforms +//........................................................................ + diff --git a/forms/source/xforms/datatypes.hxx b/forms/source/xforms/datatypes.hxx new file mode 100644 index 000000000000..50021f6db5b4 --- /dev/null +++ b/forms/source/xforms/datatypes.hxx @@ -0,0 +1,424 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FORMS_SOURCE_XFORMS_DATATYPES_HXX +#define FORMS_SOURCE_XFORMS_DATATYPES_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/xsd/XDataType.hpp> +#include <com/sun/star/xsd/DataTypeClass.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/implbase1.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/broadcasthelper.hxx> +#include "warnings_guard_unicode_regex.h" + +#include <memory> + +//........................................................................ +namespace xforms +{ +//........................................................................ + + //==================================================================== + //= OXSDDataType + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::xsd::XDataType + > OXSDDataType_Base; + typedef ::comphelper::OMutexAndBroadcastHelper OXSDDataType_BBase; + typedef ::comphelper::OPropertyContainer OXSDDataType_PBase; + + class OXSDDataType :public OXSDDataType_Base + ,public OXSDDataType_BBase // order matters: OMutexAndBroadcastHelper before + ,public OXSDDataType_PBase // OPropertyContainer + { + private: + // <properties> + sal_Bool m_bIsBasic; + sal_Int16 m_nTypeClass; + ::rtl::OUString m_sName; + ::rtl::OUString m_sPattern; + sal_uInt16 m_nWST; + // </properties> + + ::std::auto_ptr< U_NAMESPACE_QUALIFIER RegexMatcher > + m_pPatternMatcher; + bool m_bPatternMatcherDirty; + + protected: + + sal_Bool isBasic() const { return m_bIsBasic; } + sal_Int16 getTypeClass() const { return m_nTypeClass; } + const ::rtl::OUString& + getName() const { return m_sName; } + + private: + OXSDDataType( ); // never implemented + OXSDDataType( const OXSDDataType& ); // never implemented + OXSDDataType& operator=( const OXSDDataType& ); // never implemented + + protected: + // create basic data type + OXSDDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ); + ~OXSDDataType(); + + public: + DECLARE_XINTERFACE() + DECLARE_XTYPEPROVIDER() + + virtual ::rtl::OUString SAL_CALL getName( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::util::VetoException); + virtual ::rtl::OUString SAL_CALL getPattern() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPattern( const ::rtl::OUString& _pattern ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getWhiteSpaceTreatment() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setWhiteSpaceTreatment( sal_Int16 _whitespacetreatment ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException); + virtual sal_Bool SAL_CALL getIsBasic() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getTypeClass() throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL validate( const ::rtl::OUString& value ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL explainInvalid( const ::rtl::OUString& value ) throw (::com::sun::star::uno::RuntimeException); + + // XPropertySet - is a base of XDataType and needs to be disambiguated + virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + public: + OXSDDataType* clone( const ::rtl::OUString& _rNewName ) const; + + protected: + // XPropertySet and friends + virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw(::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + + // --- own overridables --- + // helper for implementing cloning of data types + virtual OXSDDataType* createClone( const ::rtl::OUString& _rName ) const = 0; + virtual void initializeClone( const OXSDDataType& _rCloneSource ); + + // helper method for validate and explainInvalid + virtual sal_uInt16 _validate( const ::rtl::OUString& value ); + virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason ); + + // helper method for checking properties values which are to be set + virtual bool checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::rtl::OUString& _rErrorMessage ); + + // register properties implemented by this instance - call the base class when overriding + virtual void registerProperties(); + }; + + //==================================================================== + //= helper for deriving from OXSDDataType + //==================================================================== +#define DECLARE_DEFAULT_CLONING( classname ) \ + virtual OXSDDataType* createClone( const ::rtl::OUString& _rName ) const; \ + virtual void initializeClone( const OXSDDataType& _rCloneSource ); \ + void initializeTypedClone( const classname& _rCloneSource ); + +#define IMPLEMENT_DEFAULT_CLONING( classname, baseclass ) \ + OXSDDataType* classname::createClone( const ::rtl::OUString& _rName ) const \ + { \ + return new classname( _rName ); \ + } \ + void classname::initializeClone( const OXSDDataType& _rCloneSource ) \ + { \ + baseclass::initializeClone( _rCloneSource ); \ + initializeTypedClone( static_cast< const classname& >( _rCloneSource ) ); \ + } \ + +#define IMPLEMENT_DEFAULT_TYPED_CLONING( classname, baseclass ) \ + OXSDDataType* classname::createClone( const ::rtl::OUString& _rName ) const \ + { \ + return new classname( _rName, getTypeClass() ); \ + } \ + void classname::initializeClone( const OXSDDataType& _rCloneSource ) \ + { \ + baseclass::initializeClone( _rCloneSource ); \ + initializeTypedClone( static_cast< const classname& >( _rCloneSource ) ); \ + } \ + +#define REGISTER_VOID_PROP( prop, memberAny, type ) \ + registerMayBeVoidProperty( PROPERTY_##prop, PROPERTY_ID_##prop, ::com::sun::star::beans::PropertyAttribute::BOUND | ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, \ + &memberAny, ::getCppuType( static_cast< type* >( NULL ) ) ); + + //==================================================================== + //= OValueLimitedType_Base + //==================================================================== + class OValueLimitedType_Base : public OXSDDataType + { + protected: + ::com::sun::star::uno::Any m_aMaxInclusive; + ::com::sun::star::uno::Any m_aMaxExclusive; + ::com::sun::star::uno::Any m_aMinInclusive; + ::com::sun::star::uno::Any m_aMinExclusive; + + double m_fCachedMaxInclusive; + double m_fCachedMaxExclusive; + double m_fCachedMinInclusive; + double m_fCachedMinExclusive; + + protected: + OValueLimitedType_Base( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ); + + virtual void initializeClone( const OXSDDataType& _rCloneSource ); + void initializeTypedClone( const OValueLimitedType_Base& _rCloneSource ); + + // XPropertySet and friends + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + + // OXSDDataType overridables + virtual bool _getValue( const ::rtl::OUString& value, double& fValue ); + virtual sal_uInt16 _validate( const ::rtl::OUString& value ); + virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason ); + + // own overridables + /** translate a given value into a human-readable string + + The value is guaranteed to be not <NULL/>, and is of type <member>ValueType</member> + */ + virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const = 0; + + /** translates a <member>ValueType</member> value into a double value + + The normalization must respect the "<" and "==" relations on the value + space. That is, if two values are equal, their normalizations must be equal, too. + Similarily, if <code>foo</code> is less than <code>bar</code>, the same + must hold for their normalizations. + + @param _rValue + the value to translate. Guranteed to be not <NULL/>, and of type <member>ValueType</member> + @param _rDoubleValue + output parameter to hold the resulting double value + */ + virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const = 0; + }; + + //==================================================================== + //= OValueLimitedType + //==================================================================== + template < typename VALUE_TYPE > + class OValueLimitedType : public OValueLimitedType_Base + { + protected: + typedef VALUE_TYPE ValueType; + inline const ::com::sun::star::uno::Type& + getCppuType() const { return ::getCppuType( static_cast< ValueType* >( NULL ) ); } + + protected: + OValueLimitedType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ); + + // OXSDDataType overridables + virtual void registerProperties(); + }; + + //==================================================================== + //= ODerivedDataType + //==================================================================== + /** helper class for implementing interfaces derived from XDataType + */ + template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS = OXSDDataType > + class ODerivedDataType :public SUPERCLASS + ,::comphelper::OPropertyArrayUsageHelper< CONCRETE_DATA_TYPE_IMPL > + { + private: + bool m_bPropertiesRegistered; + + protected: + ODerivedDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ); + + protected: + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // XPropertySet + virtual com::sun::star::uno::Reference<com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw(com::sun::star::uno::RuntimeException); + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + }; + + //==================================================================== + //= OBooleanType + //==================================================================== + class OBooleanType; + typedef ODerivedDataType< OBooleanType > OBooleanType_Base; + class OBooleanType : public OBooleanType_Base + { + public: + OBooleanType( const ::rtl::OUString& _rName ); + + protected: + DECLARE_DEFAULT_CLONING( OBooleanType ) + + // OXSDDataType overridables + virtual sal_uInt16 _validate( const ::rtl::OUString& value ); + virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason ); + }; + + //==================================================================== + //= OStringType + //==================================================================== + class OStringType; + typedef ODerivedDataType< OStringType > OStringType_Base; + class OStringType :public OStringType_Base + { + protected: + // <properties> + ::com::sun::star::uno::Any m_aLength; + ::com::sun::star::uno::Any m_aMinLength; + ::com::sun::star::uno::Any m_aMaxLength; + // </properties> + + public: + OStringType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass /* = ::com::sun::star::xsd::DataTypeClass::STRING */ ); + + protected: + DECLARE_DEFAULT_CLONING( OStringType ) + + // OXSDDataType overridables + virtual sal_uInt16 _validate( const ::rtl::OUString& value ); + virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason ); + virtual bool checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::rtl::OUString& _rErrorMessage ); + virtual void registerProperties(); + }; + + //==================================================================== + //= ODecimalType + //==================================================================== + class ODecimalType; + typedef ODerivedDataType< ODecimalType, OValueLimitedType< double > > ODecimalType_Base; + class ODecimalType : public ODecimalType_Base + { + protected: + ::com::sun::star::uno::Any m_aTotalDigits; + ::com::sun::star::uno::Any m_aFractionDigits; + + public: + ODecimalType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass /* = ::com::sun::star::xsd::DataTypeClass::DECIMAL */ ); + + protected: + DECLARE_DEFAULT_CLONING( ODecimalType ) + + // OXSDDataType overridables + virtual sal_uInt16 _validate( const ::rtl::OUString& value ); + virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason ); + virtual void registerProperties(); + + // OValueLimitedType overridables + virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const; + virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const; + + private: + using ODecimalType_Base::initializeTypedClone; + }; + + //==================================================================== + //= + //==================================================================== +#define DEFAULT_DECLARE_SUBTYPE( classname, valuetype ) \ + class classname; \ + typedef ODerivedDataType< classname, OValueLimitedType< valuetype > > classname##_Base; \ + class classname : public classname##_Base \ + { \ + public: \ + classname( const ::rtl::OUString& _rName ); \ + \ + protected: \ + DECLARE_DEFAULT_CLONING( classname ) \ + \ + /* OXSDDataType overridables */ \ + virtual sal_uInt16 _validate( const ::rtl::OUString& value ); \ + virtual bool _getValue( const ::rtl::OUString& value, double& fValue ); \ + \ + /* OValueLimitedType overridables */ \ + virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const; \ + virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const; \ + \ + private: \ + using classname##_Base::initializeTypedClone; \ + }; + + //==================================================================== + //= ODateType + //==================================================================== + DEFAULT_DECLARE_SUBTYPE( ODateType, ::com::sun::star::util::Date ) + + //==================================================================== + //= OTimeType + //==================================================================== + DEFAULT_DECLARE_SUBTYPE( OTimeType, ::com::sun::star::util::Time ) + + //==================================================================== + //= ODateTimeType + //==================================================================== + DEFAULT_DECLARE_SUBTYPE( ODateTimeType, ::com::sun::star::util::DateTime ) + + //==================================================================== + //= OShortIntegerType + //==================================================================== + class OShortIntegerType; + typedef ODerivedDataType< OShortIntegerType, OValueLimitedType< sal_Int16 > > OShortIntegerType_Base; + class OShortIntegerType : public OShortIntegerType_Base + { + public: + OShortIntegerType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ); + + protected: + DECLARE_DEFAULT_CLONING( OShortIntegerType ) + + // OXSDDataType overridables + virtual bool _getValue( const ::rtl::OUString& value, double& fValue ); + + // OValueLimitedType overridables + virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const; + virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const; + + private: + using OShortIntegerType_Base::initializeTypedClone; + }; + +//........................................................................ +} // namespace xforms +//........................................................................ + +#endif // FORMS_SOURCE_XFORMS_DATATYPES_HXX + diff --git a/forms/source/xforms/datatypes_impl.hxx b/forms/source/xforms/datatypes_impl.hxx new file mode 100644 index 000000000000..d0d0f9606b91 --- /dev/null +++ b/forms/source/xforms/datatypes_impl.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DATATYPES_INCLUDED_BY_MASTER_HEADER + #error "not to be included directly!" +#endif + +//-------------------------------------------------------------------- +template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > +ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::ODerivedDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :SUPERCLASS( _rName, _nTypeClass ) + ,m_bPropertiesRegistered( false ) +{ +} + +//-------------------------------------------------------------------- +template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > +::cppu::IPropertyArrayHelper* ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::createArrayHelper( ) const +{ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > aProps; + ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +//-------------------------------------------------------------------- +template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > +::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException ) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); +} + +//-------------------------------------------------------------------- +template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > +::cppu::IPropertyArrayHelper& SAL_CALL ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getInfoHelper() +{ + if ( !m_bPropertiesRegistered ) + { + const_cast< ODerivedDataType* >( this )->registerProperties(); + const_cast< ODerivedDataType* >( this )->m_bPropertiesRegistered = true; + } + + return *ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getArrayHelper(); +} + + +//-------------------------------------------------------------------- +template< typename VALUE_TYPE > +OValueLimitedType< VALUE_TYPE >::OValueLimitedType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass ) + :OValueLimitedType_Base( _rName, _nTypeClass ) +{ +} + diff --git a/forms/source/xforms/enumeration.cxx b/forms/source/xforms/enumeration.cxx new file mode 100644 index 000000000000..270ade4bc4bb --- /dev/null +++ b/forms/source/xforms/enumeration.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "enumeration.hxx" + +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> + +using com::sun::star::container::NoSuchElementException; +using com::sun::star::container::XIndexAccess; +using com::sun::star::lang::WrappedTargetException; +using com::sun::star::uno::Any; +using com::sun::star::uno::Reference; +using com::sun::star::uno::RuntimeException; + + +Enumeration::Enumeration( XIndexAccess* pContainer ) + : mxContainer( pContainer ), + mnIndex( 0 ) +{ + OSL_ENSURE( mxContainer.is(), "no container?" ); +} + +sal_Bool Enumeration::hasMoreElements() + throw( RuntimeException ) +{ + if( ! mxContainer.is() ) + throw RuntimeException(); + + return mnIndex < mxContainer->getCount(); +} + +Any Enumeration::nextElement() + throw( NoSuchElementException, + WrappedTargetException, + RuntimeException ) +{ + if( ! mxContainer.is() ) + throw RuntimeException(); + if( mnIndex >= mxContainer->getCount() ) + throw NoSuchElementException(); + + return mxContainer->getByIndex( mnIndex++ ); +} diff --git a/forms/source/xforms/enumeration.hxx b/forms/source/xforms/enumeration.hxx new file mode 100644 index 000000000000..8a9b89a09a15 --- /dev/null +++ b/forms/source/xforms/enumeration.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _ENUMERATION_HXX +#define _ENUMERATION_HXX + + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/uno/Reference.hxx> + +namespace com { namespace sun { namespace star { + namespace container { class XIndexAccess; } + namespace uno { class Any; } + namespace container { class NoSuchElementException; } + namespace lang { class WrappedTargetException; } + namespace uno { class RuntimeException; } +} } } + +/** implement XEnumeration based on container::XIndexAccess */ +class Enumeration + : public cppu::WeakImplHelper1<com::sun::star::container::XEnumeration> +{ + com::sun::star::uno::Reference<com::sun::star::container::XIndexAccess> mxContainer; + sal_Int32 mnIndex; + +public: + Enumeration( com::sun::star::container::XIndexAccess* ); + + virtual sal_Bool SAL_CALL hasMoreElements() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL nextElement() + throw( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); +}; + +#endif diff --git a/forms/source/xforms/evaluationcontext.hxx b/forms/source/xforms/evaluationcontext.hxx new file mode 100644 index 000000000000..4affefd34f29 --- /dev/null +++ b/forms/source/xforms/evaluationcontext.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EVALUATIONCONTEXT_HXX +#define _EVALUATIONCONTEXT_HXX + +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/xforms/XModel.hpp> + +namespace xforms +{ + + +/** define the context for the evaluation of an XPath expression */ +class EvaluationContext +{ +public: + EvaluationContext() + : mxContextNode(), + mxModel(), + mxNamespaces(), + mnContextPosition( 0 ), + mnContextSize( 0 ) + { } + + EvaluationContext( + const com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode>& xContextNode, + const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& xModel, + const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& xNamespaces, + sal_Int32 nPosition, + sal_Int32 nSize ) + : mxContextNode( xContextNode ), + mxModel( xModel ), + mxNamespaces( xNamespaces ), + mnContextPosition( nPosition ), + mnContextSize( nSize ) + { } + + com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> mxContextNode; + com::sun::star::uno::Reference<com::sun::star::xforms::XModel> mxModel; + com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> mxNamespaces; + + sal_Int32 mnContextPosition; + sal_Int32 mnContextSize; +}; + + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/makefile.mk b/forms/source/xforms/makefile.mk new file mode 100644 index 000000000000..10bbf6b49fcd --- /dev/null +++ b/forms/source/xforms/makefile.mk @@ -0,0 +1,66 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=forms +TARGET=xforms + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/model.obj \ + $(SLO)$/model_ui.obj \ + $(SLO)$/binding.obj \ + $(SLO)$/xforms_services.obj \ + $(SLO)$/unohelper.obj \ + $(SLO)$/propertysetbase.obj \ + $(SLO)$/pathexpression.obj \ + $(SLO)$/computedexpression.obj \ + $(SLO)$/boolexpression.obj \ + $(SLO)$/mip.obj \ + $(SLO)$/submission.obj \ + $(SLO)$/datatyperepository.obj \ + $(SLO)$/datatypes.obj \ + $(SLO)$/convert.obj \ + $(SLO)$/enumeration.obj \ + $(SLO)$/resourcehelper.obj \ + $(SLO)$/xmlhelper.obj \ + $(SLO)$/xformsevent.obj + + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/xforms/mip.cxx b/forms/source/xforms/mip.cxx new file mode 100644 index 000000000000..7f45ff5e9415 --- /dev/null +++ b/forms/source/xforms/mip.cxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "mip.hxx" + + +namespace xforms +{ + + +MIP::MIP() +{ + resetReadonly(); + resetRequired(); + resetRelevant(); + resetConstraint(); + resetCalculate(); + resetTypeName(); +} + +MIP::~MIP() {} + +void MIP::inherit( const MIP& rMip ) +{ + if( ! mbHasReadonly ) + { + mbHasReadonly = rMip.hasReadonly(); + mbReadonly = rMip.isReadonly(); + } + if( ! mbHasRequired ) + { + mbHasRequired = rMip.hasRequired(); + mbRequired = rMip.isRequired(); + } + if( ! mbHasRelevant ) + { + mbHasRelevant = rMip.hasRelevant(); + mbRelevant = rMip.isRelevant(); + } + if( ! mbHasConstraint ) + { + mbHasConstraint = rMip.hasConstraint(); + mbConstraint = rMip.isConstraint(); + msConstraintExplanation = rMip.getConstraintExplanation(); + } + if( ! mbHasCalculate ) + { + mbHasCalculate = rMip.hasCalculate(); + } + if( ! mbHasTypeName ) + { + mbHasTypeName = rMip.hasTypeName(); + msTypeName = rMip.getTypeName(); + } +} + +void MIP::join( const MIP& rMip ) +{ + // TODO: inherit only inheritable MIPs... + inherit( rMip ); +} + +bool MIP::hasReadonly() const { return mbHasReadonly; } +bool MIP::isReadonly() const { return mbHasReadonly ? mbReadonly : mbHasCalculate; } +void MIP::setReadonly( bool b ) { mbHasReadonly = true; mbReadonly = b; } +void MIP::resetReadonly() { mbHasReadonly = false; mbReadonly = false; } + +bool MIP::hasRequired() const { return mbHasRequired; } +bool MIP::isRequired() const { return mbRequired; } +void MIP::setRequired( bool b ) { mbHasRequired = true; mbRequired = b; } +void MIP::resetRequired() { mbHasRequired = false; mbRequired = false; } + +bool MIP::hasRelevant() const { return mbHasRelevant; } +bool MIP::isRelevant() const { return mbRelevant; } +void MIP::setRelevant( bool b ) { mbHasRelevant = true; mbRelevant = b; } +void MIP::resetRelevant() { mbHasRelevant = false; mbRelevant = true; } + +bool MIP::hasConstraint() const { return mbHasConstraint; } +bool MIP::isConstraint() const { return mbConstraint; } +void MIP::setConstraint( bool b ) { mbHasConstraint = true; mbConstraint = b; msConstraintExplanation = rtl::OUString(); } +void MIP::resetConstraint() { mbHasConstraint = false; mbConstraint = true; msConstraintExplanation = rtl::OUString(); } + +void MIP::setConstraintExplanation( const rtl::OUString& s ) { msConstraintExplanation = s; } +rtl::OUString MIP::getConstraintExplanation() const { return msConstraintExplanation; } + + +bool MIP::hasCalculate() const { return mbHasCalculate; } +void MIP::setHasCalculate( bool b ) { mbHasCalculate = b; } +void MIP::resetCalculate() { mbHasCalculate = false; } + +bool MIP::hasTypeName() const { return mbHasTypeName; } + rtl::OUString MIP::getTypeName() const { return msTypeName; } +void MIP::setTypeName( const rtl::OUString& s ) { msTypeName = s; mbHasTypeName = true; } +void MIP::resetTypeName() { msTypeName = rtl::OUString(); mbHasTypeName = false; } + + + + +} // namespace xforms diff --git a/forms/source/xforms/mip.hxx b/forms/source/xforms/mip.hxx new file mode 100644 index 000000000000..fb8b219cf7e1 --- /dev/null +++ b/forms/source/xforms/mip.hxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _MIP_HXX +#define _MIP_HXX + +#include <rtl/ustring.hxx> + +namespace xforms +{ + +/** represents the XForms *m*odel *i*tem *p*roperties (MIPs) for a + * given XNode in the instance data at a given point in time. The + * values will not be updated; for updated values new MIP objects have + * to be created/queried. */ +class MIP +{ + bool mbHasReadonly; + bool mbReadonly; + + bool mbHasRequired; + bool mbRequired; + + bool mbHasRelevant; + bool mbRelevant; + + bool mbHasConstraint; + bool mbConstraint; + + bool mbHasCalculate; + + bool mbHasTypeName; + rtl::OUString msTypeName; + + rtl::OUString msConstraintExplanation; + +public: + MIP(); + ~MIP(); + + /// inherit from upper-level MIPs + void inherit( const MIP& ); + + /// join with same-level MIPs + void join( const MIP& ); + + + // - type (static; default: xsd:string) + // (currently default implemented as empty string) + bool hasTypeName() const; + rtl::OUString getTypeName() const; + void setTypeName( const rtl::OUString& ); + void resetTypeName(); + + // - readonly (computed XPath; default: false; true if calculate exists) + bool hasReadonly() const; + bool isReadonly() const; + void setReadonly( bool ); + void resetReadonly(); + + // - required (computed XPath; default: false) + bool hasRequired() const; + bool isRequired() const; + void setRequired( bool ); + void resetRequired(); + + // - relevant (computed XPath; default: true) + bool hasRelevant() const; + bool isRelevant() const; + void setRelevant( bool ); + void resetRelevant(); + + // - constraing (computed XPath; default: true) + bool hasConstraint() const; + bool isConstraint() const; + void setConstraint( bool ); + void resetConstraint(); + + // explain _why_ a constraint failed + void setConstraintExplanation( const rtl::OUString& ); + rtl::OUString getConstraintExplanation() const; + + // - calculate (computed XPath; default: has none (false)) + // (for calculate, we only store whether a calculate MIP is present; + // the actual calculate value is handled my changing the instance + // directly) + bool hasCalculate() const; + void setHasCalculate( bool ); + void resetCalculate(); + + // - minOccurs/maxOccurs (computed XPath; default: 0/inf) + // - p3ptype (static; no default) + +}; + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/model.cxx b/forms/source/xforms/model.cxx new file mode 100644 index 000000000000..0d81c7056bec --- /dev/null +++ b/forms/source/xforms/model.cxx @@ -0,0 +1,808 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "model.hxx" + +#include "model_helper.hxx" +#include "unohelper.hxx" +#include "binding.hxx" +#include "submission.hxx" +#include "mip.hxx" +#include "evaluationcontext.hxx" +#include "xmlhelper.hxx" +#include "datatyperepository.hxx" +#include "NameContainer.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/debug.hxx> + +#include <comphelper/propertysetinfo.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <algorithm> + +// UNO classes +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XCharacterData.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/io/XInputStream.hpp> + + +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::lang::XUnoTunnel; +using com::sun::star::beans::XPropertySet; +using com::sun::star::beans::PropertyValue; +using rtl::OUString; +using rtl::OUStringBuffer; +using com::sun::star::beans::PropertyVetoException; +using com::sun::star::beans::UnknownPropertyException; +using com::sun::star::util::VetoException; +using com::sun::star::lang::WrappedTargetException; +using com::sun::star::lang::IllegalArgumentException; +using com::sun::star::ucb::XSimpleFileAccess; +using com::sun::star::io::XInputStream; + +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace xforms; + + +#if OSL_DEBUG_LEVEL > 1 +#define DBG_INVARIANT_TYPE(TYPE) class DBG_##TYPE { const TYPE* mpT; void check() { mpT->dbg_assertInvariant(); } public: DBG_##TYPE(const TYPE* pT) : mpT(pT) { check(); } ~DBG_##TYPE() { check(); } } _DBG_##TYPE(this); + +#define DBG_INVARIANT() DBG_INVARIANT_TYPE(Model) +#else +#define DBG_INVARIANT_TYPE(TYPE) +#define DBG_INVARIANT() +#endif + + + +// +// The Model +// + +void Model::ensureAtLeastOneInstance() +{ + if( ! mpInstances->hasItems() ) + { + // create a default instance + newInstance( OUString(), OUString(), true ); + } +} + + + +/** Model default constructor; create empty model */ +Model::Model() : + msID(), + mpBindings( NULL ), + mpSubmissions( NULL ), + mpInstances( new InstanceCollection ), + mxNamespaces( new NameContainer<OUString>() ), + mxBindings( mpBindings ), + mxSubmissions( mpSubmissions ), + mxInstances( mpInstances ), + mbInitialized( false ), + mbExternalData( true ) +{ + initializePropertySet(); + + // initialize bindings collections + // (not in initializer list to avoid use of incomplete 'this') + mpBindings = new BindingCollection( this ); + mxBindings = mpBindings; + + mpSubmissions = new SubmissionCollection( this ); + mxSubmissions = mpSubmissions; + + // invariant only holds after construction + DBG_INVARIANT(); +} + +Model::~Model() throw() +{ + // give up bindings & submissions; the mxBindings/mxSubmissions + // references will then delete them + mpBindings = NULL; + mpSubmissions = NULL; +} + +Model* lcl_getModel( const Reference<XUnoTunnel>& xTunnel ) +{ + Model* pModel = NULL; + if( xTunnel.is() ) + pModel = reinterpret_cast<Model*>( + xTunnel->getSomething( Model::getUnoTunnelID() ) ); + return pModel; +} + +Model* Model::getModel( const Reference<XModel>& xModel ) +{ + return lcl_getModel( Reference<XUnoTunnel>( xModel, UNO_QUERY ) ); +} + +EvaluationContext Model::getEvaluationContext() +{ + // the default context is the top-level element node. A default + // node (instanceData' is inserted when there is no default node + Reference<XDocument> xInstance = getDefaultInstance(); + Reference<XNode> xElement( xInstance->getDocumentElement(), UNO_QUERY ); + + // no element found? Then insert default element 'instanceData' + if( ! xElement.is() ) + { + xElement = Reference<XNode>( + xInstance->createElement( OUSTRING("instanceData") ), + UNO_QUERY_THROW ); + Reference<XNode>( xInstance, UNO_QUERY_THROW)->appendChild( xElement ); + } + + OSL_ENSURE( xElement.is() && + xElement->getNodeType() == NodeType_ELEMENT_NODE, + "no element in evaluation context" ); + + return EvaluationContext( xElement, this, mxNamespaces, 0, 1 ); +} + + +Model::IntSequence_t Model::getUnoTunnelID() +{ + static cppu::OImplementationId aImplementationId; + return aImplementationId.getImplementationId(); +} + +Model::XDocument_t Model::getForeignSchema() const +{ + return mxForeignSchema; +} + +void Model::setForeignSchema( const XDocument_t& rDocument ) +{ + mxForeignSchema = rDocument; +} + +rtl::OUString Model::getSchemaRef() const +{ + return msSchemaRef; +} + +void Model::setSchemaRef( const rtl::OUString& rSchemaRef ) +{ + msSchemaRef = rSchemaRef; +} + +Model::XNameContainer_t Model::getNamespaces() const +{ + return mxNamespaces; +} + +void Model::setNamespaces( const XNameContainer_t& rNamespaces ) +{ + if( rNamespaces.is() ) + mxNamespaces = rNamespaces; +} + +bool Model::getExternalData() const +{ + return mbExternalData; +} + +void Model::setExternalData( bool _bData ) +{ + mbExternalData = _bData; +} + +#if OSL_DEBUG_LEVEL > 1 +void Model::dbg_assertInvariant() const +{ + OSL_ENSURE( mpInstances != NULL, "no instances found" ); + OSL_ENSURE( mxInstances.is(), "No instance container!" ); + // OSL_ENSURE( mxInstances->hasElements(), "no instance!" ); + + OSL_ENSURE( mpBindings != NULL, "no bindings element" ); + OSL_ENSURE( mxBindings.is(), "No Bindings container" ); + + OSL_ENSURE( mpSubmissions != NULL, "no submissions element" ); + OSL_ENSURE( mxSubmissions.is(), "No Submission container" ); + + + + /* + // check bindings, and things that have to do with our binding + std::vector<MIP*> aAllMIPs; // check MIP map + sal_Int32 nCount = mpBindings->countItems(); + for( sal_Int32 i = 0; i < nCount; i++ ) + { + Binding* pBind = Binding::getBinding( + mpBindings->Collection<XPropertySet_t>::getItem( i ) ); + + // examine and check binding + OSL_ENSURE( pBind != NULL, "invalid binding found" ); + + OSL_ENSURE( Model::getModel( pBind->getModel() ) == this, + "our binding doesn't know us."); + // check this binding's MIP against MIP map + MIP* pMIP = const_cast<MIP*>( pBind->_getMIP() ); + sal_Int32 nFound = 0; + if( pMIP != NULL ) + { + aAllMIPs.push_back( pMIP ); + for( MIPs_t::const_iterator aIter = maMIPs.begin(); + aIter != maMIPs.end(); + aIter++ ) + { + if( pMIP == aIter->second ) + nFound++; + } + } + OSL_ENSURE( ( pMIP == NULL ) == ( nFound == 0 ), "MIP-map wrong" ); + } + + // check MIP map for left-over MIPs + for( MIPs_t::const_iterator aIter = maMIPs.begin(); + aIter != maMIPs.end(); + aIter++ ) + { + MIP* pMIP = aIter->second; + std::vector<MIP*>::iterator aFound = + std::find( aAllMIPs.begin(), aAllMIPs.end(), pMIP ); + if( aFound != aAllMIPs.end() ) + aAllMIPs.erase( aFound ); + } + OSL_ENSURE( aAllMIPs.empty(), "lonely MIPs found!" ); + */ +} +#endif + + +// +// MIP managment +// + +void Model::addMIP( void* pTag, const XNode_t& xNode, const MIP& rMIP ) +{ + OSL_ENSURE( pTag != NULL, "empty tag?" ); + OSL_ENSURE( xNode.is(), "no node" ); + + MIPs_t::value_type aValue( xNode, ::std::pair<void*,MIP>( pTag, rMIP ) ); + maMIPs.insert( aValue ); +} + +void Model::removeMIPs( void* pTag ) +{ + OSL_ENSURE( pTag != NULL, "empty tag?" ); + + for( MIPs_t::iterator aIter = maMIPs.begin(); + aIter != maMIPs.end(); ) + { + if( aIter->second.first == pTag ) + { + MIPs_t::iterator next( aIter ); ++next; + maMIPs.erase( aIter ); + aIter = next; + } + else + ++aIter; + } +} + +MIP Model::queryMIP( const XNode_t& xNode ) const +{ + // OSL_ENSURE( xNode.is(), "no node" ); + + // travel up inheritance chain and inherit MIPs + MIP aRet; + for( XNode_t xCurrent = xNode; + xCurrent.is(); + xCurrent = xCurrent->getParentNode() ) + { + // iterate over all MIPs for this node, and join MIPs + MIP aMIP; + MIPs_t::const_iterator aEnd = maMIPs.upper_bound( xCurrent ); + MIPs_t::const_iterator aIter = maMIPs.lower_bound( xCurrent ); + for( ; aIter != aEnd; aIter++ ) + aMIP.join( aIter->second.second ); + + // inherit from current node (or set if we are at the start node) + if( xCurrent == xNode ) + aRet = aMIP; + else + aRet.inherit( aMIP ); + } + + return aRet; +} + + + +void Model::rebind() +{ + OSL_ENSURE( mpBindings != NULL, "bindings?" ); + + // iterate over all bindings and call update + sal_Int32 nCount = mpBindings->countItems(); + for( sal_Int32 i = 0; i < nCount; i++ ) + { + Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); + OSL_ENSURE( pBind != NULL, "binding?" ); + pBind->update(); + } +} + + + +void Model::deferNotifications( bool bDefer ) +{ + // iterate over all bindings and defer notifications + sal_Int32 nCount = mpBindings->countItems(); + for( sal_Int32 i = 0; i < nCount; i++ ) + { + Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); + OSL_ENSURE( pBind != NULL, "binding?" ); + pBind->deferNotifications( bDefer ); + } +} + + +bool Model::setSimpleContent( const XNode_t& xConstNode, + const rtl::OUString& sValue ) +{ + OSL_ENSURE( xConstNode.is(), "need node to set data" ); + + bool bRet = false; + if( xConstNode.is() ) + { + // non-const node reference so we can assign children (if necessary) + XNode_t xNode( xConstNode ); + + switch( xNode->getNodeType() ) + { + case NodeType_ELEMENT_NODE: + { + // find first text node child + Reference<XNode> xChild; + for( xChild = xNode->getFirstChild(); + xChild.is() && xChild->getNodeType() != NodeType_TEXT_NODE; + xChild = xChild->getNextSibling() ) + ; // empty loop; only find first text node child + + // create text node, if none is found + if( ! xChild.is() ) + { + xChild = Reference<XNode>( + xNode->getOwnerDocument()->createTextNode( OUString() ), + UNO_QUERY_THROW ); + xNode->appendChild( xChild ); + } + xNode = xChild; + + OSL_ENSURE( xNode.is() && + xNode->getNodeType() == NodeType_TEXT_NODE, + "text node creation failed?" ); + } + // no break; continue as with text node: + + case NodeType_TEXT_NODE: + case NodeType_ATTRIBUTE_NODE: + { + // set the node value (defer notifications) + if( xNode->getNodeValue() != sValue ) + { + deferNotifications( true ); + xNode->setNodeValue( sValue ); + deferNotifications( false ); + } + bRet = true; + } + break; + + default: + { + OSL_ENSURE( false, "bound to unknown node type?" ); + } + break; + + } + } + return bRet; +} + +void Model::loadInstance( sal_Int32 nInstance ) +{ + Sequence<PropertyValue> aSequence = mpInstances->getItem( nInstance ); + + // find URL from instance + OUString sURL; + bool bOnce = false; + getInstanceData( aSequence, NULL, NULL, &sURL, &bOnce ); + + // if we have a URL, load the document and set it into the instance + if( sURL.getLength() > 0 ) + { + try + { + Reference<XInputStream> xInput = + Reference<XSimpleFileAccess>( + createInstance( + OUSTRING("com.sun.star.ucb.SimpleFileAccess") ), + UNO_QUERY_THROW )->openFileRead( sURL ); + if( xInput.is() ) + { + Reference<XDocument> xInstance = + getDocumentBuilder()->parse( xInput ); + if( xInstance.is() ) + { + OUString sEmpty; + setInstanceData( aSequence, NULL, &xInstance, + bOnce ? &sEmpty : &sURL, NULL); + mpInstances->setItem( nInstance, aSequence ); + } + } + } + catch( const Exception& ) + { + // couldn't load the instance -> ignore! + } + } +} + +void Model::loadInstances() +{ + // iterate over instance array to get PropertyValue-Sequence + const sal_Int32 nInstances = mpInstances->countItems(); + for( sal_Int32 nInstance = 0; nInstance < nInstances; nInstance++ ) + { + loadInstance( nInstance ); + } +} + +bool Model::isInitialized() const +{ + return mbInitialized; +} + +bool Model::isValid() const +{ + bool bValid = true; + sal_Int32 nCount = mpBindings->countItems(); + for( sal_Int32 i = 0; bValid && i < nCount; i++ ) + { + Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); + OSL_ENSURE( pBind != NULL, "binding?" ); + bValid = pBind->isValid(); + } + return bValid; +} + + + +// +// implement xforms::XModel +// + +rtl::OUString Model::getID() + throw( RuntimeException ) +{ + DBG_INVARIANT(); + return msID; +} + +void Model::setID( const rtl::OUString& sID ) + throw( RuntimeException ) +{ + DBG_INVARIANT(); + msID = sID; +} + +void Model::initialize() + throw( RuntimeException ) +{ + DBG_ASSERT( ! mbInitialized, "model already initialized" ); + + // load instances + loadInstances(); + + // let's pretend we're initialized and rebind all bindings + mbInitialized = true; + rebind(); +} + +void Model::rebuild() + throw( RuntimeException ) +{ + if( ! mbInitialized ) + initialize(); + else + rebind(); +} + +void Model::recalculate() + throw( RuntimeException ) +{ + rebind(); +} + +void Model::revalidate() + throw( RuntimeException ) +{ + // do nothing. We don't validate anyways! +} + +void Model::refresh() + throw( RuntimeException ) +{ + rebind(); +} + + +void SAL_CALL Model::submitWithInteraction( + const rtl::OUString& sID, + const XInteractionHandler_t& _rxHandler ) + throw( VetoException, + WrappedTargetException, + RuntimeException ) +{ + DBG_INVARIANT(); + + if( mpSubmissions->hasItem( sID ) ) + { + Submission* pSubmission = + Submission::getSubmission( mpSubmissions->getItem( sID ) ); + OSL_ENSURE( pSubmission != NULL, "no submission?" ); + OSL_ENSURE( pSubmission->getModel() == Reference<XModel>( this ), + "wrong model" ); + + // submit. All exceptions are allowed to leave. + pSubmission->submitWithInteraction( _rxHandler ); + } +} + +void Model::submit( const rtl::OUString& sID ) + throw( VetoException, WrappedTargetException, RuntimeException ) +{ + submitWithInteraction( sID, NULL ); +} + +Model::XDataTypeRepository_t SAL_CALL Model::getDataTypeRepository( ) + throw( RuntimeException ) +{ + if ( !mxDataTypes.is() ) + mxDataTypes = new ODataTypeRepository; + + return mxDataTypes; +} + +// +// instance management +// + +Model::XSet_t Model::getInstances() + throw( RuntimeException ) +{ + return mxInstances; +} + +Model::XDocument_t Model::getInstanceDocument( const rtl::OUString& rName ) + throw( RuntimeException ) +{ + ensureAtLeastOneInstance(); + Reference<XDocument> aInstance; + sal_Int32 nInstance = lcl_findInstance( mpInstances, rName ); + if( nInstance != -1 ) + getInstanceData( mpInstances->getItem( nInstance ), + NULL, &aInstance, NULL, NULL ); + return aInstance; +} + +Model::XDocument_t SAL_CALL Model::getDefaultInstance() + throw( RuntimeException ) +{ + ensureAtLeastOneInstance(); + DBG_ASSERT( mpInstances->countItems() > 0, "no instance?" ); + Reference<XDocument> aInstance; + getInstanceData( mpInstances->getItem( 0 ), NULL, &aInstance, NULL, NULL ); + return aInstance; +} + + + +// +// bindings management +// + +Model::XPropertySet_t SAL_CALL Model::createBinding() + throw( RuntimeException ) +{ + DBG_INVARIANT(); + return new Binding(); +} + +Model::XPropertySet_t Model::cloneBinding( const XPropertySet_t& xBinding ) + throw( RuntimeException ) +{ + DBG_INVARIANT(); + XPropertySet_t xNewBinding = createBinding(); + copy( xBinding, xNewBinding ); + return xNewBinding; +} + +Model::XPropertySet_t Model::getBinding( const rtl::OUString& sId ) + throw( RuntimeException ) +{ + DBG_INVARIANT(); + return mpBindings->hasItem( sId ) ? mpBindings->getItem( sId ) : NULL; +} + +Model::XSet_t Model::getBindings() + throw( RuntimeException ) +{ + DBG_INVARIANT(); + return mxBindings; +} + + + +// +// submission management +// + +Model::XSubmission_t Model::createSubmission() + throw( RuntimeException ) +{ + DBG_INVARIANT(); + return new Submission(); +} + +Model::XSubmission_t Model::cloneSubmission(const XPropertySet_t& xSubmission) + throw( RuntimeException ) +{ + DBG_INVARIANT(); + XSubmission_t xNewSubmission = createSubmission(); + XPropertySet_t xAsPropertySet( xNewSubmission.get() ); + copy( xSubmission.get(), xAsPropertySet ); + return xNewSubmission; +} + +Model::XSubmission_t Model::getSubmission( const rtl::OUString& sId ) + throw( RuntimeException ) +{ + DBG_INVARIANT(); + XSubmission_t xSubmission; + if ( mpSubmissions->hasItem( sId ) ) + xSubmission = xSubmission.query( mpSubmissions->getItem( sId ) ); + return xSubmission; +} + +Model::XSet_t Model::getSubmissions() + throw( RuntimeException ) +{ + DBG_INVARIANT(); + return mxSubmissions; +} + + + +// +// implementation of XFormsUIHelper1 interface +// can be found in file model_ui.cxx +// + + + +// +// implement XPropertySet & friends +// + +#define HANDLE_ID 0 +#define HANDLE_Instance 1 +#define HANDLE_InstanceURL 2 +#define HANDLE_ForeignSchema 3 +#define HANDLE_SchemaRef 4 +#define HANDLE_Namespaces 5 +#define HANDLE_ExternalData 6 + +#define REGISTER_PROPERTY( property, type ) \ + registerProperty( PROPERTY( property, type ), \ + new DirectPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) ); + +#define REGISTER_PROPERTY_API( property, type ) \ + registerProperty( PROPERTY( property, type ), \ + new APIPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) ); + +#define REGISTER_BOOL_PROPERTY( property ) \ + registerProperty( PROPERTY( property, sal_Bool ), \ + new BooleanPropertyAccessor< Model, bool >( this, &Model::set##property, &Model::get##property ) ); + +void Model::initializePropertySet() +{ + REGISTER_PROPERTY_API ( ID, OUString ); + REGISTER_PROPERTY ( ForeignSchema, XDocument_t ); + REGISTER_PROPERTY ( SchemaRef, OUString ); + REGISTER_PROPERTY ( Namespaces, XNameContainer_t ); + REGISTER_BOOL_PROPERTY( ExternalData ); +} + +void Model::update() + throw( RuntimeException ) +{ + rebuild(); +} + + +sal_Int64 Model::getSomething( const IntSequence_t& xId ) + throw( RuntimeException ) +{ + return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL ); +} + +Sequence<sal_Int8> Model::getImplementationId() + throw( RuntimeException ) +{ + return getUnoTunnelID(); +} + + +// +// 'shift' operators for getting data into and out of Anys +// + +void operator <<= ( com::sun::star::uno::Any& rAny, + xforms::Model* pModel) +{ + Reference<XPropertySet> xPropSet( static_cast<XPropertySet*>( pModel ) ); + rAny <<= xPropSet; +} + +bool operator >>= ( xforms::Model* pModel, + com::sun::star::uno::Any& rAny ) +{ + bool bRet = false; + + // acquire model pointer through XUnoTunnel + Reference<XUnoTunnel> xTunnel( rAny, UNO_QUERY ); + if( xTunnel.is() ) + { + pModel = reinterpret_cast<xforms::Model*>( + xTunnel->getSomething( xforms::Model::getUnoTunnelID() ) ); + bRet = true; + } + + return bRet; +} diff --git a/forms/source/xforms/model.hxx b/forms/source/xforms/model.hxx new file mode 100644 index 000000000000..be9a5134d1da --- /dev/null +++ b/forms/source/xforms/model.hxx @@ -0,0 +1,435 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _MODEL_HXX +#define _MODEL_HXX + + +// include for parent class(es) +#include <cppuhelper/implbase4.hxx> +#include <propertysetbase.hxx> +#include <com/sun/star/xforms/XModel.hpp> +#include <com/sun/star/xforms/XFormsUIHelper1.hpp> +#include <com/sun/star/util/XUpdatable.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> + + +// includes for member variables +#include <com/sun/star/uno/Reference.hxx> +#include <map> + + +// forward declaractions +namespace com { namespace sun { namespace star +{ + namespace xml { namespace dom { class XDocument; } } + namespace xml { namespace dom { class XNode; } } + namespace uno { template<typename T> class Sequence; } + namespace lang { class IndexOutOfBoundsException; } + namespace lang { class IllegalArgumentException; } + namespace beans { class XPropertySet; } + namespace container { class XSet; } + namespace container { class XNameContainer; } + namespace frame { class XModel; } +} } } +namespace rtl { class OUString; } +namespace xforms +{ + class Binding; + class MIP; + class BindingCollection; + class SubmissionCollection; + class InstanceCollection; + class EvaluationContext; +} + + +namespace xforms +{ + +/** An XForms Model. Contains: + * # (set of) instance data (XML DOM tree) + * # (set of) bindings + * # (set of) submissions + * # (NOT YET IMPLEMENTED) actions (set of) + * + * See http://www.w3.org/TR/xforms/ for more information. + */ +typedef cppu::ImplInheritanceHelper4< + PropertySetBase, + com::sun::star::xforms::XModel, + com::sun::star::xforms::XFormsUIHelper1, + com::sun::star::util::XUpdatable, + com::sun::star::lang::XUnoTunnel +> Model_t; +class Model : public Model_t +{ + // a number of local typedefs, to make the remaining header readable + typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocument> XDocument_t; + typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> XNode_t; + typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t; + typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t; + typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> XPropertySet_t; + typedef com::sun::star::uno::Reference<com::sun::star::xforms::XDataTypeRepository> XDataTypeRepository_t; + typedef com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> XNameContainer_t; + typedef com::sun::star::uno::Reference<com::sun::star::xforms::XSubmission> XSubmission_t; + typedef com::sun::star::uno::Reference<com::sun::star::frame::XModel> Frame_XModel_t; + typedef com::sun::star::uno::Reference<com::sun::star::xforms::XModel> XModel_t; + typedef com::sun::star::uno::Reference<com::sun::star::task::XInteractionHandler> XInteractionHandler_t; + + typedef com::sun::star::uno::Reference<com::sun::star::container::XSet> XSet_t; + typedef com::sun::star::beans::PropertyVetoException PropertyVetoException_t; + typedef com::sun::star::beans::UnknownPropertyException UnknownPropertyException_t; + typedef com::sun::star::util::VetoException VetoException_t; + typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t; + typedef com::sun::star::uno::RuntimeException RuntimeException_t; + typedef com::sun::star::uno::Any Any_t; + typedef com::sun::star::uno::Sequence<sal_Int8> IntSequence_t; + typedef std::multimap<XNode_t,std::pair<void*,MIP> > MIPs_t; + + +private: + + rtl::OUString msID; /// the model ID + BindingCollection* mpBindings; /// the bindings + SubmissionCollection* mpSubmissions; /// the submissions + InstanceCollection* mpInstances; /// the instance(s) + + XDataTypeRepository_t mxDataTypes; /// the XSD data-types used + XDocument_t mxForeignSchema; /// the XSD-schema part we cannot + /// map onto data types + rtl::OUString msSchemaRef; /// xforms:model/@schema attribute + + XNameContainer_t mxNamespaces; /// namespaces for entire model + + + // references to mpBindings/mpSubmissions, for UNO reference counting + XSet_t mxBindings; + XSet_t mxSubmissions; + XSet_t mxInstances; + + MIPs_t maMIPs; /// map nodes to their MIPs + + bool mbInitialized; /// has model been initialized ? + bool mbExternalData; /// is the data of this model to be considered an ingegral part of the document? + + void initializePropertySet(); + + void ensureAtLeastOneInstance(); + + +public: + + /// create a new model with an empty, default instance + Model(); + virtual ~Model() throw(); + + // get Model implementation from API object + static Model* getModel( const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& ); + + xforms::EvaluationContext getEvaluationContext(); + + + static IntSequence_t getUnoTunnelID(); + + + // get/set that part of the schema, that we can't interpret as data types + XDocument_t getForeignSchema() const; + void setForeignSchema( const XDocument_t& ); + + // get/set the xforms:model/@schema attribute + rtl::OUString getSchemaRef() const; + void setSchemaRef( const rtl::OUString& ); + + // get/set namespaces for entire model + XNameContainer_t getNamespaces() const; + void setNamespaces( const XNameContainer_t& ); + + // get/set the ExternalData property + bool getExternalData() const; + void setExternalData( bool _bData ); + + +#if OSL_DEBUG_LEVEL > 1 + void dbg_assertInvariant() const; +#endif + + + // + // MIP (model item property) management + // + + // register MIPs which apply to a given node; only to be called by bindings + // (The pTag parameter serves only to be able to remove the MIPs + // that were added using the same tag. No functions will be + // performed on it; hence the void* type.) + void addMIP( void* pTag, const XNode_t&, const MIP& ); + void removeMIPs( void* pTag ); + + /// query which MIPs appy to the given node + MIP queryMIP( const XNode_t& xNode ) const; + + /// re-bind all bindings + void rebind(); + + /// call defer notifications on all bindings + void deferNotifications( bool ); + + /// set a data value in the instance + /// (also defers notifications) + bool setSimpleContent( const XNode_t&, const rtl::OUString& ); + + /// load instance data + void loadInstance( sal_Int32 nInstance ); + void loadInstances(); + + /// has model been initialized? + bool isInitialized() const; + + /// is model currently valid (for submission)? + bool isValid() const; + + + + // + // XModel + // implement the xforms::XModel implementation + // + + + virtual rtl::OUString SAL_CALL getID() + throw( RuntimeException_t ); + + virtual void SAL_CALL setID( const rtl::OUString& sID ) + throw( RuntimeException_t ); + + virtual void SAL_CALL initialize() + throw( RuntimeException_t ); + + virtual void SAL_CALL rebuild() + throw( RuntimeException_t ); + + virtual void SAL_CALL recalculate() + throw( RuntimeException_t ); + + virtual void SAL_CALL revalidate() + throw( RuntimeException_t ); + + virtual void SAL_CALL refresh() + throw( RuntimeException_t ); + + virtual void SAL_CALL submit( const rtl::OUString& sID ) + throw( VetoException_t, WrappedTargetException_t, RuntimeException_t ); + + virtual void SAL_CALL submitWithInteraction( const ::rtl::OUString& id, const XInteractionHandler_t& _rxHandler ) + throw( VetoException_t, WrappedTargetException_t, RuntimeException_t ); + + virtual XDataTypeRepository_t SAL_CALL getDataTypeRepository( ) + throw( RuntimeException_t ); + + + // XModel: instance management + + virtual XSet_t SAL_CALL getInstances() + throw( RuntimeException_t ); + + virtual XDocument_t SAL_CALL getInstanceDocument( const rtl::OUString& ) + throw( RuntimeException_t ); + + virtual XDocument_t SAL_CALL getDefaultInstance() + throw( RuntimeException_t ); + + + + // XModel: binding management + + virtual XPropertySet_t SAL_CALL createBinding() + throw( RuntimeException_t ); + + virtual XPropertySet_t SAL_CALL cloneBinding( const XPropertySet_t& ) + throw( RuntimeException_t ); + + virtual XPropertySet_t SAL_CALL getBinding( const rtl::OUString& ) + throw( RuntimeException_t ); + + virtual XSet_t SAL_CALL getBindings() + throw( RuntimeException_t ); + + + // XModel: submission management + + virtual XSubmission_t SAL_CALL createSubmission() + throw( RuntimeException_t ); + + virtual XSubmission_t SAL_CALL cloneSubmission( const XPropertySet_t& ) + throw( RuntimeException_t ); + + virtual XSubmission_t SAL_CALL getSubmission( const rtl::OUString& ) + throw( RuntimeException_t ); + + virtual XSet_t SAL_CALL getSubmissions() + throw( RuntimeException_t ); + + + + // + // XFormsUIHelper1 & friends: + // (implementation in model_ui.cxx) + // + + /// determine a reasonable control service for a given node + /// (based on data type MIP assigned to the node) + virtual rtl::OUString SAL_CALL getDefaultServiceNameForNode( const XNode_t& xNode ) throw (RuntimeException_t); + + /// call getDefaultBindingExpressionForNode with default evaluation context + virtual rtl::OUString SAL_CALL getDefaultBindingExpressionForNode( const XNode_t& xNode ) throw (RuntimeException_t); + + /// determine a reasonable default binding expression for a given node + /// and a given evaluation context + /// @returns expression, or empty string if no expression could be derived + rtl::OUString getDefaultBindingExpressionForNode( + const XNode_t&, + const EvaluationContext& ); + + virtual rtl::OUString SAL_CALL getNodeDisplayName( const XNode_t&, + sal_Bool bDetail ) + throw( RuntimeException_t ); + + virtual rtl::OUString SAL_CALL getNodeName( const XNode_t& ) + throw( RuntimeException_t ); + + virtual rtl::OUString SAL_CALL getBindingName( const XPropertySet_t&, + sal_Bool bDetail ) + throw( RuntimeException_t ); + + virtual rtl::OUString SAL_CALL getSubmissionName( const XPropertySet_t&, + sal_Bool bDetail ) + throw( RuntimeException_t ); + + virtual XPropertySet_t SAL_CALL cloneBindingAsGhost( const XPropertySet_t& ) + throw( RuntimeException_t ); + + virtual void SAL_CALL removeBindingIfUseless( const XPropertySet_t& ) + throw( RuntimeException_t ); + + virtual XDocument_t SAL_CALL newInstance( const rtl::OUString& sName, + const rtl::OUString& sURL, + sal_Bool bURLOnce ) + throw( RuntimeException_t ); + + virtual void SAL_CALL renameInstance( const rtl::OUString& sFrom, + const rtl::OUString& sTo, + const rtl::OUString& sURL, + sal_Bool bURLOnce ) + throw( RuntimeException_t ); + + virtual void SAL_CALL removeInstance( const rtl::OUString& sName ) + throw( RuntimeException_t ); + + + virtual XModel_t SAL_CALL newModel( const Frame_XModel_t& xComponent, + const rtl::OUString& sName ) + throw( RuntimeException_t ); + virtual void SAL_CALL renameModel( const Frame_XModel_t& xComponent, + const rtl::OUString& sFrom, + const rtl::OUString& sTo ) + throw( RuntimeException_t ); + + virtual void SAL_CALL removeModel( const Frame_XModel_t& xComponent, + const rtl::OUString& sName ) + throw( RuntimeException_t ); + + + virtual XNode_t SAL_CALL createElement( const XNode_t& xParent, + const rtl::OUString& sName ) + throw( RuntimeException_t ); + + virtual XNode_t SAL_CALL createAttribute( const XNode_t& xParent, + const rtl::OUString& sName ) + throw( RuntimeException_t ); + + virtual XNode_t SAL_CALL renameNode( const XNode_t& xNode, + const rtl::OUString& sName ) + throw( RuntimeException_t ); + + virtual XPropertySet_t SAL_CALL getBindingForNode( const XNode_t&, + sal_Bool bCreate ) + throw( RuntimeException_t ); + + virtual void SAL_CALL removeBindingForNode( const XNode_t& ) + throw( RuntimeException_t ); + + virtual rtl::OUString SAL_CALL getResultForExpression( + const XPropertySet_t& xBinding, + sal_Bool bIsBindingExpression, + const rtl::OUString& sExpression ) + throw( RuntimeException_t ); + + virtual sal_Bool SAL_CALL isValidXMLName( const rtl::OUString& sName ) + throw( RuntimeException_t ); + + virtual sal_Bool SAL_CALL isValidPrefixName( const rtl::OUString& sName ) + throw( RuntimeException_t ); + + virtual void SAL_CALL setNodeValue( + const XNode_t& xNode, + const rtl::OUString& sValue ) + throw( RuntimeException_t ); + + + // + // XUpdatable + // + +public: + virtual void SAL_CALL update() + throw( RuntimeException_t ); + + // + // XUnoTunnel + // + +public: + virtual sal_Int64 SAL_CALL getSomething( const IntSequence_t& ) + throw( RuntimeException_t ); + + // + // XTypeProvider::getImplementationId + // + +public: + virtual IntSequence_t SAL_CALL getImplementationId() + throw( RuntimeException_t ); + +}; + +// finally, allow 'shifting' of Model objects into/out of Any +void operator <<= ( com::sun::star::uno::Any&, const xforms::Model* ); +bool operator >>= ( xforms::Model*, const com::sun::star::uno::Any& ); + +} // namespace +#endif diff --git a/forms/source/xforms/model_helper.hxx b/forms/source/xforms/model_helper.hxx new file mode 100644 index 000000000000..d67a83c8cdb1 --- /dev/null +++ b/forms/source/xforms/model_helper.hxx @@ -0,0 +1,167 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _MODEL_HELPER_HXX +#define _MODEL_HELPER_HXX + +// +// some helper definitions that must be available for model.cxx and +// model_ui.cxx +// + +#include "namedcollection.hxx" +#include "binding.hxx" +#include "submission.hxx" +#include "unohelper.hxx" + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +namespace xforms +{ + class Model; +} + +// +// BindingCollection +// + +namespace xforms +{ + +class BindingCollection : public NamedCollection<com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> > +{ + Model* mpModel; + +public: + BindingCollection( Model* pModel ) : mpModel( pModel ) {} + virtual ~BindingCollection() {} + + virtual bool isValid( const T& t ) const + { + return Binding::getBinding( t ) != NULL; + } + +protected: + virtual void _insert( const T& t ) + { + OSL_ENSURE( Binding::getBinding( t ) != NULL, "invalid item?" ); + Binding::getBinding( t )->_setModel( Binding::Model_t( mpModel ) ); + } + + virtual void _remove( const T& t ) + { + OSL_ENSURE( Binding::getBinding( t ) != NULL, "invalid item?" ); + Binding::getBinding( t )->_setModel( Binding::Model_t() ); + } +}; + + + +// +// SubmissionCollection +// + +class SubmissionCollection : public NamedCollection<com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> > +{ + Model* mpModel; + +public: + SubmissionCollection( Model* pModel ) : mpModel( pModel ) {} + virtual ~SubmissionCollection() {} + +public: + virtual bool isValid( const T& t ) const + { + return Submission::getSubmission( t ) != NULL; + } + +protected: + virtual void _insert( const T& t ) + { + OSL_ENSURE( Submission::getSubmission( t ) != NULL, "invalid item?" ); + Submission::getSubmission( t )->setModel( com::sun::star::uno::Reference<com::sun::star::xforms::XModel>( mpModel ) ); + } + + virtual void _remove( const T& t ) + { + OSL_ENSURE( Submission::getSubmission( t ) != NULL, "invalid item?" ); + Submission::getSubmission( t )->setModel( com::sun::star::uno::Reference<com::sun::star::xforms::XModel>( ) ); + } +}; + + +// +// InstanceCollection +// + +class InstanceCollection : public Collection<com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> > +{ +public: + virtual bool isValid( const T& t ) const + { + const com::sun::star::beans::PropertyValue* pValues = t.getConstArray(); + rtl::OUString sInstance( OUSTRING("Instance") ); + sal_Bool bFound = sal_False; + for( sal_Int32 i = 0; ( ! bFound ) && ( i < t.getLength() ); i++ ) + { + bFound |= ( pValues[i].Name == sInstance ); + } + return bFound ? true : false; + } +}; + + +// +// helper functions +// + +sal_Int32 lcl_findInstance( const InstanceCollection*, + const rtl::OUString& ); + + +// get values from Sequence<PropertyValue> describing an Instance +void getInstanceData( + const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&, + rtl::OUString* pID, + com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocument>*, + rtl::OUString* pURL, + bool* pURLOnce ); + +// set values on Sequence<PropertyValue> for an Instance +void setInstanceData( + com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&, + const rtl::OUString* pID, + const com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocument>*, + const rtl::OUString* pURL, + const bool* pURLOnce ); + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/model_ui.cxx b/forms/source/xforms/model_ui.cxx new file mode 100644 index 000000000000..a62ac1fa9ac9 --- /dev/null +++ b/forms/source/xforms/model_ui.cxx @@ -0,0 +1,1066 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "model.hxx" +#include "model_helper.hxx" +#include "mip.hxx" +#include "evaluationcontext.hxx" +#include "unohelper.hxx" +#include "submission/serialization_app_xml.hxx" +#include "resourcehelper.hxx" +#include "xmlhelper.hxx" +#include "convert.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/debug.hxx> + +// UNO classes +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xml/xpath/XPathObjectType.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XTextInputStream.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/xforms/XFormsSupplier.hpp> +#include <com/sun/star/xforms/XDataTypeRepository.hpp> +#include <com/sun/star/xsd/XDataType.hpp> +#include <com/sun/star/xsd/DataTypeClass.hpp> + + +using rtl::OUString; +using rtl::OUStringBuffer; +using com::sun::star::beans::PropertyValue; +using com::sun::star::io::XInputStream; +using com::sun::star::io::XActiveDataSink; +using com::sun::star::io::XTextInputStream; +using com::sun::star::container::XEnumeration; +using com::sun::star::container::XNameContainer; +using com::sun::star::xforms::XFormsSupplier; + +using namespace xforms; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::xpath; + + + +// +// implement XFormsUIHelper1 +// + +OUString Model::getDefaultServiceNameForNode( const XNode_t& xNode ) + throw( RuntimeException ) +{ + // determine service for control. string/text field is default. + OUString sService = OUSTRING("com.sun.star.form.component.TextField"); + + // query repository for suitable type + OSL_ENSURE( mxDataTypes.is(), "no type repository?" ); + OUString sTypeName = queryMIP( xNode ).getTypeName(); + if( mxDataTypes->hasByName( sTypeName ) ) + { + OSL_ENSURE( mxDataTypes->getDataType( sTypeName ).is(), + "has or has not?" ); + + switch( mxDataTypes->getDataType( sTypeName )->getTypeClass() ) + { + case com::sun::star::xsd::DataTypeClass::BOOLEAN: + sService = OUSTRING("com.sun.star.form.component.CheckBox"); + break; + case com::sun::star::xsd::DataTypeClass::DOUBLE: + case com::sun::star::xsd::DataTypeClass::DECIMAL: + case com::sun::star::xsd::DataTypeClass::FLOAT: + sService = OUSTRING("com.sun.star.form.component.NumericField"); + break; + + case com::sun::star::xsd::DataTypeClass::STRING: + case com::sun::star::xsd::DataTypeClass::DURATION: + case com::sun::star::xsd::DataTypeClass::DATETIME: + case com::sun::star::xsd::DataTypeClass::TIME: + case com::sun::star::xsd::DataTypeClass::DATE: + case com::sun::star::xsd::DataTypeClass::gYearMonth: + case com::sun::star::xsd::DataTypeClass::gYear: + case com::sun::star::xsd::DataTypeClass::gMonthDay: + case com::sun::star::xsd::DataTypeClass::gDay: + case com::sun::star::xsd::DataTypeClass::gMonth: + case com::sun::star::xsd::DataTypeClass::hexBinary: + case com::sun::star::xsd::DataTypeClass::base64Binary: + case com::sun::star::xsd::DataTypeClass::anyURI: + case com::sun::star::xsd::DataTypeClass::QName: + case com::sun::star::xsd::DataTypeClass::NOTATION: + default: + // keep default + break; + } + } + + return sService; +} + + +void lcl_OutPosition( OUStringBuffer& rBuffer, + const Reference<XNode>& xNode ) +{ + OSL_ENSURE( xNode->getParentNode().is(), "need parent" ); + + // count # of occurences of this node + sal_Int32 nFound = 0; + sal_Int32 nPosition = -1; + if( xNode->getParentNode().is() ) + { + for( Reference<XNode> xIter = xNode->getParentNode()->getFirstChild(); + xIter != NULL; + xIter = xIter->getNextSibling() ) + { + if( xIter->getNodeType() == xNode->getNodeType() && + xIter->getNodeName() == xNode->getNodeName() && + xIter->getNamespaceURI() == xNode->getNamespaceURI() ) + { + nFound++; + if( xIter == xNode ) + nPosition = nFound; + } + } + } + OSL_ENSURE( nFound > 0 && nPosition > 0, "node not found???" ); + + // output position (if necessary) + if( nFound > 1 ) + { + rBuffer.insert( 0, sal_Unicode(']') ); + rBuffer.insert( 0, nPosition ); + rBuffer.insert( 0, sal_Unicode('[') ); + } +} + +void lcl_OutName( OUStringBuffer& rBuffer, + const Reference<XNode>& xNode ) +{ + rBuffer.insert( 0, xNode->getNodeName() ); + OUString sPrefix = xNode->getPrefix(); + if( sPrefix.getLength() > 0 ) + { + rBuffer.insert( 0, sal_Unicode(':') ); + rBuffer.insert( 0, sPrefix ); + } +} + +void lcl_OutInstance( OUStringBuffer& rBuffer, + const Reference<XNode>& xNode, + Model* pModel ) +{ + Reference<XDocument> xDoc = xNode->getOwnerDocument(); + + if( xDoc != pModel->getDefaultInstance() ) + { + rBuffer.insert( 0, OUSTRING("')") ); + + // iterate over instances, and find the right one + OUString sInstanceName; + Reference<XEnumeration> xEnum = + pModel->getInstances()->createEnumeration(); + while( ( sInstanceName.getLength() == 0 ) && xEnum->hasMoreElements() ) + { + Sequence<PropertyValue> aValues; + xEnum->nextElement() >>= aValues; + + // get ID and instance + OUString sId; + Reference<XDocument> xInstance; + getInstanceData( aValues, &sId, &xInstance, NULL, NULL ); + + // now check whether this was our instance: + if( xInstance == xDoc ) + sInstanceName = sId; + } + + rBuffer.insert( 0, sInstanceName ); + rBuffer.insert( 0, OUSTRING("instance('") ); + } +} + +OUString Model::getDefaultBindingExpressionForNode( + const XNode_t& xNode, + const EvaluationContext& rContext) +{ + OSL_ENSURE( xNode.is(), "need node" ); + + // iterate upwards and put sections into the expression buffer. + // Stop iteration either at context node (relative expression) or + // at document root, whichever occurs first. + OUStringBuffer aBuffer; + for( Reference<XNode> xCurrent = xNode; + xCurrent.is() && xCurrent != rContext.mxContextNode; + xCurrent = xCurrent->getParentNode() ) + { + // insert a '/' for every step except the first + if( aBuffer.getLength() > 0 ) + aBuffer.insert( 0, sal_Unicode('/') ); + + switch( xCurrent->getNodeType() ) + { + case NodeType_ELEMENT_NODE: + lcl_OutPosition( aBuffer, xCurrent ); + lcl_OutName( aBuffer, xCurrent ); + break; + + case NodeType_TEXT_NODE: + lcl_OutPosition( aBuffer, xCurrent ); + aBuffer.insert( 0, OUSTRING("text()") ); + break; + + case NodeType_ATTRIBUTE_NODE: + lcl_OutName( aBuffer, xCurrent ); + aBuffer.insert( 0, sal_Unicode('@') ); + break; + + case NodeType_DOCUMENT_NODE: + // check for which instance we have + lcl_OutInstance( aBuffer, xCurrent, this ); + break; + + default: + // unknown type? fail! + OSL_ENSURE( false, "unknown node type!" ); + xCurrent.set( NULL ); + aBuffer.makeStringAndClear(); + // we'll remove the slash below + aBuffer.insert( 0, sal_Unicode('/') ); + break; + } + } + + return aBuffer.makeStringAndClear(); +} + + + +OUString Model::getDefaultBindingExpressionForNode( const XNode_t& xNode ) + throw( RuntimeException ) +{ + return getDefaultBindingExpressionForNode( xNode, getEvaluationContext() ); +} + +bool lcl_isWhitespace( const OUString& rString ) +{ + sal_Int32 nLength = rString.getLength(); + const sal_Unicode* pStr = rString.getStr(); + + bool bWhitespace = true; + for( sal_Int32 i = 0; bWhitespace && ( i < nLength ); i++ ) + { + sal_Unicode c = pStr[i]; + bWhitespace = ( c == sal_Unicode(0x09) || + c == sal_Unicode(0x0A) || + c == sal_Unicode(0x0D) || + c == sal_Unicode(0x20) ); + } + return bWhitespace; +} + +OUString Model::getNodeDisplayName( const XNode_t& xNode, + sal_Bool bDetail ) + throw( RuntimeException ) +{ + OUStringBuffer aBuffer; + + switch( xNode->getNodeType() ) + { + case NodeType_ELEMENT_NODE: + lcl_OutName( aBuffer, xNode ); + break; + + case NodeType_TEXT_NODE: + { + OUString sContent = xNode->getNodeValue(); + if( bDetail || ! lcl_isWhitespace( sContent ) ) + { + aBuffer.append( sal_Unicode('"') ); + aBuffer.append( Convert::collapseWhitespace( sContent ) ); + aBuffer.append( sal_Unicode('"') ); + } + } + break; + + case NodeType_ATTRIBUTE_NODE: + lcl_OutName( aBuffer, xNode ); + aBuffer.insert( 0, sal_Unicode('@') ); + break; + + case NodeType_DOCUMENT_NODE: + if( xNode == getDefaultInstance() ) + aBuffer.append( sal_Unicode('/') ); + else + lcl_OutInstance( aBuffer, xNode, this ); + break; + + default: + // unknown type? fail! + OSL_ENSURE( false, "unknown node type!" ); + break; + } + + return aBuffer.makeStringAndClear(); +} + +OUString Model::getNodeName( const XNode_t& xNode ) + throw( RuntimeException ) +{ + OUStringBuffer aBuffer; + + switch( xNode->getNodeType() ) + { + case NodeType_ELEMENT_NODE: + case NodeType_ATTRIBUTE_NODE: + lcl_OutName( aBuffer, xNode ); + break; + + case NodeType_TEXT_NODE: + case NodeType_DOCUMENT_NODE: + default: + // unknown type? fail! + OSL_ENSURE( false, "no name for this node type!" ); + break; + } + + return aBuffer.makeStringAndClear(); +} + +OUString Model::getBindingName( const XPropertySet_t& xBinding, + sal_Bool /*bDetail*/ ) + throw( RuntimeException ) +{ + OUString sID; + xBinding->getPropertyValue( OUSTRING("BindingID" ) ) >>= sID; + OUString sExpression; + xBinding->getPropertyValue( OUSTRING("BindingExpression" ) ) >>= sExpression; + + OUStringBuffer aBuffer; + if( sID.getLength() > 0 ) + { + aBuffer.append( sID ); + aBuffer.append( OUSTRING(" (" )); + aBuffer.append( sExpression ); + aBuffer.append( OUSTRING(")" )); + } + else + aBuffer.append( sExpression ); + + return aBuffer.makeStringAndClear(); +} + +OUString Model::getSubmissionName( const XPropertySet_t& xSubmission, + sal_Bool /*bDetail*/ ) + throw( RuntimeException ) +{ + OUString sID; + xSubmission->getPropertyValue( OUSTRING("ID") ) >>= sID; + return sID; +} + +Model::XPropertySet_t Model::cloneBindingAsGhost( const XPropertySet_t &xBinding ) + throw( RuntimeException ) +{ + // Create a new binding instance first... + Binding *pBinding = new Binding(); + + // ...and bump up the "defered notification counter" + // to prevent this binding from contributing to the + // MIPs table... + pBinding->deferNotifications(true); + + // Copy the propertyset and return result... + XPropertySet_t xNewBinding(pBinding); + copy( xBinding, xNewBinding ); + return xNewBinding; +} + +void Model::removeBindingIfUseless( const XPropertySet_t& xBinding ) + throw( RuntimeException ) +{ + Binding* pBinding = Binding::getBinding( xBinding ); + if( pBinding != NULL ) + { + if( ! pBinding->isUseful() ) + mpBindings->removeItem( pBinding ); + } +} + +Model::XDocument_t Model::newInstance( const rtl::OUString& sName, + const rtl::OUString& sURL, + sal_Bool bURLOnce ) + throw( RuntimeException ) +{ + // create a default instance with <instanceData> element + XDocument_t xInstance = getDocumentBuilder()->newDocument(); + DBG_ASSERT( xInstance.is(), "failed to create DOM instance" ); + + Reference<XNode>( xInstance, UNO_QUERY_THROW )->appendChild( + Reference<XNode>( xInstance->createElement( OUSTRING("instanceData") ), + UNO_QUERY_THROW ) ); + + Sequence<PropertyValue> aSequence; + bool bOnce = bURLOnce; // bool, so we can take address in setInstanceData + setInstanceData( aSequence, &sName, &xInstance, &sURL, &bOnce ); + sal_Int32 nInstance = mpInstances->addItem( aSequence ); + loadInstance( nInstance ); + + return xInstance; +} + +sal_Int32 lcl_findProp( const PropertyValue* pValues, + sal_Int32 nLength, + const rtl::OUString& rName ) +{ + bool bFound = false; + sal_Int32 n = 0; + for( ; !bFound && n < nLength; n++ ) + { + bFound = ( pValues[n].Name == rName ); + } + return bFound ? ( n - 1) : -1; +} + +sal_Int32 xforms::lcl_findInstance( const InstanceCollection* pInstances, + const rtl::OUString& rName ) +{ + sal_Int32 nLength = pInstances->countItems(); + sal_Int32 n = 0; + bool bFound = false; + for( ; !bFound && n < nLength; n++ ) + { + OUString sName; + getInstanceData( pInstances->getItem( n ), &sName, NULL, NULL, NULL ); + bFound = ( sName == rName ); + } + return bFound ? ( n - 1 ) : -1; +} + +void Model::renameInstance( const rtl::OUString& sFrom, + const rtl::OUString& sTo, + const rtl::OUString& sURL, + sal_Bool bURLOnce ) + throw( RuntimeException ) +{ + sal_Int32 nPos = lcl_findInstance( mpInstances, sFrom ); + if( nPos != -1 ) + { + Sequence<PropertyValue> aSeq = mpInstances->getItem( nPos ); + PropertyValue* pSeq = aSeq.getArray(); + sal_Int32 nLength = aSeq.getLength(); + + sal_Int32 nProp = lcl_findProp( pSeq, nLength, OUSTRING("ID") ); + if( nProp == -1 ) + { + // add name property + aSeq.realloc( nLength + 1 ); + pSeq = aSeq.getArray(); + pSeq[ nLength ].Name = OUSTRING("ID"); + nProp = nLength; + } + + // change name + pSeq[ nProp ].Value <<= sTo; + + // change url + nProp = lcl_findProp( pSeq, nLength, OUSTRING("URL") ); + if(nProp != -1) + pSeq[ nProp ].Value <<= sURL; + + // change urlonce + nProp = lcl_findProp( pSeq, nLength, OUSTRING("URLOnce") ); + if(nProp != -1) + pSeq[ nProp ].Value <<= bURLOnce; + + // set instance + mpInstances->setItem( nPos, aSeq ); + } +} + +void Model::removeInstance( const rtl::OUString& sName ) + throw( RuntimeException ) +{ + sal_Int32 nPos = lcl_findInstance( mpInstances, sName ); + if( nPos != -1 ) + mpInstances->removeItem( mpInstances->getItem( nPos ) ); +} + +Reference<XNameContainer> lcl_getModels( + const Reference<com::sun::star::frame::XModel>& xComponent ) +{ + Reference<XNameContainer> xRet; + Reference<XFormsSupplier> xSupplier( xComponent, UNO_QUERY ); + if( xSupplier.is() ) + { + xRet = xSupplier->getXForms(); + } + return xRet; +} + +Model::XModel_t Model::newModel( const Reference<com::sun::star::frame::XModel>& xCmp, + const OUString& sName ) + throw( RuntimeException ) +{ + Model::XModel_t xModel; + Reference<XNameContainer> xModels = lcl_getModels( xCmp ); + if( xModels.is() + && ! xModels->hasByName( sName ) ) + { + Model* pModel = new Model(); + xModel.set( pModel ); + + pModel->setID( sName ); + pModel->newInstance( OUString(), OUString(), sal_False ); + pModel->initialize(); + xModels->insertByName( sName, makeAny( xModel ) ); + } + + return xModel; +} + +void Model::renameModel( const Reference<com::sun::star::frame::XModel>& xCmp, + const OUString& sFrom, + const OUString& sTo ) + throw( RuntimeException ) +{ + Reference<XNameContainer> xModels = lcl_getModels( xCmp ); + if( xModels.is() + && xModels->hasByName( sFrom ) + && ! xModels->hasByName( sTo ) ) + { + Reference<XModel> xModel( xModels->getByName( sFrom ), UNO_QUERY ); + xModel->setID( sTo ); + xModels->insertByName( sTo, makeAny( xModel ) ); + xModels->removeByName( sFrom ); + } +} + +void Model::removeModel( const Reference<com::sun::star::frame::XModel>& xCmp, + const OUString& sName ) + throw( RuntimeException ) +{ + Reference<XNameContainer> xModels = lcl_getModels( xCmp ); + if( xModels.is() + && xModels->hasByName( sName ) ) + { + xModels->removeByName( sName ); + } +} + +Model::XNode_t Model::createElement( const XNode_t& xParent, + const OUString& sName ) + throw( RuntimeException ) +{ + Reference<XNode> xNode; + if( xParent.is() + && isValidXMLName( sName ) ) + { + // TODO: implement proper namespace handling + xNode.set( xParent->getOwnerDocument()->createElement( sName ), + UNO_QUERY ); + } + return xNode; +} + +Model::XNode_t Model::createAttribute( const XNode_t& xParent, + const OUString& sName ) + throw( RuntimeException ) +{ + Reference<XNode> xNode; + Reference<XElement> xElement( xParent, UNO_QUERY ); + if( xParent.is() + && xElement.is() + && isValidXMLName( sName ) ) + { + // handle case where attribute already exists + sal_Int32 nCount = 0; + OUString sUniqueName = sName; + while( xElement->hasAttribute( sUniqueName ) ) + { + nCount++; + sUniqueName = sName + OUString::valueOf( nCount ); + } + + // TODO: implement proper namespace handling + xNode.set( xParent->getOwnerDocument()->createAttribute( sUniqueName ), + UNO_QUERY ); + } + return xNode; +} + +Model::XNode_t Model::renameNode( const XNode_t& xNode, + const rtl::OUString& sName ) + throw( RuntimeException ) +{ + // early out if we don't have to change the name + if( xNode->getNodeName() == sName ) + return xNode; + + // refuse to change name if its an attribute, and the name is already used + if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE + && xNode->getParentNode().is() + && Reference<XElement>(xNode->getParentNode(), UNO_QUERY_THROW)->hasAttribute( sName ) ) + return xNode; + + // note old binding expression so we can adjust bindings below + OUString sOldDefaultBindingExpression = + getDefaultBindingExpressionForNode( xNode ); + + Reference<XDocument> xDoc = xNode->getOwnerDocument(); + Reference<XNode> xNew; + if( xNode->getNodeType() == NodeType_ELEMENT_NODE ) + { + Reference<XElement> xElem = xDoc->createElement( sName ); + xNew.set( xElem, UNO_QUERY ); + + // iterate over all attributes and append them to the new element + Reference<XElement> xOldElem( xNode, UNO_QUERY ); + OSL_ENSURE( xNode.is(), "no element?" ); + + Reference<XNamedNodeMap> xMap = xNode->getAttributes(); + sal_Int32 nLength = xMap.is() ? xMap->getLength() : 0; + for( sal_Int32 n = 0; n < nLength; n++ ) + { + Reference<XAttr> xAttr( xMap->item(n), UNO_QUERY ); + xElem->setAttributeNode( xOldElem->removeAttributeNode( xAttr ) ); + } + + // iterate over all children and append them to the new element + for( Reference<XNode> xCurrent = xNode->getFirstChild(); + xCurrent.is(); + xCurrent = xNode->getFirstChild() ) + { + xNew->appendChild( xNode->removeChild( xCurrent ) ); + } + + xNode->getParentNode()->replaceChild( xNew, xNode ); + } + else if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE ) + { + // create new attribute + Reference<XAttr> xAttr = xDoc->createAttribute( sName ); + xAttr->setValue( xNode->getNodeValue() ); + + // replace node + Reference<XNode> xParent = xNode->getParentNode(); + xParent->removeChild( xNode ); + xNew = xParent->appendChild( Reference<XNode>( xAttr, UNO_QUERY ) ); + } + else + { + OSL_ENSURE( false, "can't rename this node type" ); + } + + // adjust bindings (if necessary): + if( xNew.is() ) + { + // iterate over bindings and replace default expressions + OUString sNewDefaultBindingExpression = + getDefaultBindingExpressionForNode( xNew ); + for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ ) + { + Binding* pBinding = Binding::getBinding( + mpBindings->Collection<XPropertySet_t>::getItem( n ) ); + + if( pBinding->getBindingExpression() + == sOldDefaultBindingExpression ) + pBinding->setBindingExpression( sNewDefaultBindingExpression ); + } + } + + // return node; return old node if renaming failed + return xNew.is() ? xNew : xNode; +} + +Model::XPropertySet_t Model::getBindingForNode( const XNode_t& xNode, + sal_Bool bCreate ) + throw( RuntimeException ) +{ + OSL_ENSURE( xNode.is(), "no node?" ); + + // We will iterate over all bindings and determine the + // appropriateness of the respective binding for this node. The + // best one will be used. If we don't find any and bCreate is set, + // then we will create a suitable binding. + Binding* pBestBinding = NULL; + sal_Int32 nBestScore = 0; + + for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ ) + { + Binding* pBinding = Binding::getBinding( + mpBindings->Collection<XPropertySet_t>::getItem( n ) ); + + OSL_ENSURE( pBinding != NULL, "no binding?" ); + Reference<XNodeList> xNodeList = pBinding->getXNodeList(); + + sal_Int32 nNodes = xNodeList.is() ? xNodeList->getLength() : 0; + if( nNodes > 0 && xNodeList->item( 0 ) == xNode ) + { + // allright, we found a suitable node. Let's determine how + // well it fits. Score: + // - bind to exactly this node is better than whole nodeset + // - simple binding expressions is better than complex ones + sal_Int32 nScore = 0; + if( nNodes == 1 ) + nScore ++; + if( pBinding->isSimpleBindingExpression() ) + nScore ++; + + // if we found a better binding, remember it + if( nScore > nBestScore ) + { + pBestBinding = pBinding; + nBestScore = nScore; + } + } + } + + // create binding, if none was found and bCreate is set + OSL_ENSURE( ( nBestScore == 0 ) == ( pBestBinding == NULL ), + "score != binding?" ); + if( bCreate && pBestBinding == NULL ) + { + pBestBinding = new Binding(); + pBestBinding->setBindingExpression( + getDefaultBindingExpressionForNode( xNode ) ); + mpBindings->addItem( pBestBinding ); + } + + return pBestBinding; +} + +void Model::removeBindingForNode( const XNode_t& ) + throw( RuntimeException ) +{ + // determine whether suitable binding is still used +} + +OUString lcl_serializeForDisplay( const Reference< XAttr >& _rxAttrNode ) +{ + ::rtl::OUString sResult; + OSL_ENSURE( _rxAttrNode.is(), "lcl_serializeForDisplay( attr ): invalid argument!" ); + if ( _rxAttrNode.is() ) + { + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( _rxAttrNode->getName() ); + aBuffer.appendAscii( "=" ); + ::rtl::OUString sValue = _rxAttrNode->getValue(); + sal_Unicode nQuote = '"'; + if ( sValue.indexOf( nQuote ) >= 0 ) + nQuote = '\''; + aBuffer.append( nQuote ); + aBuffer.append( sValue ); + aBuffer.append( nQuote ); + aBuffer.append( (sal_Unicode)' ' ); + sResult = aBuffer.makeStringAndClear(); + } + return sResult; +} + +OUString lcl_serializeForDisplay( const Reference<XNodeList>& xNodes ) +{ + ::rtl::OUString sResult; + + // create document fragment + Reference<XDocument> xDocument( getDocumentBuilder()->newDocument() ); + Reference<XDocumentFragment> xFragment( + xDocument->createDocumentFragment() ); + Reference<XNode> xNode( xFragment, UNO_QUERY ); + OSL_ENSURE( xFragment.is(), "xFragment" ); + OSL_ENSURE( xNode.is(), "xNode" ); + + sal_Int32 nAttributeNodes = 0; + + // attach nodelist to fragment + sal_Int32 nLength = xNodes->getLength(); + for( sal_Int32 i = 0; i < nLength; i++ ) + { + Reference<XNode> xCurrent = xNodes->item( i ); + + switch ( xCurrent->getNodeType() ) + { + case NodeType_DOCUMENT_NODE: + // special-case documents: use top-level element instead + xCurrent = xCurrent->getFirstChild(); + break; + case NodeType_ATTRIBUTE_NODE: + { + Reference< XAttr > xAttr( xCurrent, UNO_QUERY ); + if ( xAttr.is() ) + { + sResult += lcl_serializeForDisplay( xAttr ); + ++nAttributeNodes; + } + } + continue; + + default: + break; + } + + // append node + xNode->appendChild( xDocument->importNode( xCurrent, sal_True ) ); + } + OSL_ENSURE( ( nAttributeNodes == 0 ) || ( nAttributeNodes == nLength ), + "lcl_serializeForDisplay: mixed attribute and non-attribute nodes?" ); + if ( nAttributeNodes ) + // had only attribute nodes + return sResult; + + // serialize fragment + CSerializationAppXML aSerialization; + aSerialization.setSource( xFragment ); + aSerialization.serialize(); + + // copy stream into buffer + Reference<XTextInputStream> xTextInputStream( + createInstance( OUSTRING("com.sun.star.io.TextInputStream") ), + UNO_QUERY ); + Reference<XActiveDataSink>( xTextInputStream, UNO_QUERY_THROW ) + ->setInputStream( aSerialization.getInputStream() ); + + /* WORK AROUND for problem in serialization: currently, multiple + XML delarations (<?xml...?>) are being written out and we don't + want them. When this is fixed, the code below is nice and + simple. The current code filters out the declarations. + OUString sResult = xTextInputStream->readString( Sequence<sal_Unicode>(), + sal_True ); + */ + + // well, the serialization prepends XML header(s) that we need to + // remove first. + OUStringBuffer aBuffer; + while( ! xTextInputStream->isEOF() ) + { + OUString sLine = xTextInputStream->readLine(); + if( sLine.getLength() > 0 + && sLine.compareToAscii( "<?xml", 5 ) != 0 ) + { + aBuffer.append( sLine ); + aBuffer.append( sal_Unicode('\n') ); + } + } + sResult = aBuffer.makeStringAndClear(); + + return sResult; +} + +OUString lcl_serializeForDisplay( const Reference<XXPathObject>& xResult ) +{ + // error handling first + if( ! xResult.is() ) + return getResource( RID_STR_XFORMS_CANT_EVALUATE ); + + + // TODO: localize + OUStringBuffer aBuffer; + + switch( xResult->getObjectType() ) + { + case XPathObjectType_XPATH_BOOLEAN: + aBuffer.append( xResult->getBoolean() + ? OUSTRING("true") + : OUSTRING("false") ); + break; + + case XPathObjectType_XPATH_STRING: + aBuffer.append( sal_Unicode('"') ); + aBuffer.append( xResult->getString() ); + aBuffer.append( sal_Unicode('"') ); + break; + + case XPathObjectType_XPATH_NODESET: + aBuffer.append( lcl_serializeForDisplay( xResult->getNodeList() ) ); + break; + + case XPathObjectType_XPATH_NUMBER: + aBuffer.append( xResult->getDouble() ); + break; + + case XPathObjectType_XPATH_UNDEFINED: + case XPathObjectType_XPATH_POINT: + case XPathObjectType_XPATH_RANGE: + case XPathObjectType_XPATH_LOCATIONSET: + case XPathObjectType_XPATH_USERS: + case XPathObjectType_XPATH_XSLT_TREE: + default: + // TODO: localized error message? + break; + } + + return aBuffer.makeStringAndClear(); +} + +OUString Model::getResultForExpression( + const XPropertySet_t& xBinding, + sal_Bool bIsBindingExpression, + const OUString& sExpression ) + throw( RuntimeException ) +{ + Binding* pBinding = Binding::getBinding( xBinding ); + if( pBinding == NULL ) + throw RuntimeException(); + + // prepare & evaluate expression + OUStringBuffer aBuffer; + ComputedExpression aExpression; + aExpression.setExpression( sExpression ); + if( bIsBindingExpression ) + { + // binding: use binding context and evaluation + aExpression.evaluate( pBinding->getEvaluationContext() ); + aBuffer.append( lcl_serializeForDisplay( aExpression.getXPath() ) ); + } + else + { + // MIP (not binding): iterate over bindings contexts + std::vector<EvaluationContext> aContext = + pBinding->getMIPEvaluationContexts(); + for( std::vector<EvaluationContext>::iterator aIter = aContext.begin(); + aIter != aContext.end(); + aIter ++ ) + { + aExpression.evaluate( *aIter ); + aBuffer.append( lcl_serializeForDisplay(aExpression.getXPath()) ); + aBuffer.append( sal_Unicode('\n') ); + } + } + return aBuffer.makeStringAndClear(); +} + +sal_Bool Model::isValidXMLName( const OUString& sName ) + throw( RuntimeException ) +{ + return isValidQName( sName, NULL ); +} + +sal_Bool Model::isValidPrefixName( const OUString& sName ) + throw( RuntimeException ) +{ + return ::isValidPrefixName( sName, NULL ); +} + +void Model::setNodeValue( + const XNode_t& xNode, + const rtl::OUString& sValue ) + throw( RuntimeException ) +{ + setSimpleContent( xNode, sValue ); +} + + +// +// helper functions from model_helper.hxx +// + +void xforms::getInstanceData( + const Sequence<PropertyValue>& aValues, + OUString* pID, + Reference<XDocument>* pInstance, + OUString* pURL, + bool* pURLOnce ) +{ + sal_Int32 nValues = aValues.getLength(); + const PropertyValue* pValues = aValues.getConstArray(); + for( sal_Int32 n = 0; n < nValues; n++ ) + { + const PropertyValue& rValue = pValues[n]; +#define PROP(NAME) \ + if( p##NAME != NULL && \ + rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(#NAME)) ) \ + rValue.Value >>= (*p##NAME) + PROP(ID); + PROP(Instance); + PROP(URL); + PROP(URLOnce); +#undef PROP + } +} + +void xforms::setInstanceData( + Sequence<PropertyValue>& aSequence, + const OUString* _pID, + const Reference<XDocument>* _pInstance, + const OUString* _pURL, + const bool* _pURLOnce ) +{ + // get old instance data + OUString sID; + Reference<XDocument> xInstance; + OUString sURL; + bool bURLOnce = false; + getInstanceData( aSequence, &sID, &xInstance, &sURL, &bURLOnce ); + const OUString* pID = ( sID.getLength() > 0 ) ? &sID : NULL; + const Reference<XDocument>* pInstance = xInstance.is() ? &xInstance : NULL; + const OUString* pURL = ( sURL.getLength() > 0 ) ? &sURL : NULL; + const bool* pURLOnce = ( bURLOnce && pURL != NULL ) ? &bURLOnce : NULL; + + // determine new instance data +#define PROP(NAME) if( _p##NAME != NULL ) p##NAME = _p##NAME + PROP(ID); + PROP(Instance); + PROP(URL); + PROP(URLOnce); +#undef PROP + + // count # of values we want to set + sal_Int32 nCount = 0; +#define PROP(NAME) if( p##NAME != NULL ) nCount++ + PROP(ID); + PROP(Instance); + PROP(URL); + PROP(URLOnce); +#undef PROP + + // realloc sequence and enter values; + aSequence.realloc( nCount ); + PropertyValue* pSequence = aSequence.getArray(); + sal_Int32 nIndex = 0; +#define PROP(NAME) \ + if( p##NAME != NULL ) \ + { \ + pSequence[ nIndex ].Name = OUSTRING(#NAME); \ + pSequence[ nIndex ].Value <<= *p##NAME; \ + nIndex++; \ + } + PROP(ID); + PROP(Instance); + PROP(URL); + PROP(URLOnce); +#undef PROP +} diff --git a/forms/source/xforms/namedcollection.hxx b/forms/source/xforms/namedcollection.hxx new file mode 100644 index 000000000000..ffae93ed2c90 --- /dev/null +++ b/forms/source/xforms/namedcollection.hxx @@ -0,0 +1,142 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _NAMEDCOLLECTION_HXX +#define _NAMEDCOLLECTION_HXX + +#include <collection.hxx> +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/container/XNameAccess.hpp> + +#include <algorithm> + +template<class T> +class NamedCollection : public cppu::ImplInheritanceHelper1< + Collection<T>, + com::sun::star::container::XNameAccess> +{ + using Collection<T>::maItems; + using Collection<T>::getItem; + using Collection<T>::hasItem; + +public: + NamedCollection() {} + virtual ~NamedCollection() {} + + const T& getItem( const rtl::OUString& rName ) const + { + OSL_ENSURE( hasItem( rName ), "invalid name" ); + return *findItem( rName ); + } + + bool hasItem( const rtl::OUString& rName ) const + { + return findItem( rName ) != maItems.end(); + } + + typedef com::sun::star::uno::Sequence<rtl::OUString> Names_t; + Names_t getNames() const + { + // iterate over members, and collect all those that have names + std::vector<rtl::OUString> aNames; + for( typename std::vector<T>::const_iterator aIter = maItems.begin(); + aIter != maItems.end(); + aIter++ ) + { + com::sun::star::uno::Reference<com::sun::star::container::XNamed> + xNamed( *aIter, com::sun::star::uno::UNO_QUERY ); + if( xNamed.is() ) + aNames.push_back( xNamed->getName() ); + } + + // copy names to Sequence and return + Names_t aResult( aNames.size() ); + rtl::OUString* pStrings = aResult.getArray(); + std::copy( aNames.begin(), aNames.end(), pStrings ); + + return aResult; + } + +protected: + typename std::vector<T>::const_iterator findItem( const rtl::OUString& rName ) const + { + for( typename std::vector<T>::const_iterator aIter = maItems.begin(); + aIter != maItems.end(); + aIter++ ) + { + com::sun::star::uno::Reference<com::sun::star::container::XNamed> + xNamed( *aIter, com::sun::star::uno::UNO_QUERY ); + if( xNamed.is() && xNamed->getName() == rName ) + return aIter; + } + return maItems.end(); + } + +public: + + // XElementAccess + virtual typename Collection<T>::Type_t SAL_CALL getElementType() + throw( typename Collection<T>::RuntimeException_t ) + { + return Collection<T>::getElementType(); + } + + virtual sal_Bool SAL_CALL hasElements() + throw( typename Collection<T>::RuntimeException_t ) + { + return Collection<T>::hasElements(); + } + + // XNameAccess : XElementAccess + virtual typename Collection<T>::Any_t SAL_CALL getByName( + const rtl::OUString& aName ) + throw( typename Collection<T>::NoSuchElementException_t, + typename Collection<T>::WrappedTargetException_t, + typename Collection<T>::RuntimeException_t ) + { + if( hasItem( aName ) ) + return com::sun::star::uno::makeAny( getItem( aName ) ); + else + throw typename Collection<T>::NoSuchElementException_t(); + + } + + virtual Names_t SAL_CALL getElementNames() + throw( typename Collection<T>::RuntimeException_t ) + { + return getNames(); + } + + virtual sal_Bool SAL_CALL hasByName( + const rtl::OUString& aName ) + throw( typename Collection<T>::RuntimeException_t ) + { + return hasItem( aName ) ? sal_True : sal_False; + } +}; + +#endif diff --git a/forms/source/xforms/pathexpression.cxx b/forms/source/xforms/pathexpression.cxx new file mode 100644 index 000000000000..ef82e87c4d18 --- /dev/null +++ b/forms/source/xforms/pathexpression.cxx @@ -0,0 +1,154 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "pathexpression.hxx" +#include "unohelper.hxx" +#include "evaluationcontext.hxx" +#include "NameContainer.hxx" + +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/xml/dom/events/XEventListener.hpp> +#include <com/sun/star/xml/dom/events/XEventTarget.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <rtl/ustrbuf.hxx> + +#include <unotools/textsearch.hxx> + +#include <algorithm> +#include <functional> + + +using rtl::OUString; +using rtl::OUStringBuffer; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Sequence; +using com::sun::star::xml::dom::XNode; +using com::sun::star::xml::dom::XNodeList; +using com::sun::star::xml::dom::events::XEventListener; +using com::sun::star::xml::dom::events::XEventTarget; +using com::sun::star::container::XNameContainer; +using com::sun::star::xml::xpath::XXPathObject; +using com::sun::star::uno::RuntimeException; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::UNO_QUERY_THROW; +using com::sun::star::xml::dom::NodeType_TEXT_NODE; +using com::sun::star::xml::xpath::XPathObjectType_XPATH_UNDEFINED; +using namespace std; + + + + +namespace xforms +{ + +PathExpression::PathExpression() + : ComputedExpression(), + maNodes() +{ +} + +PathExpression::~PathExpression() +{ +} + + + +void PathExpression::setExpression( const OUString& rExpression ) +{ + // set new expression, and clear pre-computed results + ComputedExpression::setExpression( rExpression ); + + // check expression against regular expression to determine + // whether it contains only 'simple' (i.e. static) conditions. For + // now, we check whether it only contains number positions. + // (TODO: Only works for names containing only ASCII letters+digits.) + mbIsSimple = + _checkExpression( "( */@?[a-zA-Z0-9:]+( *\\[ *[0-9 ]+ *\\] *)?)+" ); + + maNodes.clear(); +} + +const rtl::OUString PathExpression::_getExpressionForEvaluation() const +{ + OUString sExpr = ComputedExpression::_getExpressionForEvaluation(); + if( sExpr.getLength() == 0 ) + sExpr = OUSTRING("."); + return sExpr; +} + +bool PathExpression::evaluate( const EvaluationContext& rContext ) +{ + // for simple expression we don't need to re-bind (if we were bound before) + // (we will evaluate empty expressions, since they are interpreted as ".") + if( mxResult.is() && isSimpleExpression() ) + return true; + + bool bResult = _evaluate( rContext, _getExpressionForEvaluation() ); + + // clear old result, and copy new + maNodes.clear(); + if( mxResult.is() ) + { + // copy node list + Reference<XNodeList> xNodeList = mxResult->getNodeList(); + OSL_ENSURE( xNodeList.is(), "empty object (instead of empty list)" ); + sal_Int32 nLength = xNodeList.is() ? xNodeList->getLength() : 0; + for( sal_Int32 n = 0; n < nLength; n++ ) + maNodes.push_back( xNodeList->item( n ) ); + } + + return bResult; +} + + +Reference<XNode> PathExpression::getNode() const +{ + Reference<XNode> xResult; + if( ! maNodes.empty() ) + xResult = *maNodes.begin(); + return xResult; +} + +const PathExpression::NodeVector_t PathExpression::getNodeList() const +{ + return maNodes; +} + +Reference<XNodeList> PathExpression::getXNodeList() const +{ + return mxResult.is() ? mxResult->getNodeList() : Reference<XNodeList>(); +} + + +} // namespace xforms diff --git a/forms/source/xforms/pathexpression.hxx b/forms/source/xforms/pathexpression.hxx new file mode 100644 index 000000000000..00f11b56d435 --- /dev/null +++ b/forms/source/xforms/pathexpression.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PATHEXPRESSION_HXX +#define _PATHEXPRESSION_HXX + + +// include for parent class +#include "computedexpression.hxx" + +// includes for member variables +#include <vector> + +// forward declaractions +namespace com { namespace sun { namespace star +{ + namespace xml { namespace dom + { + class XNodeList; + namespace events { class XEventListener; } + } } +} } } + + + +namespace xforms +{ + +/** PathExpression represents an XPath Expression and caches results */ +class PathExpression : public ComputedExpression +{ +public: + typedef std::vector<com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> > NodeVector_t; + +private: + /// the node-list result from the last bind (cached from mxResult) + NodeVector_t maNodes; + +protected: + /// get expression for evaluation + const rtl::OUString _getExpressionForEvaluation() const; + + +public: + PathExpression(); + ~PathExpression(); + + /// set the expression string + /// (overridden to do remove old listeners) + /// (also defines simple expressions) + void setExpression( const rtl::OUString& rExpression ); + + + /// evaluate the expression relative to the content node. + bool evaluate( const xforms::EvaluationContext& rContext ); + + + // get the result of this expression as node/node list/... + com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> getNode() const; + const NodeVector_t getNodeList() const; + com::sun::star::uno::Reference<com::sun::star::xml::dom::XNodeList> getXNodeList() const; + +}; + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/propertysetbase.cxx b/forms/source/xforms/propertysetbase.cxx new file mode 100644 index 000000000000..131b2aa447b0 --- /dev/null +++ b/forms/source/xforms/propertysetbase.cxx @@ -0,0 +1,192 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "propertysetbase.hxx" + +#include <cppuhelper/typeprovider.hxx> // for getImplementationId() + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <tools/debug.hxx> + +#include <vector> + +using com::sun::star::uno::Any; +using com::sun::star::uno::Type; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::IllegalArgumentException; +using com::sun::star::beans::Property; +using com::sun::star::beans::XPropertySetInfo; + +oslInterlockedCount SAL_CALL PropertyAccessorBase::acquire() +{ + return ++m_refCount; +} + +oslInterlockedCount SAL_CALL PropertyAccessorBase::release() +{ + if ( --m_refCount == 0 ) + { + delete this; + return 0; + } + return m_refCount; +} + +PropertySetBase::PropertySetBase( ) + :m_pProperties( NULL ) +{ +} + +PropertySetBase::~PropertySetBase( ) +{ + DELETEZ( m_pProperties ); +} + +cppu::IPropertyArrayHelper& SAL_CALL PropertySetBase::getInfoHelper() +{ + if ( !m_pProperties ) + { + DBG_ASSERT( !m_aProperties.empty(), "PropertySetBase::getInfoHelper: no registered properties!" ); + m_pProperties = new cppu::OPropertyArrayHelper( &m_aProperties[0], m_aProperties.size(), sal_False ); + } + return *m_pProperties; +} + +Reference< XPropertySetInfo > SAL_CALL PropertySetBase::getPropertySetInfo( ) throw(RuntimeException) +{ + return cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); +} + +void PropertySetBase::registerProperty( const Property& rProperty, + const ::rtl::Reference< PropertyAccessorBase >& rAccessor ) +{ + DBG_ASSERT( rAccessor.get(), "PropertySetBase::registerProperty: invalid property accessor, this will crash!" ); + m_aAccessors.insert( PropertyAccessors::value_type( rProperty.Handle, rAccessor ) ); + + DBG_ASSERT( ( rAccessor->isWriteable() == true ) + == ( ( rProperty.Attributes & com::sun::star::beans::PropertyAttribute::READONLY ) == 0 ), + "PropertySetBase::registerProperty: inconsistence!" ); + + m_aProperties.push_back( rProperty ); +} + +void PropertySetBase::notifyAndCachePropertyValue( sal_Int32 nHandle ) +{ + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + + PropertyValueCache::iterator aPos = m_aCache.find( nHandle ); + if ( aPos == m_aCache.end() ) + { // method has never before been invoked for this property + try + { + // determine the type of this property + ::cppu::IPropertyArrayHelper& rPropertyMetaData = getInfoHelper(); + ::rtl::OUString sPropName; + OSL_VERIFY( rPropertyMetaData.fillPropertyMembersByHandle( &sPropName, NULL, nHandle ) ); + Property aProperty = rPropertyMetaData.getPropertyByName( sPropName ); + // default construct a value of this type + Any aEmptyValue( NULL, aProperty.Type ); + // insert into the cache + aPos = m_aCache.insert( PropertyValueCache::value_type( nHandle, aEmptyValue ) ).first; + } + catch( Exception& ) + { + DBG_ERROR( "PropertySetBase::notifyAndCachePropertyValue: this is not expected to fail!" ); + } + } + Any aOldValue = aPos->second; + // determine the current value + Any aNewValue; + getFastPropertyValue( aNewValue, nHandle ); + // remember the old value + aPos->second = aNewValue; + + aGuard.clear(); + if ( aNewValue != aOldValue ) + firePropertyChange( nHandle, aNewValue, aOldValue ); +} + +void PropertySetBase::initializePropertyValueCache( sal_Int32 nHandle ) +{ + Any aCurrentValue; + getFastPropertyValue( aCurrentValue, nHandle ); + +#if OSL_DEBUG_LEVEL > 0 + ::std::pair< PropertyValueCache::iterator, bool > aInsertResult = +#endif + m_aCache.insert( PropertyValueCache::value_type( nHandle, aCurrentValue ) ); + DBG_ASSERT( aInsertResult.second, "PropertySetBase::initializePropertyValueCache: already cached a value for this property!" ); +} + +PropertyAccessorBase& PropertySetBase::locatePropertyHandler( sal_Int32 nHandle ) const +{ + PropertyAccessors::const_iterator aPropertyPos = m_aAccessors.find( nHandle ); + DBG_ASSERT( aPropertyPos != m_aAccessors.end() && aPropertyPos->second.get(), + "PropertySetBase::locatePropertyHandler: accessor map is corrupted!" ); + // neither should this be called for handles where there is no accessor, nor should a + // NULL accssor be in the map + return *aPropertyPos->second; +} + +sal_Bool SAL_CALL PropertySetBase::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, + const Any& rValue ) + throw (IllegalArgumentException) +{ + PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); + if ( !rAccessor.approveValue( rValue ) ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + rAccessor.getValue( rOldValue ); + if ( rOldValue != rValue ) + { + rConvertedValue = rValue; // no conversion at all + return sal_True; + } + return sal_False; +} + +void SAL_CALL PropertySetBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) + throw (Exception) +{ + PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); + rAccessor.setValue( rValue ); +} + +void SAL_CALL PropertySetBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); + rAccessor.getValue( rValue ); +} diff --git a/forms/source/xforms/propertysetbase.hxx b/forms/source/xforms/propertysetbase.hxx new file mode 100644 index 000000000000..9e11efe1ebb7 --- /dev/null +++ b/forms/source/xforms/propertysetbase.hxx @@ -0,0 +1,371 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _PROPERTYSETBASE_HXX +#define _PROPERTYSETBASE_HXX + + +// include for parent class +#include <cppuhelper/weak.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <comphelper/propstate.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/proparrhlp.hxx> +#include <rtl/ref.hxx> + +// include for inlined helper function below +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <map> + +// forward declarations for method arguments +namespace com { namespace sun { namespace star { namespace uno { + class Any; + class Type; + class RuntimeException; + template<class T> class Sequence; +} } } } + +/** base class which encapsulates accessing (reading/writing) concrete property values +*/ +class PropertyAccessorBase : public ::rtl::IReference +{ +private: + oslInterlockedCount m_refCount; + +protected: + PropertyAccessorBase() : m_refCount( 0 ) { } + +public: + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const = 0; + virtual void setValue( const com::sun::star::uno::Any& rValue ) = 0; + virtual void getValue( com::sun::star::uno::Any& rValue ) const = 0; + virtual bool isWriteable() const = 0; +}; + + +/** helper class for implementing property accessors through public member functions +*/ +template< typename CLASS, typename VALUE, class WRITER, class READER > +class GenericPropertyAccessor : public PropertyAccessorBase +{ +public: + typedef WRITER Writer; + typedef READER Reader; + +private: + CLASS* m_pInstance; + Writer m_pWriter; + Reader m_pReader; + +public: + GenericPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader ) + :m_pInstance( pInstance ) + ,m_pWriter( pWriter ) + ,m_pReader( pReader ) + { + } + + virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const + { + VALUE aVal; + return ( rValue >>= aVal ); + } + + virtual void setValue( const com::sun::star::uno::Any& rValue ) + { + VALUE aTypedVal = VALUE(); + OSL_VERIFY( rValue >>= aTypedVal ); + (m_pInstance->*m_pWriter)( aTypedVal ); + } + + virtual void getValue( com::sun::star::uno::Any& rValue ) const + { + rValue = com::sun::star::uno::makeAny( (m_pInstance->*m_pReader)() ); + } + + virtual bool isWriteable() const + { + return m_pWriter != NULL; + } +}; + +/** helper class for implementing property accessors via non-UNO methods +*/ +template< typename CLASS, typename VALUE > +class DirectPropertyAccessor + :public GenericPropertyAccessor < CLASS + , VALUE + , void (CLASS::*)( const VALUE& ) + , VALUE (CLASS::*)() const + > +{ +protected: + typedef void (CLASS::*Writer)( const VALUE& ); + typedef VALUE (CLASS::*Reader)() const; +public: + DirectPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader ) + :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader ) + { + } +}; + +/** helper class for implementing non-UNO accessors to a boolean property +*/ +template< typename CLASS, typename DUMMY > +class BooleanPropertyAccessor + :public GenericPropertyAccessor < CLASS + , bool + , void (CLASS::*)( bool ) + , bool (CLASS::*)() const + > +{ +protected: + typedef void (CLASS::*Writer)( bool ); + typedef bool (CLASS::*Reader)() const; +public: + BooleanPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader ) + :GenericPropertyAccessor< CLASS, bool, Writer, Reader >( pInstance, pWriter, pReader ) + { + } +}; + +/** helper class for implementing property accessors via UNO methods +*/ +template< typename CLASS, typename VALUE > +class APIPropertyAccessor + :public GenericPropertyAccessor < CLASS + , VALUE + , void (SAL_CALL CLASS::*)( const VALUE& ) + , VALUE (SAL_CALL CLASS::*)() + > +{ +protected: + typedef void (SAL_CALL CLASS::*Writer)( const VALUE& ); + typedef VALUE (SAL_CALL CLASS::*Reader)(); +public: + APIPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader ) + :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader ) + { + } +}; + +/** bridges two XPropertySet helper implementations + + The <type scope="comphelper">OStatefulPropertySet</type> (basically, the + <type scope="cppu">OPropertySetHelper</type>) implements a comprehensive framework + for property sets, including property change notifications. + However, it lacks some easy possibilities to declare the supported properties. + Other helper structs and classes allow for this, but are lacking needed features + such as property change notifications. + + The <type>PropertySetBase</type> bridges various implementations, + so you have the best of both worlds. + */ +class PropertySetBase : public ::comphelper::OStatefulPropertySet +{ +private: + typedef com::sun::star::uno::Any Any_t; + + typedef ::std::map< const sal_Int32, ::rtl::Reference< PropertyAccessorBase > > PropertyAccessors; + typedef ::std::vector< ::com::sun::star::beans::Property > PropertyArray; + typedef ::std::map< const sal_Int32, Any_t > PropertyValueCache; + + PropertyArray m_aProperties; + cppu::IPropertyArrayHelper* m_pProperties; + PropertyAccessors m_aAccessors; + PropertyValueCache m_aCache; + +protected: + PropertySetBase(); + virtual ~PropertySetBase(); + + /** registers a new property to be supported by this instance + @param rProperty + the descriptor for the to-be-supported property + @param rAccessor + an instance which is able to provide read and possibly write access to + the property. + @precond + Must not be called after any of the property set related UNO interfaces + has been used. Usually, you will do a number of <member>registerProperty</member> + calls in the constructor of your class. + */ + void registerProperty( + const com::sun::star::beans::Property& rProperty, + const ::rtl::Reference< PropertyAccessorBase >& rAccessor + ); + + /** notifies a change in a given property value, if necessary + + The necessity of the notification is determined by a cached value for the given + property. Caching happens after notification. + + That is, when you call <member>notifyAndCachePropertyValue</member> for the first time, + a value for the given property is default constructed, and considered to be the "old value". + If this value differs from the current value, then this change is notified to all interested + listeners. Finally, the current value is remembered. + + Subsequent calls to <member>notifyAndCachePropertyValue</member> use the remembered value as + "old value", and from then on behave as the first call. + + @param nHandle + the handle of the property. Must denote a property supported by this instance, i.e. + one previously registered via <member>registerProperty</member>. + + @precond + our ref count must not be 0. The reason is that during this method's execution, + the instance might be acquired and released, which would immediately destroy + the instance if it has a ref count of 0. + + @seealso initializePropertyValueCache + */ + void notifyAndCachePropertyValue( sal_Int32 nHandle ); + + /** initializes the property value cache for the given property, with its current value + + Usually used to initialize the cache with values which are different from default + constructed values. Say you have a boolean property whose initial state + is <TRUE/>. Say you call <member>notifyAndCachePropertyValue</member> the first time: it will + default construct the "old value" for this property as <FALSE/>, and thus <b>not</b> do + any notifications if the "current value" is also <FALSE/> - which might be wrong, since + the guessing of the "old value" differed from the real initial value which was <TRUE/>. + + Too confusing? Okay, than just call this method for every property you have. + + @param nHandle + the handle of the property. Must denote a property supported by this instance, i.e. + one previously registered via <member>registerProperty</member>. + @param rValue + the value to cache + @seealso notifyAndCachePropertyValue + */ + void initializePropertyValueCache( sal_Int32 nHandle ); + + /// OPropertysetHelper methods + virtual sal_Bool SAL_CALL convertFastPropertyValue( Any_t& rConvertedValue, Any_t& rOldValue, sal_Int32 nHandle, const Any_t& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any_t& rValue ) + throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue( Any_t& rValue, sal_Int32 nHandle ) const; + + virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + +public: + /// helper struct for granting selective access to some notification-related methods + struct NotifierAccess { friend struct PropertyChangeNotifier; private: NotifierAccess() { } }; + /** retrieves the current property value for the given handle + @param nHandle + the handle of the property. Must denote a property supported by this instance, i.e. + one previously registered via <member>registerProperty</member>. + @see registerProperty + */ + inline void getCurrentPropertyValueByHandle( sal_Int32 nHandle, Any_t& /* [out] */ rValue, const NotifierAccess& ) const + { + getFastPropertyValue( rValue, nHandle ); + } + + /** notifies a change in a given property to all interested listeners + */ + inline void notifyPropertyChange( sal_Int32 nHandle, const Any_t& rOldValue, const Any_t& rNewValue, const NotifierAccess& ) const + { + const_cast< PropertySetBase* >( this )->firePropertyChange( nHandle, rNewValue, rOldValue ); + } + + using ::comphelper::OStatefulPropertySet::getFastPropertyValue; + +private: + /** locates a property given by handle + @param nHandle + the handle of the property. Must denote a property supported by this instance, i.e. + one previously registered via <member>registerProperty</member>. + @see registerProperty + */ + PropertyAccessorBase& locatePropertyHandler( sal_Int32 nHandle ) const; +}; + +/** a helper class for notifying property changes in a <type>PropertySetBase</type> instance. + + You can create an instance of this class on the stack of a method which is to programmatically + change the value of a property. In its constructor, the instance will acquire the current property + value, and in its destructor, it will notify the change of this property's value (if necessary). + + You do not need this class if you are modifying property values by using the X(Fast|Multi)PropertSet + methods, since those already care for property notifications. You only need it if you're changing + the internal representation of your property directly. + + Also note that usually, notifications in the UNO world should be done without a locked mutex. So + if you use this class in conjunction with a <type>MutexGuard</type>, ensure that you <b>first</b> + instantiate the <type>PropertyChangeNotifier</type>, and <b>then</b> the <type>MutexGuard</type>, + so your mutex is released before the notification happens. +*/ +struct PropertyChangeNotifier +{ +private: + const PropertySetBase& m_rPropertySet; + sal_Int32 m_nHandle; + com::sun::star::uno::Any m_aOldValue; + +public: + /** constructs a PropertyChangeNotifier + @param rPropertySet + the property set implementation whose property is going to be changed. Note + that this property set implementation must live at least as long as the + PropertyChangeNotifier instance does. + @param nHandle + the handle of the property which is going to be changed. Must be a valid property + handle for the given <arg>rPropertySet</arg> + */ + inline PropertyChangeNotifier( const PropertySetBase& rPropertySet, sal_Int32 nHandle ) + :m_rPropertySet( rPropertySet ) + ,m_nHandle( nHandle ) + { + m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, m_aOldValue, PropertySetBase::NotifierAccess() ); + } + inline ~PropertyChangeNotifier() + { + com::sun::star::uno::Any aNewValue; + m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, aNewValue, PropertySetBase::NotifierAccess() ); + if ( aNewValue != m_aOldValue ) + { + m_rPropertySet.notifyPropertyChange( m_nHandle, m_aOldValue, aNewValue, PropertySetBase::NotifierAccess() ); + } + } +}; + + +#define PROPERTY_FLAGS( NAME, TYPE, FLAG ) com::sun::star::beans::Property( \ + ::rtl::OUString( #NAME, sizeof( #NAME ) - 1, RTL_TEXTENCODING_ASCII_US ), \ + HANDLE_##NAME, getCppuType( static_cast< TYPE* >( NULL ) ), FLAG ) +#define PROPERTY( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND ) +#define PROPERTY_RO( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND | com::sun::star::beans::PropertyAttribute::READONLY ) + +#endif diff --git a/forms/source/xforms/resourcehelper.cxx b/forms/source/xforms/resourcehelper.cxx new file mode 100644 index 000000000000..138c64851dce --- /dev/null +++ b/forms/source/xforms/resourcehelper.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "resourcehelper.hxx" +#include "frm_resource.hxx" + +#include <rtl/ustring.hxx> +#include <tools/string.hxx> + +using rtl::OUString; + +#define OUSTRING(x) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x)) + +namespace xforms +{ + +OUString getResource( sal_uInt16 nResourceId ) +{ + return getResource( nResourceId, OUString(), OUString(), OUString() ); +} + +OUString getResource( sal_uInt16 nResourceId, + const OUString& rInfo1 ) +{ + return getResource( nResourceId, rInfo1, OUString(), OUString() ); +} + +OUString getResource( sal_uInt16 nResourceId, + const OUString& rInfo1, + const OUString& rInfo2 ) +{ + return getResource( nResourceId, rInfo1, rInfo2, OUString() ); +} + +OUString getResource( sal_uInt16 nResourceId, + const OUString& rInfo1, + const OUString& rInfo2, + const OUString& rInfo3 ) +{ + OUString sResource = frm::ResourceManager::loadString( nResourceId ); + OSL_ENSURE( sResource.getLength() > 0, "resource not found?" ); + + // use old style String class for search and replace, so we don't have to + // code this again. + String sString( sResource ); + sString.SearchAndReplaceAll( String(OUSTRING("$1")), String(rInfo1) ); + sString.SearchAndReplaceAll( String(OUSTRING("$2")), String(rInfo2) ); + sString.SearchAndReplaceAll( String(OUSTRING("$3")), String(rInfo3) ); + return OUString( sString ); +} + +} // namespace xforms diff --git a/forms/source/xforms/resourcehelper.hxx b/forms/source/xforms/resourcehelper.hxx new file mode 100644 index 000000000000..a312c5749c50 --- /dev/null +++ b/forms/source/xforms/resourcehelper.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _RESOURCEHELPER_HXX +#define _RESOURCEHELPER_HXX + +// include resource IDs +#include <frm_resource.hrc> + +#include <sal/types.h> + +namespace rtl { class OUString; } + +namespace xforms +{ + /// get a resource string for the current language + rtl::OUString getResource( sal_uInt16 ); + + // overloaded: get a resource string, and substitute parameters + rtl::OUString getResource( sal_uInt16, const rtl::OUString& ); + rtl::OUString getResource( sal_uInt16, const rtl::OUString&, + const rtl::OUString& ); + rtl::OUString getResource( sal_uInt16, const rtl::OUString&, + const rtl::OUString&, + const rtl::OUString& ); + +} // namespace + +#endif diff --git a/forms/source/xforms/submission.cxx b/forms/source/xforms/submission.cxx new file mode 100644 index 000000000000..b61ad498933e --- /dev/null +++ b/forms/source/xforms/submission.cxx @@ -0,0 +1,719 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "submission.hxx" + +#include "model.hxx" +#include "binding.hxx" +#include "mip.hxx" +#include "evaluationcontext.hxx" +#include "unohelper.hxx" +#include "submission/submission_put.hxx" +#include "submission/submission_post.hxx" +#include "submission/submission_get.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/xforms/XModel.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/xml/xpath/XPathObjectType.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/task/XInteractionContinuation.hpp> +#include <com/sun/star/xforms/InvalidDataOnSubmitException.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/interaction.hxx> +#include <unotools/processfactory.hxx> +#include <memory> + + + + +using rtl::OUString; +using rtl::OUStringBuffer; +using com::sun::star::beans::UnknownPropertyException; +using com::sun::star::beans::PropertyVetoException; +using com::sun::star::lang::IllegalArgumentException; +using com::sun::star::util::VetoException; +using com::sun::star::form::submission::XSubmissionVetoListener; +using com::sun::star::lang::WrappedTargetException; +using com::sun::star::lang::NoSupportException; +using com::sun::star::task::XInteractionHandler; +using com::sun::star::task::XInteractionRequest; +using com::sun::star::task::XInteractionContinuation; +using com::sun::star::xforms::XModel; +using com::sun::star::xforms::InvalidDataOnSubmitException; +using com::sun::star::container::XNameAccess; +using com::sun::star::xml::xpath::XXPathObject; +using com::sun::star::xml::xpath::XPathObjectType; +using com::sun::star::frame::XFrame; +using xforms::Submission; +using xforms::Model; +using xforms::MIP; +using std::auto_ptr; + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::xml::dom; + +Submission::Submission() : + msID(), + msBind(), + maRef(), + msAction(), + msMethod(), + msVersion(), + mbIndent(), + msMediaType(), + msEncoding(), + mbOmitXmlDeclaration(), + mbStandalone(), + msCDataSectionElement(), + msReplace( OUSTRING("none") ), + msSeparator(), + msIncludeNamespacePrefixes(), + m_aFactory(utl::getProcessServiceFactory()) +{ + initializePropertySet(); +} + +Submission::~Submission() throw() +{ +} + +Reference<XModel> Submission::getModel() const +{ + return mxModel; +} + +void Submission::setModel( const Reference<XModel>& xModel ) +{ + mxModel = xModel; +} + +OUString Submission::getID() const +{ + return msID; +} + +void Submission::setID( const OUString& sID ) +{ + msID = sID; +} + +OUString Submission::getBind() const +{ + return msBind; +} + +void Submission::setBind( const OUString& sBind ) +{ + msBind = sBind; +} + +OUString Submission::getRef() const +{ + return maRef.getExpression(); +} + +void Submission::setRef( const OUString& sRef ) +{ + maRef.setExpression( sRef ); +} + +OUString Submission::getAction() const +{ + return msAction; +} + +void Submission::setAction( const OUString& sAction ) +{ + msAction = sAction; +} + +OUString Submission::getMethod() const +{ + return msMethod; +} + +void Submission::setMethod( const OUString& sMethod ) +{ + msMethod = sMethod; +} + +OUString Submission::getVersion() const +{ + return msVersion; +} + +void Submission::setVersion( const OUString& sVersion ) +{ + msVersion = sVersion; +} + +bool Submission::getIndent() const +{ + return mbIndent; +} + +void Submission::setIndent( bool bIndent ) +{ + mbIndent = bIndent; +} + +OUString Submission::getMediaType() const +{ + return msMediaType; +} + +void Submission::setMediaType( const OUString& sMediaType ) +{ + msMediaType = sMediaType; +} + +OUString Submission::getEncoding() const +{ + return msEncoding; +} + +void Submission::setEncoding( const OUString& sEncoding ) +{ + msEncoding = sEncoding; +} + +bool Submission::getOmitXmlDeclaration() const +{ + return mbOmitXmlDeclaration; +} + +void Submission::setOmitXmlDeclaration( bool bOmitXmlDeclaration ) +{ + mbOmitXmlDeclaration = bOmitXmlDeclaration; +} + +bool Submission::getStandalone() const +{ + return mbStandalone; +} + +void Submission::setStandalone( bool bStandalone ) +{ + mbStandalone = bStandalone; +} + +OUString Submission::getCDataSectionElement() const +{ + return msCDataSectionElement; +} + +void Submission::setCDataSectionElement( const OUString& sCDataSectionElement ) +{ + msCDataSectionElement = sCDataSectionElement; +} + +OUString Submission::getReplace() const +{ + return msReplace; +} + +void Submission::setReplace( const OUString& sReplace ) +{ + msReplace = sReplace; +} + +OUString Submission::getSeparator() const +{ + return msSeparator; +} + +void Submission::setSeparator( const OUString& sSeparator ) +{ + msSeparator = sSeparator; +} + +Sequence< OUString > Submission::getIncludeNamespacePrefixes() const +{ + return msIncludeNamespacePrefixes; +} + +void Submission::setIncludeNamespacePrefixes( const Sequence< OUString >& rIncludeNamespacePrefixes ) +{ + msIncludeNamespacePrefixes = rIncludeNamespacePrefixes; +} + +bool Submission::doSubmit( const Reference< XInteractionHandler >& xHandler ) +{ + liveCheck(); + + // construct XXPathObject for submission doc; use bind in preference of ref + EvaluationContext aEvalContext; + ComputedExpression aExpression; + if( msBind.getLength() != 0 ) + { + Binding* pBinding = Binding::getBinding( mxModel->getBinding(msBind) ); + if( pBinding != NULL ) + { + aExpression.setExpression( pBinding->getBindingExpression() ); + aEvalContext = pBinding->getEvaluationContext(); + } + // TODO: else: illegal binding name -> raise error + } + else if( maRef.getExpression().getLength() != 0 ) + { + aExpression.setExpression( maRef.getExpression() ); + aEvalContext = Model::getModel( mxModel )->getEvaluationContext(); + } + else + { + aExpression.setExpression( OUSTRING( "/" ) ); + aEvalContext = Model::getModel( mxModel )->getEvaluationContext(); + } + aExpression.evaluate( aEvalContext ); + Reference<XXPathObject> xResult = aExpression.getXPath(); + OSL_ENSURE( xResult.is(), "no result?" ); + + // early out if we have not obtained any result + if( ! xResult.is() ) + return false; + + + // Reference< XNodeList > aList = xResult->getNodeList(); + OUString aMethod = getMethod(); + + // strip whitespace-only text node for get submission + Reference< XDocumentFragment > aFragment = createSubmissionDocument( + xResult, aMethod.equalsIgnoreAsciiCaseAscii("get")); + + // submit result; set encoding, etc. + auto_ptr<CSubmission> xSubmission; + if (aMethod.equalsIgnoreAsciiCaseAscii("PUT")) + xSubmission = auto_ptr<CSubmission>( + new CSubmissionPut( getAction(), aFragment)); + else if (aMethod.equalsIgnoreAsciiCaseAscii("post")) + xSubmission = auto_ptr<CSubmission>( + new CSubmissionPost( getAction(), aFragment)); + else if (aMethod.equalsIgnoreAsciiCaseAscii("get")) + xSubmission = auto_ptr<CSubmission>( + new CSubmissionGet( getAction(), aFragment)); + else + { + OSL_ENSURE(sal_False, "Unsupported xforms submission method"); + return false; + } + + xSubmission->setEncoding(getEncoding()); + CSubmission::SubmissionResult aResult = xSubmission->submit( xHandler ); + + if (aResult == CSubmission::SUCCESS) + { + Reference< XDocument > aInstanceDoc = getInstanceDocument(xResult); + aResult = xSubmission->replace(getReplace(), aInstanceDoc, Reference< XFrame >()); + } + + return ( aResult == CSubmission::SUCCESS ); +} + +Sequence<sal_Int8> Submission::getUnoTunnelID() +{ + static cppu::OImplementationId aImplementationId; + return aImplementationId.getImplementationId(); +} + +Submission* Submission::getSubmission( + const Reference<XPropertySet>& xPropertySet ) +{ + Reference<XUnoTunnel> xTunnel( xPropertySet, UNO_QUERY ); + return xTunnel.is() + ? reinterpret_cast<Submission*>( + xTunnel->getSomething( getUnoTunnelID() ) ) + : NULL; +} + + + + + + +void Submission::liveCheck() + throw( RuntimeException ) +{ + bool bValid = mxModel.is(); + + if( ! bValid ) + throw RuntimeException(); +} + +Model* Submission::getModelImpl() const +{ + Model* pModel = NULL; + if( mxModel.is() ) + pModel = Model::getModel( mxModel ); + return pModel; +} + + +// +// Property-Set implementation +// + +#define HANDLE_ID 0 +#define HANDLE_Bind 1 +#define HANDLE_Ref 2 +#define HANDLE_Action 3 +#define HANDLE_Method 4 +#define HANDLE_Version 5 +#define HANDLE_Indent 6 +#define HANDLE_MediaType 7 +#define HANDLE_Encoding 8 +#define HANDLE_OmitXmlDeclaration 9 +#define HANDLE_Standalone 10 +#define HANDLE_CDataSectionElement 11 +#define HANDLE_Replace 12 +#define HANDLE_Separator 13 +#define HANDLE_IncludeNamespacePrefixes 14 +#define HANDLE_Model 15 + +#define REGISTER_PROPERTY( property, type ) \ + registerProperty( PROPERTY( property, type ), \ + new DirectPropertyAccessor< Submission, type >( this, &Submission::set##property, &Submission::get##property ) ); + +#define REGISTER_PROPERTY_BOOL( property ) \ + registerProperty( PROPERTY( property, bool ), \ + new BooleanPropertyAccessor< Submission, bool >( this, &Submission::set##property, &Submission::get##property ) ); + +void Submission::initializePropertySet() +{ + REGISTER_PROPERTY ( ID, OUString ); + REGISTER_PROPERTY ( Bind, OUString ); + REGISTER_PROPERTY ( Ref, OUString ); + REGISTER_PROPERTY ( Action, OUString ); + REGISTER_PROPERTY ( Method, OUString ); + REGISTER_PROPERTY ( Version, OUString ); + REGISTER_PROPERTY_BOOL( Indent ); + REGISTER_PROPERTY ( MediaType, OUString ); + REGISTER_PROPERTY ( Encoding, OUString ); + REGISTER_PROPERTY_BOOL( OmitXmlDeclaration ); + REGISTER_PROPERTY_BOOL( Standalone ); + REGISTER_PROPERTY ( CDataSectionElement, OUString ); + REGISTER_PROPERTY ( Replace, OUString ); + REGISTER_PROPERTY ( Separator, OUString ); + REGISTER_PROPERTY ( IncludeNamespacePrefixes, Sequence< OUString > ); + REGISTER_PROPERTY ( Model, Reference<XModel> ); + + initializePropertyValueCache( HANDLE_Indent ); + initializePropertyValueCache( HANDLE_OmitXmlDeclaration ); + initializePropertyValueCache( HANDLE_Standalone ); +} + +sal_Bool SAL_CALL Submission::convertFastPropertyValue( + Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue ) + throw ( IllegalArgumentException ) +{ + if ( nHandle == HANDLE_IncludeNamespacePrefixes ) + { + // for convinience reasons (????), we accept a string which contains + // a comma-separated list of namespace prefixes + ::rtl::OUString sTokenList; + if ( rValue >>= sTokenList ) + { + std::vector< OUString > aPrefixes; + sal_Int32 p = 0; + while ( p >= 0 ) + aPrefixes.push_back( sTokenList.getToken( 0, ',', p ) ); + + Sequence< ::rtl::OUString > aConvertedPrefixes( &aPrefixes[0], aPrefixes.size() ); + return PropertySetBase::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, makeAny( aConvertedPrefixes ) ); + } + } + + return PropertySetBase::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); +} + +OUString SAL_CALL Submission::getName() + throw( RuntimeException ) +{ + return getID(); +} + +void SAL_CALL Submission::setName( const OUString& sID ) + throw( RuntimeException ) +{ + setID( sID ); +} + + + +sal_Int64 SAL_CALL Submission::getSomething( + const Sequence<sal_Int8>& aId ) + throw( RuntimeException ) +{ + return ( aId == getUnoTunnelID() ) ? reinterpret_cast<sal_Int64>(this) : 0; +} + + +OUString lcl_message( const OUString& rID, const OUString& rText ) +{ + OUStringBuffer aMessage; + aMessage.append( OUSTRING("XForms submission '") ); + aMessage.append( rID ); + aMessage.append( OUSTRING("' failed") ); + aMessage.append( rText ); + aMessage.append( OUSTRING(".") ); + return aMessage.makeStringAndClear(); +} + +void SAL_CALL Submission::submitWithInteraction( + const Reference<XInteractionHandler>& _rxHandler ) + throw ( VetoException, + WrappedTargetException, + RuntimeException ) +{ + // as long as this class is not really threadsafe, we need to copy + // the members we're interested in + Reference< XModel > xModel( mxModel ); + ::rtl::OUString sID( msID ); + + if ( !xModel.is() || !msID.getLength() ) + throw RuntimeException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "This is not a valid submission object." ) ), + *this + ); + + Model* pModel = Model::getModel( xModel ); + OSL_ENSURE( pModel != NULL, "illegal model?" ); + + // #i36765# #i47248# warning on submission of illegal data + // check for validity (and query user if invalid) + bool bValid = pModel->isValid(); + if( ! bValid ) + { + InvalidDataOnSubmitException aInvalidDataException( + lcl_message(sID, OUSTRING(" due to invalid data") ), *this ); + + if( _rxHandler.is() ) + { + // labouriously create interaction request + comphelper::OInteractionRequest* pRequest + = new comphelper::OInteractionRequest( + makeAny( aInvalidDataException ) ); + Reference<XInteractionRequest> xRequest = pRequest; + + comphelper::OInteractionApprove* pContinue + = new comphelper::OInteractionApprove(); + Reference<XInteractionContinuation> xContinue = pContinue; + pRequest->addContinuation( xContinue ); + + comphelper::OInteractionDisapprove* pCancel + = new comphelper::OInteractionDisapprove(); + Reference<XInteractionContinuation> xCancel = pCancel; + pRequest->addContinuation( xCancel ); + + // ask the handler... + _rxHandler->handle( xRequest ); + OSL_ENSURE( pContinue->wasSelected() || pCancel->wasSelected(), + "handler didn't select" ); + + // and continue, if user chose 'continue' + if( pContinue->wasSelected() ) + bValid = true; + } + + // abort if invalid (and user didn't tell us to continue) + if( ! bValid ) + throw aInvalidDataException; + } + + // attempt submission + bool bResult = false; + try + { + bResult = doSubmit( _rxHandler ); + } + catch( const VetoException& ) + { + OSL_ENSURE( sal_False, "Model::submit: Hmm. How can a single submission have a veto right?" ); + // allowed to leave + throw; + } + catch( const Exception& e ) + { + // exception caught: re-throw as wrapped target exception + throw WrappedTargetException( + lcl_message( sID, OUSTRING(" due to exception being thrown") ), + *this, makeAny( e ) ); + } + + if( bResult ) + { + mxModel->rebuild(); + } + else + { + // other failure: throw wrapped target exception, too. + throw WrappedTargetException( + lcl_message( sID, OUString() ), *this, Any() ); + } +} + +void SAL_CALL Submission::submit( ) throw ( VetoException, WrappedTargetException, RuntimeException ) +{ + submitWithInteraction( NULL ); +} + +void SAL_CALL Submission::addSubmissionVetoListener( const Reference< XSubmissionVetoListener >& /*listener*/ ) throw (NoSupportException, RuntimeException) +{ + // TODO + throw NoSupportException(); +} + +void SAL_CALL Submission::removeSubmissionVetoListener( const Reference< XSubmissionVetoListener >& /*listener*/ ) throw (NoSupportException, RuntimeException) +{ + // TODO + throw NoSupportException(); +} + +static sal_Bool _isIgnorable(const Reference< XNode >& aNode) +{ + // ignore whitespace-only textnodes + if (aNode->getNodeType() == NodeType_TEXT_NODE) + { + OUString aTrimmedValue = aNode->getNodeValue().trim(); + if (aTrimmedValue.getLength() == 0) return sal_True; + } + + return sal_False; +} + +// recursively copy relevant nodes from A to B +static void _cloneNodes(Model& aModel, const Reference< XNode >& dstParent, const Reference< XNode >& source, sal_Bool bRemoveWSNodes) +{ + if (!source.is()) return; + + Reference< XNode > cur = source; + Reference< XDocument > dstDoc = dstParent->getOwnerDocument(); + Reference< XNode > imported; + + if (cur.is()) + { + // is this node relevant? + MIP mip = aModel.queryMIP(cur); + if(mip.isRelevant() && !(bRemoveWSNodes && _isIgnorable(cur))) + { + imported = dstDoc->importNode(cur, sal_False); + imported = dstParent->appendChild(imported); + // append source children to new imported parent + for( cur = cur->getFirstChild(); cur.is(); cur = cur->getNextSibling() ) + _cloneNodes(aModel, imported, cur, bRemoveWSNodes); + } + } +} +Reference< XDocument > Submission::getInstanceDocument(const Reference< XXPathObject >& aObj) +{ + using namespace com::sun::star::xml::xpath; + // result + Reference< XDocument > aDocument; + + if (aObj->getObjectType() == XPathObjectType_XPATH_NODESET) + { + Reference< XNodeList > aList = aObj->getNodeList(); + if (aList->getLength() > 0) + aDocument = aList->item(0)->getOwnerDocument(); + } + return aDocument; +} + +Reference< XDocumentFragment > Submission::createSubmissionDocument(const Reference< XXPathObject >& aObj, sal_Bool bRemoveWSNodes) +{ + using namespace com::sun::star::xml::xpath; + Reference< XDocumentBuilder > aDocBuilder(m_aFactory->createInstance( + OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")), UNO_QUERY); + Reference< XDocument > aDocument = aDocBuilder->newDocument(); + Reference< XDocumentFragment > aFragment = aDocument->createDocumentFragment(); + + // + if (aObj->getObjectType() == XPathObjectType_XPATH_NODESET) + { + Reference< XNodeList > aList = aObj->getNodeList(); + Reference< XNode > aListItem; + for (sal_Int32 i=0; i < aList->getLength(); i++) + { + aListItem = aList->item(i); + if (aListItem->getNodeType()==NodeType_DOCUMENT_NODE) + aListItem = Reference< XNode >( + (Reference< XDocument >(aListItem, UNO_QUERY))->getDocumentElement(), UNO_QUERY); + // copy relevant nodes from instance into fragment + _cloneNodes(*getModelImpl(), Reference< XNode >(aFragment, UNO_QUERY), aListItem, bRemoveWSNodes); + } + } + return aFragment; +} + +// some forwarding: XPropertySet is implemented in our base class, +// but also available as base of XSubmission +Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL Submission::getPropertySetInfo( ) throw(RuntimeException) +{ + return PropertySetBase::getPropertySetInfo(); +} +void SAL_CALL Submission::setPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + PropertySetBase::setPropertyValue( aPropertyName, aValue ); +} +Any SAL_CALL Submission::getPropertyValue( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + return PropertySetBase::getPropertyValue( PropertyName ); +} +void SAL_CALL Submission::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + PropertySetBase::addPropertyChangeListener( aPropertyName, xListener ); +} +void SAL_CALL Submission::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + PropertySetBase::removePropertyChangeListener( aPropertyName, aListener ); +} +void SAL_CALL Submission::addVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + PropertySetBase::addVetoableChangeListener( PropertyName, aListener ); +} +void SAL_CALL Submission::removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + PropertySetBase::removeVetoableChangeListener( PropertyName, aListener ); +} + diff --git a/forms/source/xforms/submission.hxx b/forms/source/xforms/submission.hxx new file mode 100644 index 000000000000..36a687a3d5e5 --- /dev/null +++ b/forms/source/xforms/submission.hxx @@ -0,0 +1,276 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SUBMISSION_HXX +#define _SUBMISSION_HXX + + +// includes for parent classes +#include <cppuhelper/implbase2.hxx> +#include <propertysetbase.hxx> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/xml/dom/events/XEventListener.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xforms/XSubmission.hpp> + +// includes for member variables +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <computedexpression.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +// forward declaractions +namespace com { namespace sun { namespace star { + namespace xforms { class XModel; } + namespace uno { class Any; } + namespace beans { class UnknownPropertyException; + class PropertyVetoException; } + namespace lang { class IllegalArgumentException; + class WrappedTargetException; } +} } } +namespace xforms { class Model; } + + +namespace xforms +{ + +/** An XForms submission. + * + * See http://www.w3.org/TR/xforms/ for more information. + */ +typedef cppu::ImplInheritanceHelper2< + PropertySetBase, + com::sun::star::lang::XUnoTunnel, + com::sun::star::xforms::XSubmission +> Submission_t; + +class Submission : public Submission_t +{ + // submission properties + rtl::OUString msID; + rtl::OUString msBind; + ComputedExpression maRef; + rtl::OUString msAction; + rtl::OUString msMethod; + rtl::OUString msVersion; + bool mbIndent; + rtl::OUString msMediaType; + rtl::OUString msEncoding; + bool mbOmitXmlDeclaration; + bool mbStandalone; + rtl::OUString msCDataSectionElement; + rtl::OUString msReplace; + rtl::OUString msSeparator; + com::sun::star::uno::Sequence< rtl::OUString > msIncludeNamespacePrefixes; + +private: + + /// the Model to which this Submission belongs; may be NULL + com::sun::star::uno::Reference<com::sun::star::xforms::XModel> mxModel; + + // this will extract the document from the model that will be submitted + com::sun::star::uno::Reference< com::sun::star::xml::dom::XDocumentFragment > + createSubmissionDocument(const com::sun::star::uno::Reference< com::sun::star::xml::xpath::XXPathObject >& aObject, + sal_Bool bRemoveWSNodes = sal_False); + com::sun::star::uno::Reference< com::sun::star::xml::dom::XDocument > + getInstanceDocument(const com::sun::star::uno::Reference< com::sun::star::xml::xpath::XXPathObject >& aObject); + + com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory > m_aFactory; +public: + Submission(); + virtual ~Submission() throw(); + + // + // property methods: get/set value + // + + /// get XForms model + com::sun::star::uno::Reference<com::sun::star::xforms::XModel> + getModel() const; + + /// set XForms model + void setModel( + const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& ); + + rtl::OUString getID() const; /// get ID for this submission + void setID( const rtl::OUString& ); /// set ID for this submission + + rtl::OUString getBind() const; + void setBind( const rtl::OUString& ); + + rtl::OUString getRef() const; + void setRef( const rtl::OUString& ); + + rtl::OUString getAction() const; + void setAction( const rtl::OUString& ); + + rtl::OUString getMethod() const; + void setMethod( const rtl::OUString& ); + + rtl::OUString getVersion() const; + void setVersion( const rtl::OUString& ); + + bool getIndent() const; + void setIndent( bool ); + + rtl::OUString getMediaType() const; + void setMediaType( const rtl::OUString& ); + + rtl::OUString getEncoding() const; + void setEncoding( const rtl::OUString& ); + + bool getOmitXmlDeclaration() const; + void setOmitXmlDeclaration( bool ); + + bool getStandalone() const; + void setStandalone( bool ); + + rtl::OUString getCDataSectionElement() const; + void setCDataSectionElement( const rtl::OUString& ); + + rtl::OUString getReplace() const; + void setReplace( const rtl::OUString& ); + + rtl::OUString getSeparator() const; + void setSeparator( const rtl::OUString& ); + + com::sun::star::uno::Sequence< rtl::OUString > getIncludeNamespacePrefixes() const; + void setIncludeNamespacePrefixes( const com::sun::star::uno::Sequence< rtl::OUString >& ); + + + /** perform the submission + * @returns if submission was successful */ + bool doSubmit( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler ); + + + /// release the model (note: Binding is unusable without model) + void releaseModel(); + + + // helpers for UNO tunnel + static com::sun::star::uno::Sequence<sal_Int8> getUnoTunnelID(); + static Submission* getSubmission( const com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& ); + + + +private: + + /// check whether object is live, and throw suitable exception if not + /// (to be used be API methods before acting on the object) + void liveCheck() + throw( com::sun::star::uno::RuntimeException ); + + /// get the model implementation + xforms::Model* getModelImpl() const; + xforms::Model* getModelImpl( const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& xModel ) const; + + + +protected: + + // + // XPropertySet & friends: + // implement abstract methods from PropertySetHelper + // + + virtual sal_Bool SAL_CALL convertFastPropertyValue( + com::sun::star::uno::Any& rConvertedValue, + com::sun::star::uno::Any& rOldValue, + sal_Int32 nHandle, + const com::sun::star::uno::Any& rValue ) + throw ( com::sun::star::lang::IllegalArgumentException ); + +private: + void initializePropertySet(); + + +public: + + // + // XNamed: + // get/set name + // + + virtual rtl::OUString SAL_CALL getName() + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setName( const rtl::OUString& ) + throw( com::sun::star::uno::RuntimeException ); + + + + // + // XUnoTunnel + // + + virtual sal_Int64 SAL_CALL getSomething( + const com::sun::star::uno::Sequence<sal_Int8>& ) + throw( com::sun::star::uno::RuntimeException ); + + + // + // XSubmission + // + + virtual void SAL_CALL submit( ) + throw ( com::sun::star::util::VetoException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL submitWithInteraction( + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler ) + throw ( com::sun::star::util::VetoException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addSubmissionVetoListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener ) + throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSubmissionVetoListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener ) + throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // + // XPropertySet + // (need to disambiguate this) + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); +}; + + +} // namespace xforms + +#endif diff --git a/forms/source/xforms/submission/makefile.mk b/forms/source/xforms/submission/makefile.mk new file mode 100644 index 000000000000..20590cab880b --- /dev/null +++ b/forms/source/xforms/submission/makefile.mk @@ -0,0 +1,57 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=forms +TARGET=xformssubmit + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +.IF "$(SYSTEM_LIBXML)" == "YES" +CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) +.ENDIF + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/serialization_app_xml.obj \ + $(SLO)$/serialization_urlencoded.obj \ + $(SLO)$/submission_post.obj \ + $(SLO)$/submission_put.obj \ + $(SLO)$/submission_get.obj \ + $(SLO)$/replace.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/xforms/submission/replace.cxx b/forms/source/xforms/submission/replace.cxx new file mode 100644 index 000000000000..fa8ca6f383b5 --- /dev/null +++ b/forms/source/xforms/submission/replace.cxx @@ -0,0 +1,145 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include <memory> +#include "submission.hxx" +#include "serialization_app_xml.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/string.hxx> + +#include <unotools/processfactory.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <ucbhelper/content.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::task; +using namespace com::sun::star::xml::dom; + +CSubmission::SubmissionResult CSubmission::replace(const ::rtl::OUString& aReplace, const Reference<XDocument>& aDocument, const Reference<XFrame>& aFrame) +{ + if (!m_aResultStream.is()) + return CSubmission::UNKNOWN_ERROR; + + try { + Reference< XMultiServiceFactory > xFactory = utl::getProcessServiceFactory(); + if (aReplace.equalsIgnoreAsciiCaseAscii("all") || aReplace.equalsIgnoreAsciiCaseAscii("document")) { + Reference< XComponentLoader > xLoader; + if (aFrame.is()) + xLoader = Reference< XComponentLoader >(aFrame, UNO_QUERY); + + if (!xLoader.is()) + xLoader = Reference< XComponentLoader >(xFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY_THROW); + + // open the stream from the result... + // build media descriptor + Sequence< PropertyValue > descriptor(2); + descriptor[0] = PropertyValue(::rtl::OUString::createFromAscii( + "InputStream"), -1, makeAny(m_aResultStream), PropertyState_DIRECT_VALUE); + descriptor[1] = PropertyValue(::rtl::OUString::createFromAscii( + "ReadOnly"), -1, makeAny(sal_True), PropertyState_DIRECT_VALUE); + + //::rtl::OUString aURL = ::rtl::OUString::createFromAscii("private:stream"); + ::rtl::OUString aURL = m_aURLObj.GetMainURL(INetURLObject::NO_DECODE); + ::rtl::OUString aTarget = ::rtl::OUString::createFromAscii("_default"); + xLoader->loadComponentFromURL(aURL, aTarget, FrameSearchFlag::ALL, descriptor); + + return CSubmission::SUCCESS; + + } else if (aReplace.equalsIgnoreAsciiCaseAscii("instance")) { + if (aDocument.is()) { + // parse the result stream into a new document + Reference< XDocumentBuilder > xBuilder(xFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")), UNO_QUERY_THROW); + Reference< XDocument > aNewDocument = xBuilder->parse(m_aResultStream); + + if (aNewDocument.is()) { + // and replace the content of the current instance + Reference< XElement > oldRoot = aDocument->getDocumentElement(); + Reference< XElement > newRoot = aNewDocument->getDocumentElement(); + + // aDocument->removeChild(Reference< XNode >(oldRoot, UNO_QUERY_THROW)); + Reference< XNode > aImportedNode = aDocument->importNode(Reference< XNode >(newRoot, UNO_QUERY_THROW), sal_True); + Reference< XNode >(aDocument, UNO_QUERY_THROW)->replaceChild(aImportedNode, Reference< XNode >(oldRoot, UNO_QUERY_THROW)); + return CSubmission::SUCCESS; + } else { + return CSubmission::UNKNOWN_ERROR; + } + } else { + // nothing to replace + return CSubmission::UNKNOWN_ERROR; + } + } else if (aReplace.equalsIgnoreAsciiCaseAscii("none")) { + // do nothing \o/ + return CSubmission::SUCCESS; + } + } catch (Exception& e) { + ::rtl::OString aMsg("Exception during replace:\n"); + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8); + OSL_ENSURE(sal_False, aMsg.getStr()); + } + return CSubmission::UNKNOWN_ERROR; +} +::std::auto_ptr< CSerialization > CSubmission::createSerialization(const Reference< XInteractionHandler >& _xHandler,Reference<XCommandEnvironment>& _rOutEnv) +{ + // PUT always uses application/xml + ::std::auto_ptr< CSerialization > apSerialization(new CSerializationAppXML()); + apSerialization->setSource(m_aFragment); + apSerialization->serialize(); + + // create a commandEnvironment and use the default interaction handler + CCommandEnvironmentHelper *pHelper = new CCommandEnvironmentHelper; + if( _xHandler.is() ) + pHelper->m_aInteractionHandler = _xHandler; + else + pHelper->m_aInteractionHandler = CSS::uno::Reference< XInteractionHandler >(m_aFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.task.InteractionHandler")), UNO_QUERY); + OSL_ENSURE(pHelper->m_aInteractionHandler.is(), "failed to create IntreractionHandler"); + + CProgressHandlerHelper *pProgressHelper = new CProgressHandlerHelper; + pHelper->m_aProgressHandler = Reference< XProgressHandler >(pProgressHelper); + + // UCB has ownership of environment... + _rOutEnv = pHelper; + return apSerialization; +} + + + diff --git a/forms/source/xforms/submission/serialization.hxx b/forms/source/xforms/submission/serialization.hxx new file mode 100644 index 000000000000..a3e369bc19b2 --- /dev/null +++ b/forms/source/xforms/submission/serialization.hxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SERIALIZATION_HXX +#define __SERIALIZATION_HXX + +#include <map> + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> + +namespace CSS = com::sun::star; + +/** +Serialize an XObject +*/ + +typedef std::map<rtl::OUString, rtl::OUString> PropMap; + +class CSerialization +{ +protected: + CSS::uno::Reference< CSS::xml::dom::XDocumentFragment > m_aFragment; + PropMap m_properties; + +public: + virtual ~CSerialization() {} + + /** + sets the XObject that is to serialized + */ + virtual void setSource(const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment) + { + m_aFragment = aFragment; + } + + /** + set the properties from the submission element + that control aspects of the serialization + eachs serialization may support individual properties + */ + void setProperties(const CSS::uno::Sequence< CSS::beans::NamedValue >& props) + { + m_properties.clear(); + rtl::OUString aValue; + for (sal_Int32 i=0; i<props.getLength(); i++) + { + if (props[i].Value >>= aValue) + m_properties.insert(PropMap::value_type(props[i].Name, aValue)); + } + } + + /** + start the serialization process + */ + virtual void serialize()=0; + + /** + get the serialized bytes. + reads up to buffer->getLength() bytes and returns the number of + bytes read. + returns -1 on error + */ + virtual CSS::uno::Reference< CSS::io::XInputStream > getInputStream() = 0; + +}; + +#endif diff --git a/forms/source/xforms/submission/serialization_app_xml.cxx b/forms/source/xforms/submission/serialization_app_xml.cxx new file mode 100644 index 000000000000..85cf066d6343 --- /dev/null +++ b/forms/source/xforms/submission/serialization_app_xml.cxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "serialization.hxx" +#include "serialization_app_xml.hxx" + +#include <unotools/processfactory.hxx> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/xml/xpath/XPathObjectType.hpp> + +#include <libxml/tree.h> + +CSerializationAppXML::CSerializationAppXML() + : m_aFactory(utl::getProcessServiceFactory()) + , m_aPipe(CSS::uno::Reference< CSS::io::XOutputStream > (m_aFactory->createInstance( + rtl::OUString::createFromAscii("com.sun.star.io.Pipe")), CSS::uno::UNO_QUERY)) +{ + OSL_ENSURE(m_aPipe.is(), "cannot create Pipe"); +} + +CSS::uno::Reference< CSS::io::XInputStream > +CSerializationAppXML::getInputStream() +{ + // The pipes output is provided through it's + // XOutputStream interface aspect + return CSS::uno::Reference< CSS::io::XInputStream >(m_aPipe, CSS::uno::UNO_QUERY); +} + +void +CSerializationAppXML::serialize_node(const CSS::uno::Reference< CSS::xml::dom::XNode >& rNode) +{ + CSS::uno::Reference< CSS::xml::dom::XNode > aNode = rNode; + if (aNode->getNodeType() == CSS::xml::dom::NodeType_DOCUMENT_NODE) + { + CSS::uno::Reference< CSS::xml::dom::XDocument > aDoc(rNode, CSS::uno::UNO_QUERY_THROW); + aNode = CSS::uno::Reference< CSS::xml::dom::XNode >(aDoc->getDocumentElement(), CSS::uno::UNO_QUERY_THROW); + } + if (aNode->getNodeType() != CSS::xml::dom::NodeType_ELEMENT_NODE) + return; + + // clone the node to a new document and serialize that document + CSS::uno::Reference< CSS::lang::XUnoTunnel > aTunnel(aNode, CSS::uno::UNO_QUERY); + if (aTunnel.is()) + { + xmlNodePtr aNodePtr = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(CSS::uno::Sequence< sal_Int8 >()) ); + xmlDocPtr aDocPtr = xmlNewDoc((xmlChar*)"1.0"); + xmlNodePtr aDocNodePtr = xmlDocCopyNode(aNodePtr, aDocPtr, 1); + if (aDocNodePtr != NULL) { + xmlAddChild((xmlNodePtr)aDocPtr, aDocNodePtr); + xmlChar *buffer = NULL; + sal_Int32 size = 0; + xmlDocDumpMemory(aDocPtr, &buffer, (int*)&size); + + // write the xml into the pipe through it's XOutputStream interface + m_aPipe->writeBytes(CSS::uno::Sequence< sal_Int8 >((sal_Int8*)buffer, size)); + xmlFree(buffer); + } + + } else { + // can't get tunnel to native backend + // logic for generic implementation could be implemented here... + OSL_ENSURE(sal_False, "unkown dom implementation, cannot serialize"); + return; + } +} + +/* +void +CSerializationAppXML::serialize_nodeset() +{ + CSS::uno::Reference< CSS::xml::dom::XNodeList > aNodeList = m_aXPathObject->getNodeList(); + for (sal_Int32 i=0; i<aNodeList->getLength(); i++) + serialize_node(aNodeList->item(i)); + m_aPipe->closeOutput(); +} +*/ + +void +CSerializationAppXML::serialize() +{ + if (!m_aFragment.is()) return; + + CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild(); + while (cur.is()) + { + serialize_node(cur); + cur = cur->getNextSibling(); + } + m_aPipe->closeOutput(); +} diff --git a/forms/source/xforms/submission/serialization_app_xml.hxx b/forms/source/xforms/submission/serialization_app_xml.hxx new file mode 100644 index 000000000000..338df6aea083 --- /dev/null +++ b/forms/source/xforms/submission/serialization_app_xml.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SERIALIZATION_APP_XML_HXX +#define __SERIALIZATION_APP_XML_HXX + +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include "serialization.hxx" + + +class CSerializationAppXML : public CSerialization +{ +private: + CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory; + CSS::uno::Reference< CSS::io::XOutputStream > m_aPipe; + + void serialize_node(const CSS::uno::Reference< CSS::xml::dom::XNode >& aNode); + void serialize_nodeset(); + +public: + CSerializationAppXML(); + + virtual void serialize(); + // virtual void setSource(const CSS::uno::Reference< CSS::xml::xpath::XXPathObject >& object); + // virtual void setProperties(const CSS::uno::Sequence< CSS::beans::NamedValue >& props); + virtual CSS::uno::Reference< CSS::io::XInputStream > getInputStream(); +}; + +#endif diff --git a/forms/source/xforms/submission/serialization_multi_form.hxx b/forms/source/xforms/submission/serialization_multi_form.hxx new file mode 100644 index 000000000000..20e542d90bc7 --- /dev/null +++ b/forms/source/xforms/submission/serialization_multi_form.hxx @@ -0,0 +1,27 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + diff --git a/forms/source/xforms/submission/serialization_multi_related.hxx b/forms/source/xforms/submission/serialization_multi_related.hxx new file mode 100644 index 000000000000..20e542d90bc7 --- /dev/null +++ b/forms/source/xforms/submission/serialization_multi_related.hxx @@ -0,0 +1,27 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + diff --git a/forms/source/xforms/submission/serialization_urlencoded.cxx b/forms/source/xforms/submission/serialization_urlencoded.cxx new file mode 100644 index 000000000000..307d9d90aed7 --- /dev/null +++ b/forms/source/xforms/submission/serialization_urlencoded.cxx @@ -0,0 +1,210 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include <com/sun/star/xml/xpath/XPathObjectType.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XText.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> + +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <unotools/processfactory.hxx> + +#include <stdio.h> + +#include "serialization_urlencoded.hxx" + +using namespace utl; +using namespace CSS::uno; +using namespace CSS::io; +using namespace CSS::xml::xpath; +using namespace CSS::xml::dom; + +CSerializationURLEncoded::CSerializationURLEncoded() + : m_aFactory(getProcessServiceFactory()) + , m_aPipe(Reference< XOutputStream > (m_aFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY)) +{ +} + + +/* + rfc2396 + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," + mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + unreserved = alphanum | mark +*/ +sal_Bool CSerializationURLEncoded::is_unreserved(sal_Char c) +{ + //digit? + if (c >= '0' && c <= '9') return sal_True; + if (c >= 'A' && c <= 'Z') return sal_True; + if (c >= 'a' && c <= 'z') return sal_True; + switch (c) { + case '-': + case '_': + case '.': + case '!': + case '~': + case '*': + case '\'': + case '(': + case ')': + return sal_True; + } + return sal_False; +} +void CSerializationURLEncoded::encode_and_append(const ::rtl::OUString& aString, ::rtl::OStringBuffer& aBuffer) +{ + ::rtl::OString utf8String = OUStringToOString(aString, RTL_TEXTENCODING_UTF8); + const sal_uInt8 *pString = reinterpret_cast< const sal_uInt8 * >( utf8String.getStr() ); + sal_Char tmpChar[4]; tmpChar[3] = 0; + + while( *pString != 0) + { + if( *pString < 0x80 ) + { + if ( is_unreserved(*pString) ) { + aBuffer.append(*pString); + } else if (*pString == 0x20) { + aBuffer.append('+'); + } else if (*pString == 0x0d && *(pString+1) == 0x0a) { + aBuffer.append("%0D%0A"); + pString++; + } else if (*pString == 0x0a) { + aBuffer.append("%0D%0A"); + } else { + snprintf(tmpChar, 3, "%%%X", *pString % 0x100); + aBuffer.append(tmpChar); + } + } else { + snprintf(tmpChar, 3, "%%%X", *pString % 0x100); + aBuffer.append(tmpChar); + while (*pString >= 0x80) { + // continuation... + pString++; + snprintf(tmpChar, 3, "%%%X", *pString % 0x100); + aBuffer.append(tmpChar); + } + } + pString++; + } +} + +void CSerializationURLEncoded::serialize_node(const Reference< XNode >& aNode) +{ + // serialize recursive + // every element node E that has a text child T will be serialized in document order + // <E1>T1<E2>T2</E2></E1><E3>T3</E3> -> E1=T2&E2=T2&E3=T3 (En := local name) + + // this node + Reference< XNodeList > aChildList = aNode->getChildNodes(); + Reference< XNode > aChild; + // is this an element node? + if (aNode->getNodeType() == NodeType_ELEMENT_NODE) + { + ::rtl::OUString aName = aNode->getNodeName(); + // find any text children + ::rtl::OUStringBuffer aValue; + Reference< XText > aText; + for(sal_Int32 i=0; i < aChildList->getLength(); i++) + { + aChild = aChildList->item(i); + if (aChild->getNodeType() == NodeType_TEXT_NODE) + { + aText = Reference< XText >(aChild, UNO_QUERY); + aValue.append(aText->getData()); + } + } + + // found anything? + if (aValue.getLength() > 0) + { + ::rtl::OUString aUnencValue = aValue.makeStringAndClear(); + ::rtl::OStringBuffer aEncodedBuffer; + encode_and_append(aName, aEncodedBuffer); + aEncodedBuffer.append("="); + encode_and_append(aUnencValue, aEncodedBuffer); + aEncodedBuffer.append("&"); + sal_Int8 *pData = (sal_Int8*)aEncodedBuffer.getStr(); + Sequence< sal_Int8 > sData(pData, aEncodedBuffer.getLength()); + m_aPipe->writeBytes(sData); + } + } + + // element children... + for(sal_Int32 i=0; i < aChildList->getLength(); i++) + { + aChild = aChildList->item(i); + // if this is an element node, it might be a candidate for serialization + if (aChild.is() && aChild->getNodeType() == NodeType_ELEMENT_NODE) + serialize_node(aChild); + } + + // siblings... +// Reference< XNode > aSibling = aNode->getNextSibling(); +// if (aSibling.is()) +// serialize_node(aSibling); + +} + +/* +void CSerializationURLEncoded::serialize_nodeset() +{ + Reference< XNodeList > aNodeList = m_aXPathObject->getNodeList(); + for (sal_Int32 i=0; i<aNodeList->getLength(); i++) + serialize_node(aNodeList->item(i)); + m_aPipe->closeOutput(); +} +*/ + +void CSerializationURLEncoded::serialize() +{ + + // output stream to the pipe buffer + Reference< XOutputStream > out(m_aPipe, UNO_QUERY); + + CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild(); + while (cur.is()) + { + serialize_node(cur); + cur = cur->getNextSibling(); + } + m_aPipe->closeOutput(); +} + +Reference< XInputStream > CSerializationURLEncoded::getInputStream() +{ + return Reference< XInputStream >(m_aPipe, UNO_QUERY); +} + + diff --git a/forms/source/xforms/submission/serialization_urlencoded.hxx b/forms/source/xforms/submission/serialization_urlencoded.hxx new file mode 100644 index 000000000000..a3c41e7e4d5c --- /dev/null +++ b/forms/source/xforms/submission/serialization_urlencoded.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SERIALIZATION_URLENCODED_HXX +#define __SERIALIZATION_URLENCODED_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> + +#include <rtl/strbuf.hxx> + +#include "serialization.hxx" + +class CSerializationURLEncoded : public CSerialization +{ +private: + CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory; + CSS::uno::Reference< CSS::io::XOutputStream > m_aPipe; + + sal_Bool is_unreserved(sal_Char); + void encode_and_append(const rtl::OUString& aString, rtl::OStringBuffer& aBuffer); + void serialize_node(const CSS::uno::Reference< CSS::xml::dom::XNode >& aNode); + void serialize_nodeset(); + +public: + CSerializationURLEncoded(); + virtual void serialize(); + virtual CSS::uno::Reference< CSS::io::XInputStream > getInputStream(); +}; + +#endif diff --git a/forms/source/xforms/submission/submission.hxx b/forms/source/xforms/submission/submission.hxx new file mode 100644 index 000000000000..53e37b4cd131 --- /dev/null +++ b/forms/source/xforms/submission/submission.hxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SUBMISSION_HXX +#define __SUBMISSION_HXX + +#include <tools/urlobj.hxx> +#include <rtl/ustring.h> +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <unotools/processfactory.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/ucb/XProgressHandler.hpp> + +#include <com/sun/star/task/XInteractionHandler.hpp> + +#include <com/sun/star/frame/XFrame.hpp> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/implbase3.hxx> + +#include "serialization.hxx" + +namespace CSS = com::sun::star; + +class CSubmissionPut; +class CSubmissionPost; +class CSubmissionGet; + +class CCommandEnvironmentHelper : public cppu::WeakImplHelper1< CSS::ucb::XCommandEnvironment > +{ + friend class CSubmissionPut; + friend class CSubmissionPost; + friend class CSubmissionGet; + friend class CSubmission; + +protected: + CSS::uno::Reference< CSS::task::XInteractionHandler > m_aInteractionHandler; + CSS::uno::Reference< CSS::ucb::XProgressHandler > m_aProgressHandler; + +public: + virtual CSS::uno::Reference< CSS::task::XInteractionHandler > SAL_CALL getInteractionHandler() throw (CSS::uno::RuntimeException) + { + return m_aInteractionHandler; + } + virtual CSS::uno::Reference< CSS::ucb::XProgressHandler > SAL_CALL getProgressHandler() throw (CSS::uno::RuntimeException) + { + return m_aProgressHandler; + } +}; + +class CProgressHandlerHelper : public cppu::WeakImplHelper1< CSS::ucb::XProgressHandler > +{ + friend class CSubmissionPut; + friend class CSubmissionPost; + friend class CSubmissionGet; +protected: + osl::Condition m_cFinished; + osl::Mutex m_mLock; + sal_Int32 m_count; +public: + CProgressHandlerHelper() + : m_count(0) + {} + virtual void SAL_CALL push( const com::sun::star::uno::Any& /*aStatus*/) throw(com::sun::star::uno::RuntimeException) + { + m_mLock.acquire(); + m_count++; + m_mLock.release(); + } + virtual void SAL_CALL update(const com::sun::star::uno::Any& /*aStatus*/) throw(com::sun::star::uno::RuntimeException) + { + } + virtual void SAL_CALL pop() throw(com::sun::star::uno::RuntimeException) + { + m_mLock.acquire(); + m_count--; + if (m_count == 0) + m_cFinished.set(); + m_mLock.release(); + } +}; + +class CSubmission +{ + +protected: + INetURLObject m_aURLObj; + CSS::uno::Reference< CSS::xml::xpath::XXPathObject > m_aXPathObject; + CSS::uno::Reference< CSS::xml::dom::XDocumentFragment > m_aFragment; + CSS::uno::Reference< CSS::io::XInputStream > m_aResultStream; + CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory; + rtl::OUString m_aEncoding; + + ::std::auto_ptr< CSerialization > createSerialization(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler + ,com::sun::star::uno::Reference<com::sun::star::ucb::XCommandEnvironment>& _rOutEnv); + +public: + enum SubmissionResult { + SUCCESS, + INVALID_METHOD, + INVALID_URL, + INVALID_ENCODING, + E_TRANSMISSION, + UNKNOWN_ERROR + }; + + CSubmission(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment) + : m_aURLObj(aURL) + , m_aFragment(aFragment) + , m_aFactory(::utl::getProcessServiceFactory()) + {} + + virtual ~CSubmission() {} + + // virtual CSS::uno::Sequence< rtl::OUString > getSupportedEncodings() = 0; + virtual void setEncoding(const rtl::OUString& aEncoding) + { + m_aEncoding = aEncoding; + } + virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& ) = 0; + + virtual SubmissionResult replace(const rtl::OUString&, const CSS::uno::Reference< CSS::xml::dom::XDocument >&, const CSS::uno::Reference< CSS::frame::XFrame>&); + +}; + +#endif diff --git a/forms/source/xforms/submission/submission_get.cxx b/forms/source/xforms/submission/submission_get.cxx new file mode 100644 index 000000000000..57adeda664c7 --- /dev/null +++ b/forms/source/xforms/submission/submission_get.cxx @@ -0,0 +1,117 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include <memory> + +#include "submission_get.hxx" +#include "serialization_app_xml.hxx" +#include "serialization_urlencoded.hxx" + +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> +#include <osl/file.hxx> +#include <unotools/processfactory.hxx> +#include <ucbhelper/content.hxx> + +using namespace CSS::uno; +using namespace CSS::ucb; +using namespace CSS::task; +using namespace CSS::io; +using namespace rtl; +using namespace osl; +using namespace ucbhelper; +using namespace std; + + +CSubmissionGet::CSubmissionGet(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment) + : CSubmission(aURL, aFragment) +{ +} + +CSubmission::SubmissionResult CSubmissionGet::submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler) +{ + // GET always uses apllicatin/x-www-formurlencoded + auto_ptr< CSerialization > apSerialization(new CSerializationURLEncoded()); + apSerialization->setSource(m_aFragment); + apSerialization->serialize(); + + CSS::uno::Reference< XInputStream > aInStream = apSerialization->getInputStream(); + + // create a commandEnvironment and use the default interaction handler + CCommandEnvironmentHelper *pHelper = new CCommandEnvironmentHelper; + if( aInteractionHandler.is() ) + pHelper->m_aInteractionHandler = aInteractionHandler; + else + pHelper->m_aInteractionHandler = CSS::uno::Reference< XInteractionHandler >(m_aFactory->createInstance( + OUString::createFromAscii("com.sun.star.task.InteractionHandler")), UNO_QUERY); + OSL_ENSURE(pHelper->m_aInteractionHandler.is(), "failed to create IntreractionHandler"); + CProgressHandlerHelper *pProgressHelper = new CProgressHandlerHelper; + pHelper->m_aProgressHandler = CSS::uno::Reference< XProgressHandler >(pProgressHelper); + + // UCB has ownership of environment... + CSS::uno::Reference< XCommandEnvironment > aEnvironment(pHelper); + + // append query string to the URL + try { + OStringBuffer aUTF8QueryURL(OUStringToOString(m_aURLObj.GetMainURL(INetURLObject::NO_DECODE), + RTL_TEXTENCODING_UTF8)); + OStringBuffer aQueryString; + + const sal_Int32 size = 1024; + sal_Int32 n = 0; + Sequence< sal_Int8 > aByteBuffer(size); + while ((n = aInStream->readSomeBytes(aByteBuffer, size-1)) != 0) + aQueryString.append((sal_Char*)aByteBuffer.getArray(), n); + if (aQueryString.getLength() > 0 && m_aURLObj.GetProtocol() != INET_PROT_FILE) + { + aUTF8QueryURL.append('?'); + aUTF8QueryURL.append(aQueryString.makeStringAndClear()); + } + OUString aQueryURL = OStringToOUString(aUTF8QueryURL.makeStringAndClear(), RTL_TEXTENCODING_UTF8); + ucbhelper::Content aContent(aQueryURL, aEnvironment); + CSS::uno::Reference< XOutputStream > aPipe(m_aFactory->createInstance( + OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY_THROW); + aContent.openStream(aPipe); + // get reply + try { + m_aResultStream = aContent.openStream(); + } catch (Exception&) { + OSL_ENSURE(sal_False, "Cannot open reply stream from content"); + } + } catch (Exception&) + { + // XXX + OSL_ENSURE(sal_False, "Exception during UCB operatration."); + return UNKNOWN_ERROR; + } + + return SUCCESS; +} + diff --git a/forms/source/xforms/submission/submission_get.hxx b/forms/source/xforms/submission/submission_get.hxx new file mode 100644 index 000000000000..931ecb514fc4 --- /dev/null +++ b/forms/source/xforms/submission/submission_get.hxx @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SUBMISSION_GET_HXX +#define __SUBMISSION_GET_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include "submission.hxx" + +class CSubmissionGet : public CSubmission +{ +private: + CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory; +public: + CSubmissionGet(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment); + virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler); + +}; +#endif diff --git a/forms/source/xforms/submission/submission_post.cxx b/forms/source/xforms/submission/submission_post.cxx new file mode 100644 index 000000000000..fa3f2180b0b0 --- /dev/null +++ b/forms/source/xforms/submission/submission_post.cxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include <memory> + +#include "submission_post.hxx" +#include "serialization_app_xml.hxx" +#include "serialization_urlencoded.hxx" + +#include <osl/file.hxx> +#include <unotools/processfactory.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/activedatasink.hxx> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> + +using namespace CSS::uno; +using namespace CSS::ucb; +using namespace CSS::task; +using namespace CSS::io; +using namespace rtl; +using namespace osl; +using namespace ucbhelper; +using namespace std; + + +CSubmissionPost::CSubmissionPost(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment) + : CSubmission(aURL, aFragment) +{ +} + +CSubmission::SubmissionResult CSubmissionPost::submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler) +{ + // PUT always uses application/xml + CSS::uno::Reference< XCommandEnvironment > aEnvironment; + auto_ptr< CSerialization > apSerialization(createSerialization(aInteractionHandler,aEnvironment)); + + try { + ucbhelper::Content aContent(m_aURLObj.GetMainURL(INetURLObject::NO_DECODE), aEnvironment); + + // use post command + + OUString aCommandName = OUString::createFromAscii("post"); + PostCommandArgument2 aPostArgument; + aPostArgument.Source = apSerialization->getInputStream(); + //CSS::uno::Reference< XInterface > aSink( m_aFactory->createInstance( + // OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY_THROW); + CSS::uno::Reference< XActiveDataSink > aSink(new ucbhelper::ActiveDataSink); + // OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY_THROW); + aPostArgument.Sink = aSink; + aPostArgument.MediaType = OUString::createFromAscii("application/xml"); + aPostArgument.Referer = OUString(); + Any aCommandArgument; + aCommandArgument <<= aPostArgument; + aContent.executeCommand( aCommandName, aCommandArgument); + + // wait for command to finish + // pProgressHelper->m_cFinished.wait(); + + // CSS::uno::Reference< XOutputStream > xOut(aSink, UNO_QUERY_THROW); + // xOut->closeOutput(); + + try { + // m_aResultStream = CSS::uno::Reference< XInputStream >(aSink, UNO_QUERY_THROW); + m_aResultStream = aSink->getInputStream(); + } catch (Exception&) { + OSL_ENSURE(sal_False, "Cannot open reply stream from content"); + } + } catch (Exception&) + { + // XXX + OSL_ENSURE(sal_False, "Exception during UCB operatration."); + return UNKNOWN_ERROR; + } + + + return SUCCESS; +} + diff --git a/forms/source/xforms/submission/submission_post.hxx b/forms/source/xforms/submission/submission_post.hxx new file mode 100644 index 000000000000..1c0c86d6490f --- /dev/null +++ b/forms/source/xforms/submission/submission_post.hxx @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SUBMISSION_POST_HXX +#define __SUBMISSION_POST_HXX + +#include "submission.hxx" + +class CSubmissionPost : public CSubmission +{ +public: + CSubmissionPost(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment); + virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler); + +}; +#endif diff --git a/forms/source/xforms/submission/submission_put.cxx b/forms/source/xforms/submission/submission_put.cxx new file mode 100644 index 000000000000..9ed37470ba93 --- /dev/null +++ b/forms/source/xforms/submission/submission_put.cxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include <memory> + +#include "submission_put.hxx" +#include "serialization_app_xml.hxx" +#include "serialization_urlencoded.hxx" + +#include <osl/file.hxx> +#include <unotools/processfactory.hxx> +#include <ucbhelper/content.hxx> + +using namespace CSS::uno; +using namespace CSS::ucb; +using namespace CSS::task; +using namespace CSS::io; +using namespace rtl; +using namespace osl; +using namespace ucbhelper; +using namespace std; + + +CSubmissionPut::CSubmissionPut(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment) + : CSubmission(aURL, aFragment) +{ +} + +CSubmission::SubmissionResult CSubmissionPut::submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler) +{ + CSS::uno::Reference< XCommandEnvironment > aEnvironment; + auto_ptr< CSerialization > apSerialization(createSerialization(aInteractionHandler,aEnvironment)); + + try { + ucbhelper::Content aContent(m_aURLObj.GetMainURL(INetURLObject::NO_DECODE), aEnvironment); + + // insert serialized data to content -> PUT + CSS::uno::Reference< XInputStream > aInStream = apSerialization->getInputStream(); + aContent.writeStream(aInStream, sal_True); + //aContent.closeStream(); + + // no content as a result of put... + + } catch (Exception&) + { + // XXX + OSL_ENSURE(sal_False, "Exception during UCB operatration."); + return UNKNOWN_ERROR; + } + + + return SUCCESS; +} + diff --git a/forms/source/xforms/submission/submission_put.hxx b/forms/source/xforms/submission/submission_put.hxx new file mode 100644 index 000000000000..10e4fa44007d --- /dev/null +++ b/forms/source/xforms/submission/submission_put.hxx @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SUBMISSION_PUT_HXX +#define __SUBMISSION_PUT_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/frame/XFrame.hpp> + +#include "submission.hxx" + +class CSubmissionPut : public CSubmission +{ +public: + CSubmissionPut(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment); + virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler); + +}; +#endif + diff --git a/forms/source/xforms/unohelper.cxx b/forms/source/xforms/unohelper.cxx new file mode 100644 index 000000000000..738ad4f40a1a --- /dev/null +++ b/forms/source/xforms/unohelper.cxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "unohelper.hxx" + +#include <osl/diagnose.h> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <unotools/processfactory.hxx> + + +using com::sun::star::uno::Reference; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Exception; +using com::sun::star::uno::XInterface; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::Property; +using com::sun::star::beans::XPropertySet; +using com::sun::star::beans::XPropertySetInfo; +using com::sun::star::beans::PropertyAttribute::READONLY; +using rtl::OUString; + + +Reference<XInterface> xforms::createInstance( const OUString& sServiceName ) +{ + Reference<XMultiServiceFactory> xFactory = utl::getProcessServiceFactory(); + OSL_ENSURE( xFactory.is(), "can't get service factory" ); + + Reference<XInterface> xInstance = xFactory->createInstance( sServiceName ); + OSL_ENSURE( xInstance.is(), "failed to create instance" ); + + return xInstance; +} + +void xforms::copy( const Reference<XPropertySet>& xFrom, + Reference<XPropertySet>& xTo ) +{ + OSL_ENSURE( xFrom.is(), "no source" ); + OSL_ENSURE( xTo.is(), "no target" ); + + // get property names & infos, and iterate over target properties + Sequence<Property> aProperties = + xTo->getPropertySetInfo()->getProperties(); + sal_Int32 nProperties = aProperties.getLength(); + const Property* pProperties = aProperties.getConstArray(); + Reference<XPropertySetInfo> xFromInfo = xFrom->getPropertySetInfo(); + for( sal_Int32 n = 0; n < nProperties; n++ ) + { + const OUString& rName = pProperties[n].Name; + + // if both set have the property, copy the value + // (catch and ignore exceptions, if any) + if( xFromInfo->hasPropertyByName( rName ) ) + { + try + { + Property aProperty = xFromInfo->getPropertyByName( rName ); + if ( ( aProperty.Attributes & READONLY ) == 0 ) + xTo->setPropertyValue(rName, xFrom->getPropertyValue( rName )); + } + catch( const Exception& ) + { + // ignore any errors; we'll copy as good as we can + } + } + // else: no property? then ignore. + } +} diff --git a/forms/source/xforms/unohelper.hxx b/forms/source/xforms/unohelper.hxx new file mode 100644 index 000000000000..d6cb46fcbc40 --- /dev/null +++ b/forms/source/xforms/unohelper.hxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _UNOHELPER_HXX +#define _UNOHELPER_HXX + +#include <sal/types.h> + +// forward declarations +namespace rtl { class OUString; } +namespace com { namespace sun { namespace star { + namespace uno { + class XInterface; + template<class T> class Reference; + } + namespace beans { class XPropertySet; } +} } } + + +#define OUSTRING(msg) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( msg ) ) + +namespace xforms +{ + +/** instantiate a UNO service using the process global service factory */ +com::sun::star::uno::Reference<com::sun::star::uno::XInterface> + createInstance( const rtl::OUString& sServiceName ); + +/** copy the properties from one PropertySet into the next */ +void copy( const com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& , com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& ); + +} // namespace + +#endif diff --git a/forms/source/xforms/warnings_guard_unicode_regex.h b/forms/source/xforms/warnings_guard_unicode_regex.h new file mode 100644 index 000000000000..2d7605cb9524 --- /dev/null +++ b/forms/source/xforms/warnings_guard_unicode_regex.h @@ -0,0 +1,48 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_WARNINGS_GUARD_UNICODE_REGEX_H +#define INCLUDED_WARNINGS_GUARD_UNICODE_REGEX_H + +// Because the GCC system_header mechanism doesn't work in .c/.cxx compilation +// units and more important affects the rest of the current include file, the +// warnings guard is separated into this header file on its own. + +// External unicode includes (from icu) cause warning C4668 on Windows. +// We want to minimize the patches to external headers, so the warnings are +// disabled here instead of in the header file itself. +#ifdef _MSC_VER +#pragma warning(push, 1) +#elif defined __GNUC__ +#pragma GCC system_header +#endif +#include <unicode/regex.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // INCLUDED_WARNINGS_GUARD_UNICODE_REGEX_H diff --git a/forms/source/xforms/xforms_services.cxx b/forms/source/xforms/xforms_services.cxx new file mode 100644 index 000000000000..867a80bd7bbd --- /dev/null +++ b/forms/source/xforms/xforms_services.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "services.hxx" + +#include "binding.hxx" +#include "model.hxx" +#include "NameContainer.hxx" + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/container/XNameContainer.hpp> + +using com::sun::star::uno::Reference; +using com::sun::star::uno::XInterface; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::uno::RuntimeException; +using com::sun::star::form::binding::XValueBinding; +using com::sun::star::beans::XPropertySet; +using com::sun::star::container::XNameContainer; +using rtl::OUString; + + +namespace frm +{ + +Reference<XInterface> Model_CreateInstance( + const Reference<XMultiServiceFactory>& ) + throw( RuntimeException ) +{ + return static_cast<XPropertySet*>( new xforms::Model ); +} + +Reference<XInterface> XForms_CreateInstance( + const Reference<XMultiServiceFactory>& ) + throw( RuntimeException ) +{ + return static_cast<XNameContainer*>( new NameContainer<Reference<XPropertySet> >() ); +} + +} diff --git a/forms/source/xforms/xforms_services.hxx b/forms/source/xforms/xforms_services.hxx new file mode 100644 index 000000000000..e40550bc6550 --- /dev/null +++ b/forms/source/xforms/xforms_services.hxx @@ -0,0 +1,27 @@ + + +namespace com { namespace sun { namespace star { + namespace uno { class XInterface; } + namespace uno { template<class T> class Reference<T>; } + namespace uno { class RuntimeException; } + namespace lang { class XMultiServiceFactory; } +} } } + + +namespace frm +{ + com::sun::star::uno::Reference<com::sun::star::uno::XInterface> + SAL_CALL Binding_CreateInstance( + const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory) + throw( com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference<com::sun::star::uno::XInterface> + SAL_CALL Model_CreateInstance( + const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory) + throw( com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference<com::sun::star::uno::XInterface> + SAL_CALL XForms_CreateInstance( + const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory) + throw( com::sun::star::uno::RuntimeException ); +} diff --git a/forms/source/xforms/xformsevent.cxx b/forms/source/xforms/xformsevent.cxx new file mode 100644 index 000000000000..56f8f2e9ca4a --- /dev/null +++ b/forms/source/xforms/xformsevent.cxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "xformsevent.hxx" + +namespace com { +namespace sun { +namespace star { +namespace xforms { + +using rtl::OUString; +using com::sun::star::uno::RuntimeException; + +void SAL_CALL XFormsEventConcrete::initXFormsEvent(const OUString& typeArg, + sal_Bool canBubbleArg, sal_Bool cancelableArg) + throw (RuntimeException) +{ + initEvent(typeArg, canBubbleArg, cancelableArg); +} + +OUString SAL_CALL XFormsEventConcrete::getType() throw (RuntimeException) +{ + return m_eventType; +} + +XFormsEventConcrete::XEventTarget_t SAL_CALL XFormsEventConcrete::getTarget() throw (RuntimeException) +{ + return m_target; +} + +XFormsEventConcrete::XEventTarget_t SAL_CALL XFormsEventConcrete::getCurrentTarget() throw (RuntimeException) +{ + return m_currentTarget; +} + +XFormsEventConcrete::PhaseType_t SAL_CALL XFormsEventConcrete::getEventPhase() throw (RuntimeException) +{ + return m_phase; +} + +sal_Bool SAL_CALL XFormsEventConcrete::getBubbles() throw (RuntimeException) +{ + return m_bubbles; +} + +sal_Bool SAL_CALL XFormsEventConcrete::getCancelable() throw (RuntimeException) +{ + return m_cancelable; +} + +XFormsEventConcrete::Time_t SAL_CALL XFormsEventConcrete::getTimeStamp() throw (RuntimeException) +{ + return m_time; +} + +void SAL_CALL XFormsEventConcrete::stopPropagation() throw (RuntimeException) +{ + if(m_cancelable) + m_canceled = sal_True; +} +void SAL_CALL XFormsEventConcrete::preventDefault() throw (RuntimeException) +{ +} + +void SAL_CALL XFormsEventConcrete::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException) +{ + m_eventType = eventTypeArg; + m_bubbles = canBubbleArg; + m_cancelable = cancelableArg; +} + +} } } } diff --git a/forms/source/xforms/xformsevent.hxx b/forms/source/xforms/xformsevent.hxx new file mode 100644 index 000000000000..c770c0db6d56 --- /dev/null +++ b/forms/source/xforms/xformsevent.hxx @@ -0,0 +1,66 @@ +#ifndef __XFORMSEVENT_HXX +#define __XFORMSEVENT_HXX + +#include <sal/types.h> +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xforms/XFormsEvent.hpp> +#include <com/sun/star/xml/dom/events/XEventTarget.hpp> + +namespace com { +namespace sun { +namespace star { +namespace xforms { + +class XFormsEventConcrete : public cppu::WeakImplHelper1< XFormsEvent > { + + public: + + typedef com::sun::star::uno::RuntimeException RuntimeException_t; + typedef com::sun::star::uno::Reference< com::sun::star::xml::dom::events::XEventTarget > XEventTarget_t; + typedef com::sun::star::xml::dom::events::PhaseType PhaseType_t; + typedef com::sun::star::util::Time Time_t; + + inline XFormsEventConcrete( void ) : m_canceled(sal_False) {} + virtual ~XFormsEventConcrete( void ) {} + + virtual rtl::OUString SAL_CALL getType() throw (RuntimeException_t); + virtual XEventTarget_t SAL_CALL getTarget() throw (RuntimeException_t); + virtual XEventTarget_t SAL_CALL getCurrentTarget() throw (RuntimeException_t); + virtual PhaseType_t SAL_CALL getEventPhase() throw (RuntimeException_t); + virtual sal_Bool SAL_CALL getBubbles() throw (RuntimeException_t); + virtual sal_Bool SAL_CALL getCancelable() throw (RuntimeException_t); + virtual Time_t SAL_CALL getTimeStamp() throw (RuntimeException_t); + virtual void SAL_CALL stopPropagation() throw (RuntimeException_t); + virtual void SAL_CALL preventDefault() throw (RuntimeException_t); + + virtual void SAL_CALL initXFormsEvent( + const rtl::OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg ) + throw (RuntimeException_t); + + virtual void SAL_CALL initEvent( + const rtl::OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException_t); + + private: + + sal_Bool m_canceled; + + protected: + + rtl::OUString m_eventType; + XEventTarget_t m_target; + XEventTarget_t m_currentTarget; + PhaseType_t m_phase; + sal_Bool m_bubbles; + sal_Bool m_cancelable; + Time_t m_time; +}; + +} } } } + +#endif diff --git a/forms/source/xforms/xmlhelper.cxx b/forms/source/xforms/xmlhelper.cxx new file mode 100644 index 000000000000..a8aaa19aea34 --- /dev/null +++ b/forms/source/xforms/xmlhelper.cxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "xmlhelper.hxx" + +#include "unohelper.hxx" +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> + +using rtl::OUString; +using com::sun::star::uno::Reference; +using com::sun::star::uno::UNO_QUERY_THROW; +using com::sun::star::container::XNameContainer; +using com::sun::star::xml::dom::XDocumentBuilder; + + +// +// determine valid XML name +// + +// character class: +// 1: NameStartChar +// 2: NameChar +// 4: NCNameStartChar +// 8: NCNameChar +inline sal_uInt8 lcl_getCharClass( sal_Unicode c ) +{ + sal_uInt8 nClass = 0; + + // NameStartChar + if( (c >= 'A' && c <= 'Z') + || c == '_' + || (c >= 'a' && c <= 'z') + || (c >= 0x00C0 && c <= 0x00D6) + || (c >= 0x00D8 && c <= 0x00F6) + || (c >= 0x00F8 && c <= 0x02FF) + || (c >= 0x0370 && c <= 0x037D) + || (c >= 0x037F && c <= 0x1FFF) + || (c >= 0x200C && c <= 0x200D) + || (c >= 0x2070 && c <= 0x218F) + || (c >= 0x2C00 && c <= 0x2FEF) + || (c >= 0x3001 && c <= 0xD7FF) + || (c >= 0xF900 && c <= 0xFDCF) + || (c >= 0xFDF0 && c <= 0xFFFD) + + // surrogates + || (c >= 0xD800 && c <= 0xDBFF) + || (c >= 0xDC00 && c <= 0xDFFF) ) + { + nClass = 15; + } + else if( c == '-' + || c == '.' + || (c >= '0' && c <= '9') + || (c == 0x00B7) + || (c >= 0x0300 && c <= 0x036F) + || (c >= 0x203F && c <= 0x2040) ) + { + nClass = 10; + } + else if( c == ':' ) + { + nClass = 3; + } + + return nClass; +} + +bool isValidQName( const OUString& sName, + const Reference<XNameContainer>& /*xNamespaces*/ ) +{ + sal_Int32 nLength = sName.getLength(); + const sal_Unicode* pName = sName.getStr(); + + bool bRet = false; + sal_Int32 nColon = 0; + if( nLength > 0 ) + { + bRet = ( ( lcl_getCharClass( pName[0] ) & 4 ) != 0 ); + for( sal_Int32 n = 1; n < nLength; n++ ) + { + sal_uInt8 nClass = lcl_getCharClass( pName[n] ); + bRet &= ( ( nClass & 2 ) != 0 ); + if( nClass == 3 ) + nColon++; + } + } + if( nColon > 1 ) + bRet = sal_False; + + return bRet; +} + +bool isValidPrefixName( const OUString& sName, + const Reference<XNameContainer>& /*xNamespaces*/ ) +{ + sal_Int32 nLength = sName.getLength(); + const sal_Unicode* pName = sName.getStr(); + bool bRet = false; + + if( nLength > 0 ) + { + bRet = ( ( lcl_getCharClass( pName[0] ) & 4 ) != 0 ); + for( sal_Int32 n = 1; n < nLength; n++ ) + bRet &= ( ( lcl_getCharClass( pName[n] ) & 8 ) != 0 ); + } + + return bRet; +} + +Reference<XDocumentBuilder> getDocumentBuilder() +{ + Reference<XDocumentBuilder> xBuilder( + xforms::createInstance( + OUSTRING("com.sun.star.xml.dom.DocumentBuilder") ), + UNO_QUERY_THROW ); + OSL_ENSURE( xBuilder.is(), "no document builder?" ); + return xBuilder; +} + diff --git a/forms/source/xforms/xmlhelper.hxx b/forms/source/xforms/xmlhelper.hxx new file mode 100644 index 000000000000..d5822138a306 --- /dev/null +++ b/forms/source/xforms/xmlhelper.hxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLHELPER_HXX +#define _XMLHELPER_HXX + +#include <sal/types.h> + + +namespace rtl { class OUString; } +namespace com { namespace sun { namespace star { + namespace uno { template<typename T> class Reference; } + namespace container { class XNameContainer; } + namespace xml { namespace dom { class XDocumentBuilder; } } +} } } + + +bool isValidQName( const rtl::OUString& sName, + const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& xNamespaces ); + +bool isValidPrefixName( const rtl::OUString& sName, + const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& xNamespaces ); + +com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocumentBuilder> getDocumentBuilder(); + + +#endif diff --git a/forms/source/xforms/xpathlib/extension.cxx b/forms/source/xforms/xpathlib/extension.cxx new file mode 100644 index 000000000000..4c23eac63be0 --- /dev/null +++ b/forms/source/xforms/xpathlib/extension.cxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include <stdio.h> +#include <com/sun/star/xml/xpath/Libxml2ExtensionHandle.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include "extension.hxx" +#include "xpathlib.hxx" +#include "frm_module.hxx" + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::xforms; +using namespace com::sun::star::xml::xpath; +using namespace com::sun::star::beans; +using com::sun::star::xml::dom::XNode; + +Reference< XInterface > SAL_CALL CLibxml2XFormsExtension::Create( + const Reference< XMultiServiceFactory >& /*aFactory*/) +{ + // printf("_create_\n"); + Reference< XInterface > aInstance(static_cast< XXPathExtension* >(new CLibxml2XFormsExtension(/*aFactory*/))); + return aInstance; +} + +::rtl::OUString SAL_CALL CLibxml2XFormsExtension::getImplementationName_Static() +{ + // printf("_implname_\n"); + return ::rtl::OUString::createFromAscii("com.sun.star.comp.xml.xpath.XFormsExtension"); +} + +Sequence< ::rtl::OUString > SAL_CALL CLibxml2XFormsExtension::getSupportedServiceNames_Static() +{ + // printf("_services_\n"); + Sequence< ::rtl::OUString > aSequence(1); + aSequence[0] = ::rtl::OUString::createFromAscii("com.sun.star.xml.xpath.XPathExtension"); + return aSequence; +} + +Libxml2ExtensionHandle SAL_CALL CLibxml2XFormsExtension::getLibxml2ExtensionHandle() throw (RuntimeException) +{ + Libxml2ExtensionHandle aHandle; + aHandle.functionLookupFunction = reinterpret_cast< sal_Int64 >( &xforms_lookupFunc ); + aHandle.functionData = reinterpret_cast< sal_Int64 >( this ); + aHandle.variableLookupFunction = (sal_Int64)0; + aHandle.variableData = (sal_Int64)0; + return aHandle; +} + +void SAL_CALL CLibxml2XFormsExtension::initialize(const Sequence< Any >& aSequence) throw (RuntimeException) +{ + NamedValue aValue; + for (sal_Int32 i = 0; i < aSequence.getLength(); i++) + { + if (! (aSequence[i] >>= aValue)) + throw RuntimeException(); + if (aValue.Name.equalsAscii("Model")) + aValue.Value >>= m_aModel; + else if (aValue.Name.equalsAscii("ContextNode")) + aValue.Value >>= m_aContextNode; + } +} + +Reference< XModel > CLibxml2XFormsExtension::getModel() +{ + return m_aModel; +} + +Reference< XNode > CLibxml2XFormsExtension::getContextNode() +{ + return m_aContextNode; +} + +extern "C" void SAL_CALL createRegistryInfo_CLibxml2XFormsExtension() +{ + static frm::OMultiInstanceAutoRegistration< CLibxml2XFormsExtension > aRegistration; +} diff --git a/forms/source/xforms/xpathlib/extension.hxx b/forms/source/xforms/xpathlib/extension.hxx new file mode 100644 index 000000000000..303b832f9f43 --- /dev/null +++ b/forms/source/xforms/xpathlib/extension.hxx @@ -0,0 +1,39 @@ +#include <rtl/ustring.h> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/xml/xpath/XXPathExtension.hpp> +#include <com/sun/star/xforms/XModel.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> + + + + +class CLibxml2XFormsExtension : public cppu::WeakImplHelper2< + com::sun::star::xml::xpath::XXPathExtension, com::sun::star::lang::XInitialization> +{ +private: + com::sun::star::uno::Reference <com::sun::star::xforms::XModel> m_aModel; + com::sun::star::uno::Reference <com::sun::star::xml::dom::XNode> m_aContextNode; + +public: + static com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL Create( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& aFactory); + static rtl::OUString SAL_CALL getImplementationName_Static(); + static com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + + com::sun::star::uno::Reference< com::sun::star::xforms::XModel > getModel(); + com::sun::star::uno::Reference< com::sun::star::xml::dom::XNode > getContextNode(); + + virtual com::sun::star::xml::xpath::Libxml2ExtensionHandle SAL_CALL getLibxml2ExtensionHandle() throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL initialize(const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aSequence) throw (com::sun::star::uno::RuntimeException); + +}; diff --git a/forms/source/xforms/xpathlib/makefile.mk b/forms/source/xforms/xpathlib/makefile.mk new file mode 100644 index 000000000000..08e58eb2834c --- /dev/null +++ b/forms/source/xforms/xpathlib/makefile.mk @@ -0,0 +1,56 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=forms +TARGET=xformsxpath + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +INCPRE+=$(PRJ)$/source$/inc + +.IF "$(SYSTEM_LIBXML)" == "YES" +CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) +.ENDIF + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/xpathlib.obj \ + $(SLO)$/extension.obj + + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/xforms/xpathlib/xpathlib.cxx b/forms/source/xforms/xpathlib/xpathlib.cxx new file mode 100644 index 000000000000..2fd6a93b614a --- /dev/null +++ b/forms/source/xforms/xpathlib/xpathlib.cxx @@ -0,0 +1,567 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include <string.h> +#include <sal/types.h> +#include <rtl/alloc.h> +#include <rtl/ustring.hxx> +#include <rtl/string.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <tools/datetime.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/xforms/XModel.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> + +#include "xpathlib.hxx" + +#include "extension.hxx" + +// C interface + +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xforms; +using namespace com::sun::star::lang; + +xmlXPathFunction xforms_lookupFunc(void *, const xmlChar *xname, const xmlChar *) +{ + + const char *name = (char *)xname; + if (strcmp("boolean-from-string", name)==0) + return xforms_booleanFromStringFunction; + else if ((strcmp("if", name))==0) + return xforms_ifFunction; + else if ((strcmp("avg", name))==0) + return xforms_avgFunction; + else if ((strcmp("min", name))==0) + return xforms_minFunction; + else if ((strcmp("max", name))==0) + return xforms_maxFunction; + else if ((strcmp("count-non-empty", name))==0) + return xforms_countNonEmptyFunction; + else if ((strcmp("index", name))==0) + return xforms_indexFunction; + else if ((strcmp("property", name))==0) + return xforms_propertyFunction; + else if ((strcmp("now", name))==0) + return xforms_nowFunction; + else if ((strcmp("days-from-date", name))==0) + return xforms_daysFromDateFunction; + else if ((strcmp("seconds-from-dateTime", name))==0) + return xforms_secondsFromDateTimeFunction; + else if ((strcmp("seconds", name))==0) + return xforms_secondsFuction; + else if ((strcmp("months", name))==0) + return xforms_monthsFuction; + else if ((strcmp("instance", name))==0) + return xforms_instanceFuction; + else if ((strcmp("current", name))==0) + return xforms_currentFunction; + else + return NULL; +} + +// boolean functions +void xforms_booleanFromStringFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar *pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8); + if (aString.equalsIgnoreAsciiCaseAscii("true") || aString.equalsIgnoreAsciiCaseAscii("1")) + xmlXPathReturnTrue(ctxt); + else if (aString.equalsIgnoreAsciiCaseAscii("false") || aString.equalsIgnoreAsciiCaseAscii("0")) + xmlXPathReturnFalse(ctxt); + else + XP_ERROR(XPATH_NUMBER_ERROR); +} + +void xforms_ifFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 3) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar *s2 = xmlXPathPopString(ctxt); + + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + xmlChar *s1 = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + bool aBool = xmlXPathPopBoolean(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + + if (aBool) + xmlXPathReturnString(ctxt, s1); + else + xmlXPathReturnString(ctxt, s2); + +} + +// Number Functions +void xforms_avgFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + // use sum(), div() and count() + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + + // save nodeset + xmlXPathObjectPtr pObject = valuePop(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + //push back a copy + valuePush(ctxt, xmlXPathObjectCopy(pObject)); + // get the Sum + xmlXPathSumFunction(ctxt, 1); + double nSum = xmlXPathPopNumber(ctxt); + // push a copy once more + valuePush(ctxt, xmlXPathObjectCopy(pObject)); + xmlXPathCountFunction(ctxt, 1); + double nCount = xmlXPathPopNumber(ctxt); + // push args for div() + xmlXPathReturnNumber(ctxt, nSum); + xmlXPathReturnNumber(ctxt, nCount); + xmlXPathDivValues(ctxt); + // the result is now on the ctxt stack + xmlXPathFreeObject(pObject); +} + +void xforms_minFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + double nMinimum = 0; + double nNumber = 0; + for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++) + { + nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i)); + if (xmlXPathIsNaN(nNumber)) + { + xmlXPathReturnNumber(ctxt, xmlXPathNAN); + return; + } + if (i == 0) + nMinimum = nNumber; + else if (nNumber < nMinimum) + nMinimum = nNumber; + } + xmlXPathReturnNumber(ctxt, nMinimum); +} + +void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + double nMaximum = 0; + double nNumber = 0; + for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++) + { + nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i)); + if (xmlXPathIsNaN(nNumber)) + { + xmlXPathReturnNumber(ctxt, xmlXPathNAN); + return; + } + if (i == 0) + nMaximum = nNumber; + else if (nNumber > nMaximum) + nMaximum = nNumber; + } + xmlXPathReturnNumber(ctxt, nMaximum); +} +void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + xmlChar *aString; + sal_Int32 nNotEmpty = 0; + for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++) + { + aString = xmlXPathCastNodeToString(xmlXPathNodeSetItem(pNodeSet, i)); + if (strlen((char*)aString) > 0) nNotEmpty++; + } + xmlXPathReturnNumber(ctxt, nNotEmpty); +} +void xforms_indexFunction(xmlXPathParserContextPtr /*ctxt*/, int /*nargs*/) +{ + // function index takes a string argument that is the IDREF of a + // 'repeat' and returns the current 1-based position of the repeat + // index of the identified repeat -- see xforms/9.3.1 + + // doc.getElementByID + // (...) +} + +// String Functions +static const char* _version = "1.0"; +static const char* _conformance = "conformance"; +void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar* pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8); + if (aString.equalsIgnoreAsciiCaseAscii("version")) + xmlXPathReturnString(ctxt, (xmlChar*)_version); + else if (aString.equalsIgnoreAsciiCaseAscii("conformance-level")) + xmlXPathReturnString(ctxt, (xmlChar*)_conformance); + else + xmlXPathReturnEmptyString(ctxt); +} + +// Date and Time Functions + +static ::rtl::OString makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_True) +{ + ::rtl::OStringBuffer aDateTimeString; + aDateTimeString.append((sal_Int32)aDateTime.GetYear()); + aDateTimeString.append("-"); + if (aDateTime.GetMonth()<10) aDateTimeString.append("0"); + aDateTimeString.append((sal_Int32)aDateTime.GetMonth()); + aDateTimeString.append("-"); + if (aDateTime.GetDay()<10) aDateTimeString.append("0"); + aDateTimeString.append((sal_Int32)aDateTime.GetDay()); + aDateTimeString.append("T"); + if (aDateTime.GetHour()<10) aDateTimeString.append("0"); + aDateTimeString.append((sal_Int32)aDateTime.GetHour()); + aDateTimeString.append(":"); + if (aDateTime.GetMin()<10) aDateTimeString.append("0"); + aDateTimeString.append((sal_Int32)aDateTime.GetMin()); + aDateTimeString.append(":"); + if (aDateTime.GetSec()<10) aDateTimeString.append("0"); + aDateTimeString.append((sal_Int32)aDateTime.GetSec()); + if (bUTC) aDateTimeString.append("Z"); + + return aDateTimeString.makeStringAndClear(); +} + +// returns current system date and time in canonical xsd:dateTime +// format +void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int /*nargs*/) +{ + /* + A single lexical representation, which is a subset of the lexical representations + allowed by [ISO 8601], is allowed for dateTime. This lexical representation is the + [ISO 8601] extended format CCYY-MM-DDThh:mm:ss where "CC" represents the century, + "YY" the year, "MM" the month and "DD" the day, preceded by an optional leading "-" + sign to indicate a negative number. If the sign is omitted, "+" is assumed. The letter + "T" is the date/time separator and "hh", "mm", "ss" represent hour, minute and second + respectively. + */ + + /* + 3.2.7.2 Canonical representation + The canonical representation for dateTime is defined by prohibiting certain options + from the Lexical representation (par.3.2.7.1). Specifically, either the time zone must + be omitted or, if present, the time zone must be Coordinated Universal Time (UTC) + indicated by a "Z". + */ + DateTime aDateTime; + ::rtl::OString aDateTimeString = makeDateTimeString(aDateTime); + xmlChar *pString = static_cast<xmlChar*>(xmlMalloc(aDateTimeString.getLength()+1)); + strncpy((char*)pString, (char*)aDateTimeString.getStr(), aDateTimeString.getLength()); + pString[aDateTimeString.getLength()] = 0; + xmlXPathReturnString(ctxt, pString); +} + +static sal_Bool parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime) +{ + // take apart a canonical literal xsd:dateTime string + //CCYY-MM-DDThh:mm:ss(Z) + + ::rtl::OUString aDateTimeString = aString.trim(); + + // check length + if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20) + return sal_False; + + sal_Int32 nDateLength = 10; + sal_Int32 nTimeLength = 8; + + ::rtl::OUString aDateTimeSep = ::rtl::OUString::createFromAscii("T"); + ::rtl::OUString aDateSep = ::rtl::OUString::createFromAscii("-"); + ::rtl::OUString aTimeSep = ::rtl::OUString::createFromAscii(":"); + ::rtl::OUString aUTCString = ::rtl::OUString::createFromAscii("Z"); + + ::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength); + ::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength); + + sal_Int32 nIndex = 0; + sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32(); + sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32(); + sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32(); + nIndex = 0; + sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32(); + sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32(); + sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32(); + + Date tmpDate((USHORT)nDay, (USHORT)nMonth, (USHORT)nYear); + Time tmpTime(nHour, nMinute, nSecond); + DateTime tmpDateTime(tmpDate, tmpTime); + if (aString.indexOf(aUTCString) < 0) + tmpDateTime.ConvertToUTC(); + + aDateTime = tmpDateTime; + + return sal_True; +} + + +void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + // number of days from 1970-01-01 to supplied xsd:date(Time) + + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar* pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8); + + DateTime aDateTime; + if (parseDateTime(aString, aDateTime)) + { + Date aReferenceDate(1, 1, 1970); + sal_Int32 nDays = aDateTime - aReferenceDate; + xmlXPathReturnNumber(ctxt, nDays); + } + else + xmlXPathReturnNumber(ctxt, xmlXPathNAN); + + +} + + +void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + // number of seconds from 1970-01-01T00:00:00Z to supplied xsd:date(Time) + + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar* pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8); + + DateTime aDateTime; + + if (parseDateTime(aString, aDateTime)) + { + Date aReferenceDate(1, 1, 1970); + Time aReferenceTime(0, 0, 0); + sal_Int32 nDays = aDateTime - aReferenceDate; + sal_Int32 nSeconds = nDays * 24 * 60 * 60; + nSeconds += aDateTime.GetHour() * 60 * 60; + nSeconds += aDateTime.GetMin() * 60; + nSeconds += aDateTime.GetSec(); + xmlXPathReturnNumber(ctxt, nSeconds); + } + else + xmlXPathReturnNumber(ctxt, xmlXPathNAN); + +} + +static sal_Bool parseDuration(const xmlChar* aString, sal_Bool& bNegative, sal_Int32& nYears, sal_Int32& nMonth, sal_Int32& nDays, + sal_Int32& nHours, sal_Int32& nMinutes, sal_Int32& nSeconds) +{ + sal_Bool bTime = sal_False; // in part after T + sal_Int32 nLength = strlen((char*)aString)+1; + char *pString = (char*)rtl_allocateMemory(nLength); + char *pString0 = pString; + strncpy(pString, (char*)aString, nLength); + + if (pString[0] == '-') { + bNegative = sal_True; + pString++; + } + + if (pString[0] != 'P') + return sal_False; + pString++; + char* pToken = pString; + while(pToken[0] != 0) + { + switch(pToken[0]) { + case 'Y': + pToken[0] = 0; + nYears = atoi(pString); + pString = ++pToken; + break; + case 'M': + pToken[0] = 0; + if (!bTime) + nMonth = atoi(pString); + else + nMinutes = atoi(pString); + pString = ++pToken; + break; + case 'D': + pToken[0] = 0; + nDays = atoi(pString); + pString = ++pToken; + break; + case 'H': + pToken[0] = 0; + nHours = atoi(pString); + pString = ++pToken; + break; + case 'S': + pToken[0] = 0; + nSeconds = atoi(pString); + pString = ++pToken; + break; + case 'T': + bTime = sal_True; + pString = ++pToken; + break; + default: + pToken++; + } + } + rtl_freeMemory(pString0); + return sal_True; +} + +void xforms_secondsFuction(xmlXPathParserContextPtr ctxt, int nargs) +{ + // convert a xsd:duration to seconds + // (-)PnYnMnDTnHnMnS + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar* pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + + sal_Bool bNegative = sal_False; + sal_Int32 nYears = 0; + sal_Int32 nMonths = 0; + sal_Int32 nDays = 0; + sal_Int32 nHours = 0; + sal_Int32 nMinutes = 0; + sal_Int32 nSeconds = 0; + + if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds)) + { + nSeconds += nMinutes*60; + nSeconds += nHours*60*60; + nSeconds += nDays*24*60*60; + // year and month are ignored according to spec + if (bNegative) + nSeconds = 0 - nSeconds; + xmlXPathReturnNumber(ctxt, nSeconds); + } + else + xmlXPathReturnNumber(ctxt, xmlXPathNAN); +} + +void xforms_monthsFuction(xmlXPathParserContextPtr ctxt, int nargs) +{ + // convert a xsd:duration to seconds + // (-)PnYnMnDTnHnMnS + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar* pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + + sal_Bool bNegative = sal_False; + sal_Int32 nYears = 0; + sal_Int32 nMonths = 0; + sal_Int32 nDays = 0; + sal_Int32 nHours = 0; + sal_Int32 nMinutes = 0; + sal_Int32 nSeconds = 0; + + if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds)) + { + nMonths += nYears*12; + // Days, Houres, Minutes and seconds are ignored, see spec + if (bNegative) + nMonths = 0 - nMonths; + xmlXPathReturnNumber(ctxt, nMonths); + } + else + xmlXPathReturnNumber(ctxt, xmlXPathNAN); + +} + +// Node-set Functions +void xforms_instanceFuction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY); + xmlChar *pString = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE); + ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8); + + Reference< XModel > aModel = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getModel(); + if (aModel.is()) + { + Reference< XDocument > aInstance = aModel->getInstanceDocument(aString); + if (aInstance.is()) + { + try { + // xmlXPathObjectPtr xmlXPathNewNodeSet (xmlNodePtr val); + Reference< XUnoTunnel > aTunnel(aInstance, UNO_QUERY_THROW); + xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) ); + xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode); + xmlXPathReturnNodeSet(ctxt, pObject->nodesetval); + } catch (RuntimeException&) + { + xmlXPathReturnEmptyNodeSet(ctxt); + } + } + else + xmlXPathReturnEmptyNodeSet(ctxt); + } + else + xmlXPathReturnEmptyNodeSet(ctxt); + +} + +// Node-set Functions, XForms 1.1 +void xforms_currentFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + if (nargs != 0) XP_ERROR(XPATH_INVALID_ARITY); + + Reference< XNode > aNode = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getContextNode(); + + if (aNode.is()) + { + try { + Reference< XUnoTunnel > aTunnel(aNode, UNO_QUERY_THROW); + xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) ); + xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode); + xmlXPathReturnNodeSet(ctxt, pObject->nodesetval); + } + catch (RuntimeException&) + { + xmlXPathReturnEmptyNodeSet(ctxt); + } + } + else + xmlXPathReturnEmptyNodeSet(ctxt); +} diff --git a/forms/source/xforms/xpathlib/xpathlib.hxx b/forms/source/xforms/xpathlib/xpathlib.hxx new file mode 100644 index 000000000000..d9fe96e598ca --- /dev/null +++ b/forms/source/xforms/xpathlib/xpathlib.hxx @@ -0,0 +1,83 @@ + + +#include <libxml/tree.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> + +/* + entry functions for libxml xpath engine + +*/ + +/** + * xmlXPathParserContext: + * + * An XPath parser context. It contains pure parsing informations, + * an xmlXPathContext, and the stack of objects. + */ +#if 0 +// for reference from xpath.h +struct _xmlXPathParserContext { + const xmlChar *cur; /* the current char being parsed */ + const xmlChar *base; /* the full expression */ + + int error; /* error code */ + + xmlXPathContextPtr context; /* the evaluation context */ + xmlXPathObjectPtr value; /* the current value */ + int valueNr; /* number of values stacked */ + int valueMax; /* max number of values stacked */ + xmlXPathObjectPtr *valueTab; /* stack of values */ + + xmlXPathCompExprPtr comp; /* the precompiled expression */ + int xptr; /* it this an XPointer expression */ + xmlNodePtr ancestor; /* used for walking preceding axis */ +}; + +#endif + +extern "C" +{ + +// XForms +/* +void xforms_getInstanceDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_rebuildFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_recalculateFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_revalidateFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_refreshFunction(xmlXPathParserContextPtr ctxt, int nargs); +*/ + +// XForms Core Functions +// boolean functions +void xforms_booleanFromStringFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_ifFunction(xmlXPathParserContextPtr ctxt, int nargs); + +// Number Functions +void xforms_avgFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_minFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_indexFunction(xmlXPathParserContextPtr ctxt, int nargs); + +// String Functions +void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_versionFunction(xmlXPathParserContextPtr ctxt, int nargs); + +// Date and Time Functions +void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_secondsFuction(xmlXPathParserContextPtr ctxt, int nargs); +void xforms_monthsFuction(xmlXPathParserContextPtr ctxt, int nargs); + +// Node-set Functions +void xforms_instanceFuction(xmlXPathParserContextPtr ctxt, int nargs); + +// Node-set Functions; XForms 1.1 +void xforms_currentFunction(xmlXPathParserContextPtr ctxt, int nargs); + +// --- lookup --- +xmlXPathFunction xforms_lookupFunc(void *ctxt, const xmlChar *name, const xmlChar *ns_uri); + +} diff --git a/forms/util/frm.dxp b/forms/util/frm.dxp new file mode 100644 index 000000000000..9e59e94034a6 --- /dev/null +++ b/forms/util/frm.dxp @@ -0,0 +1,3 @@ +component_writeInfo +component_getImplementationEnvironment +component_getFactory diff --git a/forms/util/frm.map b/forms/util/frm.map new file mode 100644 index 000000000000..7975644b139a --- /dev/null +++ b/forms/util/frm.map @@ -0,0 +1,8 @@ +FORMS_1_0 { + global: + component_getImplementationEnvironment; + component_writeInfo; + component_getFactory; + local: + *; +}; diff --git a/forms/util/frm.xml b/forms/util/frm.xml new file mode 100644 index 000000000000..d3603acdf909 --- /dev/null +++ b/forms/util/frm.xml @@ -0,0 +1,571 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description SYSTEM "module-description.dtd"> +<module-description> + <module-name>forms</module-name> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OFormsCollection</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.Forms</supported-service> + <supported-service>com.sun.star.form.FormComponents</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ODatabaseForm</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormComponents</supported-service> + <supported-service>com.sun.star.form.component.Form</supported-service> + <supported-service>com.sun.star.form.component.HTMLForm</supported-service> + <supported-service>com.sun.star.form.component.DataForm</supported-service> + <supported-service>com.sun.star.sdb.RowSet</supported-service> + <supported-service>com.sun.star.sdbc.RowSet</supported-service> + <supported-service>com.sun.star.sdb.ResultSet</supported-service> + <supported-service>com.sun.star.sdbcx.ResultSet</supported-service> + <supported-service>com.sun.star.sdbc.ResultSet</supported-service> + <service-dependency>com.sun.star.util.URLTransformer</service-dependency> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OFixedTextModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.FixedText</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlFixedTextModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OHiddenModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.HiddenControl</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OFileControlModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.FileControl</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlFileControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OGroupBoxModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.GroupBox</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlGroupBoxModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OImageButtonModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.ImageButton</supported-service> + <supported-service>com.sun.star.form.component.SubmitButton</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlImageControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OButtonModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.CommandButton</supported-service> + <supported-service>com.sun.star.form.component.SubmitButton</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlButtonModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OGridControlModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.GridControl</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ORadioButtonModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseRadioButton</supported-service> + <supported-service>com.sun.star.form.component.DatabaseRadioButton</supported-service> + <supported-service>com.sun.star.form.component.RadioButton</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlRadioButtonModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OCheckBoxModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseCheckBox</supported-service> + <supported-service>com.sun.star.form.component.DatabaseCheckBox</supported-service> + <supported-service>com.sun.star.form.component.CheckBox</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlCheckBoxModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OComboBoxModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseComboBox</supported-service> + <supported-service>com.sun.star.form.component.DatabaseComboBox</supported-service> + <supported-service>com.sun.star.form.component.ComboBox</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlComboBoxModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + <service-dependency>com.sun.star.util.NumberFormatter</service-dependency> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OListBoxModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseListBox</supported-service> + <supported-service>com.sun.star.form.component.DatabaseListBox</supported-service> + <supported-service>com.sun.star.form.component.ListBox</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlListBoxModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + <service-dependency>com.sun.star.util.NumberFormatter</service-dependency> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OEditModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseTextField</supported-service> + <supported-service>com.sun.star.form.component.DatabaseTextField</supported-service> + <supported-service>com.sun.star.form.component.TextField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlEditModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + <service-dependency>com.sun.star.util.NumberFormatter</service-dependency> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ODateModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseDateField</supported-service> + <supported-service>com.sun.star.form.component.DatabaseDateField</supported-service> + <supported-service>com.sun.star.form.component.DateField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlDateFieldModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OTimeModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseTimeField</supported-service> + <supported-service>com.sun.star.form.component.DatabaseTimeField</supported-service> + <supported-service>com.sun.star.form.component.TimeField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlTimeFieldModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ONumericModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseNumericField</supported-service> + <supported-service>com.sun.star.form.component.DatabaseNumericField</supported-service> + <supported-service>com.sun.star.form.component.NumericField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlNumericFieldModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OCurrencyModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.component.DatabaseCurrencyField</supported-service> + <supported-service>com.sun.star.form.component.CurrencyField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlCurrencyFieldModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OPatternModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.DatabasePatternField</supported-service> + <supported-service>com.sun.star.form.component.PatternField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlPatternFieldModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OImageControlModel</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.DatabaseImageControl</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlImageControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author>Frank Schoenheit</author> + <name>com.sun.star.comp.forms.OFormattedFieldWrapper</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.binding.BindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableControlModel</supported-service> + <supported-service>com.sun.star.form.validation.ValidatableBindableControlModel</supported-service> + <supported-service>com.sun.star.form.binding.BindableDatabaseFormattedField</supported-service> + <supported-service>com.sun.star.form.component.DatabaseFormattedField</supported-service> + <supported-service>com.sun.star.form.component.FormattedField</supported-service> + <supported-service>com.sun.star.form.DataAwareControlModel</supported-service> + <supported-service>com.sun.star.form.FormComponent</supported-service> + <supported-service>com.sun.star.form.FormControlModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlFormattedFieldModel</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ORadioButtonControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.RadioButton</supported-service> + <supported-service>com.sun.star.awt.UnoControlRadioButton</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OCheckBoxControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.CheckBox</supported-service> + <supported-service>com.sun.star.awt.UnoControlCheckBox</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OGroupBoxControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.GroupBox</supported-service> + <supported-service>com.sun.star.awt.UnoControlGroupBox</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OListBoxControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.ListBox</supported-service> + <supported-service>com.sun.star.awt.UnoControlListBox</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OComboBoxControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.ComboBox</supported-service> + <supported-service>com.sun.star.awt.UnoControlComboBox</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OEditControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.TextField</supported-service> + <supported-service>com.sun.star.awt.UnoControlEdit</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ODateControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.DateField</supported-service> + <supported-service>com.sun.star.awt.UnoControlDateField</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OTimeControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.TimeField</supported-service> + <supported-service>com.sun.star.awt.UnoControlTimeField</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.ONumericControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.NumericField</supported-service> + <supported-service>com.sun.star.awt.UnoControlNumericField</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OCurrencyControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.CurrencyField</supported-service> + <supported-service>com.sun.star.awt.UnoControlCurrencyField</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OPatternControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.PatternField</supported-service> + <supported-service>com.sun.star.awt.UnoControlPatternField</supported-service> + </component-description> + <component-description> + <author>Frank Schoenheit</author> + <name>com.sun.star.comp.forms.OFormattedControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.FormattedField</supported-service> + <supported-service>com.sun.star.awt.UnoControlFormattedField</supported-service> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OButtonControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.CommandButton</supported-service> + <supported-service>com.sun.star.form.control.SubmitButton</supported-service> + <supported-service>com.sun.star.awt.UnoControlButton</supported-service> + <service-dependency>com.sun.star.util.URLTransformer</service-dependency> + <service-dependency>com.sun.star.awt.Pointer</service-dependency> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OImageButtonControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.ImageButton</supported-service> + <supported-service>com.sun.star.form.control.SubmitButton</supported-service> + <supported-service>com.sun.star.awt.UnoControlImageControl</supported-service> + <service-dependency>com.sun.star.util.URLTransformer</service-dependency> + <service-dependency>com.sun.star.awt.Pointer</service-dependency> + </component-description> + <component-description> + <author></author> + <name>com.sun.star.comp.forms.OImageControlControl</name> + <description></description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.ImageControl</supported-service> + <supported-service>com.sun.star.awt.UnoControlImageControl</supported-service> + </component-description> + <component-description> + <author>Frank Schönheit</author> + <name>com.sun.star.comp.forms.OScrollBarModel</name> + <description>specifies the model of a scroll bar control which can exist in a form layer.</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.ScrollBar</supported-service> + <supported-service>com.sun.star.awt.UnoControlScrollBarModel</supported-service> + </component-description> + <component-description> + <author>Frank Schönheit</author> + <name>com.sun.star.comp.forms.OSpinButtonModel</name> + <description>specifies the model of a spin button control which can exist in a form layer.</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.SpinButton</supported-service> + <supported-service>com.sun.star.awt.UnoControlSpinButtonModel</supported-service> + </component-description> + <component-description> + <author>Frank Schönheit</author> + <name>com.sun.star.comp.form.ONavigationBarModel</name> + <description>specifies the model of a control which provides navigation and other form controller related functionality.</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.component.NavigationToolBar</supported-service> + <supported-service>com.sun.star.awt.UnoControlModel</supported-service> + </component-description> + <component-description> + <author>Frank Schönheit</author> + <name>com.sun.star.comp.form.ONavigationBarControl</name> + <description>specifies a control which provides navigation and other form controller related functionality.</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.form.control.NavigationToolBar</supported-service> + <supported-service>com.sun.star.awt.UnoControl</supported-service> + </component-description> + <project-build-dependency>sal</project-build-dependency> + <project-build-dependency>osl</project-build-dependency> + <project-build-dependency>one</project-build-dependency> + <project-build-dependency>cppu</project-build-dependency> + <project-build-dependency>cppuhelper</project-build-dependency> + <project-build-dependency>tools</project-build-dependency> + <project-build-dependency>vcl</project-build-dependency> + <project-build-dependency>svtool</project-build-dependency> + <project-build-dependency>sfx2</project-build-dependency> + <project-build-dependency>vos</project-build-dependency> + <project-build-dependency>unotools</project-build-dependency> + <project-build-dependency>toolkit</project-build-dependency> + <runtime-module-dependency>sal</runtime-module-dependency> + <runtime-module-dependency>osl</runtime-module-dependency> + <runtime-module-dependency>one</runtime-module-dependency> + <runtime-module-dependency>cppu</runtime-module-dependency> + <runtime-module-dependency>cppuhelper</runtime-module-dependency> + <runtime-module-dependency>tools</runtime-module-dependency> + <runtime-module-dependency>vcl</runtime-module-dependency> + <runtime-module-dependency>svtool</runtime-module-dependency> + <runtime-module-dependency>sfx2</runtime-module-dependency> + <runtime-module-dependency>vos</runtime-module-dependency> + <runtime-module-dependency>unotools</runtime-module-dependency> + <runtime-module-dependency>toolkit</runtime-module-dependency> +</module-description> diff --git a/forms/util/makefile.mk b/forms/util/makefile.mk new file mode 100644 index 000000000000..66de3cb83fb2 --- /dev/null +++ b/forms/util/makefile.mk @@ -0,0 +1,114 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. +PRJNAME=forms +TARGET=frm +USE_DEFFILE=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Library ----------------------------------- +# --- frm --------------------------------------- +LIB1TARGET=$(SLB)$/forms.lib +LIB1FILES=\ + $(SLB)$/common.lib \ + $(SLB)$/resource.lib \ + $(SLB)$/component.lib \ + $(SLB)$/helper.lib \ + $(SLB)$/solarcomponent.lib \ + $(SLB)$/solarcontrol.lib \ + $(SLB)$/richtext.lib \ + $(SLB)$/runtime.lib \ + $(SLB)$/xforms.lib \ + $(SLB)$/xformssubmit.lib \ + $(SLB)$/xformsxpath.lib + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) + +SHL1STDLIBS= \ + $(EDITENGLIB) \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(VCLLIB) \ + $(SVTOOLLIB) \ + $(SVLLIB) \ + $(TKLIB) \ + $(SFX2LIB) \ + $(VOSLIB) \ + $(UNOTOOLSLIB) \ + $(COMPHELPERLIB) \ + $(DBTOOLSLIB) \ + $(TKLIB) \ + $(SVXCORELIB) \ + $(UCBHELPERLIB) \ + $(LIBXML2LIB) \ + $(ICUUCLIB) \ + $(ICUINLIB) + +SHL1LIBS=$(LIB1TARGET) +SHL1DEPN=$(LIB1TARGET) \ + makefile.mk + + +SHL1VERSIONMAP=$(TARGET).map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +# === .res file ========================================================== + +RES1FILELIST=\ + $(SRS)$/resource.srs \ + +RESLIB1NAME=$(TARGET) +RESLIB1SRSFILES=$(RES1FILELIST) + +.IF "$(GUI)"=="OS2" +SHL1STDLIBS += pthread.lib libz.lib +.ENDIF + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + +# --- Filter-Datei --- + +$(MISC)$/$(SHL1TARGET).flt: makefile.mk + @echo ------------------------------ + @echo __CT >$@ + @echo createRegistryInfo >>$@ + @echo queryInterface >>$@ + @echo queryAggregation >>$@ + @echo NavigationToolBar >>$@ + @echo ONavigationBar >>$@ + diff --git a/forms/workben/xforms/sickness.odt b/forms/workben/xforms/sickness.odt Binary files differnew file mode 100644 index 000000000000..b48082212a51 --- /dev/null +++ b/forms/workben/xforms/sickness.odt diff --git a/forms/workben/xforms/simple_validation.odt b/forms/workben/xforms/simple_validation.odt Binary files differnew file mode 100644 index 000000000000..216fba738204 --- /dev/null +++ b/forms/workben/xforms/simple_validation.odt diff --git a/forms/workben/xforms/vacationrequest.odt b/forms/workben/xforms/vacationrequest.odt Binary files differnew file mode 100644 index 000000000000..ce4854257328 --- /dev/null +++ b/forms/workben/xforms/vacationrequest.odt diff --git a/forms/workben/xforms/xforms-ubl.odt b/forms/workben/xforms/xforms-ubl.odt Binary files differnew file mode 100644 index 000000000000..7ffaab9bc16b --- /dev/null +++ b/forms/workben/xforms/xforms-ubl.odt |