From ecd4928b327f5561364c5068c9ff5f1668e92d13 Mon Sep 17 00:00:00 2001 From: Christian W. Damus Date: Wed, 10 Feb 2016 21:48:20 -0500 Subject: Bug 485220: [Architecture] Provide a more modular architecture https://bugs.eclipse.org/bugs/show_bug.cgi?id=485220 Factor UI dependencies out of the UML Element Types bundle. This includes moving some advices that interact with the user into a new org.eclipse.papyrus.uml.service.types.ui bundle. Pull up the PasteCommandService and IPasteCommandProvider API into the Infra Diagram layer where the extension point is defined. Deprecate the old API in the UML layer. Introduce a service for participation of languages in CSS styling: * styling reset actions in the Reset Style command * access to semantic model classes and properties to make available to CSS Factor PapyrusObservableValue and cohorts out of the UML Tools bundle into the Infra Layer for more general reuse and to relieve the Diagram Infrastructure layer of UML dependencies. The old API remains as deprecated. Remove the Infra Diagram Layer dependency on UML Layer for property testers governing deletion in the diagram. Includes introduction of a new IGraphicalDeletionHelper OSGi service for delegation of the determination of whether an element can be deleted from the diagram and replacement of the XML expression properties * org.eclipse.papyrus.uml.diagram.common.isSemanticDeletion * org.eclipse.papyrus.uml.diagram.common.isReadOnly by * org.eclipse.papyrus.infra.gmfdiag.common.isSemanticDeletion * org.eclipse.papyrus.infra.gmfdiag.common.canDelete (where the latter is the negation of the property that it supersedes) Extract UML dependencies from the Diagram Outline and CSS Editor bundles. Remove unused MDTUtil APIs that referenced a UML-specific annotation. Move the Diagram Infrastructure CSS Palette bundle into the UML layer because it serves to provide extensions on the Palette Service, which is an overtly UML-specific capability. All client APIs for the Properties View are moved from org.eclipse.papyrus.views.properties bundle to a new org.eclipse.papyrus.infra.properties.ui bundle. This includes renaming of: * extension points * label-provider contexts * XWT namespaces Add an "all UI tests" suite. Define a componentized hierarchical build layout of the main plug-ins Change-Id: I43f8f3644857a18b69715f5a2f1da9b1cf286d67 --- .../pom.xml | 8 +- .../pom.xml | 8 +- .../.classpath | 7 + .../.project | 28 + .../.settings/org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 291 +++++++ .../.settings/org.eclipse.jdt.ui.prefs | 68 ++ .../META-INF/MANIFEST.MF | 45 + .../about.html | 28 + .../build.properties | 14 + .../model/Environment.xmi | 230 +++++ .../plugin.properties | 21 + .../plugin.xml | 52 ++ .../pom.xml | 12 + .../schema/configuration.exsd | 83 ++ .../schema/context.exsd | 137 +++ .../schema/labelprovider.exsd | 109 +++ .../infra/properties/internal/ui/Activator.java | 121 +++ .../extensions/ContextBindingsExtensionPoint.java | 81 ++ .../properties/internal/ui/messages/Messages.java | 52 ++ .../internal/ui/messages/messages.properties | 10 + .../ui/observable/PreferencesObservableValue.java | 63 ++ .../internal/ui/runtime/ConfigurationConflict.java | 70 ++ .../ui/runtime/IInternalConfigurationManager.java | 135 +++ .../properties/ui/creation/CreateInDialog.java | 180 ++++ .../properties/ui/creation/CreationContext.java | 63 ++ .../ui/creation/EcorePropertyEditorFactory.java | 537 ++++++++++++ .../properties/ui/creation/EditionDialog.java | 351 ++++++++ .../ui/creation/PropertyEditorFactory.java | 240 +++++ .../AbstractEMFModelElementFactory.java | 41 + .../ui/modelelement/AbstractModelElement.java | 235 +++++ .../modelelement/AbstractModelElementFactory.java | 40 + .../ui/modelelement/AnnotationModelElement.java | 73 ++ .../AnnotationModelElementFactory.java | 55 ++ .../ui/modelelement/CompositeModelElement.java | 256 ++++++ .../properties/ui/modelelement/DataSource.java | 559 ++++++++++++ .../ui/modelelement/DataSourceChangedEvent.java | 32 + .../ui/modelelement/DataSourceFactory.java | 242 ++++++ .../ui/modelelement/EMFModelElement.java | 308 +++++++ .../ui/modelelement/EMFModelElementFactory.java | 41 + .../ui/modelelement/IDataSourceListener.java | 29 + .../properties/ui/modelelement/ModelElement.java | 188 ++++ .../ui/modelelement/ModelElementFactory.java | 42 + .../ui/modelelement/PreferencesModelElement.java | 37 + .../PreferencesModelElementFactory.java | 31 + .../properties/ui/preferences/Preferences.java | 268 ++++++ .../ui/providers/ContainerContentProvider.java | 60 ++ .../providers/CreateInFeatureContentProvider.java | 27 + .../ui/providers/EncapsulatedComboViewer.java | 47 + .../ui/providers/EncapsulatedViewerFilter.java | 36 + .../ui/providers/FeatureContentProvider.java | 67 ++ .../providers/PropertiesHeaderLabelProvider.java | 55 ++ .../ui/providers/SelectionLabelProvider.java | 61 ++ .../ui/providers/XWTCompliantMaskProvider.java | 31 + .../XWTCompliantMaskProviderListener.java | 23 + .../ui/runtime/ConfigurationManagerRegistry.java | 257 ++++++ .../ui/runtime/DefaultDisplayEngine.java | 406 +++++++++ .../infra/properties/ui/runtime/DisplayEngine.java | 103 +++ .../ui/runtime/EmbeddedDisplayEngine.java | 239 +++++ .../ui/runtime/IConfigurationManager.java | 211 +++++ .../properties/ui/runtime/PropertiesRuntime.java | 52 ++ .../ui/runtime/SectionDiscriminator.java | 108 +++ .../infra/properties/ui/runtime/TabModel.java | 196 +++++ .../ui/runtime/ViewConstraintEngine.java | 28 + .../ui/runtime/ViewConstraintEngineImpl.java | 64 ++ .../properties/ui/util/EMFURLStreamHandler.java | 147 ++++ .../ui/util/PropertiesDisplayHelper.java | 125 +++ .../infra/properties/ui/util/PropertiesUtil.java | 303 +++++++ .../ui/widgets/AbstractPropertyEditor.java | 663 ++++++++++++++ .../properties/ui/widgets/BooleanCheckbox.java | 36 + .../infra/properties/ui/widgets/BooleanCombo.java | 37 + .../infra/properties/ui/widgets/BooleanRadio.java | 38 + .../infra/properties/ui/widgets/BooleanToggle.java | 98 +++ .../ui/widgets/BrowseFilePropertyEditor.java | 175 ++++ .../CompletionStyledTextMultiReference.java | 65 ++ .../CompletionStyledTextReferenceDialog.java | 109 +++ .../ui/widgets/CustomizablePropertyEditor.java | 44 + .../infra/properties/ui/widgets/DoubleEditor.java | 39 + .../infra/properties/ui/widgets/EnumCombo.java | 58 ++ .../infra/properties/ui/widgets/EnumRadio.java | 76 ++ .../infra/properties/ui/widgets/FloatEditor.java | 39 + .../infra/properties/ui/widgets/IntegerEditor.java | 36 + .../infra/properties/ui/widgets/IntegerMask.java | 73 ++ .../properties/ui/widgets/IntegerSpinner.java | 105 +++ .../infra/properties/ui/widgets/InvalidWidget.java | 62 ++ .../infra/properties/ui/widgets/MaskProvider.java | 29 + .../infra/properties/ui/widgets/MultiDouble.java | 63 ++ .../infra/properties/ui/widgets/MultiInteger.java | 69 ++ .../properties/ui/widgets/MultiReference.java | 106 +++ .../MultiReferenceEditorWithPropertyView.java | 169 ++++ ...ltiReferencePropertyEditorWithPropertyView.java | 62 ++ .../infra/properties/ui/widgets/MultiString.java | 90 ++ .../properties/ui/widgets/MultiStringFile.java | 99 +++ .../properties/ui/widgets/ReferenceCombo.java | 68 ++ .../properties/ui/widgets/ReferenceDialog.java | 99 +++ .../properties/ui/widgets/ReferenceLabel.java | 63 ++ .../infra/properties/ui/widgets/StringCombo.java | 68 ++ .../infra/properties/ui/widgets/StringEditor.java | 36 + .../ui/widgets/StringEditorWithReferences.java | 166 ++++ .../properties/ui/widgets/StringFileSelector.java | 146 ++++ .../ui/widgets/StringFileSelectorEMF.java | 58 ++ .../infra/properties/ui/widgets/StringLabel.java | 61 ++ .../infra/properties/ui/widgets/StringMask.java | 114 +++ .../properties/ui/widgets/StringMultiline.java | 38 + .../ui/widgets/StringMultilineWithReferences.java | 183 ++++ .../ui/widgets/UnlimitedNaturalEditor.java | 29 + .../infra/properties/ui/widgets/ViewEditor.java | 415 +++++++++ .../ui/widgets/XWTStringFileSelectorEMF.java | 48 + .../properties/ui/widgets/layout/GridData.java | 651 ++++++++++++++ .../ui/widgets/layout/PropertiesLayout.java | 961 +++++++++++++++++++++ .../infra/properties/ui/xwt/XWTSection.java | 247 ++++++ .../properties/ui/xwt/XWTSectionDescriptor.java | 109 +++ .../infra/properties/ui/xwt/XWTTabDescriptor.java | 144 +++ .../ui/xwt/XWTTabDescriptorProvider.java | 284 ++++++ .../META-INF/MANIFEST.MF | 6 +- .../org.eclipse.papyrus.infra.properties/pom.xml | 8 +- plugins/infra/properties/pom.xml | 20 + 117 files changed, 14613 insertions(+), 18 deletions(-) create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.classpath create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.project create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.core.resources.prefs create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.core.prefs create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.ui.prefs create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/META-INF/MANIFEST.MF create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/about.html create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/build.properties create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/model/Environment.xmi create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.properties create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.xml create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/pom.xml create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/configuration.exsd create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/context.exsd create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/labelprovider.exsd create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/Activator.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/extensions/ContextBindingsExtensionPoint.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/Messages.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/messages.properties create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/observable/PreferencesObservableValue.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/ConfigurationConflict.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/IInternalConfigurationManager.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreateInDialog.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreationContext.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EcorePropertyEditorFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EditionDialog.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/PropertyEditorFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractEMFModelElementFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElement.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElementFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElement.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElementFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/CompositeModelElement.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSource.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceChangedEvent.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElement.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElementFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/IDataSourceListener.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElement.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElementFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElement.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElementFactory.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/preferences/Preferences.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/ContainerContentProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/CreateInFeatureContentProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedComboViewer.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedViewerFilter.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/FeatureContentProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/PropertiesHeaderLabelProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/SelectionLabelProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProviderListener.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ConfigurationManagerRegistry.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DefaultDisplayEngine.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DisplayEngine.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/EmbeddedDisplayEngine.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/IConfigurationManager.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/PropertiesRuntime.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/SectionDiscriminator.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/TabModel.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngine.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngineImpl.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/EMFURLStreamHandler.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesDisplayHelper.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesUtil.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/AbstractPropertyEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCheckbox.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCombo.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanRadio.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanToggle.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BrowseFilePropertyEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextMultiReference.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextReferenceDialog.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CustomizablePropertyEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/DoubleEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumCombo.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumRadio.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/FloatEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerMask.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerSpinner.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/InvalidWidget.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MaskProvider.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiDouble.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiInteger.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReference.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferenceEditorWithPropertyView.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferencePropertyEditorWithPropertyView.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiString.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiStringFile.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceCombo.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceDialog.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceLabel.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringCombo.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditorWithReferences.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelector.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelectorEMF.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringLabel.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMask.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultiline.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultilineWithReferences.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/UnlimitedNaturalEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ViewEditor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/XWTStringFileSelectorEMF.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/GridData.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/PropertiesLayout.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSection.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSectionDescriptor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptor.java create mode 100644 plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptorProvider.java create mode 100644 plugins/infra/properties/pom.xml (limited to 'plugins/infra/properties') diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.edit/pom.xml b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.edit/pom.xml index 1f1e99fb5df..facf33f1262 100644 --- a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.edit/pom.xml +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.edit/pom.xml @@ -2,13 +2,11 @@ 4.0.0 - org.eclipse.papyrus.releng + org.eclipse.papyrus.infra-properties org.eclipse.papyrus - 1.2.0-SNAPSHOT - ../../../../releng/main + 0.0.1-SNAPSHOT org.eclipse.papyrus.infra.properties.edit - org.eclipse.papyrus 1.2.0-SNAPSHOT eclipse-plugin - \ No newline at end of file + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.editor/pom.xml b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.editor/pom.xml index f5783dd9713..aa82b8bc856 100644 --- a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.editor/pom.xml +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.editor/pom.xml @@ -2,13 +2,11 @@ 4.0.0 - org.eclipse.papyrus.releng + org.eclipse.papyrus.infra-properties org.eclipse.papyrus - 1.2.0-SNAPSHOT - ../../../../releng/main + 0.0.1-SNAPSHOT org.eclipse.papyrus.infra.properties.editor - org.eclipse.papyrus 1.2.0-SNAPSHOT eclipse-plugin - \ No newline at end of file + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.classpath b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.classpath new file mode 100644 index 00000000000..eca7bdba8f0 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.project b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.project new file mode 100644 index 00000000000..10139af5ffd --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.project @@ -0,0 +1,28 @@ + + + org.eclipse.papyrus.infra.properties.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.core.resources.prefs b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..f88d7da2697 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//src/org/eclipse/papyrus/infra/properties/internal/ui/messages/messages.properties=ISO-8859-1 diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.core.prefs b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..b3aa6d60f94 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,291 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=260 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=260 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=5 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.ui.prefs b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..954281dbc31 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,68 @@ +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.insert_inferred_type_arguments=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_type_arguments=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_anonymous_class_creation=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup.use_type_arguments=false +cleanup_profile=_Papyrus +cleanup_settings_version=2 +eclipse.preferences.version=1 +formatter_profile=_Papyrus +formatter_settings_version=12 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/META-INF/MANIFEST.MF b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..332d9bb892f --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/META-INF/MANIFEST.MF @@ -0,0 +1,45 @@ +Manifest-Version: 1.0 +Export-Package: org.eclipse.papyrus.infra.properties.internal.ui;x-internal:=true, + org.eclipse.papyrus.infra.properties.internal.ui.extensions;x-friends:="org.eclipse.papyrus.views.properties", + org.eclipse.papyrus.infra.properties.internal.ui.messages;x-internal:=true, + org.eclipse.papyrus.infra.properties.internal.ui.observable;x-internal:=true, + org.eclipse.papyrus.infra.properties.internal.ui.runtime;x-friends:="org.eclipse.papyrus.customization.properties,org.eclipse.papyrus.views.properties", + org.eclipse.papyrus.infra.properties.ui.creation, + org.eclipse.papyrus.infra.properties.ui.modelelement, + org.eclipse.papyrus.infra.properties.ui.preferences, + org.eclipse.papyrus.infra.properties.ui.providers, + org.eclipse.papyrus.infra.properties.ui.runtime, + org.eclipse.papyrus.infra.properties.ui.util, + org.eclipse.papyrus.infra.properties.ui.widgets, + org.eclipse.papyrus.infra.properties.ui.widgets.layout, + org.eclipse.papyrus.infra.properties.ui.xwt +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: . +Bundle-Name: %pluginName +Bundle-Localization: plugin +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.emf.ecore;bundle-version="2.6.0";visibility:=reexport, + org.eclipse.emf.databinding;bundle-version="1.2.0", + org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.core.resources;bundle-version="3.6.0", + org.eclipse.papyrus.infra.properties;bundle-version="1.2.0", + org.eclipse.papyrus.infra.widgets;bundle-version="1.2.0", + org.eclipse.papyrus.infra.emf;bundle-version="1.2.0", + org.eclipse.papyrus.infra.core.log;bundle-version="1.2.0", + org.eclipse.papyrus.infra.core;bundle-version="1.2.0", + org.eclipse.emf.edit;bundle-version="2.8.0", + org.eclipse.ui.views.properties.tabbed;bundle-version="3.5.300", + org.eclipse.papyrus.infra.services.labelprovider;bundle-version="1.2.0", + org.eclipse.papyrus.infra.widgets.toolbox;bundle-version="1.2.0", + org.eclipse.papyrus.emf.facet.custom.core;bundle-version="1.2.0", + org.eclipse.xwt;bundle-version="1.1.0", + org.eclipse.papyrus.infra.ui.emf;bundle-version="1.2.0", + org.eclipse.papyrus.emf.facet.custom.ui;bundle-version="1.2.0", + org.eclipse.core.databinding.property;bundle-version="1.6.0" +Bundle-Vendor: %Bundle-Vendor +Bundle-Version: 1.2.0.qualifier +Eclipse-BuddyPolicy: dependent +Bundle-Activator: org.eclipse.papyrus.infra.properties.internal.ui.Activator +Bundle-ManifestVersion: 2 +Bundle-Description: %pluginDescription +Bundle-SymbolicName: org.eclipse.papyrus.infra.properties.ui;singleton:=true diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/about.html b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/about.html new file mode 100644 index 00000000000..d35d5aed64c --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/about.html @@ -0,0 +1,28 @@ + + + + +About + + +

About This Content

+ +

June 5, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/build.properties b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/build.properties new file mode 100644 index 00000000000..800139464b5 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/build.properties @@ -0,0 +1,14 @@ +# +#Mon Sep 12 09:30:04 CEST 2011 +output..=bin/ +bin.includes = .,\ + META-INF/,\ + plugin.xml,\ + plugin.properties,\ + schema/,\ + about.html,\ + model/ +jars.compile.order=. +src.includes = about.html +source..=src/ +bin..=bin/ diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/model/Environment.xmi b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/model/Environment.xmi new file mode 100644 index 00000000000..ce094a1c8a7 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/model/Environment.xmi @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.properties b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.properties new file mode 100644 index 00000000000..45b04f0585c --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.properties @@ -0,0 +1,21 @@ +############################################################################# +# Copyright (c) 2011, 2016 CEA LIST, Christian W. Damus, and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# CEA LIST - Initial API and implementation +# Christian W. Damus - bug 485220 +############################################################################# + +pluginName = Papyrus Properties Run-time +providerName = Eclipse Modeling Project + +Bundle-Vendor = Eclipse Modeling Project +page.name = Property views +extension-point.context = Context + +pluginDescription=This plug-in contains the runtime elements for the property view framework, as well as a set of basic tools: basic property editors, EMF Data manipulation, ... \ No newline at end of file diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.xml b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.xml new file mode 100644 index 00000000000..2c1352e8ebc --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/plugin.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/pom.xml b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/pom.xml new file mode 100644 index 00000000000..14076b4f844 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + org.eclipse.papyrus.infra-properties + org.eclipse.papyrus + 0.0.1-SNAPSHOT + + org.eclipse.papyrus.infra.properties.ui + 1.2.0-SNAPSHOT + eclipse-plugin + \ No newline at end of file diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/configuration.exsd b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/configuration.exsd new file mode 100644 index 00000000000..b8419825fe9 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/configuration.exsd @@ -0,0 +1,83 @@ + + + + + + + + + Internal extension point for Properties UI configuration management. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Registers the product's provider of the configuration manager. Only one configuration manager declared on the extension point will be loaded. + + + + + + + A class implementing the internal configuration manager provider protocol. + + + + + + + + + + + + + + + 2.0 + + + + + + + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/context.exsd b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/context.exsd new file mode 100644 index 00000000000..ba564029f8e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/context.exsd @@ -0,0 +1,137 @@ + + + + + + + + + Extension point used to associate Contexts with preference pages in the Properties Framework. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specifies a binding of a particular registered Properties context model to some preference page (usually different than the default Papyrus Properties View preference page). + + + + + + + References the Properties Context (by name) to associate with a preference page. The name is used instead of the URI because that is what the enablement preferences use to identify contexts and it is how (temporarily) missing contexts are tracked. + + + + + + + Indicates the preference page in which to present the customization of the referenced properties context. + + + + + + + + + + + + + + + 0.8.0 + + + + + + + + + <extension + point="org.eclipse.papyrus.infra.properties.ui.Context"> + <context contextModel="Model/UML.xmi"> + </context> +</extension> + + + + + + + + + There is no API associated with this extension point. + + + + + + + + + Sample Implementation : +org.eclipse.papyrus.infra.properties.ui.uml + + + + + + + + + /***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ + + + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/labelprovider.exsd b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/labelprovider.exsd new file mode 100644 index 00000000000..fa42bbb084f --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/schema/labelprovider.exsd @@ -0,0 +1,109 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/Activator.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/Activator.java new file mode 100644 index 00000000000..5deb1637927 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/Activator.java @@ -0,0 +1,121 @@ +/***************************************************************************** + * Copyright (c) 2010, 2016 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 485220 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.internal.ui; + +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.papyrus.infra.core.log.LogHelper; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + /** + * The plug-in ID + */ + public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.properties.ui"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * Log + */ + public static LogHelper log; + + /** + * The constructor + */ + public Activator() { + super(); + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + log = new LogHelper(plugin); + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns the image at the given path from this plugin + * + * @param path + * the path of the image to be displayed + * @return The Image at the given location, or null if it couldn't be found + */ + public Image getImage(String path) { + return getImage(PLUGIN_ID, path); + } + + /** + * Returns the image from the given image descriptor + * + * @param pluginId + * The plugin in which the image is located + * @param path + * The path to the image from the plugin + * @return + * The Image at the given location, or null if it couldn't be found + */ + public Image getImage(String pluginId, String path) { + final ImageRegistry registry = getImageRegistry(); + String key = pluginId + "/" + path; //$NON-NLS-1$ + Image image = registry.get(key); + if (image == null) { + registry.put(key, AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, path)); + image = registry.get(key); + } + return image; + } + + /** + * Returns the image from the given path + * + * @param imagePath + * The path of the image, in the form // + * @return + * The Image at the given location, or null if none was found + */ + public Image getImageFromPlugin(String imagePath) { + if (imagePath.startsWith("/")) { //$NON-NLS-1$ + String pluginId, path; + imagePath = imagePath.substring(1, imagePath.length()); + pluginId = imagePath.substring(0, imagePath.indexOf("/")); //$NON-NLS-1$ + path = imagePath.substring(imagePath.indexOf("/"), imagePath.length()); //$NON-NLS-1$ + return getImage(pluginId, path); + } else { + return getImage(imagePath); + } + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/extensions/ContextBindingsExtensionPoint.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/extensions/ContextBindingsExtensionPoint.java new file mode 100644 index 00000000000..41555718225 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/extensions/ContextBindingsExtensionPoint.java @@ -0,0 +1,81 @@ +/***************************************************************************** + * Copyright (c) 2015, 2016 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Mickael ADAM (ALL4TEC) mickael.adam@all4tec.net - adds isVisible implementation + * Christian W. Damus - bugs 469188, 485220 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.internal.ui.extensions; + +import java.util.function.BiConsumer; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; + +/** + * Handles the extension point org.eclipse.papyrus.infra.properties.ui.context + * Registers the given Context preference page bindings. + * + * @author Camille Letavernier + */ +public class ContextBindingsExtensionPoint { + + + private static final String PREFPAGE_BINDING = "preferencePageBinding"; //$NON-NLS-1$ + + private static final String CONTEXT = "context"; //$NON-NLS-1$ + + private static final String PAGE = "page"; //$NON-NLS-1$ + + /** The extension id. */ + private final String EXTENSION_ID = "org.eclipse.papyrus.infra.properties.ui.context"; //$NON-NLS-1$ + + /** + * Constructor + */ + public ContextBindingsExtensionPoint(BiConsumer bindingProcessor) { + super(); + + IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID); + + for (IConfigurationElement e : config) { + try { + switch (e.getName()) { + case PREFPAGE_BINDING: + processPrefPageBinding(e, bindingProcessor); + break; + } + } catch (Exception ex) { + Activator.log.error(ex); + } + } + } + + private void processPrefPageBinding(IConfigurationElement config, BiConsumer bindingProcessor) { + boolean valid = true; + + String context = config.getAttribute(CONTEXT); + if ((context == null) || context.isEmpty()) { + valid = false; + Activator.log.warn(String.format("Missing context name in preference page binding extension in plug-in %s", config.getContributor().getName())); + } + + String page = config.getAttribute(PAGE); + if ((page == null) || page.isEmpty()) { + valid = false; + Activator.log.warn(String.format("Missing page ID in preference page binding extension in plug-in %s", config.getContributor().getName())); + } + + if (valid) { + bindingProcessor.accept(context, page); + } + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/Messages.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/Messages.java new file mode 100644 index 00000000000..febe5b0ada8 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/Messages.java @@ -0,0 +1,52 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.internal.ui.messages; + +import org.eclipse.osgi.util.NLS; + +/** + * String externalisation for plug-in org.eclipse.papyrus.infra.properties.ui + * + * @author Camille Letavernier + */ +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.papyrus.infra.properties.internal.ui.messages.messages"; //$NON-NLS-1$ + + public static String EcorePropertyEditorFactory_CreateANew; + + public static String EditionDialog_CanNotFindview; + + public static String EditionDialog_CreateANewElement; + + public static String Preferences_ConflictWarning1; + + public static String Preferences_ConflictWarning2; + + public static String Preferences_ConflictWarningTitle; + + public static String Preferences_Contexts; + + public static String Preferences_Custom; + + public static String Preferences_Plugin; + + public static String PropertyEditorFactory_CreateANewElement; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/messages.properties b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/messages.properties new file mode 100644 index 00000000000..b5530c8e19c --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/messages/messages.properties @@ -0,0 +1,10 @@ +EcorePropertyEditorFactory_CreateANew=Create a new +EditionDialog_CanNotFindview=Can not find view <%s> +EditionDialog_CreateANewElement=Create a new Element +Preferences_ConflictWarning1=Warning : When two sections with the same ID are displayed in the same property view, only the first of them is displayed. The following conflicts may occur : \n\n +Preferences_ConflictWarning2=\nPlease note that if these sections apply to different elements, there won't be any conflict. Do you wish to continue ? +Preferences_ConflictWarningTitle=Warning : Conflicts detected +Preferences_Contexts=Contexts : +Preferences_Custom=custom +Preferences_Plugin=plugin +PropertyEditorFactory_CreateANewElement=Create a new element diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/observable/PreferencesObservableValue.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/observable/PreferencesObservableValue.java new file mode 100644 index 00000000000..3641cc0e305 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/observable/PreferencesObservableValue.java @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.internal.ui.observable; + +import org.eclipse.core.databinding.observable.Diffs; +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + + +public class PreferencesObservableValue extends AbstractObservableValue implements IPropertyChangeListener { + + protected String key; + + protected IPreferenceStore store; + + public PreferencesObservableValue(String key, IPreferenceStore store) { + this.key = key; + this.store = store; + store.addPropertyChangeListener(this); + } + + public Object getValueType() { + return String.class; + } + + @Override + protected Object doGetValue() { + if (store.contains(key)) { + return store.getString(key); + } + return null; + } + + @Override + protected void doSetValue(Object value) { + if (value instanceof String) { + store.setValue(key, (String) value); + } + } + + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(key)) { + fireValueChange(Diffs.createValueDiff(event.getOldValue(), event.getNewValue())); + } + } + + @Override + public void dispose() { + store.removePropertyChangeListener(this); + super.dispose(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/ConfigurationConflict.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/ConfigurationConflict.java new file mode 100644 index 00000000000..9deed35f476 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/ConfigurationConflict.java @@ -0,0 +1,70 @@ +/***************************************************************************** + * Copyright (c) 2011, 2015 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 482927 + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.internal.ui.runtime; + +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.papyrus.infra.properties.contexts.Context; + +/** + * Represents a conflict in the applied Property view configurations + * + * @author Camille Letavernier + * + */ +public class ConfigurationConflict { + + /** + * The ID of the section being in conflict + */ + public String sectionID; + + /** + * The list of contexts being in conflict + */ + public List conflictingContexts; + + /** + * Constructor. + * + * Creates a conflict descriptor for the given section ID + * + * @param sectionID + * The ID of the section being in conflict + */ + public ConfigurationConflict(String sectionID) { + conflictingContexts = new LinkedList(); + this.sectionID = sectionID; + } + + /** + * Adds a conflicting context + * + * @param context + */ + public void addContext(Context context) { + conflictingContexts.add(context); + } + + @Override + public String toString() { + String result = sectionID + " : "; //$NON-NLS-1$ + for (Context context : conflictingContexts) { + result += context.getUserLabel() + ", "; //$NON-NLS-1$ + } + return result.substring(0, result.length() - 2); + } + + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/IInternalConfigurationManager.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/IInternalConfigurationManager.java new file mode 100644 index 00000000000..6bcf7065bb1 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/internal/ui/runtime/IInternalConfigurationManager.java @@ -0,0 +1,135 @@ +/***************************************************************************** + * Copyright (c) 2010, 2016 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - Factor out workspace storage for pluggable storage providers (CDO) + * Christian W. Damus (CEA) - Support implicit enablement of prototypes of unavailable contexts (CDO) + * Christian W. Damus - bugs 482930, 469188, 485220 + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.internal.ui.runtime; + +import java.util.Collection; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.internal.ContextExtensionPoint; +import org.eclipse.papyrus.infra.properties.ui.runtime.IConfigurationManager; + +/** + * Internal interface for manipulation of the Properties Run-time configuration. + */ +public interface IInternalConfigurationManager extends IConfigurationManager { + + /** + * Checks the conflicts between all applied {@linkplain #getEnabledContexts() enabled}) configurations + * A Conflict may occur when two sections have the same ID : they can't + * be displayed at the same time + * + * @return + * The list of conflicts + */ + Collection checkConflicts(); + + /** + * Checks the conflicts between those of the specified configurations that are enabled. + * A Conflict may occur when two sections have the same ID : they can't + * be displayed at the same time. + * + * @param contexts + * a set of configurations to check for conflicts (amongst the subset of these + * that are actually {@linkplain #isEnabled(Context) enabled} + * + * @return + * The list of conflicts + * + * @see #isEnabled(Context) + */ + Collection checkConflicts(Collection contexts); + + /** + * Enables a Context + * + * @param context + * The Context to enable + * @param update + * If true, the constraint engine will be updated to handle the + * modification + * If false, you should call manually {@link #update()} to refresh + * the constraint engine + * + * @see #disableContext(Context, boolean) + */ + void enableContext(Context context, boolean update); + + /** + * Disable a Context. + * + * @param context + * The Context to disable + * @param update + * If true, the constraint engine will be updated to handle the + * modification + * If false, you should call manually {@link #update()} to refresh + * the constraint engine + * @see Preferences + * @see #enableContext(Context, boolean) + */ + void disableContext(Context context, boolean update); + + /** + * Updates the constraint engine to handle changes in the contexts + * activation + */ + void update(); + + + /** + * Programmatically register a new context to this ConfigurationManager. + * Most of the time, new contexts should be registered through {@link ContextExtensionPoint}. + * However, you can still call this method when creating a Context at runtime, programmatically + * (Wizards, ...) + * All {@link Context} should have unique names + * + * @param context + * The new context to register + * @param apply + * Whether the context should be enabled or not + * + * @see ConfigurationManager#addContext(URI) + */ + void addContext(Context context, boolean apply); + + /** + * Refresh the given Context. This method should be called when a model is edited + * at runtime, to re-load it from persistent storage. + * + * @param context + * A Context model to re-load + */ + void refresh(Context context); + + /** + * Disable, then unregisters a Context. The Context won't be available anymore in the framework + * (not even in the Preferences page). This method won't delete the context's files + * on the file system. + * + * @param context + * The context to delete + */ + void deleteContext(Context context); + + // + // Nested types + // + + interface Provider { + IInternalConfigurationManager getConfigurationManager(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreateInDialog.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreateInDialog.java new file mode 100644 index 00000000000..da1d6f28280 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreateInDialog.java @@ -0,0 +1,180 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.creation; + +import java.util.Arrays; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.widgets.layout.PropertiesLayout; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + + +public class CreateInDialog extends TrayDialog { + + /** + * The ContentProvider for browsing potential container EObjects + */ + protected IStaticContentProvider containerContentProvider; + + /** + * The ContentProvider for browsing potential containment EReferences. + * The input of this content provider is the object selected through the + * containerContentProvider + */ + protected IStaticContentProvider referenceContentProvider; + + /** + * The LabelProvider for displaying potential container EObjects + */ + protected ILabelProvider containerLabelProvider; + + /** + * The LabelProvider for displaying potential containment EReferences + */ + protected ILabelProvider referenceLabelProvider; + + /** + * This dialog's shell's title + */ + protected String title; + + protected EObject container; + + protected EReference containmentReference; + + protected ReferenceDialog referenceDialog; + + /** + * The instance of object being created + */ + protected Object input; + + public CreateInDialog(Shell parentShell, Object input) { + super(parentShell); + this.input = input; + } + + @Override + public void create() { + super.create(); + getShell().setText(title); + getShell().setImage(Activator.getDefault().getImage(org.eclipse.papyrus.infra.widgets.Activator.PLUGIN_ID, "icons/papyrus.png")); //$NON-NLS-1$ + Label label = new Label(getDialogArea(), SWT.NONE); + label.setText("Choose the parent element for the new object:"); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, false); + data.horizontalIndent = 5; + data.verticalIndent = 5; + label.setLayoutData(data); + + final ReferenceDialog containerDialog = new ReferenceDialog(getDialogArea(), SWT.NONE); + containerDialog.setLabel("Container : "); + containerDialog.setLabelProvider(containerLabelProvider); + containerDialog.setContentProvider(containerContentProvider); + containerDialog.setInput(input); + + referenceDialog = new ReferenceDialog(getDialogArea(), SWT.NONE); + referenceDialog.setLabel("Reference : "); + referenceDialog.setLabelProvider(referenceLabelProvider); + referenceDialog.setContentProvider(referenceContentProvider); + + containerDialog.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + container = (EObject) containerDialog.getValue(); + referenceDialog.setInput(container); + referenceContentProvider.inputChanged(null, null, container); + if (referenceContentProvider.getElements().length == 0) { + referenceDialog.setValue(null); + } else if (referenceContentProvider.getElements().length == 1) { + referenceDialog.setValue(referenceContentProvider.getElements()[0]); + } else { + if (!Arrays.asList(referenceContentProvider.getElements()).contains(referenceDialog.getValue())) { + referenceDialog.setValue(null); + } + } + updateControls(); + } + }); + + referenceDialog.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + containmentReference = (EReference) referenceDialog.getValue(); + updateControls(); + } + }); + + updateControls(); + getShell().setSize(450, 180); + } + + protected void updateControls() { + referenceDialog.setReadOnly(referenceContentProvider.getElements().length < 2); + + if (container == null || containmentReference == null) { + getButton(OK).setEnabled(false); + return; + } + + getButton(OK).setEnabled(container.eClass().getEAllReferences().contains(containmentReference)); + } + + @Override + protected Composite getDialogArea() { + return (Composite) super.getDialogArea(); + } + + public EObject getContainer() { + return container; + } + + public EReference getContainmentReference() { + return containmentReference; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + composite.setLayout(new PropertiesLayout(true)); + return composite; + } + + @Override + protected boolean isResizable() { + return true; + } + + public void setProviders(IStaticContentProvider containerContentProvider, IStaticContentProvider referenceContentProvider, ILabelProvider containerLabelProvider, ILabelProvider referenceLabelProvider) { + this.containerContentProvider = containerContentProvider; + this.referenceContentProvider = referenceContentProvider; + this.containerLabelProvider = containerLabelProvider; + this.referenceLabelProvider = referenceLabelProvider; + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreationContext.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreationContext.java new file mode 100644 index 00000000000..6f75e132c43 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/CreationContext.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.properties.ui.creation; + + +/** + * Encapsulation of the context within which the Properties view is creating a new element. + * Primarily, this context comprises the model element in which a new element is being created (whatever that means for the particular data model). + */ +public interface CreationContext { + + /** + * A null implementation of the context. It does nothing and provides no context. + */ + CreationContext NULL = new CreationContext() { + + public void pushCreatedElement(Object newElement) { + // Pass + } + + public void popCreatedElement(Object newElement) { + // Pass + } + + public Object getCreationContextElement() { + return null; + } + }; + + /** + * Obtains the model element in the context of which we are creating new model elements. + * + * @return the contextual model element, or {@code null} if unknown + */ + Object getCreationContextElement(); + + /** + * Attaches this context to an element being newly created, in such a way (as appropriate to the particular data model) that + * clients would be able to retrieve this context from that element. + * + * @param newElement + * an element being created within the scope of my {@linkplain #getCreationContextElement() creation context} + */ + void pushCreatedElement(Object newElement); + + /** + * Detaches this context from an newly created element for which we have completed its editing. + * + * @param newElement + * the newly created element + */ + void popCreatedElement(Object newElement); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EcorePropertyEditorFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EcorePropertyEditorFactory.java new file mode 100644 index 00000000000..647339918e7 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EcorePropertyEditorFactory.java @@ -0,0 +1,537 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * Christian W. Damus (CEA) - bug 430077 + * Christian W. Damus (CEA) - bug 443497 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.creation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.common.notify.Notifier; +import org.eclipse.emf.common.notify.impl.AdapterImpl; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.emf.utils.EClassNameComparator; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.internal.ui.messages.Messages; +import org.eclipse.papyrus.infra.properties.ui.providers.CreateInFeatureContentProvider; +import org.eclipse.papyrus.infra.ui.emf.dialog.NestedEditingDialogContext; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; + + +/** + * A ReferenceFactory used to instantiate and edit EObjects. + * The specified nsUri and ClassName are used to instantiate the EObject. + * The matching {@link org.eclipse.papyrus.infra.properties.contexts.View}s from all + * applied {@link org.eclipse.papyrus.infra.properties.contexts.Context}s are used to + * display the right form to edit the EObject. + * + * If no EClass is specified, a list of all concrete subclasses of {@link #type} will be displayed before the instantiation. + * + * @author Camille Letavernier + */ +public class EcorePropertyEditorFactory extends PropertyEditorFactory { + + /** + * The (abstract) EClass to instantiate + */ + protected EClass type; + + /** + * The (concrete) EClass to instantiate + * Should be a subclass of {@link #type} + */ + protected EClass eClass; + + /** + * The Namespace URI of the (concrete) EClass to instantiate + */ + protected String nsUri; + + /** + * The name of the (concrete) EClass to instantiate + */ + protected String className; + + /** + * The reference in which the object will be set. + */ + protected EReference referenceIn; + + /** + * The ContentProvider for browsing potential container EObjects + */ + protected IStaticContentProvider containerContentProvider; + + /** + * The ContentProvider for browsing potential containment EReferences. + * The input of this content provider is the object selected through the + * containerContentProvider + */ + protected CreateInFeatureContentProvider referenceContentProvider; + + /** + * The LabelProvider for displaying potential container EObjects + */ + protected ILabelProvider containerLabelProvider; + + /** + * The LabelProvider for displaying potential containment EReferences + */ + protected ILabelProvider referenceLabelProvider; + + /** + * Store information about where each object should be added on validation + */ + protected Map createIn = new HashMap(); + + /** + * + * Constructor. + * + * The factory will be able to instantiate the given EClass + * + * @param type + * The type of EClass to instantiate when creating new EObjects. + */ + public EcorePropertyEditorFactory(EReference referenceIn) { + if (referenceIn == null) { + throw new IllegalArgumentException("The referenceIn parameter must be set"); //$NON-NLS-1$ + } + + this.referenceIn = referenceIn; + this.type = referenceIn.getEReferenceType(); + } + + /** + * @return the nsUri of the EClass used by this factory to instantiate new EObjects + * @see #getClassName + */ + public String getNsUri() { + return nsUri; + } + + /** + * @return the className of the EClass used by this factory to instantiate new EObjects + * @see #getNsUri() + */ + public String getClassName() { + return className; + } + + /** + * Sets the nsUri of the EClass used by this factory to instantiate new EObjects + * + * @param nsUri + * @see #getClassName + */ + public void setNsUri(String nsUri) { + this.nsUri = nsUri; + checkEClass(); + } + + /** + * Sets the className of the EClass used by this factory to instantiate new EObjects + * + * @param className + * @see #getNsUri() + */ + public void setClassName(String className) { + this.className = className; + checkEClass(); + } + + private void checkEClass() { + if (nsUri != null && className != null) { + EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(nsUri); + if (ePackage == null) { + Activator.log.warn("Cannot find the EPackage corresponding to URI " + nsUri); //$NON-NLS-1$ + return; + } + eClass = (EClass) ePackage.getEClassifier(className); + if (eClass == null) { + Activator.log.warn("Cannot find the EClass " + className + " in the package " + nsUri); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean canCreateObject() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public final Object createObject(Control widget, Object context) { + Object result; + + final ResourceSet previous = NestedEditingDialogContext.getInstance().push(context); + + try { + result = doCreateObject(widget, context); + } finally { + NestedEditingDialogContext.getInstance().pop(previous); + } + + return result; + } + + protected Object doCreateObject(Control widget, Object context) { + Object instance; + + if (referenceIn.isContainment()) { + instance = simpleCreateObject(widget); + } else { + instance = createObjectInDifferentContainer(widget); + } + + return createObject(widget, context, instance); + } + + @Override + protected Object doEdit(final Control widget, final Object source, final Set views, final String dialogTitle) { + Object result; + + try { + NestedEditingDialogContext.getInstance().enter(); + try { + result = getOperationExecutor(source).execute(new Callable() { + public Object call() throws Exception { + return basicDoEdit(widget, source, views, dialogTitle); + } + }, dialogTitle); + } finally { + NestedEditingDialogContext.getInstance().exit(); + } + } catch (OperationCanceledException e) { + if (!NestedEditingDialogContext.getInstance().isNested()) { + // Propagate to the caller if not in a nested edit dialog + throw e; + } + + // Let the client think that there's nothing needing to be done, that the referenced object + // was edited "in place" instead of being replaced by some other object + result = null; + } + + return result; + } + + protected final Object basicDoEdit(Control widget, Object source, Set views, String dialogTitle) { + return super.doEdit(widget, source, views, dialogTitle); + } + + @Override + protected void handleEditCancelled(Control widget, Object source) { + throw new OperationCanceledException(); + } + + protected EObject simpleCreateObject(Control widget) { + EClass eClass = chooseEClass(widget); + if (eClass == null) { + return null; + } + + EObject instance = eClass.getEPackage().getEFactoryInstance().create(eClass); + return instance; + } + + protected EObject createObjectInDifferentContainer(Control widget) { + EObject instance = simpleCreateObject(widget); + if (instance == null) { + return null; + } + + // Try to get the current resource set for a wide scope of places to put a new element + Object containerInput = NestedEditingDialogContext.getInstance().getResourceSet(); + if (containerInput == null) { + // Only have the object that we've created for context + containerInput = instance; + } + + containerContentProvider.inputChanged(null, null, containerInput); + referenceContentProvider.setType(instance.eClass()); + CreateInDialog dialog = new CreateInDialog(widget.getShell(), instance); + dialog.setProviders(containerContentProvider, referenceContentProvider, containerLabelProvider, referenceLabelProvider); + dialog.setTitle(getCreationDialogTitle()); + int result = dialog.open(); + if (result != Window.OK) { + return null; + } + CreateIn createIn = new CreateIn(); + createIn.createInObject = dialog.getContainer(); + createIn.createInReference = dialog.getContainmentReference(); + this.createIn.put(instance, createIn); + + return instance; + } + + /** + * Gets the EClass to instantiate + * If the {@link #eClass} has been specified, then it is returned. + * Otherwise, displays a list of all valid concrete EClasses that + * are subtypes of {@link #type}, from which the user can choose + * the one to instantiate. + * + * @param widget + * The control used to open a selection list (if more than one EClass + * can be instantiated) + * @return + * The EClass to instantiate + */ + protected EClass chooseEClass(Control widget) { + if (eClass != null) { + return eClass; + } + + List availableClasses = getAvailableEClasses(); + if (availableClasses.isEmpty()) { + return null; + } + + if (availableClasses.size() == 1) { + this.className = availableClasses.get(0).getName(); + return availableClasses.get(0); + } + + final Menu menu = new Menu(widget); + for (EClass eClass : availableClasses) { + final MenuItem item = new MenuItem(menu, SWT.NONE); + item.setText(eClass.getName()); + item.setData("eClass", eClass); //$NON-NLS-1$ + item.addSelectionListener(new SelectionListener() { + + public void widgetSelected(SelectionEvent e) { + EcorePropertyEditorFactory.this.eClass = (EClass) item.getData("eClass"); //$NON-NLS-1$ + } + + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + }); + } + + menu.setVisible(true); + + // The menu is blocking the thread + Display display = widget.getDisplay(); + while (menu.isVisible()) { + try { + if (!display.readAndDispatch()) { + display.sleep(); + } + } catch (Throwable ex) { + Activator.log.error(ex); + } + } + if (!display.isDisposed()) { + display.update(); + } + + EClass eClass = this.eClass; + if (eClass != null) { + className = eClass.getName(); + } + this.eClass = null; + + return eClass; + } + + /** + * @return + * The list of {@link EClass} that can be instantiated. + * This is the list of all concrete subclasses of {@link #type} + */ + protected List getAvailableEClasses() { + List availableEClasses = EMFHelper.getSubclassesOf(type, true); + Collections.sort(availableEClasses, new EClassNameComparator()); + return availableEClasses; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection validateObjects(Collection objectsToValidate) { + if (!referenceIn.isContainment()) { + for (Object objectToValidate : objectsToValidate) { + // We add the object to the containment reference + // They will be automatically added to the edited reference + // (referenceIn) after this method returns + CreateIn creationInformation = this.createIn.get(objectToValidate); + if (creationInformation != null) { + creationInformation.createInObject.eSet(creationInformation.createInReference, objectToValidate); + } else { + Activator.log.warn("Unknown object : " + objectToValidate); + } + } + } + + return objectsToValidate; + } + + /** + * {@inheritDoc} + */ + @Override + public String getCreationDialogTitle() { + return Messages.EcorePropertyEditorFactory_CreateANew + className; + } + + @Override + public String getEditionDialogTitle(Object objectToEdit) { + if (objectToEdit instanceof EObject) { + return "Edit " + ((EObject) objectToEdit).eClass().getName(); + } + return super.getEditionDialogTitle(objectToEdit); + } + + /** + * @return + * The EClass that will be instantiated, or null if this hasn't been forced + */ + public EClass getEClass() { + return eClass; + } + + protected class CreateIn { + + /** + * The (containment) reference in which the object will be created + * May be the same or different from {@link #referenceIn} + */ + public EReference createInReference; + + /** + * The (container) EObject in which the object will be created + */ + public EObject createInObject; + } + + /** + * Sets the same label provider for both #referenceLabelProvider + * and #containerLabelProvider + * + * @param labelProvider + */ + public void setLabelProvider(ILabelProvider labelProvider) { + setContainerLabelProvider(labelProvider); + setReferenceLabelProvider(labelProvider); + } + + public void setReferenceLabelProvider(ILabelProvider labelProvider) { + this.referenceLabelProvider = labelProvider; + } + + public void setContainerLabelProvider(ILabelProvider labelProvider) { + this.containerLabelProvider = labelProvider; + } + + public void setContainerContentProvider(IStaticContentProvider contentProvider) { + this.containerContentProvider = contentProvider; + } + + public void setReferenceContentProvider(CreateInFeatureContentProvider contentProvider) { + this.referenceContentProvider = contentProvider; + } + + @Override + protected CreationContext getCreationContext(Object element) { + return (element instanceof EObject) ? getCreationContext((EObject) element, true) : super.getCreationContext(element); + } + + /** + * Gets the creation context providing the element in which a {@code modelElement} is being created. + * + * @param modelElement + * a model element that is currently being created and probably is, therefore, not yet attached to the model + * @param demandCreate + * whether to create the context and implicitly attach it if it is not already attached. This is only appropriate in the case that the {@code modelElement} is the element in which context we are creating new elements + * + * @return the creation context, or {@code null} if none is currently attached and we did not elect to create it on demand + */ + public static CreationContext getCreationContext(EObject modelElement, boolean demandCreate) { + class EObjectCreationContext extends AdapterImpl implements CreationContext { + + private EObject context; + + private List createdElements = new ArrayList(2); // Anticipate small depth of dialog nesting + + EObjectCreationContext(EObject context) { + this.context = context; + context.eAdapters().add(this); + } + + @Override + public boolean isAdapterForType(Object type) { + return type == CreationContext.class; + } + + public Object getCreationContextElement() { + return context; + } + + public void popCreatedElement(Object newElement) { + if (createdElements.remove(newElement)) { + ((Notifier) newElement).eAdapters().remove(this); + + if (createdElements.isEmpty()) { + // Don't need this context adapter any more + context.eAdapters().remove(this); + } + } + } + + public void pushCreatedElement(Object newElement) { + createdElements.add(newElement); + ((Notifier) newElement).eAdapters().add(this); + } + } + + CreationContext result = (CreationContext) EcoreUtil.getExistingAdapter(modelElement, CreationContext.class); + if ((result == null) && demandCreate) { + result = new EObjectCreationContext(modelElement); + } + + return result; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EditionDialog.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EditionDialog.java new file mode 100644 index 00000000000..e5ce3412a69 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/EditionDialog.java @@ -0,0 +1,351 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 404874 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.creation; + +import java.io.IOException; +import java.text.Collator; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.Tab; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.internal.ui.messages.Messages; +import org.eclipse.papyrus.infra.properties.ui.runtime.DefaultDisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.papyrus.infra.properties.ui.xwt.XWTSection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SelectionDialog; + + +/** + * A dialog used to display an edition form for a given object. + * The form is described by the given {@link View}s + * + * @author Camille Letavernier + */ +// TODO : This dialog should use the Embedded Display Engine +public class EditionDialog extends SelectionDialog { + + private Set views; + + private Object input; + + private Set sections = new HashSet(); + + private boolean cancelable = false; + + /** + * + * Constructor. + * + * @param shell + * The shell in which the dialog will be opened + * @param cancelable + * Whether the cancel button is active or not. The values are data-binded, ie. + * edited in real time, before the ok button is pressed. If the cancel button + * is active, callers are responsible for undoing the changes. + */ + protected EditionDialog(Shell shell, boolean cancelable) { + super(shell); + this.cancelable = cancelable; + } + + /** + * + * Constructor. + * + * @param shell + * The shell in which the dialog will be opened + */ + protected EditionDialog(Shell shell) { + this(shell, false); + } + + @Override + public void create() { + super.create(); + if (getShell().getText() == null || "".equals(getShell().getText())) { //$NON-NLS-1$ + setTitle(Messages.EditionDialog_CreateANewElement); + } + getShell().setImage(Activator.getDefault().getImage("org.eclipse.papyrus.infra.widgets", "/icons/papyrus.png")); //$NON-NLS-1$ //$NON-NLS-2$ + getShell().addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + dispose(); + } + + }); + + display(); + + // The values are data-binded, thus are edited in real time. It is not possible to cancel (However, Ctrl+Z should work) + getButton(IDialogConstants.CANCEL_ID).setEnabled(cancelable); + } + + @Override + public Composite getDialogArea() { + return (Composite) super.getDialogArea(); + } + + /** + * Sets the object being edited by this dialog + * + * @param input + */ + public void setInput(Object input) { + this.input = input; + } + + /** + * Sets the Views used to edit the input object + * + * @param views + */ + public void setViews(Set views) { + this.views = views; + } + + /** + * Provide information about context and view, as well as the element for which the dialog + * should be provided. It will call setViews in turn. + * + * @param contextName + * The name of the context + * @param contextURI + * The URI of the context, tries to load context, if it has not been done yet + * @param viewName + * The name of the view + */ + public void setViewData(String contextName, String viewName) { + setViewData(contextName, null, viewName); + } + + /** + * Provide information about context and view, as well as the element for which the dialog + * should be provided. + * + * @param contextName + * The name of the context + * @param contextURI + * The URI of the context. If the context is not available yet, the function uses this URI to load it. + * @param viewName + * The name of the view + */ + public void setViewData(String contextName, URI contextURI, String viewName) { + + Context context = PropertiesRuntime.getConfigurationManager().getContext(contextName); + if ((context == null) && (contextURI != null)) { + // might not have been loaded yet + loadFromURI(contextURI); + context = PropertiesRuntime.getConfigurationManager().getContext(contextName); + } + + Set views = new HashSet(); + + if (context != null) { + for (View view : context.getViews()) { + if (view.getName().equals(viewName)) { + views.add(view); + break; + } + } + } + if (views.isEmpty()) { + throw new RuntimeException(String.format(Messages.EditionDialog_CanNotFindview, viewName)); + } + setViews(views); + } + + /** + * Load the passed context into the configuration manager. + */ + protected void loadFromURI(URI uri) { + try { + PropertiesRuntime.getConfigurationManager().addContext(uri); + } catch (IOException io) { + Activator.log.error(io); + } + } + + private void display() { + DisplayEngine display = new DefaultDisplayEngine(); + + IStructuredSelection selection = new StructuredSelection(input); + + Composite parent = new Composite(getDialogArea(), SWT.NONE); + parent.setLayout(new FillLayout()); + parent.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); + getShell().setSize(600, 400); + + final Set tabsList = new LinkedHashSet(); + + for (View view : views) { + for (Section section : view.getSections()) { + tabsList.add(section.getTab()); + } + } + + List allTabs = new LinkedList(tabsList); + + Collections.sort(allTabs, new Comparator() { + + /** + * compares two tabs each other + * + * @param tab1 + * first tab to compare + * @param tab2 + * second tab to compare + * @return a negative integer if the first tab should be placed before the second tab + */ + @Override + public int compare(Tab tab1, Tab tab2) { + int priority1 = getPriority(tab1); + int priority2 = getPriority(tab2); + + if (priority1 < priority2) { + return -1; + } + + if (priority1 > priority2) { + return 1; + } + + // p1 == p2 + + priority1 = getXWTTabPriority(tab1); + priority2 = getXWTTabPriority(tab2); + + if (priority1 < priority2) { + return -1; + } + + if (priority1 > priority2) { + return 1; + } + + // p1 == p2 + + String label1 = tab1.getLabel(); + String label2 = tab2.getLabel(); + + return Collator.getInstance().compare(label1, label2); + } + + private Tab getPreviousTab(Tab tab) { + Tab afterTab = tab.getAfterTab(); + if (tabsList.contains(afterTab)) { + return afterTab; + } + + // not found. Return null + return null; + } + + private int getPriority(Tab tab) { + Tab previousTab = getPreviousTab(tab); + if (previousTab != null) { + return getPriority(previousTab) + 1; + } + + return getXWTTabPriority(tab); + } + + private int getXWTTabPriority(Tab tab) { + return tab.getPriority(); + } + + }); + + Map tabs = new LinkedHashMap(); + if (allTabs.size() > 1) { + CTabFolder tabFolder = new CTabFolder(parent, SWT.BOTTOM); + tabFolder.setSelectionBackground(new Color[] { tabFolder.getDisplay().getSystemColor(SWT.COLOR_WHITE), tabFolder.getBackground() }, new int[] { 100 }, true); + tabFolder.setLayout(new FillLayout()); + for (Tab tab : allTabs) { + CTabItem item = new CTabItem(tabFolder, SWT.NONE); + Composite tabControl = new Composite(tabFolder, SWT.NONE); + item.setControl(tabControl); + item.setText(tab.getLabel()); + tabs.put(tab, tabControl); + } + } else if (!allTabs.isEmpty()) { + Tab tab = allTabs.get(0); + tabs.put(tab, parent); + } + + for (View view : views) { + for (Section section : view.getSections()) { + XWTSection xwtSection = new XWTSection(section, view, display); + sections.add(xwtSection); + + xwtSection.createControls(tabs.get(section.getTab()), null); + xwtSection.setInput(null, selection); + xwtSection.refresh(); + } + } + + getShell().pack(); + Point size = getShell().getSize(); + int minWidth = 600; + if (size.x < minWidth) { + size.x = minWidth; + } + getShell().setSize(size); + } + + /** + * Disposes this dialog + */ + public void dispose() { + for (XWTSection section : sections) { + section.dispose(); + } + sections.clear(); + } + + @Override + protected void okPressed() { + // Bug 404874: Work-around for Mac platform, where finishing the dialog does not trigger + // focus-lost on the last edited control (which would commit its changes) + getOkButton().forceFocus(); + super.okPressed(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/PropertyEditorFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/PropertyEditorFactory.java new file mode 100644 index 00000000000..b06af100c97 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/creation/PropertyEditorFactory.java @@ -0,0 +1,240 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * Christian W. Damus (CEA) - bug 430077 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.creation; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintEngine; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.messages.Messages; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.papyrus.infra.widgets.creation.IAtomicOperationExecutor; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.swt.widgets.Control; + +/** + * A generic ReferenceValueFactory, which uses the Property View configurations + * to edit objects. For a given object, the factory uses the matching constraints + * to find the property views associated to the object, and displays these views + * in a Dialog. + * This factory cannot instantiate new objects. However, subclasses should override {@link #createObject(Control)} and {@link #canCreateObject()} to + * enable + * this behavior. + * + * @see org.eclipse.papyrus.infra.properties.ui.creation.EditionDialog + * + * @author Camille Letavernier + */ +public class PropertyEditorFactory implements ReferenceValueFactory { + + /** + * + * Constructor. + * + */ + public PropertyEditorFactory() { + } + + /** + * Return a null value. Implementors should override when object creation + * needs to be supported. Implementors may rely on {@link #createObject(Control, Object)} + * + * @param widget + * The widget from which this method is called. May be used to retrieve the current shell + * @param context + * The object being edited, in which context the new object is to be created and which will as a result have a reference to the new object. + * If there is no context object (creation of a free-floating object) or it cannot be determined, this may be {@code null} + * @return + * The newly created object + * + * @see ReferenceValueFactory#createObject(Control, Object) + * @see #createObject(Control, Object, Object) + */ + @Override + public Object createObject(Control widget, Object context) { + return null; + } + + /** + * This class cannot instantiate objects. However, this method provides + * a base implementation to be used by subclasses. + * + * Subclasses should instantiate the base object, which will then be + * editable via a property dialog. + * + * @param widget + * The widget used to open the dialog + * @param context + * The object being edited, in which context the new object is to be created and which will as a result have a reference to the new object. + * If there is no context object (creation of a free-floating object) or it cannot be determined, this may be {@code null} + * @param source + * The created EObject. If null, nothing will happen + * @return + * The source EObject, which potential in-place modifications + */ + protected Object createObject(Control widget, Object context, Object source) { + if (source == null) { + return null; + } + + IStructuredSelection selection = new StructuredSelection(source); + + ConstraintEngine constraintEngine = PropertiesRuntime.getConstraintEngine(); + Set views = constraintEngine.getDisplayUnits(selection); + if (!views.isEmpty()) { + CreationContext creationContext = getCreationContext(context); + creationContext.pushCreatedElement(source); + try { + return doEdit(widget, source, views, getCreationDialogTitle()); + } finally { + creationContext.popCreatedElement(source); + } + } + + return source; + } + + /** + * Get the creation context for the specified {@code element} in which we are creating a new model element. + * This default implementation simply returns the {@linkplain CreationContext#NULL null implementation}. + * Subclasses should provide implementation suitable to their data model. + * + * @param element + * an element in which context we are creating a new model element + * + * @return the encapsulated creation context (never {@code null}) + */ + protected CreationContext getCreationContext(Object element) { + return CreationContext.NULL; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection validateObjects(Collection objectsToValidate) { + return objectsToValidate; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean canEdit() { + return true; + } + + /** + * Edits the given object via the matching Property view, if any + * The editing Dialog is directly binded to the underlying object, which means that all modifications are applied + * in real time, and cannot be undone (Except via the "Undo" command). The "Cancel" button is thus disabled. + * + * @see org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory#edit(org.eclipse.swt.widgets.Control, java.lang.Object) + * + * @param widget + * The widget calling the factory. The Dialog for editing the object will open in this widget's shell + * @param source + * The object to edit + */ + @Override + public Object edit(Control widget, Object source) { + IStructuredSelection selection = new StructuredSelection(source); + + ConstraintEngine constraintEngine = PropertiesRuntime.getConstraintEngine(); + + Set views = constraintEngine.getDisplayUnits(selection); + if (!views.isEmpty()) { + return doEdit(widget, source, views, getEditionDialogTitle(source)); + } + + return source; + } + + protected Object doEdit(Control widget, Object source, Set views, String dialogTitle) { + EditionDialog dialog = new EditionDialog(widget.getShell(), true); + dialog.setTitle(dialogTitle); + dialog.setViews(views); + dialog.setInput(source); + + if (dialog.open() != Window.OK) { + handleEditCancelled(widget, source); + return null; + } + + return source; + } + + protected void handleEditCancelled(Control widget, Object source) { + // Pass + } + + /** + * The standard Property Editor Factory cannot instantiate new objects. + * However, subclasses may override this method to return true if they + * implement {@link #createObject(Control)} + * + * @see org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory#canCreateObject() + * + * @return + * True if the factory can create a new instance + */ + @Override + public boolean canCreateObject() { + return false; + } + + /** + * @return + * The title of the dialog used to edit the newly created instance + * + * @see #canCreateObject() + * @see #createObject(Control) + */ + public String getCreationDialogTitle() { + return Messages.PropertyEditorFactory_CreateANewElement; + } + + public String getEditionDialogTitle(Object objectToEdit) { + return "Edit an element"; + } + + /** + * Obtains the most appropriate operation executor for the object being edited. + * + * @param context + * the object being edited + * @return the executor to use to run operations (never {@code null}) + */ + public IAtomicOperationExecutor getOperationExecutor(Object context) { + IAtomicOperationExecutor result; + if (context instanceof IAdaptable) { + result = ((IAdaptable) context).getAdapter(IAtomicOperationExecutor.class); + } else { + result = Platform.getAdapterManager().getAdapter(context, IAtomicOperationExecutor.class); + } + + if (result == null) { + result = IAtomicOperationExecutor.DEFAULT; + } + + return result; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractEMFModelElementFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractEMFModelElementFactory.java new file mode 100644 index 00000000000..3553264e716 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractEMFModelElementFactory.java @@ -0,0 +1,41 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; + +/** + * A partial implementation of a ModelElementFactory for creating {@link EMFModelElement}s + * + * @author Camille Letavernier + * + */ +public abstract class AbstractEMFModelElementFactory extends AbstractModelElementFactory { + + @Override + protected void updateModelElement(T modelElement, Object newSourceElement) { + EObject eObject = EMFHelper.getEObject(newSourceElement); + if (eObject == null) { + throw new IllegalArgumentException("Cannot resolve EObject selection: " + newSourceElement); + } + + updateEMFModelElement(modelElement, eObject); + } + + public static void updateEMFModelElement(EMFModelElement modelElement, EObject newEObject) { + modelElement.source = newEObject; + modelElement.domain = EMFHelper.resolveEditingDomain(newEObject); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElement.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElement.java new file mode 100644 index 00000000000..ca41ce96107 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElement.java @@ -0,0 +1,235 @@ +/***************************************************************************** + * Copyright (c) 2011, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.databinding.observable.DisposeEvent; +import org.eclipse.core.databinding.observable.IDisposeListener; +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.properties.ui.creation.PropertyEditorFactory; +import org.eclipse.papyrus.infra.tools.databinding.DelegatingObservable; +import org.eclipse.papyrus.infra.tools.databinding.IDelegatingObservable; +import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; + +/** + * Provides a default implementation for ModelElement methods applied on the + * modelElement's properties. + * + * @author Camille Letavernier + */ +public abstract class AbstractModelElement implements ModelElement, IDataSourceListener { + + /** + * The DataSource owning this ModelElement + */ + protected DataSource dataSource; + + private final Map observables = new HashMap(); + + private IDisposeListener observableDisposeListener; + + AbstractModelElementFactory factory; + + /** + * Constructor. + */ + protected AbstractModelElement() { + super(); + } + + @SuppressWarnings("unchecked") + void setFactory(AbstractModelElementFactory factory) { + this.factory = (AbstractModelElementFactory) factory; + } + + public IStaticContentProvider getContentProvider(String propertyPath) { + return EmptyContentProvider.instance; + } + + public ILabelProvider getLabelProvider(String propertyPath) { + return null; + } + + public boolean isOrdered(String propertyPath) { + return true; + } + + public boolean isUnique(String propertyPath) { + return false; + } + + public boolean isMandatory(String propertyPath) { + return false; + } + + public boolean isEditable(String propertyPath) { + return true; + } + + public boolean forceRefresh(String propertyPath) { + return false; + } + + public void setDataSource(DataSource source) { + if (this.dataSource != source) { + if (this.dataSource != null) { + this.dataSource.removeDataSourceListener(this); + } + + this.dataSource = source; + + if (this.dataSource != null) { + this.dataSource.addDataSourceListener(this); + } + } + } + + public final void dataSourceChanged(DataSourceChangedEvent event) { + if (event.getDataSource() == dataSource) { + // The data source changed. Update for the new selection + IStructuredSelection selection = dataSource.getSelection(); + if (selection.isEmpty()) { + factory.updateModelElement(this, null); + } else if (selection.size() == 1) { + factory.updateModelElement(this, selection.getFirstElement()); + } else { + updateMultipleSelection(selection); + } + + // Update our observables + for (Map.Entry next : observables.entrySet()) { + IDelegatingObservable wrapper = ((IDelegatingObservable) next.getValue()); + wrapper.setDelegate(doGetObservable(next.getKey())); + } + } + } + + void updateMultipleSelection(IStructuredSelection selection) { + throw new IllegalArgumentException("multiple selection"); //$NON-NLS-1$ + } + + /** + * @see org.eclipse.papyrus.infra.properties.ui.modelelement.ModelElement#getValueFactory(java.lang.String) + * + * @param propertyPath + * @return a default factory based on the property view configuration to + * edit objects, as if they were selected in an editor + */ + public ReferenceValueFactory getValueFactory(String propertyPath) { + return new PropertyEditorFactory(); + } + + public Object getDefaultValue(String propertyPath) { + return null; + } + + public boolean getDirectCreation(String propertyPath) { + return false; + } + + public final IObservable getObservable(String propertyPath) { + if (!observables.containsKey(propertyPath)) { + IObservable observable = doGetObservable(propertyPath); + if (observable != null) { + // Wrap it so that we may replace the delegate as needed + observable = DelegatingObservable.wrap(observable); + observable.addDisposeListener(getObservableDisposeListener()); + ReferenceCountedObservable.Util.retain(observable); + observables.put(propertyPath, observable); + } + } + return observables.get(propertyPath); + } + + /** + * Creates the IObservable for the given propertyPath + * + * @param propertyPath + * The path of the property we want to observe + * @return + * The new IObservable + */ + protected abstract IObservable doGetObservable(String propertyPath); + + public void dispose() { + for (IObservable observable : observables.values()) { + if (observableDisposeListener != null) { + // Don't let the listener concurrently modify the map in case releasing triggers dispose + observable.removeDisposeListener(observableDisposeListener); + } + + ReferenceCountedObservable.Util.release(observable); + } + + observables.clear(); + observableDisposeListener = null; + } + + public IValidator getValidator(String propertyPath) { + return null; + } + + private IDisposeListener getObservableDisposeListener() { + if (observableDisposeListener == null) { + observableDisposeListener = new IDisposeListener() { + + public void handleDispose(DisposeEvent event) { + // Remove this property + for (Iterator> entries = observables.entrySet().iterator(); entries.hasNext();) { + if (entries.next().getValue() == event.getObservable()) { + entries.remove(); + break; + } + } + } + }; + } + + return observableDisposeListener; + } + + + /** + * @see org.eclipse.papyrus.infra.properties.ui.modelelement.ModelElement#getNameResolutionHelper(java.lang.String) + * + * @param propertyPath + * @return + */ + public INameResolutionHelper getNameResolutionHelper(String propertyPath) { + return null; + } + + /** + * + * @see org.eclipse.papyrus.infra.properties.ui.modelelement.ModelElement#getPapyrusConverter(java.lang.String) + * + * @param propertyPath + * @return + */ + public IPapyrusConverter getPapyrusConverter(String propertyPath) { + return null; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElementFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElementFactory.java new file mode 100644 index 00000000000..26838568c95 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AbstractModelElementFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; + + +/** + * This is the AbstractModelElementFactory type. Enjoy. + */ +public abstract class AbstractModelElementFactory implements ModelElementFactory { + + protected AbstractModelElementFactory() { + super(); + } + + public final ModelElement createFromSource(Object sourceElement, DataContextElement context) { + AbstractModelElement result = doCreateFromSource(sourceElement, context); + + if (result != null) { + result.setFactory(this); + } + + return result; + } + + protected abstract T doCreateFromSource(Object sourceElement, DataContextElement context); + + protected abstract void updateModelElement(T modelElement, Object newSourceElement); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElement.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElement.java new file mode 100644 index 00000000000..a532ba13c60 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElement.java @@ -0,0 +1,73 @@ +/***************************************************************************** + * Copyright (c) 2011, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 323802 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.ui.emf.databinding.AnnotationObservableValue; + +/** + * A ModelElement for handling EAnnotations + * + * @author Camille Letavernier + */ +public class AnnotationModelElement extends AbstractModelElement { + + /** + * The EModelElement owning the represented EAnnotation + */ + protected EModelElement source; + + /** + * The editing domain on which the modification commands will be executed + */ + protected EditingDomain domain; + + /** + * The name of the annotation being represented + */ + protected String annotationName; + + /** + * + * Constructor. + * + * @param source + * The EModelElement owning the EAnnotation that will be edited + * @param domain + * The EditingDomain on which the commands will be executed + * @param annotationName + * The name of the EAnnotation to edit. The EAnnotation doesn't need to exist yet + */ + public AnnotationModelElement(EModelElement source, EditingDomain domain, String annotationName) { + this.source = source; + this.domain = domain; + this.annotationName = annotationName; + } + + /** + * {@inheritDoc} + */ + @Override + public IObservable doGetObservable(String propertyPath) { + return new AnnotationObservableValue(source, domain, annotationName, propertyPath); + } + + @Override + public boolean isEditable(String propertyPath) { + return !EMFHelper.isReadOnly(source); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElementFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElementFactory.java new file mode 100644 index 00000000000..c799d042794 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/AnnotationModelElementFactory.java @@ -0,0 +1,55 @@ +/***************************************************************************** + * Copyright (c) 2011, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; + +/** + * A ModelElementFactory for AnnotationModelElements + * + * @author Camille Letavernier + */ +public class AnnotationModelElementFactory extends AbstractModelElementFactory { + + @Override + protected AnnotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) { + EObject source = EMFHelper.getEObject(sourceElement); + if (source == null) { + Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$ + return null; + } + + if (!(source instanceof EModelElement)) { + Activator.log.warn("The selected element must be an EModelElement"); //$NON-NLS-1$ + } + + EditingDomain domain = EMFHelper.resolveEditingDomain(source); + return new AnnotationModelElement((EModelElement) source, domain, context.getName()); + } + + @Override + protected void updateModelElement(AnnotationModelElement modelElement, Object newSourceElement) { + EObject eObject = EMFHelper.getEObject(newSourceElement); + if (!(eObject instanceof EModelElement)) { + throw new IllegalArgumentException("Cannot resolve EModelElement selection: " + newSourceElement); + } + modelElement.source = (EModelElement) eObject; + modelElement.domain = EMFHelper.resolveEditingDomain(eObject); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/CompositeModelElement.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/CompositeModelElement.java new file mode 100644 index 00000000000..491043d012d --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/CompositeModelElement.java @@ -0,0 +1,256 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.tools.databinding.MultipleObservableValue; +import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; + +/** + * A ModelElement to handle MultiSelection property views. + * It is composed of standard ModelElement. The result of method + * calls are an aggregation of the results of the same method calls + * on each sub-element, when this makes sense (i.e. for booleans) + * When an aggregation is not possible, the result of the same method + * call on the first element is returned (e.g. for Content and Label providers) + * + * @author Camille Letavernier + */ +public class CompositeModelElement extends AbstractModelElement { + + private final BoundModelElementFactory subModelElementFactory; + + + public CompositeModelElement(BoundModelElementFactory subModelElementFactory) { + super(); + + this.subModelElementFactory = subModelElementFactory; + } + + @Override + public IObservable doGetObservable(String propertyPath) { + + AggregatedObservable observableComposite = null; + + for (ModelElement element : elements) { + IObservable observable = element.getObservable(propertyPath); + + // Otherwise, we use a standard AggregatedComposite + if (observableComposite == null) { + if (observable instanceof AggregatedObservable) { + observableComposite = (AggregatedObservable) observable; + } else { + if (observable instanceof IObservableValue) { + observableComposite = new MultipleObservableValue().aggregate(observable); + if (observableComposite == null) { + return null; + } + } else { + return null; // The support for CompositeObservableList is too complicated. + // There are too many non-trivial choices (Union or Intersection display, + // unadapted behavior of MultipleValueEditors, ...) + // observableComposite = new MultipleObservableList(); + } + } + } else { + if ((observableComposite = observableComposite.aggregate(observable)) == null) { + return null; + } + } + } + + return observableComposite; + } + + @Override + void updateMultipleSelection(IStructuredSelection selection) { + ListIterator subElements = elements.listIterator(); + Iterator newSourceElements = selection.iterator(); + + // Re-use existing sub-elements, just updating them + while (newSourceElements.hasNext() && subElements.hasNext()) { + ModelElement nextSubElement = subElements.next(); + if (nextSubElement instanceof AbstractModelElement) { + // Can reuse it + AbstractModelElement reusable = (AbstractModelElement) nextSubElement; + reusable.factory.updateModelElement(reusable, newSourceElements.next()); + } else { + // Replace it + nextSubElement.dispose(); + + ModelElement newSubElement = subModelElementFactory.createModelElement(newSourceElements.next()); + if (newSubElement != null) { + subElements.set(newSubElement); + } else { + // TODO: Report a warning? + subElements.remove(); + } + } + } + + // And create new ones if necessary + while (newSourceElements.hasNext()) { + ModelElement newSubElement = subModelElementFactory.createModelElement(newSourceElements.next()); + if (newSubElement != null) { + subElements.add(newSubElement); + } // TODO: Else report a warning? + } + + // And destroy any unneeded sub-elements + while (subElements.hasNext()) { + subElements.next().dispose(); + subElements.remove(); + } + } + + /** + * Adds a sub-model element to this CompositeModelElement + * + * @param element + * The sub-model element to be added + */ + public void addModelElement(ModelElement element) { + elements.add(element); + } + + @Override + public IStaticContentProvider getContentProvider(String propertyPath) { + if (elements.isEmpty()) { + return EmptyContentProvider.instance; + } + + return elements.get(0).getContentProvider(propertyPath); + } + + @Override + public ILabelProvider getLabelProvider(String propertyPath) { + if (elements.isEmpty()) { + return null; + } + + return elements.get(0).getLabelProvider(propertyPath); + } + + @Override + public boolean isOrdered(String propertyPath) { + if (elements.isEmpty()) { + return false; + } + + for (ModelElement element : elements) { + if (element.isOrdered(propertyPath)) { + return true; + } + } + + return false; + } + + @Override + public boolean isUnique(String propertyPath) { + if (elements.isEmpty()) { + return false; + } + + for (ModelElement element : elements) { + if (!element.isUnique(propertyPath)) { + return false; + } + } + + return true; + } + + @Override + public boolean isMandatory(String propertyPath) { + if (elements.isEmpty()) { + return false; + } + + for (ModelElement element : elements) { + if (!element.isMandatory(propertyPath)) { + return false; + } + } + + return true; + } + + @Override + public boolean isEditable(String propertyPath) { + if (elements.isEmpty()) { + return false; + } + + for (ModelElement element : elements) { + if (!element.isEditable(propertyPath)) { + return false; + } + } + + return true; + } + + private List elements = new LinkedList(); + + @Override + public boolean forceRefresh(String propertyPath) { + if (elements.isEmpty()) { + return false; + } + + for (ModelElement element : elements) { + if (element.forceRefresh(propertyPath)) { + return true; + } + } + + return false; + } + + @Override + public Object getDefaultValue(String propertyPath) { + if (elements.isEmpty()) { + return null; + } + return elements.get(0).getDefaultValue(propertyPath); + } + + public List getSubElements() { + return elements; + } + + // + // Nested types + // + + /** + * Protocol for a factory that a {@link CompositeModelElement} uses to create sub-elements for a multiple + * selection. It binds all of the necessary context so that the only input is a selected source element. + */ + public interface BoundModelElementFactory { + + ModelElement createModelElement(Object sourceElement); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSource.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSource.java new file mode 100644 index 00000000000..c34812a4b43 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSource.java @@ -0,0 +1,559 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 417409 + * Christian W. Damus - bug 455075 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.LabelProviderChangedEvent; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.swt.graphics.Image; + +/** + * A DataSource is an object encapsulating one or more {@link ModelElement}s. + * It contains methods to resolve property paths, and forward the methods to + * the right ModelElement. + * + * For example, a UML class stereotyped with the SysML::Blocks::Block will have + * two ModelElements : one for UML, and one for the Block stereotype. + * + * It will be able to resolve paths such as UML:Class:name or + * SysML:Blocks:Block:isEncapsulated + * + * The methods such as isUnique, isEditable or getContentProvider will be + * delegated to the resolved ModelElement, with a truncated property path. + * + * For example, a call to DataSource#isEditable("UML:Class:name") will be + * forwarded to UMLModelElement#isEditable("name") + * + * @author Camille Letavernier + */ +public class DataSource implements IChangeListener { + + private final ListenerList changeListeners = new ListenerList(ListenerList.IDENTITY); + + private final ListenerList dataSourceListeners = new ListenerList(ListenerList.IDENTITY); + + private View view; + + private IStructuredSelection selection; + + private Map elements = new HashMap(); + + /** + * Constructs a new DataSource from the given view and selection + * + * @param realm + * @param view + * @param selection + * + * @see DataSourceFactory#createDataSourceFromSelection(IStructuredSelection, View) + */ + protected DataSource(View view, IStructuredSelection selection) { + this.view = view; + this.selection = selection; + } + + /** + * Return the instance of ModelElement associated to the given path + * + * @param propertyPath + * The propertyPath to lookup + * @return + * The ModelElement associated to the given propertyPath + */ + public ModelElement getModelElement(String propertyPath) { + // ConfigurationManager.instance.getProperty(propertyPath) + String key = propertyPath.substring(0, propertyPath.lastIndexOf(":")); //$NON-NLS-1$ + if (!elements.containsKey(key)) { // Try to resolve the modelElements on-the-fly + ModelElement element = DataSourceFactory.instance.getModelElementFromPropertyPath(this, propertyPath); + if (element == null) { + Activator.log.warn("Unable to find a ModelElement for " + propertyPath + ". Elements : " + elements); //$NON-NLS-1$ //$NON-NLS-2$ + } + elements.put(key, element); + } + return elements.get(key); + } + + private String getLocalPropertyPath(String propertyPath) { + return propertyPath.substring(propertyPath.lastIndexOf(":") + 1); //$NON-NLS-1$ + } + + /** + * Returns an IObservable corresponding to the given property path + * The observable may be either an IObservableValue or an IObservableList + * The call to this method is delegated to the corresponding ModelElement + * The IObservable objects returned by this method may be shared by + * many instances, which means they should not be disposed directly. + * They will be disposed when this DataSource is disposed. + * + * @param propertyPath + * The property path for which we want to retrieve an ObservableValue + * @return + * The IObservable corresponding to the given propertyPath + */ + public IObservable getObservable(String propertyPath) { + String localPropertyPath = getLocalPropertyPath(propertyPath); + ModelElement element = getModelElement(propertyPath); + + if (element == null) { + return null; + } + + IObservable observable = element.getObservable(localPropertyPath); + if (observable != null) { + observable.addChangeListener(this); + } + + return observable; + } + + @Override + public String toString() { + return "[DataSource] " + super.toString(); //$NON-NLS-1$ + } + + /** + * Returns an IStaticContentProvider corresponding to the given property path + * The call to this method is delegated to the corresponding ModelElement + * + * @param propertyPath + * The property path for which we want to retrieve a ContentProvider + * @return + * The IStaticContentProvider corresponding to the given propertyPath + */ + public IStaticContentProvider getContentProvider(final String propertyPath) { + class Delegator extends EncapsulatedContentProvider implements IDataSourceListener { + + { + createDelegate(); + DataSource.this.addDataSourceListener(this); + } + + @Override + public void dispose() { + disposeDelegate(); + DataSource.this.removeDataSourceListener(this); + } + + private void disposeDelegate() { + if (encapsulated != null) { + encapsulated.dispose(); + encapsulated = null; + } + + // If I had any temporary elements, then they cannot now be relevant + clearTemporaryElements(); + } + + private void createDelegate() { + encapsulate(doGetContentProvider(propertyPath)); + } + + public void dataSourceChanged(DataSourceChangedEvent event) { + disposeDelegate(); + createDelegate(); + } + } + + return new Delegator(); + } + + protected IStaticContentProvider doGetContentProvider(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return EmptyContentProvider.instance; + } + + String localPropertyPath = getLocalPropertyPath(propertyPath); + return element.getContentProvider(localPropertyPath); + } + + /** + * Returns an ILabelProvider corresponding to the given property path + * The call to this method is delegated to the corresponding ModelElement + * + * @param propertyPath + * The property path for which we want to retrieve an ILabelProvider + * @return + * The ILabelProvider corresponding to the given propertyPath + */ + public ILabelProvider getLabelProvider(final String propertyPath) { + class Delegator extends LabelProvider implements IDataSourceListener, ILabelProviderListener { + private ILabelProvider delegate; + + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); + + { + DataSource.this.addDataSourceListener(this); + } + + @Override + public void dispose() { + disposeDelegate(); + super.dispose(); + } + + private void disposeDelegate() { + if (delegate != null) { + delegate.removeListener(this); + delegate.dispose(); + delegate = null; + } + } + + public void dataSourceChanged(DataSourceChangedEvent event) { + disposeDelegate(); + } + + @Override + public void addListener(ILabelProviderListener listener) { + listeners.addIfAbsent(listener); + } + + @Override + public void removeListener(ILabelProviderListener listener) { + listeners.remove(listener); + } + + public void labelProviderChanged(LabelProviderChangedEvent event) { + if (!listeners.isEmpty()) { + LabelProviderChangedEvent forward = new LabelProviderChangedEvent(this, event.getElements()); + for (ILabelProviderListener next : listeners) { + try { + next.labelProviderChanged(forward); + } catch (Exception e) { + Activator.log.error("Uncaught exception in label provider listener.", e); //$NON-NLS-1$ + } + } + } + } + + ILabelProvider getDelegate() { + if (delegate == null) { + delegate = doGetLabelProvider(propertyPath); + if (delegate == null) { + delegate = new LabelProvider(); + } + delegate.addListener(this); + } + + return delegate; + } + + @Override + public Image getImage(Object element) { + return getDelegate().getImage(element); + } + + @Override + public String getText(Object element) { + return getDelegate().getText(element); + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return getDelegate().isLabelProperty(element, property); + } + } + + return new Delegator(); + } + + protected ILabelProvider doGetLabelProvider(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return null; + } + String localPropertyPath = getLocalPropertyPath(propertyPath); + return element.getLabelProvider(localPropertyPath); + } + + /** + * Adds a change listener to this DataSource. The listener will be notified + * each time a change occurs on one of the IObservable produced by this DataSource + * + * @see DataSource#getObservable(String) + * @param listener + * The Change listener + */ + public void addChangeListener(IChangeListener listener) { + changeListeners.add(listener); + } + + /** + * Removes a change listener from this DataSource. + * + * @param listener + * The listener to remove + * @see DataSource#addChangeListener(IChangeListener) + */ + public void removeChangeListener(IChangeListener listener) { + changeListeners.remove(listener); + } + + public void addDataSourceListener(IDataSourceListener listener) { + dataSourceListeners.add(listener); + } + + public void removeDataSourceListener(IDataSourceListener listener) { + dataSourceListeners.remove(listener); + } + + public void handleChange(ChangeEvent event) { + Object[] listeners = changeListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + try { + ((IChangeListener) listeners[i]).handleChange(event); + } catch (Exception e) { + Activator.log.error("Uncaught exception in observable change listener.", e); //$NON-NLS-1$ + } + } + } + + protected void fireDataSourceChanged() { + Object[] listeners = dataSourceListeners.getListeners(); + if (listeners.length > 0) { + DataSourceChangedEvent event = new DataSourceChangedEvent(this); + for (int i = 0; i < listeners.length; i++) { + try { + ((IDataSourceListener) listeners[i]).dataSourceChanged(event); + } catch (Exception e) { + Activator.log.error("Uncaught exception in data-source listener.", e); //$NON-NLS-1$ + } + } + } + } + + /** + * @return The view associated to this DataSource + */ + public View getView() { + return view; + } + + /** + * @return the selection associated to this DataSource + */ + public IStructuredSelection getSelection() { + return selection; + } + + /** + * @param selection + * the selection to set + */ + public void setSelection(IStructuredSelection selection) { + if (!selection.equals(this.selection)) { + this.selection = selection; + + fireDataSourceChanged(); + } + } + + /** + * @param propertyPath + * @return + * true if the property represented by this propertyPath is ordered + */ + public boolean isOrdered(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return false; + } + return element.isOrdered(getLocalPropertyPath(propertyPath)); + } + + /** + * @param propertyPath + * @return + * true if the property represented by this propertyPath is unique + */ + public boolean isUnique(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return false; + } + return element.isUnique(getLocalPropertyPath(propertyPath)); + } + + /** + * @param propertyPath + * @return + * true if the property represented by this propertyPath is mandatory + */ + public boolean isMandatory(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return false; + } + return element.isMandatory(getLocalPropertyPath(propertyPath)); + } + + /** + * @param propertyPath + * @return + * true if the property represented by this propertyPath is editable + */ + public boolean isEditable(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return false; + } + return element.isEditable(getLocalPropertyPath(propertyPath)); + } + + /** + * Returns true if the given property should be refresh each time a change + * occurs in the property view. May help when the IObservable doesn't + * catch some change events (For example, for some Ecore derived + * properties). + * + * @param propertyPath + * @return true if the refresh should be forced + */ + public boolean forceRefresh(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return false; + } + return element.forceRefresh(getLocalPropertyPath(propertyPath)); + } + + /** + * Return the value factory associated to the given path. May be null + * + * @param propertyPath + * The property path to lookup + * @return + * The factory used to edit and/or instantiate values for this property path + */ + public ReferenceValueFactory getValueFactory(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return null; + } + return element.getValueFactory(getLocalPropertyPath(propertyPath)); + } + + /** + * Return the default value for the given property path + * + * @param propertyPath + * @return + * The default value for the given property + */ + public Object getDefaultValue(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return null; + } + return element.getDefaultValue(getLocalPropertyPath(propertyPath)); + } + + /** + * Indicates if the widget should use the direct creation. + * The direct edition will disable the possibility to browse + * existing elements when the "add" button is pressed. + * + * This is essentially relevant for containment references : this method + * should return false if the widget should only allow creation of new + * elements. + * + * @param propertyPath + * @return + * True if the widget should use the direct edition option for the given property + */ + public boolean getDirectCreation(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return true; + } + return element.getDirectCreation(getLocalPropertyPath(propertyPath)); + } + + /** + * Disposes this data source. + * This will dispose all ModelElements and IObservable created by this DataSource + */ + public void dispose() { + for (ModelElement element : elements.values()) { + if (element != null) { + element.dispose(); + } + } + elements.clear(); + } + + /** + * return the IValidator for a property path + * + * @param propertyPath + * @return + */ + public IValidator getValidator(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return null; + } + return element.getValidator(getLocalPropertyPath(propertyPath)); + } + + /** + * return the NameResolutionHelper to use for completion + * + * @param propertyPath + * @return + */ + public INameResolutionHelper getNameResolutionHelper(String propertyPath) { + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return null; + } + return element.getNameResolutionHelper(getLocalPropertyPath(propertyPath)); + } + + /** + * return the Papyrus Converter to convert the object to edit or display string and to find the object from a string + * + * @param propertyPath + * @return + */ + public IPapyrusConverter getPapyrusConverter(String propertyPath){ + ModelElement element = getModelElement(propertyPath); + if (element == null) { + return null; + } + return element.getPapyrusConverter(getLocalPropertyPath(propertyPath)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceChangedEvent.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceChangedEvent.java new file mode 100644 index 00000000000..d358847911a --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceChangedEvent.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import java.util.EventObject; + + +/** + * This is the DataSourceChangedEvent type. Enjoy. + */ +public class DataSourceChangedEvent extends EventObject { + + private static final long serialVersionUID = 1L; + + DataSourceChangedEvent(DataSource source) { + super(source); + } + + public DataSource getDataSource() { + return (DataSource) getSource(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceFactory.java new file mode 100644 index 00000000000..d2c69c49d7a --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/DataSourceFactory.java @@ -0,0 +1,242 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 435103 + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; +import org.eclipse.papyrus.infra.properties.contexts.DataContextRoot; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.environment.ModelElementFactoryDescriptor; +import org.eclipse.papyrus.infra.properties.ui.util.PropertiesUtil; +import org.eclipse.papyrus.infra.properties.ui.xwt.XWTSection; +import org.eclipse.papyrus.infra.tools.util.ClassLoaderHelper; +import org.eclipse.papyrus.infra.widgets.Activator; + +/** + * A Factory to build and populate DataSource with the right ModelElements + * + * @author Camille Letavernier + */ +public class DataSourceFactory { + + /** + * Singleton instance for DataSourceFactory + */ + public static final DataSourceFactory instance = new DataSourceFactory(); + + /** + * Creates a new DataSource from a selection and a view. + * + * @param selection + * The selection of Objects + * @param view + * The view to display + * @return The DataSource that can be passed to the DisplayEngine to display + * the view + */ + public DataSource createDataSourceFromSelection(IStructuredSelection selection, View view) { + SelectionEntry selectionEntry = new SelectionEntry(selection, view); + + if (!sources.containsKey(selectionEntry)) { + DataSource source = new DataSource(view, selection); + sources.put(selectionEntry, source); + } + + return sources.get(selectionEntry); + } + + public void removeFromCache(IStructuredSelection selection, View view) { + if (selection == null || view == null) { + return; + } + + SelectionEntry entry = new SelectionEntry(selection, view); + sources.remove(entry); + } + + /** + * Returns the ModelElement corresponding to the given propertyPath and + * DataSource + * + * @param source + * The DataSource used to retrieved informations such as the View + * and the Selection + * @param propertyPath + * The path describing the property for which we want a + * ModelElement + * @return The matching modelElement + */ + public ModelElement getModelElementFromPropertyPath(DataSource source, String propertyPath) { + String key = propertyPath.substring(0, propertyPath.lastIndexOf(":")); //$NON-NLS-1$ + for (Context context : PropertiesUtil.getDependencies(source.getView().getContext())) { + DataContextElement element = PropertiesUtil.getContextElementByQualifiedName(key, context.getDataContexts()); + if (element != null) { + ModelElement modelElement = DataSourceFactory.instance.createModelElement(element, source.getSelection()); + if (modelElement != null) { + modelElement.setDataSource(source); + } + return modelElement; + } + } + return null; + } + + /** + * Creates a ModelElement from the given DataContextElement and Selection. + * + * @param contextElement + * The contextElement for which we are creating a ModelElement + * @param selection + * The list of objects currently selected + * @return The model element corresponding to the given contextElement and + * selection + */ + private ModelElement createModelElement(final DataContextElement contextElement, IStructuredSelection selection) { + if (selection.size() == 1) { // Single Selection + ModelElement modelElement = createFromSource(selection.getFirstElement(), contextElement); + return modelElement; + } else { // MultiSelection + // Bind the context element in a factory for the composite to create sub-elements + CompositeModelElement composite = new CompositeModelElement(new CompositeModelElement.BoundModelElementFactory() { + + public ModelElement createModelElement(Object sourceElement) { + return createFromSource(sourceElement, contextElement); + } + }); + + Iterator it = selection.iterator(); + while (it.hasNext()) { + ModelElement element = createFromSource(it.next(), contextElement); + if (element != null) { + composite.addModelElement(element); + } + } + + return composite; + } + } + + /** + * Retrieves the ModelElementFactory for the given DataContextElement. The + * ModelElementFactory is declared by the DataContextRoot owning the given + * DataContextElement + * + * @param context + * The DataContextElement for which we want to retrieve the + * ModelElementFactory + * @return The ModelElementFactory corresponding to the given + * DataContextElement + */ + private ModelElementFactory getFactory(DataContextElement context) { + DataContextRoot rootPackage = getRootPackage(context); + ModelElementFactoryDescriptor factoryDescriptor = rootPackage.getModelElementFactory(); + + if (factoryDescriptor == null) { + Activator.log.warn("No ModelElementFactory is attached to DataContextElement " + getQualifiedName(context)); //$NON-NLS-1$ + return null; + } + if (factoryDescriptor.eIsProxy()) { + Activator.log.warn("Unresolved reference to the ModelElementFactory: " + EcoreUtil.getURI(factoryDescriptor)); //$NON-NLS-1$ + return null; + } + + String factoryName = factoryDescriptor.getFactoryClass(); + ModelElementFactory factory = ClassLoaderHelper.newInstance(factoryName, ModelElementFactory.class); + + return factory; + } + + private ModelElement createFromSource(Object source, DataContextElement context) { + ModelElementFactory factory = getFactory(context); + + if (factory == null) { + return null; + } + + return factory.createFromSource(source, context); + } + + private DataContextRoot getRootPackage(DataContextElement context) { + if (context.getPackage() == null) { + return (DataContextRoot) context; + } + return getRootPackage(context.getPackage()); + } + + private String getQualifiedName(DataContextElement context) { + if (context.getPackage() == null) { + return context.getName(); + } + return getQualifiedName(context.getPackage()) + ":" + context.getName(); //$NON-NLS-1$ + } + + /** + * Singleton Constructor. + */ + private DataSourceFactory() { + + } + + private class SelectionEntry { + + private IStructuredSelection selection; + + private View view; + + public SelectionEntry(IStructuredSelection selection, View view) { + if (selection == null) { + throw new IllegalArgumentException("The selection must not be null"); + } + if (view == null) { + throw new IllegalArgumentException("The view must not be null"); + } + this.selection = selection; + this.view = view; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SelectionEntry)) { + return false; + } + + SelectionEntry other = (SelectionEntry) obj; + return other.view.equals(view) && selection.equals(other.selection); + } + + @Override + public int hashCode() { + return selection.hashCode() + view.hashCode(); + } + } + + /** + * More than one {@link XWTSection} may share the same DataSource. + * They all need to listen on the same source, so that they can correctly + * refresh themselves. We maintain a cache for each Selection/View pair. + * + * The cache is cleaned when the sections are disposed. + */ + // TODO : More than one view can be displayed at the same time. The cache should only + // rely on a selection ; not on a selection-view pair. + // We may use a (ISelection, Context) key : the DataSource must be associated to a single context + private Map sources = new HashMap(); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElement.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElement.java new file mode 100644 index 00000000000..98b3abf675b --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElement.java @@ -0,0 +1,308 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * Christian W. Damus (CEA) - bug 323802 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.emf.databinding.EMFProperties; +import org.eclipse.emf.databinding.FeaturePath; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; +import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResourceSet; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.creation.EcorePropertyEditorFactory; +import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; +import org.eclipse.papyrus.infra.ui.emf.databinding.EMFObservableList; +import org.eclipse.papyrus.infra.ui.emf.databinding.EMFObservableValue; +import org.eclipse.papyrus.infra.ui.emf.dialog.NestedEditingDialogContext; +import org.eclipse.papyrus.infra.ui.emf.providers.EMFContentProvider; +import org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; + +/** + * A ModelElement to manipulate EMF objects. + * This ModelElement uses EMFProperties to retrieve Observables when there + * is no Editing Domain, and {@link EMFObservableValue} / {@link EMFObservableList} when + * an Editing domain is available + * + * @author Camille Letavernier + */ +public class EMFModelElement extends AbstractModelElement { + + /** + * The EObject manipulated by this ModelElement + */ + protected EObject source; + + /** + * The Editing Domain of the EObject for this ModelElement + */ + protected EditingDomain domain; + + /** + * + * Constructs a new EMFModelElement for the given EObject + * + * @param source + */ + public EMFModelElement(EObject source) { + this(source, null); + } + + /** + * + * Constructs a new EMFModelElement for the given EObject and Editing Domain + * + * @param source + * @param domain + */ + public EMFModelElement(EObject source, EditingDomain domain) { + this.source = source; + this.domain = domain; + } + + /** + * @return the EditingDomain for this ModelElement + */ + public EditingDomain getDomain() { + return domain; + } + + /** + * @return the EObject for this ModelElement + */ + public EObject getSource() { + return source; + } + + @Override + protected IObservable doGetObservable(String propertyPath) { + FeaturePath featurePath = getFeaturePath(propertyPath); + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return null; + } + + if (feature.getUpperBound() != 1) { + IObservableList list = domain == null ? EMFProperties.list(featurePath).observe(source) : new EMFObservableList(EMFProperties.list(featurePath).observe(source), domain, getSource(featurePath), feature); + return list; + } + + IObservableValue value = domain == null ? EMFProperties.value(featurePath).observe(source) : new EMFObservableValue(getSource(featurePath), feature, domain); + return value; + } + + /** + * Returns the last EObject by following the given featurePath from the {@link #source} EObject + * The last feature of the featurePath can be used to retrieve value from the returned EObject + * + * @param featurePath + * @return the EObject found by resolving to the given FeaturePath + */ + public EObject getSource(FeaturePath featurePath) { + EObject currentSource = source; + EStructuralFeature[] features = featurePath.getFeaturePath(); + for (int i = 0; i < features.length - 1; i++) { + currentSource = (EObject) currentSource.eGet(features[i]); + } + return currentSource; + } + + /** + * Returns the feature represented by the given FeaturePath + * + * @param featurePath + * @return + * The last feature obtained by navigating the feature path + */ + public EStructuralFeature getFeature(FeaturePath featurePath) { + EStructuralFeature[] features = featurePath.getFeaturePath(); + return features[features.length - 1]; + } + + /** + * Returns the feature represented by the given propertyPath. + * + * @param propertyPath + * The property path may contain one or more dots to navigate the properties (e.g. : feature1.feature2.feature3) + * @return + * The last feature obtained by resolving the full property path + */ + public EStructuralFeature getFeature(String propertyPath) { + FeaturePath featurePath = getFeaturePath(propertyPath); + return getFeature(featurePath); + } + + /** + * Returns the featurePath corresponding to the given propertyPath + * + * @param propertyPath + * The property path may contain one or more dots to navigate the properties (e.g. : feature1.feature2.feature3) + * @return + * The featurePath corresponding to the given propertyPath + */ + public FeaturePath getFeaturePath(String propertyPath) { + String[] featureNames = propertyPath.split("\\."); //$NON-NLS-1$ + EStructuralFeature[] features = new EStructuralFeature[featureNames.length]; + + int i = 0; + EClass currentClass = source.eClass(); + for (String featureName : featureNames) { + EStructuralFeature feature = currentClass.getEStructuralFeature(featureName); + features[i++] = feature; + if (i < featureNames.length) { + if (feature instanceof EReference) { + EReference reference = (EReference) feature; + EClassifier type = reference.getEType(); + if (type instanceof EClass) { + currentClass = (EClass) type; + continue; + } + } + + Activator.log.warn("Cannot find feature path " + propertyPath + " for EClass " + source.eClass()); //$NON-NLS-1$ //$NON-NLS-2$ + return null; + } + } + + return FeaturePath.fromList(features); + } + + @Override + public IStaticContentProvider getContentProvider(String propertyPath) { + FeaturePath featurePath = getFeaturePath(propertyPath); + EStructuralFeature feature = getFeature(featurePath); + if (feature != null) { + return new EMFContentProvider(getSource(featurePath), feature); + } + return super.getContentProvider(propertyPath); + } + + @Override + public ILabelProvider getLabelProvider(String propertyPath) { + try { + LabelProviderService lpSvc = (source.eResource() != null) // + ? ServiceUtilsForEObject.getInstance().getService(LabelProviderService.class, source) // + : ServiceUtilsForResourceSet.getInstance().getService(LabelProviderService.class, NestedEditingDialogContext.getInstance().getResourceSet()); + return lpSvc.getLabelProvider(); + } catch (ServiceException ex) { + // The service registry isn't always present in the properties view. Don't log an error and use a standard label provider + return new EMFLabelProvider(); + } + } + + @Override + public boolean isOrdered(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return true; + } + return feature.isOrdered(); + } + + @Override + public boolean isUnique(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return false; + } + return feature.isUnique(); + } + + @Override + public boolean isMandatory(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return false; + } + + return EMFHelper.isRequired(feature); + } + + @Override + public final boolean isEditable(String propertyPath) { + return isFeatureEditable(propertyPath) && isElementEditable(); + } + + protected boolean isFeatureEditable(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return false; + } + return feature.isChangeable(); + } + + protected boolean isElementEditable() { + return !EMFHelper.isReadOnly(source); + } + + @Override + public boolean forceRefresh(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return false; + } + return feature.isDerived(); + } + + @Override + public ReferenceValueFactory getValueFactory(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature != null) { + if (feature instanceof EReference) { + EReference reference = (EReference) feature; + if (reference.isContainment()) { + return new EcorePropertyEditorFactory(reference); + } + } + } + + return super.getValueFactory(propertyPath); + } + + @Override + public Object getDefaultValue(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return null; + } + return feature.getDefaultValue(); + } + + @Override + public boolean getDirectCreation(String propertyPath) { + EStructuralFeature feature = getFeature(propertyPath); + if (feature == null) { + return false; + } + + if (feature instanceof EAttribute) { + return false; + } + + return ((EReference) feature).isContainment(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElementFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElementFactory.java new file mode 100644 index 00000000000..202ae3587bc --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/EMFModelElementFactory.java @@ -0,0 +1,41 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; + +/** + * A ModelElementFactory for creating {@link EMFModelElement}s + * + * @author Camille Letavernier + * + */ +public class EMFModelElementFactory extends AbstractEMFModelElementFactory { + + @Override + protected EMFModelElement doCreateFromSource(Object sourceElement, DataContextElement context) { + EObject source = EMFHelper.getEObject(sourceElement); + if (source == null) { + Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$ + return null; + } + + EditingDomain domain = EMFHelper.resolveEditingDomain(source); + return new EMFModelElement(source, domain); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/IDataSourceListener.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/IDataSourceListener.java new file mode 100644 index 00000000000..c03e8cdef95 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/IDataSourceListener.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import java.util.EventListener; + +import org.eclipse.core.databinding.observable.IObservable; + + +/** + * A listener protocol for changes to a {@link DataSource} (especially its selection). Data sources are not {@linkplain IObservable observables} because that would confuse the XWT bindings framework. + * + * @see DataSource + * @see DataSource#addDataSourceListener(IDataSourceListener) + */ +public interface IDataSourceListener extends EventListener { + + void dataSourceChanged(DataSourceChangedEvent event); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElement.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElement.java new file mode 100644 index 00000000000..0da61ff117e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElement.java @@ -0,0 +1,188 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; + +/** + * An interface representing Model Elements. A ModelElement is associated to a + * DataContextElement, and should provide access to all properties for a given + * object, though the mean of {@link IObservable}s. It should also be able to + * provide informations about each property, such as a ContentProvider for + * references. + * + * @author Camille Letavernier + */ +public interface ModelElement { + + /** + * Returns an IObservable for the given propertyPath. The IObservable + * may be either an IObservableValue or an IObservableList. + * The IObservable objects returned by this method may be shared by + * many instances, which means they should not be disposed directly. + * They will be disposed when this ModelElement is disposed. + * + * @param propertyPath + * The property for which we need an IObservable + * @return + * The IObservable corresponding to the given propertyPath + */ + public IObservable getObservable(String propertyPath); + + /** + * Returns an IStaticContentProvider for the given propertyPath. The + * returned value should not be null. If there is no content provider, + * use {@link EmptyContentProvider#instance} + * + * @param propertyPath + * The name of the property for which we want a Content provider + * @return + * The IStaticContentProvider containing the available values for + * the given property + */ + public IStaticContentProvider getContentProvider(String propertyPath); + + /** + * Returns an ILabelProvider for the given propertypath, or null if + * a default LabelProvider should be used. + * + * @param propertyPath + * @return + * the LabelProvider for the given path + */ + public ILabelProvider getLabelProvider(String propertyPath); + + /** + * Returns true if the given property should be ordered. Only relevant + * for Collection properties. + * + * @param propertyPath + * @return + * true is the property should be ordered + */ + public boolean isOrdered(String propertyPath); + + /** + * Returns true if the elements from the given property should be unique. + * Only relevant for Colleciton properties. + * + * @param propertyPath + * @return + * true if the elements should be unique + */ + public boolean isUnique(String propertyPath); + + /** + * Returns true if the given property is Mandatory. + * + * @param propertyPath + * @return true if the property is mandatory + */ + public boolean isMandatory(String propertyPath); + + /** + * Returns true if the given property is editable. + * + * @param propertyPath + * @return true if the given property is editable. + */ + public boolean isEditable(String propertyPath); + + /** + * Returns true if the given property should be refreshed each time a + * change occurs in the property view. This may help when the IObservable + * doesn't catch some change events (For example, for some Ecore derived + * properties). + * + * @param propertyPath + * @return true if the refresh should be forced + */ + public boolean forceRefresh(String propertyPath); + + /** + * Sets the DataSource associated to this model element + * + * @param source + * The DataSource to associate to this model element + */ + public void setDataSource(DataSource source); + + /** + * @param propertyPath + * the propertyPath to lookup + * @return the default factory used to handle operations such as object + * creation or edition, or null if these operations are not supported. + * This factory will typically be used by Multiple value editors, to + * create or edit a single entry. + */ + public ReferenceValueFactory getValueFactory(String propertyPath); + + /** + * @param propertyPath + * @return The default value for the property + */ + public Object getDefaultValue(String propertyPath); + + /** + * Indicates if the widget should be use the direct creation. + * The direct edition will disable the possibility to browse + * existing elements when the "add" button is pressed. + * + * This is essentially relevant for containment references : this method + * should return false if the widget should only allow creation of new + * elements. + * + * @param propertyPath + * @return True if the widget should use the direct edition option for the given property + * + */ + public boolean getDirectCreation(String propertyPath); + + /** + * Disposes this ModelElement + * All created IObservable will be disposed + */ + public void dispose(); + + + /** + * return the Validator of a given String propertyPath + * + * @param propertyPath + * @return + */ + public IValidator getValidator(String propertyPath); + + /** + * return the INameResolutionHelper to use for completion + * + * @param propertyPath + * @return + */ + public INameResolutionHelper getNameResolutionHelper(String propertyPath); + + /** + * return the Papyrus Converter to convert the object to edit or display string and to find the object from a string + * + * @param localPropertyPath + * @return + */ + public IPapyrusConverter getPapyrusConverter(String localPropertyPath); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElementFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElementFactory.java new file mode 100644 index 00000000000..ab98e9038c2 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/ModelElementFactory.java @@ -0,0 +1,42 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; + +/** + * An interface representing ModelElementFactories. + * ModelElementFactories are meant to be instantiated reflectively, thus should + * always provide a 0-arg constructor. + * + * @author Camille Letavernier + */ +public interface ModelElementFactory { + + /** + * Creates a new ModelElement for given Object and DataContextElement + * + * @param sourceElement + * The Object for which we need to build a ModelElement. Note that this element + * comes directly from the Eclipse selection, and may need to be adapted to get + * the actual semantic object (e.g. sourceElement may be a GMF EditPart, and needs + * to be adapted to retrieve the EObject). The factory is responsible for resolving + * the semantic object in such a case. + * @param context + * The DataContextElement containing the properties that the Property View framework + * is susceptible to ask for. + * @return + * The ModelElement corresponding to the sourceElement + */ + public ModelElement createFromSource(Object sourceElement, DataContextElement context); + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElement.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElement.java new file mode 100644 index 00000000000..b17c70cf199 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElement.java @@ -0,0 +1,37 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; +import org.eclipse.papyrus.infra.properties.internal.ui.observable.PreferencesObservableValue; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + + +public class PreferencesModelElement extends AbstractModelElement { + + protected DataContextElement context; + + protected IPreferenceStore store; + + public PreferencesModelElement(DataContextElement context) { + this.context = context; + store = new ScopedPreferenceStore(InstanceScope.INSTANCE, context.getName()); + } + + @Override + protected IObservable doGetObservable(String propertyPath) { + return new PreferencesObservableValue(propertyPath, store); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElementFactory.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElementFactory.java new file mode 100644 index 00000000000..11d635a85d0 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/modelelement/PreferencesModelElementFactory.java @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2012, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.modelelement; + +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; + + +public class PreferencesModelElementFactory extends AbstractModelElementFactory { + + @Override + protected PreferencesModelElement doCreateFromSource(Object sourceElement, DataContextElement context) { + return new PreferencesModelElement(context); + } + + @Override + protected void updateModelElement(PreferencesModelElement modelElement, Object newSourceElement) { + //The is nothing to update. We use the DataContextElement to retrieve the proper PreferenceStore, and it shouldn't have changed. + //We don't care about the current selection + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/preferences/Preferences.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/preferences/Preferences.java new file mode 100644 index 00000000000..470884ada7b --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/preferences/Preferences.java @@ -0,0 +1,268 @@ +/***************************************************************************** + * Copyright (c) 2010, 2015 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 482930 + * Christian W. Damus - bug 482927 + * Christian W. Damus - bug 469188 + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.preferences; + +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.internal.ui.messages.Messages; +import org.eclipse.papyrus.infra.properties.internal.ui.runtime.ConfigurationConflict; +import org.eclipse.papyrus.infra.properties.internal.ui.runtime.IInternalConfigurationManager; +import org.eclipse.papyrus.infra.properties.ui.runtime.IConfigurationManager; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +/** + * The PreferencePage for the Papyrus Property View. Offers an UI to enable or disable + * property view contexts. + * + * @author Camille Letavernier + */ +public class Preferences extends PreferencePage implements IWorkbenchPreferencePage, IExecutableExtension { + + private String id; + + @Override + public void init(IWorkbench workbench) { + // Nothing + } + + /** + * Queries my unique identifier as configured on the extension point. + * + * @return my unique identifier + */ + public final String getID() { + return id; + } + + @Override + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + this.id = config.getAttribute("id"); //$NON-NLS-1$ + } + + @Override + protected Control createContents(Composite parent) { + Composite self = new Composite(parent, SWT.NONE); + self.setLayout(new GridLayout(1, false)); + self.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + createHeaderContents(self); + + Label label = new Label(self, SWT.NONE); + label.setText(Messages.Preferences_Contexts); + + final IConfigurationManager configurationManager = PropertiesRuntime.getConfigurationManager(); + + List sortedContexts = configurationManager.getContextsForPreferencePage(getID()).stream() + .sorted(contextOrdering()) + .collect(Collectors.toList()); + + for (Context context : sortedContexts) { + boolean applied = configurationManager.isApplied(context); + Button checkbox = new Button(self, SWT.CHECK); + checkbox.setText(getLabel(context)); + checkbox.setSelection(applied); + final Context theContext = context; + contextState.setContextState(theContext, applied); + + checkbox.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + contextState.setContextState(theContext, ((Button) e.widget).getSelection()); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + }); + + checkboxes.put(context, checkbox); + } + + createFooterContents(self); + + contextState.snapshot(); + return null; + } + + /** + * Overridden by subclasses to create optional header content above the + * list of context check-boxes. + * + * @param parent + * the parent composite + */ + protected void createHeaderContents(Composite parent) { + // Pass + } + + /** + * Overridden by subclasses to create optional footer content below the + * list of context check-boxes. + * + * @param parent + * the parent composite + */ + protected void createFooterContents(Composite parent) { + // Pass + } + + protected Comparator contextOrdering() { + return Comparator.comparingInt(this::getCategory).thenComparing( + Comparator.comparing(Context::getUserLabel)); + } + + protected int getCategory(Context context) { + IConfigurationManager mgr = PropertiesRuntime.getConfigurationManager(); + return mgr.isCustomizable(context) + ? mgr.isPlugin(context) ? 0 : 1 + : 1000; + } + + @Override + public boolean performOk() { + return contextState.saveContext() && super.performOk(); + } + + @Override + public void performApply() { + contextState.saveContext(); + } + + @Override + public void performDefaults() { + IConfigurationManager mgr = PropertiesRuntime.getConfigurationManager(); + for (Context context : mgr.getContexts()) { + boolean applied = mgr.isAppliedByDefault(context); + Button checkbox = checkboxes.get(context); + if (checkbox != null) { + checkbox.setSelection(applied); + contextState.setContextState(context, applied); + } + } + } + + private String getLabel(Context context) { + String qualifier; + + if (PropertiesRuntime.getConfigurationManager().isPlugin(context)) { + qualifier = Messages.Preferences_Plugin; + } else if (PropertiesRuntime.getConfigurationManager().isMissing(context)) { + qualifier = "missing"; + } else { + qualifier = Messages.Preferences_Custom; + } + + return String.format("%s (%s)", context.getUserLabel(), qualifier); //$NON-NLS-1$ + } + + private final ContextState contextState = new ContextState(); + + private Map checkboxes = new HashMap(); + + private class ContextState { + + private Map contexts = new HashMap<>(); + + private Map snapshot; + + ContextState() { + super(); + } + + void snapshot() { + snapshot = new HashMap<>(contexts); + } + + public void setContextState(Context context, boolean applied) { + contexts.put(context, applied); + } + + public boolean saveContext() { + IInternalConfigurationManager mgr = (IInternalConfigurationManager) PropertiesRuntime.getConfigurationManager(); + for (Entry entry : contexts.entrySet()) { + if (entry.getValue()) { + mgr.enableContext(entry.getKey(), false); + } else { + mgr.disableContext(entry.getKey(), false); + } + } + + mgr.update(); + + Set delta = getChangedContexts(); + if (!delta.isEmpty()) { + Collection conflicts = mgr.checkConflicts(delta); + + if (!conflicts.isEmpty()) { + String errorMessage = Messages.Preferences_ConflictWarning1; + for (ConfigurationConflict conflict : conflicts) { + errorMessage += conflict.toString() + "\n"; //$NON-NLS-1$ + } + errorMessage += Messages.Preferences_ConflictWarning2; + + MessageDialog dialog = new MessageDialog(getShell(), Messages.Preferences_ConflictWarningTitle, null, errorMessage, MessageDialog.WARNING, + new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, + 1); + int result = dialog.open(); + if (result != 0) { + return false; + } + } + + snapshot(); + } + + return true; + } + + Set getChangedContexts() { + return (snapshot == null) + ? contexts.keySet() + : snapshot.keySet().stream() + .filter(c -> !Objects.equals(snapshot.get(c), contexts.get(c))) + .collect(Collectors.toSet()); + } + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/ContainerContentProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/ContainerContentProvider.java new file mode 100644 index 00000000000..cf39358ea50 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/ContainerContentProvider.java @@ -0,0 +1,60 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.ui.emf.providers.strategy.SemanticEMFContentProvider; + +public class ContainerContentProvider extends SemanticEMFContentProvider { + + protected EClass type; + + protected Object input; + + public ContainerContentProvider(EObject source, EReference reference) { + super(source.eResource().getResourceSet()); + type = (EClass) reference.getEType(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + this.input = newInput; + if (newInput instanceof EObject) { + this.type = ((EObject) newInput).eClass(); + } + } + + @Override + public boolean isValidValue(Object value) { + Object adaptedValue = getAdaptedValue(value); + if (adaptedValue instanceof EObject) { + // We cannot create objects in a read-only object + if (EMFHelper.isReadOnly((EObject) adaptedValue)) { + return false; + } + + // We need at least one valid containment reference to store this + // type of object + for (EReference reference : ((EObject) adaptedValue).eClass().getEAllReferences()) { + if (reference.isContainment() && EMFHelper.isSubclass(this.type, reference.getEReferenceType())) { + return true; + } + } + } + return false; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/CreateInFeatureContentProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/CreateInFeatureContentProvider.java new file mode 100644 index 00000000000..2b6e29987f6 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/CreateInFeatureContentProvider.java @@ -0,0 +1,27 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; + + +public interface CreateInFeatureContentProvider extends IStaticContentProvider, IStructuredContentProvider { + + /** + * Sets the type of feature we're looking for + * + * @param type + */ + public void setType(EClass type); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedComboViewer.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedComboViewer.java new file mode 100644 index 00000000000..6e0f6aa3375 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedComboViewer.java @@ -0,0 +1,47 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ViewerFilter; + +@Deprecated +public class EncapsulatedComboViewer extends ComboViewer { + + public EncapsulatedComboViewer(ComboViewer viewer) { + super(viewer.getCCombo()); + if (viewer.getContentProvider() != null) { + super.setContentProvider(viewer.getContentProvider()); + } + if (viewer.getInput() != null) { + super.setInput(viewer.getInput()); + } + if (viewer.getLabelProvider() != null) { + super.setLabelProvider(viewer.getLabelProvider()); + } + if (viewer.getFilters() != null) { + super.setFilters(viewer.getFilters()); + } + } + + @Override + public void setFilters(ViewerFilter[] filters) { + for (ViewerFilter filter : filters) { + addFilter(filter); + } + } + + @Override + public void addFilter(ViewerFilter filter) { + super.addFilter(new EncapsulatedViewerFilter(filter)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedViewerFilter.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedViewerFilter.java new file mode 100644 index 00000000000..a9447ae4182 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/EncapsulatedViewerFilter.java @@ -0,0 +1,36 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.papyrus.infra.widgets.providers.UnsetObject; + + +public class EncapsulatedViewerFilter extends ViewerFilter { + + private ViewerFilter viewerFilter; + + public EncapsulatedViewerFilter(ViewerFilter encapsulated) { + this.viewerFilter = encapsulated; + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element == UnsetObject.instance || element == UnchangedObject.instance) { + return true; + } + return viewerFilter.select(viewer, parentElement, element); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/FeatureContentProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/FeatureContentProvider.java new file mode 100644 index 00000000000..ddeebb7d4e4 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/FeatureContentProvider.java @@ -0,0 +1,67 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; + +public class FeatureContentProvider implements CreateInFeatureContentProvider { + + private EClass type; + + // private Viewer viewer; + + private Object input; + + public FeatureContentProvider(EClass type) { + this.type = type; + } + + public void setType(EClass type) { + this.type = type; + } + + public void dispose() { + // Nothing + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // this.viewer = viewer; + this.input = newInput; + } + + public Object[] getElements() { + return getElements(input); + } + + public Object[] getElements(Object inputElement) { + EObject inputEObject = EMFHelper.getEObject(input); + if (inputEObject == null) { + return new Object[0]; + } + List elements = new LinkedList(); + for (EReference reference : inputEObject.eClass().getEAllReferences()) { + if (reference.isContainment()) { + if (EMFHelper.isSubclass(type, reference.getEReferenceType())) { + elements.add(reference); + } + } + } + return elements.toArray(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/PropertiesHeaderLabelProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/PropertiesHeaderLabelProvider.java new file mode 100644 index 00000000000..e65df2d93d1 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/PropertiesHeaderLabelProvider.java @@ -0,0 +1,55 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; +import org.eclipse.papyrus.infra.services.labelprovider.service.impl.LabelProviderServiceImpl; +import org.eclipse.swt.graphics.Image; + +/** + * An extensible LabelProvider for the Properties View header. It is based + * on the papyrus {@link LabelProviderService} + * + * @author Camille Letavernier + */ +public class PropertiesHeaderLabelProvider extends LabelProvider { + + + private final ILabelProvider delegate; + + /** + * The {@link LabelProviderService} Context + */ + public final static String PROPERTIES_HEADER_CONTEXT = "org.eclipse.papyrus.infra.properties.ui.header.labelProvider.context"; + + public PropertiesHeaderLabelProvider() { + LabelProviderService labelProviderService = new LabelProviderServiceImpl(); + delegate = labelProviderService.getLabelProvider(PROPERTIES_HEADER_CONTEXT); + } + + @Override + public String getText(Object element) { + return delegate.getText(element); + } + + @Override + public Image getImage(Object element) { + return delegate.getImage(element); + } + + @Override + public void dispose() { + delegate.dispose(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/SelectionLabelProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/SelectionLabelProvider.java new file mode 100644 index 00000000000..eb79db1f085 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/SelectionLabelProvider.java @@ -0,0 +1,61 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import java.util.Collection; +import java.util.TreeMap; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.services.labelprovider.service.ExtensibleLabelProvider; +import org.eclipse.papyrus.infra.services.labelprovider.service.IFilteredLabelProvider; + +/** + * A class for providing labels for a selected element. + * This label provider dispatchs the calls to the label providers + * registered through an extension point, according to the given selection + * + * @author Camille Letavernier + * + * @deprecated Use PropertiesHeaderLabelProvider instead + */ +@Deprecated +public class SelectionLabelProvider extends ExtensibleLabelProvider { + + public static final String EXTENSION_ID = "org.eclipse.papyrus.infra.properties.ui.labelprovider"; //$NON-NLS-1$ + + public static final String LABEL_PROVIDER_PROPERTY = "labelProvider"; //$NON-NLS-1$ + + public static final String PRIORITY_PROPERTY = "priority"; //$NON-NLS-1$ + + protected final TreeMap> labelProviders = new TreeMap>(); + + public SelectionLabelProvider() { + super(); + readExtensionPoint(); + } + + protected void readExtensionPoint() { + IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID); + + for (IConfigurationElement e : config) { + try { + final IFilteredLabelProvider provider = (IFilteredLabelProvider) e.createExecutableExtension(LABEL_PROVIDER_PROPERTY); + final int priority = Integer.parseInt(e.getAttribute(PRIORITY_PROPERTY)); + registerProvider(priority, provider); + } catch (Exception ex) { + Activator.log.error("Cannot load the label provider : " + e.getAttribute(LABEL_PROVIDER_PROPERTY), ex); + } + } + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProvider.java new file mode 100644 index 00000000000..23c749b4bad --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProvider.java @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +import org.eclipse.papyrus.infra.properties.ui.widgets.MaskProvider; + +/** + * Given the way the XWT files are parsed, the MaskProvider is passed to its + * parent before being fully initialized. + * + * This interface enables a MaskProvider to notify its parent when it is ready, + * so that the parent is forced to wait for its MaskProvider to be ready before + * it can call any method on it. + * + * @author Camille Letavernier + */ +public interface XWTCompliantMaskProvider extends MaskProvider { + + public void addMaskProviderListener(XWTCompliantMaskProviderListener listener); + + public void removeMaskProviderListener(XWTCompliantMaskProviderListener listener); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProviderListener.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProviderListener.java new file mode 100644 index 00000000000..15614c01573 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/providers/XWTCompliantMaskProviderListener.java @@ -0,0 +1,23 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.providers; + +/** + * + * @author Camille Letavernier + * + * @see XWTCompliantMaskProvider + */ +public interface XWTCompliantMaskProviderListener { + + public void notifyReady(XWTCompliantMaskProvider provider); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ConfigurationManagerRegistry.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ConfigurationManagerRegistry.java new file mode 100644 index 00000000000..f7d0c8c4ee2 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ConfigurationManagerRegistry.java @@ -0,0 +1,257 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.Property; +import org.eclipse.papyrus.infra.properties.environment.CompositeWidgetType; +import org.eclipse.papyrus.infra.properties.environment.LayoutType; +import org.eclipse.papyrus.infra.properties.environment.Namespace; +import org.eclipse.papyrus.infra.properties.environment.PropertyEditorType; +import org.eclipse.papyrus.infra.properties.environment.StandardWidgetType; +import org.eclipse.papyrus.infra.properties.environment.Type; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.internal.ui.runtime.ConfigurationConflict; +import org.eclipse.papyrus.infra.properties.internal.ui.runtime.IInternalConfigurationManager; + +/** + * Registry of configuration manager implementations. + */ +class ConfigurationManagerRegistry { + + ConfigurationManagerRegistry() { + super(); + } + + IInternalConfigurationManager getConfigurationManager() { + IInternalConfigurationManager result = null; + + for (IConfigurationElement config : Platform.getExtensionRegistry().getConfigurationElementsFor(Activator.PLUGIN_ID, "configuration")) { //$NON-NLS-1$ + switch (config.getName()) { + case "configurationManager": //$NON-NLS-1$ + try { + if (result == null) { + result = createConfigurationManager(config); + } else { + Activator.log.warn("Multiple configuration managers installed. Ignoring implementation provided by " + config.getContributor().getName()); //$NON-NLS-1$ + } + } catch (Exception e) { + Activator.log.error("Invalid configuration manager extension.", e); //$NON-NLS-1$ + } + + break; + } + } + + if (result == null) { + result = createNullConfigurationManager(); + } + + return result; + } + + private IInternalConfigurationManager createConfigurationManager(IConfigurationElement config) throws Exception { + IInternalConfigurationManager.Provider provider = (IInternalConfigurationManager.Provider) config.createExecutableExtension("class"); //$NON-NLS-1$ + IInternalConfigurationManager result = provider.getConfigurationManager(); + + if (result == null) { + Activator.log.error("Extension does not provide a configuration manger in contributor " + config.getContributor().getName(), null); //$NON-NLS-1$ + } + + return result; + } + + private IInternalConfigurationManager createNullConfigurationManager() { + Activator.log.error("No configuration manager is installed. The properties UI will not function.", null); //$NON-NLS-1$ + + return new IInternalConfigurationManager() { + + private ViewConstraintEngine constraintEngine; + + @Override + public boolean isPlugin(Context context) { + return false; + } + + @Override + public boolean isMissing(Context context) { + return true; + } + + @Override + public boolean isEnabled(Context context) { + return false; + } + + @Override + public boolean isCustomizable(Context propertyViewConfiguration) { + return false; + } + + @Override + public Boolean isAppliedByDefault(Context context) { + return Boolean.FALSE; + } + + @Override + public boolean isApplied(Context context) { + return false; + } + + @Override + public ResourceSet getResourceSet() { + return null; + } + + @Override + public Property getProperty(String propertyPath, Context context) { + return null; + } + + @Override + public Namespace getNamespaceByName(String name) { + return null; + } + + @Override + public Collection getMissingContexts() { + return Collections.emptySet(); + } + + @Override + public Collection getEnabledContexts() { + return Collections.emptySet(); + } + + @Override + public StandardWidgetType getDefaultWidgetType() { + return null; + } + + @Override + public LayoutType getDefaultLayoutType() { + return null; + } + + @Override + public PropertyEditorType getDefaultEditorType(Property property) { + return null; + } + + @Override + public PropertyEditorType getDefaultEditorType(Type propertyType, boolean multiple) { + return null; + } + + @Override + public CompositeWidgetType getDefaultCompositeType() { + return null; + } + + @Override + public Collection getCustomizableContexts() { + return Collections.emptySet(); + } + + @Override + public List getContextsForPreferencePage(String page) { + return Collections.emptyList(); + } + + @Override + public Collection getContexts() { + return Collections.emptySet(); + } + + @Override + public Context getContext(String contextName) { + return null; + } + + @Override + public Context getContext(URI uri) throws IOException { + throw new IOException("Properties configuration manager is unavailable"); //$NON-NLS-1$ + } + + @Override + public ViewConstraintEngine getConstraintEngine() { + if (constraintEngine == null) { + constraintEngine = new ViewConstraintEngineImpl(this); + } + + return constraintEngine; + } + + @Override + public Set getBaseNamespaces() { + return Collections.emptySet(); + } + + @Override + public void addContext(URI uri) throws IOException { + throw new IOException("Properties configuration manager is unavailable"); //$NON-NLS-1$ + } + + @Override + public void update() { + // Pass + } + + @Override + public void refresh(Context context) { + // Pass + } + + @Override + public void enableContext(Context context, boolean update) { + // Pass + } + + @Override + public void disableContext(Context context, boolean update) { + // Pass + } + + @Override + public void deleteContext(Context context) { + // Pass + } + + @Override + public Collection checkConflicts(Collection contexts) { + return Collections.emptySet(); + } + + @Override + public Collection checkConflicts() { + return Collections.emptySet(); + } + + @Override + public void addContext(Context context, boolean apply) { + // Pass + } + }; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DefaultDisplayEngine.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DefaultDisplayEngine.java new file mode 100644 index 00000000000..d7453d4cc20 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DefaultDisplayEngine.java @@ -0,0 +1,406 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - Use URIs to support non-URL-compatible storage (CDO) + * Christian W. Damus (CEA) - bug 417409 + * Christian W. Damus (CEA) - bug 444227 + * Christian W. Damus - bug 450478 + * Christian W. Damus - bug 454536 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.properties.catalog.PropertiesURIHandler; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.Tab; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; +import org.eclipse.papyrus.infra.properties.ui.util.EMFURLStreamHandler; +import org.eclipse.papyrus.infra.properties.ui.xwt.XWTTabDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptor; +import org.eclipse.xwt.DefaultLoadingContext; +import org.eclipse.xwt.ILoadingContext; +import org.eclipse.xwt.IXWTLoader; +import org.eclipse.xwt.XWT; + +/** + * A default implementation for {@link DisplayEngine} + * + * @author Camille Letavernier + */ +public class DefaultDisplayEngine implements DisplayEngine { + + private ILoadingContext loadingContext = new DefaultLoadingContext(getClass().getClassLoader()); + + private Map currentTabs = new HashMap(); + + private TabModel displayedSections = new TabModel(); + + private TabModel controls = new TabModel(); + + private boolean allowDuplicate; + + private Object xmlCache; + + /** + * Constructs a new DisplayEnginet that doesn't allow the duplication of sections + */ + public DefaultDisplayEngine() { + this(false); + } + + /** + * Constructor. + * + * @param allowDuplicate + * If false, two calls of {@link #createSection(Composite, Section, DataSource)} with the same + * section will display the section only once : only the first call is taken into account + * The main property view doesn't allow duplication, to avoid redundancy when two views link to + * the same section. + */ + public DefaultDisplayEngine(boolean allowDuplicate) { + this.allowDuplicate = allowDuplicate; + } + + @Override + public List getTabDescriptors(Set views) { + Map result = new LinkedHashMap(); + + Set selectedSections = new HashSet(); + + for (View view : views) { + for (Section section : view.getSections()) { + if (selectedSections.contains(section.getName())) { + continue; + } + + Tab tab = section.getTab(); + + if (tab == null) { + Activator.log.warn("Null tab for " + section); //$NON-NLS-1$ + continue; + } + + XWTTabDescriptor descriptor; + + if (result.containsKey(tab.getId())) { + descriptor = result.get(tab.getId()); + } else { + descriptor = new XWTTabDescriptor(tab); + result.put(tab.getId(), descriptor); + } + + descriptor.addSection(section, view, this); + selectedSections.add(section.getName()); + } + } + + for (Map.Entry next : result.entrySet()) { + XWTTabDescriptor existing = currentTabs.get(next.getKey()); + if ((existing != null) && !existing.equals(next.getValue())) { + // Will have to rebuild this tab + disposeControls(next.getKey()); + } + } + + currentTabs = result; + + return new ArrayList(result.values()); + } + + /** + * Disposes the controls created by this DisplayEngine for the specified section. + * This should not dispose the engine itself, which can be reused. + */ + protected void disposeControls(Section section) { + Control control = controls.remove(section); + if (control != null) { + control.dispose(); + } + + DataSource dataSource = displayedSections.remove(section); + if (dataSource != null) { + dataSource.dispose(); + } + } + + /** + * Disposes the controls created by this DisplayEngine for the specified tab ID. + * This should not dispose the engine itself, which can be reused. + */ + protected void disposeControls(String tabID) { + for (Control control : this.controls.remove(tabID)) { + control.dispose(); + } + + for (DataSource dataSource : displayedSections.remove(tabID)) { + dataSource.dispose(); + } + } + + protected void disposeControls() { + for (String next : new ArrayList(controls.tabIDs())) { + disposeControls(next); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + disposeControls(); + } + + /** + * Invalidates any caches that I may have because the displayed property UI contexts, constraints, or views have + * changed in some way. + */ + public void invalidate() { + // Forget the cached XML property definitions because they may have changed + xmlCache = null; + } + + @Override + public Control createSection(Composite parent, Section section, DataSource source) { + if (source == null) { + return null; + } + + DataSource existing = getDataSource(section); + if (!allowDuplicate && (existing != null)) { + if (isUnloaded(existing) || conflictingArity(existing.getSelection(), source.getSelection())) { + // If it's a left-over from an unloaded resource, then rebuild the properties UI because + // element-browser widgets and other things may remember the previous (now invalid) + // resource-set context. Also, cannot reuse a multiple-selection data source for + // single-selection and vice-versa + disposeControls(section); + } else { + // Update the data source and fire the bindings + existing.setSelection(source.getSelection()); + + return null; + } + } + + Control control = createSection(parent, section, loadXWTFile(section), source); + + addDataSource(section, source); + + if (control != null) { + addControl(section, control); + } + + return control; + } + + protected DataSource getDataSource(Section section) { + return displayedSections.get(section); + } + + /** + * Queries whether any object selected in a data source is unloaded (now an EMF proxy object). + * + * @param dataSource + * a data source + * @return whether it contains an unloaded model element + */ + protected boolean isUnloaded(DataSource dataSource) { + boolean result = false; + + for (Iterator iter = dataSource.getSelection().iterator(); !result && iter.hasNext();) { + EObject next = EMFHelper.getEObject(iter.next()); + result = (next != null) && next.eIsProxy(); + } + + return result; + } + + protected boolean conflictingArity(IStructuredSelection selection1, IStructuredSelection selection2) { + return (selection1.size() <= 1) != (selection2.size() <= 1); + } + + /** + * Adds a new {@code dataSource} for a property {@code section}. + * + * @return the previously-recorded data source, if any, for this {@code section} which has now been displaced + */ + protected DataSource addDataSource(Section section, DataSource dataSource) { + return displayedSections.put(section, dataSource); + } + + protected void addControl(final Section section, Control control) { + controls.put(section, control); + + control.addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + // Perhaps the tabbed properties view is disposing a tab that is not shown by the new selection + displayedSections.remove(section); + controls.remove(section); + } + }); + } + + @Override + public void refreshSection(Composite parent, Section section, DataSource source) { + for (Control control : parent.getChildren()) { + control.dispose(); + } + + Control control = createSection(parent, section, loadXWTFile(section), source); + + addDataSource(section, source); + + if (control != null) { + addControl(section, control); + } + } + + @Override + public Control createSection(Composite parent, Section section, URI sectionFile, DataSource source) { + if (sectionFile == null) { + sectionFile = loadXWTFile(section); + if (sectionFile == null) { + return null; + } + } + + ILoadingContext xwtContext = XWT.getLoadingContext(); + XWT.setLoadingContext(loadingContext); + + Control control = null; + + try { + ResourceSet rset = section.eResource().getResourceSet(); + URL url = new URL(null, sectionFile.toString(), new EMFURLStreamHandler(rset.getURIConverter())); + + Map options = new HashMap(); + options.put(IXWTLoader.CONTAINER_PROPERTY, parent); + options.put(IXWTLoader.DATACONTEXT_PROPERTY, source); + options.put(IXWTLoader.XML_CACHE_PROPERTY, (xmlCache != null) ? xmlCache : Boolean.TRUE); + control = (Control) XWT.loadWithOptions(url, options); + xmlCache = options.get(IXWTLoader.XML_CACHE_PROPERTY); + + if (control != null) { + control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + addControl(section, control); + } + } catch (Exception ex) { + Activator.log.error("Error while loading " + section.getSectionFile(), ex); //$NON-NLS-1$ + disposeControls(section.getTab().getId()); + Label label = new Label(parent, SWT.NONE); + label.setText("An error occured in the property view. The file " + section.getSectionFile() + " could not be loaded"); //$NON-NLS-1$ //$NON-NLS-2$ + } + layout(parent); + + XWT.setLoadingContext(xwtContext); + + return control; + } + + private URI loadXWTFile(Section section) { + EObject tab = section.eContainer(); + Context context = (Context) tab.eContainer(); + if (context.eResource() == null) { + context = PropertiesRuntime.getConfigurationManager().getContext(context.getName()); + Activator.log.warn("No resource for Context : " + context + " ; refreshing the model"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + URI sectionURI = URI.createURI(section.getSectionFile()); + URI baseURI = context.eResource().getURI(); + if (PropertiesURIHandler.PROPERTIES_SCHEME.equals(baseURI.scheme())) { + PropertiesURIHandler handler = new PropertiesURIHandler(); + baseURI = handler.getConvertedURI(baseURI); + } + sectionURI = sectionURI.resolve(baseURI); + + return sectionURI; + } + + private void layout(Composite parent) { + parent.getParent().getParent().layout(); + parent.getParent().layout(); + parent.layout(); + } + + @Override + public void removeSection(Composite parent) { + for (Control control : parent.getChildren()) { + control.dispose(); + } + layout(parent); + } + + /** + * Creates a proxy for a {@code section} that makes it distinct from other occurrences of the same section, according to some + * arbitrary {@code disciminator}. + * + * @param section + * a section to be repeated with unique discriminators + * @param discriminator + * this {@code section}'s discriminator value + * + * @return the proxy instance combining the identity of the {@code section} with its unique {@code discriminator} + */ + public static Section discriminate(Section section, Object discriminator) { + if (section == null) { + throw new IllegalArgumentException("null section"); + } + if (discriminator == null) { + throw new IllegalArgumentException("null discriminator"); + } + if (SectionDiscriminator.isDiscriminated(section)) { + throw new IllegalArgumentException("section already has a discriminator"); + } + + return SectionDiscriminator.discriminate(section, discriminator); + } + + /** + * Obtains the discriminator for a {@code section} proxy, if it is a proxy. + * + * @param section + * a section that is repeated with unique discriminators + * @return this {@code section}'s discriminator value, or {@code null} if it is a singleton (non-proxy) section + */ + public static Object getDiscriminator(Section section) { + if (section == null) { + throw new IllegalArgumentException("null section"); + } + + return SectionDiscriminator.getDiscriminator(section); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DisplayEngine.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DisplayEngine.java new file mode 100644 index 00000000000..f15b31d59f4 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/DisplayEngine.java @@ -0,0 +1,103 @@ +/***************************************************************************** + * Copyright (c) 2010, 2013 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - Use URIs to support non-URL-compatible storage (CDO) + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.util.List; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptor; + +/** + * An interface representing a Display Engine. + * A Display Engine is responsible for displaying {@link Section}s in a given Composite. + * It is also responsible for retrieving the {@link ITabDescriptor}s for a given set of {@link View}s + * + * @author Camille Letavernier + */ +public interface DisplayEngine { + + /** + * Returns a list of ITabDescriptors for the given set of Views. + * The list of tabs is retrieved by navigating the views' sections + * + * @param views + * The views from which to retrieve the tab descriptors + * @return + * The tab descriptors corresponding to the given views + */ + public List getTabDescriptors(Set views); + + /** + * Displays the section in the given parent Composite, and binds the widgets + * to the given DataSource. + * + * @param parent + * The Composite widget in which the section is displayed + * @param section + * The section to display + * @param source + * The DataSource to bind to the section's widgets. + * @return + * The generated Control + */ + public Control createSection(Composite parent, Section section, DataSource source); + + /** + * Displays the section in the given parent Composite. The section is loaded from + * the given URL instead of the section's sectionFile. + * + * @param parent + * The Composite widget in which the section is displayed. Should not be null + * @param section + * The section to display. Should not be null + * @param sectionFile + * The URI replacing the section's sectionFile. If null, the section's sectionFile will + * be used + * @param source + * The DataSource to bind to the section's widgets. May be null. + * @return + * The generated Control + */ + public Control createSection(Composite parent, Section section, URI sectionFile, DataSource source); + + /** + * Refresh the given section. + * + * @param parent + * The Composite in which the section should be displayed. + * @param section + * The section to display. + * @param source + * The DataSource to bind to the section's widgets. + */ + public void refreshSection(Composite parent, Section section, DataSource source); + + /** + * Dispose the section's contents. + * + * @param self + * The Composite containing the section's Control. + */ + public void removeSection(Composite self); + + /** + * Disposes this display engine + */ + public void dispose(); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/EmbeddedDisplayEngine.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/EmbeddedDisplayEngine.java new file mode 100644 index 00000000000..3819ef53204 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/EmbeddedDisplayEngine.java @@ -0,0 +1,239 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.text.Collator; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.Tab; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.ui.xwt.XWTSection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.views.properties.tabbed.ISection; + +/** + * A Property View display engine which can be embedded in a composite + * + * @author Camille Letavernier + */ +public class EmbeddedDisplayEngine extends DefaultDisplayEngine implements SelectionListener { + + private String lastTabId; + + /** + * The displayed CTabFolder + * May be null + */ + protected CTabFolder currentFolder; + + protected Composite self; + + /** + * The currently displayed sections + */ + protected Set displayedSections = new HashSet(); + + /** + * + * @param views + * @param parent + * @param selection + * @param style + * SWT.BOTTOM or SWT.TOP (Tabs' position) + */ + public void display(Set views, Composite parent, ISelection selection, int style) { + disposeControls(); + + self = new Composite(parent, SWT.NONE); + + self.setLayout(new FillLayout()); + + final Set tabsList = new LinkedHashSet(); + + for (View view : views) { + for (Section section : view.getSections()) { + tabsList.add(section.getTab()); + } + } + + List allTabs = new LinkedList(tabsList); + + Collections.sort(allTabs, new Comparator() { + + /** + * compares two tabs each other + * + * @param tab1 + * first tab to compare + * @param tab2 + * second tab to compare + * @return a negative integer if the first tab should be placed before the second tab + */ + public int compare(Tab tab1, Tab tab2) { + int priority1 = getPriority(tab1); + int priority2 = getPriority(tab2); + + if (priority1 < priority2) { + return -1; + } + + if (priority1 > priority2) { + return 1; + } + + // p1 == p2 + + priority1 = getXWTTabPriority(tab1); + priority2 = getXWTTabPriority(tab2); + + if (priority1 < priority2) { + return -1; + } + + if (priority1 > priority2) { + return 1; + } + + // p1 == p2 + + String label1 = tab1.getLabel(); + String label2 = tab2.getLabel(); + + return Collator.getInstance().compare(label1, label2); + } + + private Tab getPreviousTab(Tab tab) { + Tab afterTab = tab.getAfterTab(); + if (tabsList.contains(afterTab)) { + return afterTab; + } + + // not found. Return null + return null; + } + + private int getPriority(Tab tab) { + Tab previousTab = getPreviousTab(tab); + if (previousTab != null) { + return getPriority(previousTab) + 1; + } + + return getXWTTabPriority(tab); + } + + private int getXWTTabPriority(Tab tab) { + return tab.getPriority(); + } + + }); + + Map tabs = new LinkedHashMap(); + + if (allTabs.size() > 1) { + CTabItem selectedTab = null; + + currentFolder = new CTabFolder(self, style); + currentFolder.setSelectionBackground(new Color[] { currentFolder.getDisplay().getSystemColor(SWT.COLOR_WHITE), currentFolder.getBackground() }, new int[] { 100 }, true); + currentFolder.setLayout(new FillLayout()); + for (Tab tab : allTabs) { + CTabItem item = new CTabItem(currentFolder, SWT.NONE); + Composite tabControl = new Composite(currentFolder, SWT.NONE); + item.setControl(tabControl); + item.setText(tab.getLabel()); + item.setData("id", tab.getId()); //$NON-NLS-1$ + if (tab.getId().equals(lastTabId)) { + selectedTab = item; + } + tabs.put(tab, tabControl); + } + currentFolder.addSelectionListener(this); + + + if (selectedTab == null) { + selectedTab = currentFolder.getItem(0); + } + + currentFolder.setSelection(selectedTab); + } else if (!allTabs.isEmpty()) { + Tab tab = allTabs.get(0); + tabs.put(tab, self); + } else { + return; + } + + for (View view : views) { + for (Section section : view.getSections()) { + XWTSection xwtSection = new XWTSection(section, view, this); + + xwtSection.createControls(tabs.get(section.getTab()), null); + xwtSection.setInput(null, selection); + xwtSection.refresh(); + + displayedSections.add(xwtSection); + } + } + + self.layout(); + } + + @Override + protected void disposeControls() { + super.disposeControls(); + if (self != null) { + self.dispose(); + self = null; + currentFolder = null; + } + + // if(currentFolder != null) { + // currentFolder.dispose(); + // currentFolder = null; + // } + + for (ISection section : displayedSections) { + section.dispose(); + } + } + + public void widgetSelected(SelectionEvent e) { + if (e.widget instanceof CTabFolder) { + CTabFolder folder = (CTabFolder) e.widget; + CTabItem lastTab = folder.getSelection(); + Object lastId = lastTab.getData("id"); //$NON-NLS-1$ + if (lastId != null && lastId instanceof String) { + lastTabId = (String) lastId; + } + } + } + + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/IConfigurationManager.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/IConfigurationManager.java new file mode 100644 index 00000000000..609a68a236e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/IConfigurationManager.java @@ -0,0 +1,211 @@ +/***************************************************************************** + * Copyright (c) 2010, 2016 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - Factor out workspace storage for pluggable storage providers (CDO) + * Christian W. Damus (CEA) - Support implicit enablement of prototypes of unavailable contexts (CDO) + * Christian W. Damus - bugs 482930, 469188, 485220 + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.Property; +import org.eclipse.papyrus.infra.properties.environment.CompositeWidgetType; +import org.eclipse.papyrus.infra.properties.environment.LayoutType; +import org.eclipse.papyrus.infra.properties.environment.Namespace; +import org.eclipse.papyrus.infra.properties.environment.PropertyEditorType; +import org.eclipse.papyrus.infra.properties.environment.StandardWidgetType; +import org.eclipse.papyrus.infra.properties.environment.Type; +import org.eclipse.papyrus.infra.properties.internal.ContextExtensionPoint; + + +/** + * Central API of the Property View framework. It lists the available environments and contexts, + * and is responsible for Enabling or Disabling contexts programmatically. + * + * All {@link Context}s should have unique names. + * + * @author Camille Letavernier + */ +public interface IConfigurationManager { + + /** + * Tests if a Context is enabled. + * + * @param context + * @return + * true if the given context is enabled. + */ + boolean isApplied(Context context); + + Boolean isAppliedByDefault(Context context); + + /** + * @return the list of enabled contexts + */ + Collection getEnabledContexts(); + + /** + * Queries whether a given context is {@linkplain #getEnabledContexts() enabled}. + * + * @param context + * a context + * @return whether it is currently enabled + * + * @see #getEnabledContexts() + */ + boolean isEnabled(Context context); + + /** + * Tests if a Context is a plugin context. plugin contexts + * are registered through {@link ContextExtensionPoint} and are + * read-only. + * + * @param context + * @return + * True if the context comes from a plugin, and is thus read-only + */ + boolean isPlugin(Context context); + + /** + * Queries whether the specified {@code context} is a proxy for a missing context. That is a + * context that is expected to exist but is (temporarily) unavailable. + * + * @param context + * a context + * @return whether it represents a missing context + */ + boolean isMissing(Context context); + + /** + * Loads a Context from the given URI. The model is loaded in the {@link ConfigurationManager}'s resourceSet + * + * @param uri + * The URI from which the Context is loaded + * @return + * The loaded context + * @throws IOException + * If the URI doesn't represent a valid Context model + */ + Context getContext(URI uri) throws IOException; + + /** + * Returns the context from the given context name + * + * @param contextName + * The name of the context to retrieve + * @return + * The context corresponding to the given name + */ + Context getContext(String contextName); + + /** + * Returns all the known contexts, even if they are not applied + * To get only applied contexts, see {@link #getEnabledContexts()} + * + * @return All known contexts + */ + Collection getContexts(); + + /** + * Returns all the known customizable contexts. + * + * @return All known contexts + * + * @see {@link #getEnabledContexts()} + */ + Collection getCustomizableContexts(); + + /** + * Obtains proxies (not the EMF kind) for all contexts that the system knows about + * but are currently unavailable. + * + * @return the current collection of missing contexts + */ + Collection getMissingContexts(); + + /** + * @return the default implementation of CompositeWidgetType + */ + CompositeWidgetType getDefaultCompositeType(); + + /** + * @return the default implementation of LayoutType + */ + LayoutType getDefaultLayoutType(); + + /** + * @return the default implementation of StandardWidgetType + */ + StandardWidgetType getDefaultWidgetType(); + + /** + * @param propertyType + * @param multiple + * @return the default implementation of PropertyEditorType for the given property Type + * and multiplicity + */ + PropertyEditorType getDefaultEditorType(Type propertyType, boolean multiple); + + /** + * Returns the default XWT namespaces + * + * @return the default XWT namespaces + */ + Set getBaseNamespaces(); + + /** + * @param name + * @return + * The namespace corresponding to the given name + */ + Namespace getNamespaceByName(String name); + + /** + * @param property + * @return + * the default PropertyEditorType for the given Property + */ + PropertyEditorType getDefaultEditorType(Property property); + + /** + * Retrieves the Property object associated to the propertyPath in the given context + * + * @param propertyPath + * @param context + * @return + * The property associated to the given propertyPath + */ + Property getProperty(String propertyPath, Context context); + + /** + * Returns the ResourceSet associated to the ConfigurationManager, + * ie. the ResourceSet containing all Environments and Contexts + * + * @return + */ + ResourceSet getResourceSet(); + + boolean isCustomizable(Context propertyViewConfiguration); + + ViewConstraintEngine getConstraintEngine(); + + List getContextsForPreferencePage(String page); + + void addContext(URI uri) throws IOException; + +} \ No newline at end of file diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/PropertiesRuntime.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/PropertiesRuntime.java new file mode 100644 index 00000000000..1594341270b --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/PropertiesRuntime.java @@ -0,0 +1,52 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintEngine; +import org.eclipse.papyrus.infra.properties.contexts.View; + +/** + * Access to core Properties UI run-time services. + */ +public class PropertiesRuntime { + + private static final IConfigurationManager configManager = new ConfigurationManagerRegistry().getConfigurationManager(); + + /** + * Not instantiable by clients. + */ + private PropertiesRuntime() { + super(); + } + + /** + * Obtains the Papyrus Properties Configuration Manager. The result will never be null + * but, if no suitable instance of the configuration manager API is installed, the + * result will be a useless configuration manager that provides no configurations at all. + * + * @return the configuration manager + */ + public static IConfigurationManager getConfigurationManager() { + return configManager; + } + + /** + * Obtains the {@linkplain #getConfigurationManager() configuration manager}'s constraint engine. + * + * @return the constraint engine + */ + public static ConstraintEngine getConstraintEngine() { + return getConfigurationManager().getConstraintEngine(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/SectionDiscriminator.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/SectionDiscriminator.java new file mode 100644 index 00000000000..f10c6cfc92f --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/SectionDiscriminator.java @@ -0,0 +1,108 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.papyrus.infra.properties.contexts.Section; + +/** + * A proxy for {@link Section}s that distinguishes multiple occurrences of the same instance via an arbitrary discriminator. + */ +class SectionDiscriminator implements InvocationHandler { + private static final Class[] PROXY_INTERFACES = { Section.class, EObject.class, InternalEObject.class }; + + private final Section section; + private final Object discriminator; + + SectionDiscriminator(Section section, Object discriminator) { + this.section = section; + this.discriminator = discriminator; + } + + static Section discriminate(Section section, Object discriminator) { + return (Section) Proxy.newProxyInstance(section.getClass().getClassLoader(), PROXY_INTERFACES, new SectionDiscriminator(section, discriminator)); + } + + static Object getDiscriminator(Section section) { + Object result = null; + + if (Proxy.isProxyClass(section.getClass())) { + InvocationHandler handler = Proxy.getInvocationHandler(section); + if (handler instanceof SectionDiscriminator) { + result = ((SectionDiscriminator) handler).discriminator; + } + } + + return result; + } + + static boolean isDiscriminated(Section section) { + boolean result = false; + + if ((section != null) && Proxy.isProxyClass(section.getClass())) { + InvocationHandler handler = Proxy.getInvocationHandler(section); + result = handler instanceof SectionDiscriminator; + } + + return result; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object result = null; + + if (method.getDeclaringClass() == Object.class) { + // Don't delegate equals(), hashCode(), and monitor protocol + if (method.getName().equals("equals")) { //$NON-NLS-1$ + if ((args[0] != null) && Proxy.isProxyClass(args[0].getClass())) { + result = this.equals(Proxy.getInvocationHandler(args[0])); + } else { + result = proxy == args[0]; + } + } else if (method.getName().equals("hashCode")) { //$NON-NLS-1$ + result = this.hashCode(); + } else { + result = method.invoke(this, args); + } + } else { + result = method.invoke(section, args); + } + + return result; + } + + @Override + public boolean equals(Object obj) { + boolean result = obj == this; + if (!result && (obj instanceof SectionDiscriminator)) { + SectionDiscriminator other = (SectionDiscriminator) obj; + result = other.section == this.section && other.discriminator.equals(this.discriminator); + } + return result; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + discriminator.hashCode(); + result = prime * result + section.hashCode(); + return result; + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/TabModel.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/TabModel.java new file mode 100644 index 00000000000..bc65c45e809 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/TabModel.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.papyrus.infra.properties.contexts.Section; + + +/** + * An encapsulation of the hierarchical tab structure of the property sheets managed by a {@link DisplayEngine}. + * It supports distinction of repeated {@code Section}s via proxies that combine section instances with + * arbitrary {@linkplain SectionDiscriminator discriminators}. + */ +class TabModel { + + private final Map model = new HashMap(); + + TabModel() { + super(); + } + + public Set tabIDs() { + Set result = new HashSet(); + + for (Path next : model.keySet()) { + result.add(next.tabID); + } + + return Collections.unmodifiableSet(result); + } + + public V get(Section section) { + return model.get(new Path(section)); + } + + public V get(String tabID, String sectionID) { + return model.get(new Path(tabID, sectionID)); + } + + public Collection get(String tabID) { + List result = new ArrayList(4); + + Path key = new Path(tabID); + for (Map.Entry next : model.entrySet()) { + if (next.getKey().equals(key)) { + result.add(next.getValue()); + } + } + + return Collections.unmodifiableList(result); + } + + public V put(Section section, V value) { + return model.put(new Path(section), value); + } + + public V put(String tabID, String sectionID, V value) { + return model.put(new Path(tabID, sectionID), value); + } + + public V remove(Section section) { + return model.remove(new Path(section)); + } + + public V remove(String tabID, String sectionID) { + return model.remove(new Path(tabID, sectionID)); + } + + public Collection remove(String tabID) { + List result = new ArrayList(4); + + Path key = new Path(tabID); + for (V next = model.remove(key); next != null; next = model.remove(key)) { + result.add(next); + } + + return Collections.unmodifiableList(result); + } + + public Collection clear() { + List result = new ArrayList(model.values()); + + model.clear(); + + return Collections.unmodifiableList(result); + } + + @Override + public String toString() { + return String.format("TabModel%s", model.toString()); //$NON-NLS-1$ + } + + // + // Nested types + // + + final static class Path { + + // Do not intern this string! Deliberately constructing a new String instance + private static final String WILDCARD = new String("*"); //$NON-NLS-1$ + + final String tabID; + + final String sectionID; + + final Object discriminator; + + Path(String tabID, String sectionID, Object discriminator) { + checkWildcard(tabID); + checkWildcard(sectionID); + + this.tabID = tabID; + this.sectionID = sectionID; + this.discriminator = (discriminator == null) ? WILDCARD : discriminator; + } + + Path(String tabID, String sectionID) { + this(tabID, sectionID, WILDCARD); + } + + /** + * Create a wildcard path for all sections in a tab. + */ + Path(String tabID) { + checkWildcard(tabID); + + this.tabID = tabID; + this.sectionID = WILDCARD; + this.discriminator = WILDCARD; + } + + /** + * Create a path for a specific section. + */ + Path(Section section) { + this(section.getTab().getId(), section.getName(), SectionDiscriminator.getDiscriminator(section)); + } + + static void checkWildcard(String id) { + // Deliberately testing for identity of non-interned string + if ((id == null) || (id == WILDCARD)) { + throw new IllegalArgumentException("Attempt to create a wildcard path explicitly"); //$NON-NLS-1$ + } + } + + @Override + public String toString() { + return String.format("(%s, %s)", tabID, sectionID); //$NON-NLS-1$ + } + + @Override + public int hashCode() { + // This isn't great for hash-map performance, but wildcards have to have the same hash as the keys they + // match, otherwise using them to access the map won't work + return tabID.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Path)) { + return false; + } + + Path other = (Path) obj; + return equals(tabID, other.tabID) && equals(sectionID, other.sectionID) && equals(discriminator, other.discriminator); + } + + private static boolean equals(Object anID, Object anotherID) { + // Deliberately testing for identity of non-interned string + return (anID == WILDCARD) || (anotherID == WILDCARD) || anID.equals(anotherID); + } + + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngine.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngine.java new file mode 100644 index 00000000000..d8f32115fe7 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngine.java @@ -0,0 +1,28 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tessier (CEA LIST) - Initial API and implementation + /*****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintEngine; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.View; + + +public interface ViewConstraintEngine extends ConstraintEngine { + + public Set getViews(final ISelection forSelection); + + public void addContext(final Context context); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngineImpl.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngineImpl.java new file mode 100644 index 00000000000..e6ef500dce2 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/runtime/ViewConstraintEngineImpl.java @@ -0,0 +1,64 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.runtime; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.papyrus.infra.constraints.ConstraintDescriptor; +import org.eclipse.papyrus.infra.constraints.runtime.DefaultConstraintEngine; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.View; + +/** + * The implementation for ViewConstraintEngine + * + * @author Camille Letavernier + */ +public class ViewConstraintEngineImpl extends DefaultConstraintEngine implements ViewConstraintEngine { + + private final IConfigurationManager configManager; + + public ViewConstraintEngineImpl(IConfigurationManager configManager) { + super(View.class); + + this.configManager = configManager; + } + + @Override + public synchronized void refresh() { + constraints.clear(); + Collection contexts = configManager.getEnabledContexts(); + for (Context context : contexts) { + addContext(context); + } + + fireConstraintsChanged(); + } + + @Override + public void addContext(final Context context) { + for (View view : context.getViews()) { + for (ConstraintDescriptor descriptor : view.getConstraints()) { + addConstraint(descriptor); + } + } + } + + @Override + public Set getViews(final ISelection forSelection) { + return getDisplayUnits(forSelection); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/EMFURLStreamHandler.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/EMFURLStreamHandler.java new file mode 100644 index 00000000000..0dce764eafb --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/EMFURLStreamHandler.java @@ -0,0 +1,147 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.util; + +import static org.eclipse.emf.ecore.resource.ContentHandler.CHARSET_PROPERTY; +import static org.eclipse.emf.ecore.resource.ContentHandler.CONTENT_TYPE_PROPERTY; +import static org.eclipse.emf.ecore.resource.ContentHandler.OPTION_REQUESTED_PROPERTIES; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.URIConverter; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; + + +/** + * An URL stream handler to use to encapsulate an EMF {@link URI} in a Java {@link URL}. + */ +public class EMFURLStreamHandler extends URLStreamHandler { + + private final URIConverter uriConverter; + + public EMFURLStreamHandler(URIConverter uriConverter) { + super(); + + this.uriConverter = uriConverter; + } + + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new EMFURLConnection(u, uriConverter); + } + + // + // Nested types + // + + private static class EMFURLConnection extends URLConnection { + + private final URIConverter uriConverter; + + private final URI uri; + + private Map contentDescription; + + private boolean connected; + + private InputStream input; + + protected EMFURLConnection(URL url, URIConverter uriConverter) { + super(url); + + this.uriConverter = uriConverter; + + this.uri = URI.createURI(url.toExternalForm(), true); + } + + @Override + public void connect() throws IOException { + if (!connected) { + try { + input = uriConverter.getURIHandler(uri).createInputStream(uri, createInputStreamOptions()); + connected = true; + } catch (Exception e) { + throw new IOException("Failed to connect: " + e.getMessage()); + } + } + } + + @Override + public String getContentEncoding() { + return (String) getContentDescription().get(CHARSET_PROPERTY); + } + + @Override + public String getContentType() { + return (String) getContentDescription().get(CONTENT_TYPE_PROPERTY); + } + + @Override + public int getContentLength() { + return -1; + } + + @Override + public boolean getDoInput() { + return true; + } + + @Override + public boolean getDoOutput() { + return false; + } + + @Override + public InputStream getInputStream() throws IOException { + if (!connected) { + connect(); + } + + return input; + } + + private Map getContentDescription() { + if (contentDescription == null) { + try { + contentDescription = uriConverter.getURIHandler(uri).contentDescription(uri, getContentDescriptionOptions()); + } catch (IOException e) { + Activator.log.error(e); + contentDescription = Collections.emptyMap(); + } + } + + return contentDescription; + } + + private Map createInputStreamOptions() { + Map result = new java.util.HashMap(); + result.put(URIConverter.OPTION_RESPONSE, new java.util.HashMap()); + return result; + } + + private Map getContentDescriptionOptions() { + Set requestedProperties = new java.util.HashSet(); + requestedProperties.add(CONTENT_TYPE_PROPERTY); + requestedProperties.add(CHARSET_PROPERTY); + + return Collections.singletonMap(OPTION_REQUESTED_PROPERTIES, requestedProperties); + } + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesDisplayHelper.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesDisplayHelper.java new file mode 100644 index 00000000000..56dfbd1af78 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesDisplayHelper.java @@ -0,0 +1,125 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.util; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintEngine; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.EmbeddedDisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +/** + * Helper class for displaying an embedded Properties View for + * a selection in a specific composite + * + * + * @author Camille Letavernier + * + */ +public class PropertiesDisplayHelper { + + /** + * Displays the properties view associated to the selection in the given Composite + * + * @param selection + * @param parent + * + * @return The display engine used to build the view. Must be disposed by caller + */ + public static DisplayEngine display(Object selection, Composite parent) { + return display(PropertiesRuntime.getConstraintEngine(), buildSelection(selection), parent); + } + + /** + * Displays the properties view associated to the selection in the given Composite + * + * @param selection + * @param parent + * + * @return The display engine used to build the view. Must be disposed by caller + */ + public static DisplayEngine display(Collection selection, Composite parent) { + return display(PropertiesRuntime.getConstraintEngine(), buildSelection(selection), parent); + } + + /** + * Displays the properties view associated to the selection in the given Composite + * + * The views are computed based on the given ConstraintEngine + * + * @param selection + * @param parent + * @param constraints + * + * @return The display engine used to build the view. Must be disposed by caller + */ + public static DisplayEngine display(ConstraintEngine constraints, Object selection, Composite parent) { + return display(constraints, buildSelection(selection), parent); + } + + /** + * Displays the properties view associated to the selection in the given Composite + * + * The views are computed based on the given ConstraintEngine + * + * @param selection + * @param parent + * @param constraints + * + * @return The display engine used to build the view. Must be disposed by caller + */ + public static DisplayEngine display(ConstraintEngine constraints, Collection selection, Composite parent) { + return display(constraints, buildSelection(selection), parent); + } + + /** + * Displays the properties view associated to the selection in the given Composite + * + * The views are computed based on the given ConstraintEngine + * + * @param selection + * @param parent + * @param constraints + * + * @return The display engine used to build the view. Must be disposed by caller + */ + public static DisplayEngine display(ConstraintEngine constraints, ISelection selection, Composite parent) { + EmbeddedDisplayEngine display = new EmbeddedDisplayEngine(); + + Set views = constraints.getDisplayUnits(selection); + + // Composite self = new Composite(parent, SWT.BORDER); + // self.setLayout(new GridLayout(1, false)); + + display.display(views, parent, selection, SWT.NONE); + + return display; + } + + private static IStructuredSelection buildSelection(Collection elements) { + return new StructuredSelection(elements); + } + + private static IStructuredSelection buildSelection(Object element) { + return new StructuredSelection(element); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesUtil.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesUtil.java new file mode 100644 index 00000000000..c9147c1045d --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/util/PropertiesUtil.java @@ -0,0 +1,303 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.util; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; +import org.eclipse.papyrus.infra.properties.contexts.DataContextPackage; +import org.eclipse.papyrus.infra.properties.contexts.Property; +import org.eclipse.papyrus.infra.properties.environment.Namespace; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; + +/** + * A Helper class for miscellaneous elements of the Property view framework + * + * @author Camille Letavernier + */ +public class PropertiesUtil { + + /** + * @param source + * @return + * the given String with the first letter capitalized + */ + public static String firstToUpper(String source) { + if (source.length() == 0) { + return source; + } + return source.substring(0, 1).toUpperCase() + source.substring(1); + } + + /** + * @param source + * @return + * the given String with the first letter lowered + */ + public static String firstToLower(String source) { + if (source.length() == 0) { + return source; + } + return source.substring(0, 1).toLowerCase() + source.substring(1); + } + + /** + * Returns the formatted label of the property + * + * @param property + * @return + */ + public static String getLabel(Property property) { + if (property.getLabel() == null || property.getLabel().trim().equals("")) { + return getLabel(property.getName()); + } + + return property.getLabel(); + } + + /** + * @param variableName + * @return + * A formatted version of the given variable name + */ + public static String getLabel(String variableName) { + // "CamelCase" to "Natural case" + String formattedValue = variableName; + + // replace fooBar by foo Bar + formattedValue = formattedValue.replaceAll("([a-z])([A-Z])", "$1 $2"); //$NON-NLS-1$ //$NON-NLS-2$ + + // replace FOOAndBar by FOO And Bar + formattedValue = formattedValue.replaceAll("([A-Z]+)([A-Z])([a-z])", "$1 $2$3"); //$NON-NLS-1$ //$NON-NLS-2$ + + // Capitalize the first word and lower the other ones : foo Bar -> Foo bar + // Keep the upper case for acronyms FOO Bar -> FOO bar + String[] words = formattedValue.split("\\s+"); //$NON-NLS-1$ + formattedValue = firstToUpper(words[0]); + for (int i = 1; i < words.length; i++) { + formattedValue += " "; //$NON-NLS-1$ + if (words[i].matches("^[A-Z]{2,}")) { //$NON-NLS-1$ + formattedValue += words[i]; + } else { + formattedValue += firstToLower(words[i]); + } + } + + Activator.log.debug("\"" + formattedValue + "\""); //$NON-NLS-1$ //$NON-NLS-2$ + return formattedValue; + } + + /** + * Tests if the given value is equal to the namespace's value + * + * @param namespace + * @param value + * @return + * True if they are equal + */ + public static boolean namespaceEquals(Namespace namespace, String value) { + if (namespace == null) { + return value == null || value.trim().equals(""); //$NON-NLS-1$ + } else { + return namespace.getValue().equals(value); + } + } + + /** + * Tests if the given name is equal to the namespace's name + * + * @param namespace + * @param name + * @return + * True if they are equal + */ + public static boolean namespaceEqualsByName(Namespace namespace, String name) { + if (namespace == null) { + return name == null || name.trim().equals(""); //$NON-NLS-1$ + } else { + return namespace.getName().equals(name); + } + } + + /** + * Return the full value of the namespace declaration + * e.g. clr-namespace:org.eclipse.papyrus.infra.properties.ui + * + * @param namespace + * The namespace we want to prefix + * @return + * The prefixed namespace + */ + public static String getPrefixedValue(Namespace namespace) { + String prefixedValue = ""; //$NON-NLS-1$ + if (namespace.getPrefix() != null && !namespace.getPrefix().trim().equals("")) { //$NON-NLS-1$ + prefixedValue = namespace.getPrefix() + ":"; //$NON-NLS-1$ + } + prefixedValue += namespace.getValue(); + + return prefixedValue; + } + + /** + * Return the full name of the namespace declaration + * e.g. xmlns:ppe + * + * @param namespace + * The namespace for which we want to get the qualified name + * @return + * The namespace's qualified name + */ + public static String getQualifiedName(Namespace namespace) { + if (namespace.getName() == null || namespace.getName().trim().equals("")) { //$NON-NLS-1$ + return "xmlns"; //$NON-NLS-1$ + } else { + return "xmlns:" + namespace.getName(); //$NON-NLS-1$ + } + } + + /** + * Retrieve the DataContextElement matching the given qualifiedName. + * + * @param qualifiedName + * The fully qualified name of the DataContextElement. The separator is ":" + * e.g. : UML:NamedElement + * @param fromContextElements + * The collection of DataContextElements in which the method should look + * @return + * The matching DataContextElement, or null if none was found + */ + public static DataContextElement getContextElementByQualifiedName(String qualifiedName, Collection fromContextElements) { + int index = qualifiedName.indexOf(":"); //$NON-NLS-1$ + if (index >= 0) { + String name = qualifiedName.substring(0, index); + qualifiedName = qualifiedName.substring(qualifiedName.indexOf(":") + 1, qualifiedName.length()); //$NON-NLS-1$ + for (DataContextElement contextElement : fromContextElements) { + if (contextElement instanceof DataContextPackage && contextElement.getName().equals(name)) { + DataContextElement result = getContextElementByQualifiedName(qualifiedName, ((DataContextPackage) contextElement).getElements()); + if (result != null) { + return result; + } + } + } + } else { + for (DataContextElement element : fromContextElements) { + if (element.getName().equals(qualifiedName)) { + return element; + } + } + } + return null; + } + + /** + * Returns the list of Context on which the given context depends, directly + * or indirectly + * + * @param context + * The context for which we want to retrieve the list of dependencies + * @return + * The list of Contexts on which the given context depends + */ + public static List getDependencies(Context context) { + List result = new LinkedList(); + if (context == null) { + return result; + } + + result.add(context); + findDependencies(context, result); + return result; + } + + private static void findDependencies(Context context, List result) { + for (Context dependency : context.getDependencies()) { + if (!result.contains(dependency)) { + result.add(dependency); + findDependencies(dependency, result); + } + } + } + + /** + * Returns the set of DataContextElement containing the whole inheritance hierarchy + * for the given source DataContextElements + * + * @param source + * The collection of DataContextElements for which we want to retrieve all inherited elements + * @return + * All DataContextElements inherited (Directly or indirectly) by at least one of the source + * context elements + */ + public static Set getAllContextElements(Collection source) { + Set result = new HashSet(); + getAllContextElements(source, result); + return result; + } + + private static void getAllContextElements(Collection source, Set result) { + for (DataContextElement element : source) { + if (!result.contains(element)) { + result.add(element); + getAllContextElements(element.getSupertypes(), result); + } + } + } + + /** + * A util method to make big strings fit in a restricted amount of space, + * such as a tooltip. The method will add new lines in the string at + * a regular interval. + * + * @param string + * The string to split + * @param maxCharPerLine + * The maximum number of characters per line in the resulting string + * @return + * The split string + */ + public static String resizeString(String string, int maxCharPerLine) { + if (string == null || string.trim().length() <= maxCharPerLine) { + return string.trim(); + } + + String[] stringChunks = string.split("\n|\r|\r\n|\n\r"); //$NON-NLS-1$ + + List chunks = new LinkedList(); + + for (String chunk : stringChunks) { + chunk = chunk.trim(); + if (chunk.length() > maxCharPerLine) { + Matcher matcher = Pattern.compile("(.{0," + maxCharPerLine + "}\\b\\p{Punct}?)").matcher(chunk); //$NON-NLS-1$ //$NON-NLS-2$ + while (matcher.find()) { + String group = matcher.group(1); + chunks.add(group); + } + } else { + chunks.add(chunk); + } + } + + String result = ""; //$NON-NLS-1$ + for (String chunk : chunks) { + result += chunk.trim() + "\n"; //$NON-NLS-1$ + } + + return result.trim(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/AbstractPropertyEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/AbstractPropertyEditor.java new file mode 100644 index 00000000000..898a610c48b --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/AbstractPropertyEditor.java @@ -0,0 +1,663 @@ +/***************************************************************************** + * Copyright (c) 2010, 2015 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 417409 + * Christian W. Damus (CEA) - bug 443417 + * Christian W. Damus (CEA) - bug 444227 + * Christian W. Damus - bug 469188 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.Property; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSourceChangedEvent; +import org.eclipse.papyrus.infra.properties.ui.modelelement.IDataSourceListener; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.papyrus.infra.properties.ui.util.PropertiesUtil; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.AbstractListEditor; +import org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.widgets.Control; + + +/** + * An Abstract class to factorize code for PropertyEditors. PropertyEditors are + * not required to extend this class, but could benefit from + * its methods. + * + * @author Camille Letavernier + */ +public abstract class AbstractPropertyEditor implements IChangeListener, CustomizablePropertyEditor { + + /** + * The qualified propertyPath. Represents the property edited by this widget + */ + protected String propertyPath; // Format : "DataContextElement:propertyName" + + /** + * The DataSource representing the semantic objects + */ + protected DataSource input; + + private IDataSourceListener dataSourceListener; + + protected boolean readOnly = false; + + protected boolean isEditable = true; + + /** + * The SWT Widget (For list properties only) + */ + protected AbstractListEditor listEditor; + + /** + * The SWT Widget (For single values only) + */ + protected AbstractValueEditor valueEditor; + + /** + * The IObservableList representing the semantic property + * (For list properties only) + */ + protected IObservableList observableList; + + /** + * The IObservableValue representing the semantic property + * (For single values only) + */ + protected IObservableValue observableValue; + + + protected IValidator modelValidator; + + protected IConverter targetToModelConverter; + + /** + * Indicates if the editor's label should be displayed + */ + protected boolean showLabel = true; + + /** + * The custom label used by this editor. If set, it replaces the property's default label + */ + protected String customLabel; + + /** + * The maximum number of characters per line for wrapping descriptions + */ + public static int descriptionMaxCharPerLine = 200; + + /** + * Constructor. + * When using this constructor, you should explicitly call the #setEditor method. + */ + protected AbstractPropertyEditor() { + } + + /** + * Constructor. Constructs a new PropertyEditor with the given ListEditor + * + * @param editor + */ + protected AbstractPropertyEditor(AbstractListEditor editor) { + setEditor(editor); + } + + /** + * Constructor. Constructs a new PropertyEditor with the given ValueEditor + * + * @param editor + */ + protected AbstractPropertyEditor(AbstractValueEditor editor) { + setEditor(editor); + } + + /** + * Sets the ListEditor for this PropertyEditor + * + * @param editor + */ + protected void setEditor(AbstractListEditor editor) { + this.listEditor = editor; + addDisposeListener(editor); + } + + /** + * Sets the ValueEditor for this PropertyEditor + * + * @param editor + */ + protected void setEditor(AbstractValueEditor editor) { + this.valueEditor = editor; + addDisposeListener(editor); + } + + private void addDisposeListener(AbstractEditor editor) { + editor.addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + if (input != null) { + input.removeChangeListener(AbstractPropertyEditor.this); + } + } + }); + } + + /** + * Checks if this editor has all the input needed to do the dataBinding. + * As this editor can be instantiated through the XWT Framework, which is + * based on an XML parser, there is no determinism in the order in which + * the parameters are set. + */ + protected void checkInput() { + if (propertyPath != null && input != null) { + isEditable = input.isEditable(propertyPath); + try { + doBinding(); + } catch (Exception ex) { + // TODO : Handle the exception here. Display something ? + Activator.log.error(ex); + } + + if (getInputObservable() instanceof ICommitListener && getEditor() != null) { + getEditor().addCommitListener((ICommitListener) getInputObservable()); + } + + updateLabel(); + updateDescription(); + } + } + + /** + * Binds the AbstractEditor (Either List or Value editor) to the semantic element + */ + protected void doBinding() { + if (listEditor != null) { + IObservableList inputObservableList = getInputObservableList(); + + if (inputObservableList != null) { + listEditor.setModelObservable(inputObservableList); + } + + } else if (valueEditor != null) { + IObservableValue inputObservableValue = getInputObservableValue(); + + if (inputObservableValue != null) { + valueEditor.setStrategies(); + + + + IValidator modelVal = getValidator(); + if (modelVal != null) { + + valueEditor.setModelValidator(modelVal); + } + valueEditor.setModelObservable(inputObservableValue); + + + + + } + } + + boolean isReadOnly = getReadOnly(); + applyReadOnly(isReadOnly); + + if (input.forceRefresh(propertyPath)) { + input.addChangeListener(this); + } + } + + /** + * Applies the readOnly state to the editor + * + * @param readOnly + * Indicates if this widget should be read-only + */ + protected void applyReadOnly(boolean readOnly) { + AbstractEditor editor = getEditor(); + if ((editor != null) && !editor.isDisposed()) { + editor.setReadOnly(readOnly); + } + } + + /** + * {@inheritDoc} + */ + // TODO : This method handles a change on the DataSource. This should not be a ChangeEvent, as the DataSource is not an IObservable + // This method should be changed, and the source of the event should be checked (Otherwise, it cannot be extended). + // TODO : Remove the "final" modifier to let subclasses extend this behavior, + // when the source of the event is checked. Until then, it is not safe to override this method + @Override + public final void handleChange(ChangeEvent event) { + // Handle the "forceRefresh" behavior when the input DataSource sends a ChangeEvent + AbstractEditor editor = getEditor(); + if (editor != null) { + editor.refreshValue(); + + // And refresh the read-only state + isEditable = input.isEditable(propertyPath); + applyReadOnly(getReadOnly()); + } + } + + /** + * Sets the property path for this PropertyEditor. + * The propertyPath elements should be separated by ":" + * e.g. UML:NamedElement:name + * + * @param path + */ + @Override + public void setProperty(String path) { + propertyPath = path; + checkInput(); + updateLabel(); + updateDescription(); + } + + /** + * Updates the label for this PropertyEditor. + */ + public void updateLabel() { + String label = getLabel(); + // if(input != null && propertyPath != null && input.isMandatory(propertyPath)) { + // label += " *"; //$NON-NLS-1$ + // } + + updateLabel(label); + } + + /** + * Updates the label for this PropertyEditor. + */ + public void updateLabel(String label) { + if (showLabel) { + if (valueEditor != null) { + valueEditor.setLabel(label); + } else if (listEditor != null) { + listEditor.setLabel(label); + } + } + } + + /** + * @return the property path for this Property editor. + */ + @Override + public String getProperty() { + return propertyPath; + } + + /** + * Sets the input DataSource for this Property editor. + * + * @param input + */ + @Override + public void setInput(DataSource input) { + final DataSource oldInput = this.input; + if (input != oldInput) { + if (oldInput != null) { + unhookDataSourceListener(oldInput); + } + + this.input = input; + + if (input != null) { + hookDataSourceListener(input); + } + + // Only do this after attaching our listener so that it will be ahead of + // any ModelElements created for properties + checkInput(); + } + } + + protected void unhookDataSourceListener(DataSource oldInput) { + oldInput.removeDataSourceListener(getDataSourceListener()); + } + + protected void hookDataSourceListener(DataSource newInput) { + newInput.addDataSourceListener(getDataSourceListener()); + } + + /** + * @return the input DataSource for this Property editor + */ + @Override + public DataSource getInput() { + return input; + } + + /** + * @return the formatted property name for this Property Editor + */ + protected String getLabel() { + if (customLabel != null) { + return customLabel; + } + + Property property = getModelProperty(); + if (property == null || property.getLabel() == null || property.getLabel().trim().equals("")) { //$NON-NLS-1$ + return PropertiesUtil.getLabel(getLocalPropertyPath()); + } + + return property.getLabel(); + } + + /** + * Updates the description for this PropertyEditor. + * The description is the widget's ToolTipText + */ + protected void updateDescription() { + String description = ""; //$NON-NLS-1$ + Property property = getModelProperty(); + + if (property != null) { + description = property.getDescription(); + } + + // Append the propertyPath to the description + if (description == null || description.trim().equals("")) { //$NON-NLS-1$ + description = getLocalPropertyPath(); + } else { + description = PropertiesUtil.resizeString(description, descriptionMaxCharPerLine); + description = getLocalPropertyPath() + ": " + description; + } + + + updateDescription(description); + } + + /** + * Updates the description for this PropertyEditor. + * The description is the widget's ToolTipText + */ + protected void updateDescription(String description) { + if (valueEditor != null) { + valueEditor.setToolTipText(description); + } else if (listEditor != null) { + + listEditor.setToolTipText(description); + } + } + + /** + * Finds the property associated to the Editor's {@link #propertyPath} + * + * @return The property associated to the Editor's {@link #propertyPath} + */ + protected Property getModelProperty() { + if (propertyPath == null) { + return null; + } + Context context = getContext(); + + return PropertiesRuntime.getConfigurationManager().getProperty(propertyPath, context); + } + + private Context getContext() { + if (input == null) { + return null; + } else { + return input.getView().getContext(); + } + } + + /** + * Marks this editor as readOnly + * + * @param readOnly + */ + @Override + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + if (getEditor() != null) { + getEditor().setReadOnly(getReadOnly()); + } + } + + /** + * @return the AbstractEditor for this PropertyEditor + */ + public AbstractEditor getEditor() { + return valueEditor == null ? listEditor : valueEditor; + } + + /** + * Tests if this editor is read-only + * + * @return + * True if this editor is read-only + */ + @Override + public boolean getReadOnly() { + boolean result = readOnly || !isEditable || getInputObservable() == null; + return result; + } + + /** + * @return the IObservableList for this propertyEditor, or null if it is not + * available + */ + protected IObservableList getInputObservableList() { + if (observableList == null) { + try { + observableList = (IObservableList) input.getObservable(propertyPath); + } catch (Exception ex) { + Activator.log.error("Cannot find a valid IObservableList for " + propertyPath, ex); //$NON-NLS-1$ + } + } + + return observableList; + } + + /** + * @return the IObservableValue for this propertyEditor, or null if it is not + * available + */ + protected IObservableValue getInputObservableValue() { + if (observableValue == null) { + try { + observableValue = (IObservableValue) input.getObservable(propertyPath); + } catch (Exception ex) { + Activator.log.error("Cannot find a valid IObservableValue for " + propertyPath, ex); //$NON-NLS-1$ + } + } + + return observableValue; + } + + /** + * Returns the IObservable for this propertyEditor, or null if it is + * not available + * + * @return The IObservable associated to this propertyEditor + */ + protected IObservable getInputObservable() { + if (input == null || propertyPath == null) { + return null; + } + + if (listEditor != null) { + return getInputObservableList(); + } + if (valueEditor != null) { + return getInputObservableValue(); + } + return null; + } + + /** + * @return the last segment of the property path (Which is the property name) + */ + protected String getLocalPropertyPath() { + return propertyPath.substring(propertyPath.lastIndexOf(":") + 1); //$NON-NLS-1$ + } + + /** + * Sets the editor's Layout Data + * + * @param data + */ + public void setLayoutData(Object data) { + if (getEditor() != null) { + getEditor().setLayoutData(data); + } + } + + /** + * Returns the editor's Layout Data + * + * @return + * The editor's layout data + */ + public Object getLayoutData() { + return getEditor() == null ? null : getEditor().getLayoutData(); + } + + /** + * Indicates whether the editor's label should be displayed or not + * + * @param showLabel + */ + @Override + public void setShowLabel(boolean showLabel) { + AbstractEditor editor = getEditor(); + this.showLabel = showLabel; + if (editor != null) { + editor.setDisplayLabel(showLabel); + } + } + + /** + * Indicates whether the editor's label is displayed or not + * + * @return + * true if the label should be displayed + */ + @Override + public boolean getShowLabel() { + return this.showLabel; + } + + /** + * Sets the label for this editor. The label will replace the property's + * default label + * + * @param customLabel + * The label to use with this property editor + */ + @Override + public void setCustomLabel(String customLabel) { + this.customLabel = customLabel; + updateLabel(); + } + + /** + * @return the custom label used by this property editor. May be null + */ + @Override + public String getCustomLabel() { + return this.customLabel; + } + + /** + * @return the Control defined by this Property Editor + */ + public Control getControl() { + if (valueEditor == null) { + return listEditor; + } + return valueEditor; + } + + /** + * @return the IValidator for this property editor + */ + + public IValidator getValidator() { + if (modelValidator == null) { + try { + modelValidator = input.getValidator(propertyPath); + } catch (Exception ex) { + Activator.log.error("Cannot find a valid Validator for " + propertyPath, ex); //$NON-NLS-1$ + + } + } + + return modelValidator; + } + + private IDataSourceListener getDataSourceListener() { + if (dataSourceListener == null) { + dataSourceListener = new IDataSourceListener() { + + @Override + public void dataSourceChanged(DataSourceChangedEvent event) { + // The data source's selection changed. Update my validator or clear it if now there is none + IObservableValue observable = AbstractPropertyEditor.this.observableValue; + + if (observable != null) { + if ((modelValidator != null) && (valueEditor != null) && !valueEditor.isDisposed()) { + modelValidator = null; + + // First, clear the validator to disable validation + valueEditor.setStrategies(); + valueEditor.setModelValidator(null); + + // Then re-enable to later when ready for user input + observable.getRealm().asyncExec(new Runnable() { + + @Override + public void run() { + if ((valueEditor != null) && !valueEditor.isDisposed()) { + valueEditor.setStrategies(); + valueEditor.setModelValidator(getValidator()); + } + } + }); + } + + // And refresh the read-only state + if ((propertyPath != null) && (input != null)) { + observable.getRealm().asyncExec(new Runnable() { + + @Override + public void run() { + isEditable = input.isEditable(propertyPath); + applyReadOnly(getReadOnly()); + } + }); + } + } + } + }; + } + + return dataSourceListener; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCheckbox.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCheckbox.java new file mode 100644 index 00000000000..842b118c2ea --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCheckbox.java @@ -0,0 +1,36 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing booleans through a CheckBox + * + * @see org.eclipse.papyrus.infra.widgets.editors.BooleanCheckbox + * + * @author Camille Letavernier + */ +public class BooleanCheckbox extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public BooleanCheckbox(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.BooleanCheckbox(parent, style)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCombo.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCombo.java new file mode 100644 index 00000000000..adc527e488e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanCombo.java @@ -0,0 +1,37 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing booleans through a ComboBox + * + * @see org.eclipse.papyrus.infra.widgets.editors.BooleanCombo + * + * @author Camille Letavernier + * + */ +public class BooleanCombo extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public BooleanCombo(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.BooleanCombo(parent, style)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanRadio.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanRadio.java new file mode 100644 index 00000000000..dc4a5395f27 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanRadio.java @@ -0,0 +1,38 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing booleans with two Radio buttons + * + * @see org.eclipse.papyrus.infra.widgets.editors.BooleanRadio + * + * @author Camille Letavernier + * + */ +public class BooleanRadio extends AbstractPropertyEditor { + + /** + * + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public BooleanRadio(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.BooleanRadio(parent, style)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanToggle.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanToggle.java new file mode 100644 index 00000000000..746b77ccaca --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BooleanToggle.java @@ -0,0 +1,98 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; + + +/** + * A Widget for editing Booleans. The widget is a button with two states. + * The button can have either an image or a text + * + * @author Camille Letavernier + */ +public class BooleanToggle extends AbstractPropertyEditor { + + private org.eclipse.papyrus.infra.widgets.editors.BooleanToggle toggle; + + private String imagePath; + + private String text; + + /** + * + * Constructor. + * + * @param parent + * The parent in which the widget will be created + * @param style + */ + public BooleanToggle(Composite parent, int style) { + toggle = createBooleanToggle(parent, style); + setEditor(toggle); + } + + /** + * Creates the boolean toggle. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the boolean toggle. + */ + protected org.eclipse.papyrus.infra.widgets.editors.BooleanToggle createBooleanToggle(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.BooleanToggle(parent, style); + } + + /** + * Sets this button's text + * + * @param text + */ + public void setText(String text) { + toggle.setText(this.text = text); + } + + /** + * Return this button's text + * + * @return this button's text + */ + public String getText() { + return text; + } + + /** + * Sets this button's image + * + * @param imagePath + * The path to the image, in the form // + */ + public void setImage(String imagePath) { + this.imagePath = imagePath; + Image image = Activator.getDefault().getImageFromPlugin(imagePath); + toggle.setImage(image); + } + + /** + * Returns the path to this editor's image + * + * @return + * The path to this editor's image + */ + public String getImage() { + return imagePath; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BrowseFilePropertyEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BrowseFilePropertyEditor.java new file mode 100644 index 00000000000..4e37e2cb8ec --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/BrowseFilePropertyEditor.java @@ -0,0 +1,175 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.widgets.editors.BrowseFileEditor; +import org.eclipse.swt.widgets.Composite; + + +/** + * Property editor for attribute that need a file selection. + * Its display have unique button with an associated menu to choice where file comes frome. + */ +public class BrowseFilePropertyEditor extends AbstractPropertyEditor { + + /** The browse file editor. */ + private BrowseFileEditor browseFileEditor = null; + + /** The filtered extensions This should be a 1-1 mapping with {@link #filterNames}. */ + protected String[] filterExtensions = null; + + /** + * The name of the filters. + * This should be a 1-1 mapping with {@link #filterExtensions} + */ + protected String[] filterNames = null; + + /** Enables the "browse workspace" feature. */ + protected boolean allowWorkspace = true; + + /** Enables the "browse file system" feature. */ + protected boolean allowFileSystem = true; + + /** + * Instantiates a new browse file property editor. + * + * @param parent + * the parent + * @param style + * the style + */ + public BrowseFilePropertyEditor(Composite parent, int style) { + browseFileEditor = createBrowseFileEditor(parent, style); + super.setEditor(browseFileEditor); + } + + /** + * Set label to browse button. + * + * @param buttonLabel + * Label to set + */ + public void setButtonLabel(String buttonLabel) { + browseFileEditor.setButtonLabel(buttonLabel); + } + + + /** + * @return Label of browse button + */ + public String getButtonLabel() { + return browseFileEditor.getButtonLabel(); + } + + /** + * Creates the browse file editor. + * + * @param parent + * the parent + * @param style + * the style + * @return the browse file editor + */ + private BrowseFileEditor createBrowseFileEditor(Composite parent, int style) { + + return new BrowseFileEditor(parent, style); + } + + /** + * Sets the filter extensions. + * + * @param filterExtensions + * the new filter extensions + */ + public void setFilterExtensions(String[] filterExtensions) { + this.filterExtensions = filterExtensions; + checkFilters(); + } + + /** + * Gets the filter extensions. + * + * @return the filter extensions + */ + public String[] getFilterExtensions() { + return this.filterExtensions; + } + + /** + * Sets the filter names. + * + * @param filterNames + * the new filter names + */ + public void setFilterNames(String[] filterNames) { + this.filterNames = filterNames; + checkFilters(); + } + + /** + * Gets the filter names. + * + * @return the filter names + */ + public String[] getFilterNames() { + return this.filterNames; + } + + /** + * Checks if the filters are valid. + */ + protected void checkFilters() { + if (filterExtensions != null && filterNames != null) { + browseFileEditor.setFilters(filterExtensions, filterNames); + } + } + + /** + * Indicates whether the editor should allow browsing the workspace or not. + * + * @param allowWorkspace + * the new allow workspace + */ + public void setAllowWorkspace(boolean allowWorkspace) { + this.allowWorkspace = allowWorkspace; + browseFileEditor.setAllowWorkspace(allowWorkspace); + } + + /** + * Gets the allow workspace. + * + * @return true if the editor can browse the workspace + */ + public boolean getAllowWorkspace() { + return allowWorkspace; + } + + /** + * Indicates whether the editor should allow browsing the file system or not. + * + * @param allowFileSystem + * the new allow file system + */ + public void setAllowFileSystem(boolean allowFileSystem) { + this.allowFileSystem = allowFileSystem; + browseFileEditor.setAllowFileSystem(allowFileSystem); + } + + /** + * Gets the allow file system. + * + * @return true if the editor can browse the fileSystem + */ + public boolean getAllowFileSystem() { + return allowFileSystem; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextMultiReference.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextMultiReference.java new file mode 100644 index 00000000000..0761956873a --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextMultiReference.java @@ -0,0 +1,65 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.widgets.editors.CompletionStyledTextMultipleReferenceEditor; +import org.eclipse.papyrus.infra.widgets.editors.MultipleReferenceEditor; +import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing multiple references in a List + * + * @see org.eclipse.papyrus.widgets.editors.BooleanCheckbox + * + * @author Camille Letavernier + */ +public class CompletionStyledTextMultiReference extends MultiReference { + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public CompletionStyledTextMultiReference(Composite parent, int style) { + super(parent, style); + } + + + /** + * @see org.eclipse.papyrus.infra.properties.ui.widgets.MultiReference#createMultipleReferenceEditor(org.eclipse.swt.widgets.Composite, int) + * + * @param parent + * @param style + * @return + */ + @Override + protected MultipleReferenceEditor createMultipleReferenceEditor(Composite parent, int style) { + return new CompletionStyledTextMultipleReferenceEditor(parent, style); + } + + /** + * @see org.eclipse.papyrus.infra.properties.ui.widgets.MultiReference#doBinding() + * + */ + @Override + protected void doBinding() { + if (editor instanceof ISetPapyrusConverter) { + ((ISetPapyrusConverter) editor).setPapyrusConverter(input.getPapyrusConverter(propertyPath)); + } + super.doBinding(); + } + + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextReferenceDialog.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextReferenceDialog.java new file mode 100644 index 00000000000..a13b64bc544 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CompletionStyledTextReferenceDialog.java @@ -0,0 +1,109 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.swt.widgets.Composite; + +/** + * @author VL222926 + * + */ +public class CompletionStyledTextReferenceDialog extends AbstractPropertyEditor { + + /** + * The ReferenceDialog widget + */ + protected org.eclipse.papyrus.infra.widgets.editors.CompletionStyledTextReferenceDialog editor; + + /** + * The ValueFactory used to create or edit Objects directly from + * this editor + */ + protected ReferenceValueFactory factory; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public CompletionStyledTextReferenceDialog(Composite parent, int style) { + editor = createReferenceDialog(parent, style); + setEditor(editor); + } + + /** + * Creates the reference dialog. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the reference dialog. + */ + protected org.eclipse.papyrus.infra.widgets.editors.CompletionStyledTextReferenceDialog createReferenceDialog(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.CompletionStyledTextReferenceDialog(parent, style); + } + + /** + * + * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#doBinding() + * + */ + @Override + protected void doBinding() { + + IStaticContentProvider provider = input.getContentProvider(propertyPath); + editor.setLabelProvider(input.getLabelProvider(propertyPath)); + editor.setContentProvider(provider); + editor.setDirectCreation(input.getDirectCreation(propertyPath)); + editor.setMandatory(input.isMandatory(propertyPath)); + if (factory == null) { // Use the default factory from the DataSource + editor.setValueFactory(input.getValueFactory(propertyPath)); + } else { // Use the factory explicitly specified + editor.setValueFactory(factory); + } + IPapyrusConverter parser = input.getPapyrusConverter(propertyPath); + if (parser != null) { + editor.setPapyrusConverter(parser); + + } + super.doBinding(); + } + + /** + * Sets the ValueFactory used to create or edit Objects directly from + * this editor + * + * @param factory + */ + public void setFactory(ReferenceValueFactory factory) { + this.factory = factory; + editor.setValueFactory(factory); + } + + /** + * @return The ValueFactory used to create or edit Objects directly from + * this editor + */ + public ReferenceValueFactory getFactory() { + return factory; + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CustomizablePropertyEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CustomizablePropertyEditor.java new file mode 100644 index 00000000000..d31dcfb63e1 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/CustomizablePropertyEditor.java @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tessier (CEA LIST) - Initial API and implementation + /*****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; + +/** + * The inteface to be implemented by all PropertyEditors + * + * @author Camille Letavernier + * + */ +public interface CustomizablePropertyEditor { + + public DataSource getInput(); + + public void setInput(DataSource input); + + public String getProperty(); + + public void setProperty(String property); + + public boolean getShowLabel(); + + public void setShowLabel(boolean showLabel); + + public String getCustomLabel(); + + public void setCustomLabel(String customLabel); + + public void setReadOnly(boolean readOnly); + + public boolean getReadOnly(); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/DoubleEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/DoubleEditor.java new file mode 100644 index 00000000000..9b4dd044edf --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/DoubleEditor.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing Doubles through a Text field + * + * @see org.eclipse.papyrus.infra.widgets.editors.DoubleEditor + * + * @author Camille Letavernier + */ +public class DoubleEditor extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public DoubleEditor(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.DoubleEditor(parent, style)); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumCombo.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumCombo.java new file mode 100644 index 00000000000..46f2812c1c1 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumCombo.java @@ -0,0 +1,58 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing enumerations through a ComboBox + * + * @see org.eclipse.papyrus.infra.widgets.editors.BooleanCheckbox + * + * @author Camille Letavernier + */ +public class EnumCombo extends AbstractPropertyEditor { + + /** + * The EnumCombo widget + */ + protected org.eclipse.papyrus.infra.widgets.editors.EnumCombo enumCombo; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public EnumCombo(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.EnumCombo(parent, style)); + enumCombo = (org.eclipse.papyrus.infra.widgets.editors.EnumCombo) valueEditor; + } + + /** + * @Problem : The different options come from input. + * When we don't have an input (e.g. : during preview), + * we don't have the different values, and we can't + * display the correct preview. + * @TODO : Retrieve the values from the DataContext if possible. + */ + @Override + protected void doBinding() { + enumCombo.setProviders(input.getContentProvider(propertyPath), input.getLabelProvider(propertyPath)); + + enumCombo.setUnsettable(!input.isMandatory(propertyPath)); + + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumRadio.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumRadio.java new file mode 100644 index 00000000000..7d495d4d3e6 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/EnumRadio.java @@ -0,0 +1,76 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing booleans with radio buttons. + * This Editor should only be used with Enums which have only + * a small amount of values. + * + * @see org.eclipse.papyrus.infra.widgets.editors.EnumRadio + * + * @author Camille Letavernier + */ +public class EnumRadio extends AbstractPropertyEditor { + + /** + * The EnumRadio widget + */ + protected org.eclipse.papyrus.infra.widgets.editors.EnumRadio enumRadio; + + private int numColumns = -1; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public EnumRadio(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.EnumRadio(parent, style)); + enumRadio = (org.eclipse.papyrus.infra.widgets.editors.EnumRadio) valueEditor; + } + + /** + * Sets the maximum number of columns for this editor. The radio values + * will be distributed according to this number + * + * @param numColumns + */ + public void setNumColumns(int numColumns) { + this.numColumns = numColumns; + enumRadio.setNumColumns(numColumns); + } + + /** + * Return the maximum number of columns for this editor + * + * @return + * The number of columns for this editor + */ + public int getNumColumns() { + return numColumns; + } + + @Override + protected void doBinding() { + enumRadio.setProviders(input.getContentProvider(propertyPath), input.getLabelProvider(propertyPath)); + + // enumRadio.setUnsettable(! input.isMandatory(propertyPath)); + + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/FloatEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/FloatEditor.java new file mode 100644 index 00000000000..f0b163f56cf --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/FloatEditor.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing floats through a Text field + * + * @see org.eclipse.papyrus.infra.widgets.editors.FloatEditor + * + * @author Camille Letavernier + */ +public class FloatEditor extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public FloatEditor(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.FloatEditor(parent, style)); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerEditor.java new file mode 100644 index 00000000000..694d5c20413 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerEditor.java @@ -0,0 +1,36 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing integers through a Text field + * + * @see org.eclipse.papyrus.infra.widgets.editors.IntegerEditor + * + * @author Camille Letavernier + */ +public class IntegerEditor extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public IntegerEditor(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.IntegerEditor(parent, style)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerMask.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerMask.java new file mode 100644 index 00000000000..2b06d00312c --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerMask.java @@ -0,0 +1,73 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.properties.ui.providers.XWTCompliantMaskProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A widget to edit mask-based Integer values + * The integer value is interpreted as a list of boolean values + * The widget cannot use more than 32 masks + * + * @author Camille Letavernier + */ +@Deprecated +public class IntegerMask extends InvalidWidget { + + /** + * + * Constructor. + * + * @param parent + * The composite in which this widget will be created + * @param style + */ + public IntegerMask(Composite parent, int style) { + super(parent, style); + } + + /** + * @return the number of columns for this editor + * + */ + public int getNumColumns() { + return 0; + } + + /** + * Sets the number of columns for this editor. The mask checkboxes will be + * distributed according to this number + * + * @param numColumns + */ + public void setNumColumns(int numColumns) { + // + } + + /** + * Sets the MaskProvider for this editor + * + * @param provider + */ + public void setMaskProvider(XWTCompliantMaskProvider provider) { + // + } + + /** + * + * @return the MaskProvider associated to this editor + */ + public XWTCompliantMaskProvider getMaskProvider() { + return null; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerSpinner.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerSpinner.java new file mode 100644 index 00000000000..ab08ffed887 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/IntegerSpinner.java @@ -0,0 +1,105 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A widget for editing Integer values with a SWT Spinner + * + * @author Camille Letavernier + * + * @see org.eclipse.papyrus.infra.widgets.editors.IntegerSpinner + * @see org.eclipse.swt.widgets.Spinner + */ +public class IntegerSpinner extends AbstractPropertyEditor { + + private org.eclipse.papyrus.infra.widgets.editors.IntegerSpinner spinner; + + private int minimum = 0, maximum = 100, increment = 1; + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public IntegerSpinner(Composite parent, int style) { + spinner = createIntegerSpinner(parent, style); + spinner.setMinimum(minimum); + spinner.setMaximum(maximum); + spinner.setIncrement(increment); + setEditor(spinner); + } + + /** + * Creates the integer spinner. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the integer spinner. + */ + protected org.eclipse.papyrus.infra.widgets.editors.IntegerSpinner createIntegerSpinner(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.IntegerSpinner(parent, style); + } + + /** + * @return the minimum value for the spinner + */ + public int getMinimum() { + return minimum; + } + + /** + * @param minimum + * the minimum value for the spinner + */ + public void setMinimum(int minimum) { + this.minimum = minimum; + spinner.setMinimum(minimum); + } + + /** + * @return the maximum value for the spinner + */ + public int getMaximum() { + return maximum; + } + + /** + * @param maximum + * the maximum value for the spinner + */ + public void setMaximum(int maximum) { + this.maximum = maximum; + spinner.setMaximum(maximum); + } + + /** + * @return the increment value for the spinner + */ + public int getIncrement() { + return increment; + } + + /** + * @param increment + * the increment value for the spinner + */ + public void setIncrement(int increment) { + this.increment = increment; + spinner.setIncrement(increment); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/InvalidWidget.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/InvalidWidget.java new file mode 100644 index 00000000000..89cee91ad48 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/InvalidWidget.java @@ -0,0 +1,62 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.widgets.editors.StringLabel; +import org.eclipse.swt.widgets.Composite; + +/** + * A class for displaying invalid widgets without raising Java errors + * The widget will display an error, and may display the property label + * if it is available + * + * @author Camille Letavernier + */ +public class InvalidWidget extends AbstractPropertyEditor { + + /** + * + * Constructor. + * + * @param parent + * The Composite in which the editor will be created + * @param style + * The style to apply to the editor + */ + public InvalidWidget(Composite parent, int style) { + super(); + StringLabel editor = createStringLabel(parent, style); + setEditor(editor); + + editor.getValueLabel().setText("Property view Error : invalid widget type"); //$NON-NLS-1$ + editor.getValueLabel().setImage(Activator.getDefault().getImage("icons/error.gif")); //$NON-NLS-1$ + } + + /** + * Creates the string label. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the string label. + */ + protected StringLabel createStringLabel(Composite parent, int style) { + return new StringLabel(parent, style); + } + + @Override + public void doBinding() { + // Skip to avoid the binding between the property's value and the CLabel + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MaskProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MaskProvider.java new file mode 100644 index 00000000000..32d260d9201 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MaskProvider.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import java.util.Map; + +/** + * An interface for providing Masks for editing mask-based integer values + * + * @author Camille Letavernier + * + * @see StringMask + */ +public interface MaskProvider { + + /** + * @return the list of masks and their String descriptions + */ + public Map getMasks(); +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiDouble.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiDouble.java new file mode 100644 index 00000000000..50fc47e9807 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiDouble.java @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + + + +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.MultipleDoubleEditor; +import org.eclipse.swt.widgets.Composite; + +public class MultiDouble extends AbstractPropertyEditor { + + /** + * The MultipleDoubleEditor widget + */ + protected MultipleDoubleEditor editor; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public MultiDouble(Composite parent, int style) { + editor = createMultipleDoubleEditor(parent, style); + super.setEditor(editor); + } + + /** + * Creates the multiple double editor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the multiple double editor. + */ + protected MultipleDoubleEditor createMultipleDoubleEditor(Composite parent, int style) { + return new MultipleDoubleEditor(parent, style); + } + + @Override + protected void doBinding() { + editor.setOrdered(input.isOrdered(propertyPath)); + editor.setUnique(input.isUnique(propertyPath)); + + if (getInputObservableList() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableList()); + } + + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiInteger.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiInteger.java new file mode 100644 index 00000000000..e3e85dfc340 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiInteger.java @@ -0,0 +1,69 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.MultipleIntegerEditor; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing multiple integers in a List + * + * @see org.eclipse.papyrus.widgets.editors.MultipleIntegerEditor + * + * @author Camille Letavernier + */ +public class MultiInteger extends AbstractPropertyEditor { + + /** + * The MultipleIntegerEditor widget + */ + protected MultipleIntegerEditor editor; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public MultiInteger(Composite parent, int style) { + editor = createMultipleIntegerEditor(parent, style); + super.setEditor(editor); + } + + /** + * Creates the multiple integer editor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the multiple integer editor. + */ + protected MultipleIntegerEditor createMultipleIntegerEditor(Composite parent, int style) { + return new MultipleIntegerEditor(parent, style); + } + + @Override + protected void doBinding() { + editor.setOrdered(input.isOrdered(propertyPath)); + editor.setUnique(input.isUnique(propertyPath)); + + if (getInputObservableList() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableList()); + } + + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReference.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReference.java new file mode 100644 index 00000000000..f367c9730a3 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReference.java @@ -0,0 +1,106 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.MultipleReferenceEditor; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing multiple references in a List + * + * @see org.eclipse.papyrus.widgets.editors.BooleanCheckbox + * + * @author Camille Letavernier + */ +public class MultiReference extends AbstractPropertyEditor { + + /** + * The MultipleReferenceEditor widget + */ + protected MultipleReferenceEditor editor; + + /** + * The ReferenceValueFactory allowing creation and direct editing of values + */ + protected ReferenceValueFactory factory; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public MultiReference(Composite parent, int style) { + editor = createMultipleReferenceEditor(parent, style); + super.setEditor(editor); + } + + /** + * Creates the reference editor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return The reference editor + */ + protected MultipleReferenceEditor createMultipleReferenceEditor(Composite parent, int style) { + return new MultipleReferenceEditor(parent, style); + } + + @Override + protected void doBinding() { + IStaticContentProvider contentProvider = input.getContentProvider(propertyPath); + ILabelProvider labelProvider = input.getLabelProvider(propertyPath); + + if (getInputObservableList() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableList()); + } + + editor.setProviders(contentProvider, labelProvider); + editor.setOrdered(input.isOrdered(propertyPath)); + editor.setUnique(input.isUnique(propertyPath)); + if (factory == null) { + editor.setFactory(input.getValueFactory(propertyPath)); + } else { + editor.setFactory(factory); + } + editor.setDirectCreation(input.getDirectCreation(propertyPath)); + + super.doBinding(); + } + + /** + * Sets the {@link ReferenceValueFactory} for this Editor. The factory + * allows creation and direct edition of objects. + * + * @param factory + */ + public void setFactory(ReferenceValueFactory factory) { + this.factory = factory; + editor.setFactory(factory); + } + + /** + * @return the {@link ReferenceValueFactory} used by this editor + */ + public ReferenceValueFactory getFactory() { + return factory; + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferenceEditorWithPropertyView.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferenceEditorWithPropertyView.java new file mode 100644 index 00000000000..13b79835819 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferenceEditorWithPropertyView.java @@ -0,0 +1,169 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import java.util.Set; + +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.ui.runtime.EmbeddedDisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.editors.AbstractListEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.MultipleReferenceEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + +public class MultiReferenceEditorWithPropertyView extends AbstractListEditor implements ISelectionChangedListener { + + protected MultipleReferenceEditor multiReferenceEditor; + + protected Composite propertiesComposite; + + protected EmbeddedDisplayEngine displayEngine = new EmbeddedDisplayEngine(); + + public MultiReferenceEditorWithPropertyView(Composite parent, int style) { + super(parent, style); + // parent.setBackground(getDisplay().getSystemColor(SWT.COLOR_RED)); + ((GridLayout) getLayout()).numColumns++; + + multiReferenceEditor = createMultipleReferenceEditor(style); + multiReferenceEditor.addSelectionChangedListener(this); + multiReferenceEditor.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, true)); + + propertiesComposite = new Composite(this, style); + propertiesComposite.setLayout(new FillLayout()); + propertiesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + /** + * Creates the multi reference editor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the multi reference editor. + */ + protected MultipleReferenceEditor createMultipleReferenceEditor(int style) { + return new MultipleReferenceEditor(this, style); + } + + @Override + public GridData getDefaultLayoutData() { + GridData data = super.getDefaultLayoutData(); + data.grabExcessVerticalSpace = true; + data.grabExcessHorizontalSpace = true; + data.verticalAlignment = SWT.FILL; + return data; + } + + @Override + public Object getEditableType() { + return Object.class; + } + + @Override + public void setReadOnly(boolean readOnly) { + multiReferenceEditor.setReadOnly(readOnly); + propertiesComposite.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return multiReferenceEditor.isReadOnly(); + } + + @Override + public void setToolTipText(String text) { + multiReferenceEditor.setToolTipText(text); + } + + @Override + public void setLabel(String label) { + multiReferenceEditor.setLabel(label); + } + + public void setOrdered(boolean ordered) { + multiReferenceEditor.setOrdered(ordered); + } + + public void setUnique(boolean unique) { + multiReferenceEditor.setUnique(unique); + } + + @Override + public void setModelObservable(IObservableList modelObservable) { + multiReferenceEditor.setModelObservable(modelObservable); + + // If the properties view of the first element contains a recursive view, we may have a StackOverFlow here. + // Do not force the initial selection. + + // if(!modelObservable.isEmpty()) { + // multiReferenceEditor.getViewer().setSelection(new StructuredSelection(modelObservable.get(0))); + // } + } + + @Override + public void dispose() { + super.dispose(); + multiReferenceEditor.removeSelectionChangedListener(this); + } + + @Override + public void selectionChanged(SelectionChangedEvent event) { + ISelection selection = event.getSelection(); + + Set views = PropertiesRuntime.getConstraintEngine().getDisplayUnits(selection); + displayEngine.display(views, propertiesComposite, selection, SWT.NONE); + this.layout(); + propertiesComposite.layout(); + + // TODO : How can we force the property view layout ? + // In the tabbed property view, we need to go up to the 4th parent + getParent().layout(); // This one works in the embedded editor + + // In the Eclipse Tabbed Property View, we need to go this far... + getParent().getParent().getParent().getParent().layout(); + } + + public void setFactory(ReferenceValueFactory valueFactory) { + multiReferenceEditor.setFactory(valueFactory); + } + + public void setDirectCreation(boolean directCreation) { + multiReferenceEditor.setDirectCreation(directCreation); + } + + public void setLabelProvider(ILabelProvider labelProvider) { + multiReferenceEditor.setLabelProvider(labelProvider); + } + + @Override + public void addCommitListener(ICommitListener commitListener) { + multiReferenceEditor.addCommitListener(commitListener); + } + + @Override + public void changeColorField() { + // TODO Auto-generated method stub + + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferencePropertyEditorWithPropertyView.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferencePropertyEditorWithPropertyView.java new file mode 100644 index 00000000000..df9d8305401 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiReferencePropertyEditorWithPropertyView.java @@ -0,0 +1,62 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.swt.widgets.Composite; + + +public class MultiReferencePropertyEditorWithPropertyView extends AbstractPropertyEditor { + + protected MultiReferenceEditorWithPropertyView editor; + + public MultiReferencePropertyEditorWithPropertyView(Composite parent, int style) { + editor = createMultiReferenceEditorWithPropertyView(parent, style); + setEditor(editor); + } + + /** + * Creates the multi reference editor with property view. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the multi reference editor with property view. + */ + protected MultiReferenceEditorWithPropertyView createMultiReferenceEditorWithPropertyView(Composite parent, int style) { + return new MultiReferenceEditorWithPropertyView(parent, style); + } + + @Override + protected void doBinding() { + // IStaticContentProvider contentProvider = input.getContentProvider(propertyPath); + ILabelProvider labelProvider = input.getLabelProvider(propertyPath); + + if (getInputObservableList() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableList()); + } + + if (labelProvider != null) { + editor.setLabelProvider(labelProvider); + } + + editor.setOrdered(input.isOrdered(propertyPath)); + editor.setUnique(input.isUnique(propertyPath)); + + editor.setFactory(input.getValueFactory(propertyPath)); + editor.setDirectCreation(input.getDirectCreation(propertyPath)); + + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiString.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiString.java new file mode 100644 index 00000000000..c6751cb8869 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiString.java @@ -0,0 +1,90 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.MultipleStringEditor; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing multiple strings in a list + * + * @see org.eclipse.papyrus.infra.widgets.editors.MultipleStringEditor + * + * @author Camille Letavernier + */ +public class MultiString extends AbstractPropertyEditor { + + /** + * The MultipleStringEditor widget + */ + protected MultipleStringEditor editor; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public MultiString(Composite parent, int style) { + editor = createMultipleStringEditor(parent, style); + super.setEditor(editor); + } + + /** + * Creates the multiple string editor + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the multiple string editor. + */ + protected MultipleStringEditor createMultipleStringEditor(Composite parent, int style) { + return new MultipleStringEditor(parent, style); + } + + @Override + protected void doBinding() { + editor.setOrdered(input.isOrdered(propertyPath)); + editor.setUnique(input.isUnique(propertyPath)); + editor.setDirectCreation(input.getDirectCreation(propertyPath)); + ReferenceValueFactory factory = input.getValueFactory(propertyPath); + if (factory != null) { + editor.setFactory(input.getValueFactory(propertyPath)); + } + + IStaticContentProvider provider = input.getContentProvider(propertyPath); + if (provider != null) { + editor.setContentProvider(provider); + } + + if (getInputObservableList() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableList()); + } + + super.doBinding(); + } + + /** + * + * @return the ListViewer associated to this editor + */ + public TreeViewer getViewer() { + return editor.getViewer(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiStringFile.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiStringFile.java new file mode 100644 index 00000000000..4e09f5186d3 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/MultiStringFile.java @@ -0,0 +1,99 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.MultipleStringFileEditor; +import org.eclipse.swt.widgets.Composite; + + +public class MultiStringFile extends AbstractPropertyEditor { + + public MultipleStringFileEditor editor; + + /** + * The filtered extensions + * This should be a 1-1 mapping with {@link #filterNames} + */ + protected String[] filterExtensions; + + /** + * The name of the filters. + * This should be a 1-1 mapping with {@link #filterExtensions} + */ + protected String[] filterNames; + + public MultiStringFile(Composite parent, int style) { + editor = createMultipleStringFileEditor(parent, style); + setEditor(editor); + } + + /** + * Creates the multiple string file editor + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the multiple string file editor. + */ + protected MultipleStringFileEditor createMultipleStringFileEditor(Composite parent, int style) { + return new MultipleStringFileEditor(parent, style); + } + + @Override + protected void doBinding() { + editor.setOrdered(input.isOrdered(propertyPath)); + editor.setUnique(input.isUnique(propertyPath)); + + if (getInputObservableList() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableList()); + } + + super.doBinding(); + } + + /** + * + * @param filterExtensions + */ + public void setFilterExtensions(String[] filterExtensions) { + this.filterExtensions = filterExtensions; + checkFilters(); + } + + public String[] getFilterExtensions() { + return this.filterExtensions; + } + + /** + * + * @param filterNames + */ + public void setFilterNames(String[] filterNames) { + this.filterNames = filterNames; + checkFilters(); + } + + public String[] getFilterNames() { + return this.filterNames; + } + + /** + * Checks if the filters are valid + */ + protected void checkFilters() { + if (filterExtensions != null && filterNames != null) { + editor.setFilters(filterExtensions, filterNames); + } + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceCombo.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceCombo.java new file mode 100644 index 00000000000..edcfb132f77 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceCombo.java @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.HierarchicToFlatContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.TreeToFlatContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing references through a ComboBox + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo + * + * @author Camille Letavernier + */ +public class ReferenceCombo extends AbstractPropertyEditor { + + /** + * The ReferenceCombo widget + */ + protected org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo combo; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public ReferenceCombo(Composite parent, int style) { + combo = new org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo(parent, style); + super.setEditor(combo); + } + + @Override + protected void doBinding() { + IStaticContentProvider contentProvider = input.getContentProvider(propertyPath); + if (contentProvider instanceof IHierarchicContentProvider) { + contentProvider = new HierarchicToFlatContentProvider((IHierarchicContentProvider) contentProvider); + // combo.setViewer(new EncapsulatedComboViewer(combo.getViewer())); + } else if (contentProvider instanceof ITreeContentProvider) { + contentProvider = new TreeToFlatContentProvider((ITreeContentProvider) contentProvider); + // combo.setViewer(new EncapsulatedComboViewer(combo.getViewer())); + } + + ILabelProvider labelProvider = input.getLabelProvider(propertyPath); + + combo.setProviders(contentProvider, labelProvider); + combo.setUnsettable(!input.isMandatory(propertyPath)); + + super.doBinding(); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceDialog.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceDialog.java new file mode 100644 index 00000000000..3bcf73e4267 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceDialog.java @@ -0,0 +1,99 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing references through a Dialog + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog + * + * @author Camille Letavernier + */ +public class ReferenceDialog extends AbstractPropertyEditor { + + /** + * The ReferenceDialog widget + */ + protected org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog editor; + + /** + * The ValueFactory used to create or edit Objects directly from + * this editor + */ + protected ReferenceValueFactory factory; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public ReferenceDialog(Composite parent, int style) { + editor = createReferenceDialog(parent, style); + setEditor(editor); + } + + /** + * Creates the reference dialog. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the reference dialog. + */ + protected org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog createReferenceDialog(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog(parent, style); + } + + @Override + protected void doBinding() { + IStaticContentProvider provider = input.getContentProvider(propertyPath); + editor.setLabelProvider(input.getLabelProvider(propertyPath)); + editor.setContentProvider(provider); + editor.setDirectCreation(input.getDirectCreation(propertyPath)); + editor.setMandatory(input.isMandatory(propertyPath)); + if (factory == null) { // Use the default factory from the DataSource + editor.setValueFactory(input.getValueFactory(propertyPath)); + } else { // Use the factory explicitly specified + editor.setValueFactory(factory); + } + + super.doBinding(); + } + + /** + * Sets the ValueFactory used to create or edit Objects directly from + * this editor + * + * @param factory + */ + public void setFactory(ReferenceValueFactory factory) { + this.factory = factory; + editor.setValueFactory(factory); + } + + /** + * @return The ValueFactory used to create or edit Objects directly from + * this editor + */ + public ReferenceValueFactory getFactory() { + return factory; + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceLabel.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceLabel.java new file mode 100644 index 00000000000..cdf487cb721 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ReferenceLabel.java @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.editors.StringLabel; +import org.eclipse.swt.widgets.Composite; + +/** + * A property editor to display a reference's value as a CLabel, filled + * via a LabelProvider + * + * @author Camille Letavernier + * + */ +public class ReferenceLabel extends AbstractPropertyEditor { + + private StringLabel editor; + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public ReferenceLabel(Composite parent, int style) { + editor = createReferenceLabel(parent, style); + setEditor(editor); + } + + /** + * Creates the string label. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the string label. + */ + protected StringLabel createReferenceLabel(Composite parent, int style) { + return new StringLabel(parent, style); + } + + @Override + public void doBinding() { + ILabelProvider labelProvider = input.getLabelProvider(propertyPath); + if (labelProvider != null) { + editor.setLabelProvider(labelProvider); + } + + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringCombo.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringCombo.java new file mode 100644 index 00000000000..2169fc50521 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringCombo.java @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A Property Editor for editing a String with an editable combo. + * The combo proposes a set of default values. + * + * @author Camille Letavernier + */ +public class StringCombo extends AbstractPropertyEditor { + + /** + * The StringCombo widget used by this property editor + */ + protected org.eclipse.papyrus.infra.widgets.editors.StringCombo editor; + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public StringCombo(Composite parent, int style) { + editor = createStringCombo(parent, style); + super.setEditor(editor); + } + + /** + * Creates the string combo dialog. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the string combo dialog. + */ + protected org.eclipse.papyrus.infra.widgets.editors.StringCombo createStringCombo(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.StringCombo(parent, style); + } + + @Override + public void doBinding() { + IStaticContentProvider contentProvider = input.getContentProvider(propertyPath); + editor.setContentProvider(contentProvider); + editor.setUnsettable(!input.isMandatory(propertyPath)); + + ILabelProvider labelProvider = input.getLabelProvider(propertyPath); + if (labelProvider != null) { + editor.setLabelProvider(labelProvider); + } + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditor.java new file mode 100644 index 00000000000..acee3cf7f0e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditor.java @@ -0,0 +1,36 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing strings through a Text field + * + * @see org.eclipse.papyrus.infra.widgets.editors.StringEditor + * + * @author Camille Letavernier + */ +public class StringEditor extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public StringEditor(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.StringEditor(parent, style)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditorWithReferences.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditorWithReferences.java new file mode 100644 index 00000000000..b9b90fd9021 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringEditorWithReferences.java @@ -0,0 +1,166 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.emf.utils.TextReferencesHelper; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.widgets.editors.TreeSelectorDialog; +import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * A StringEditor with support for inserting references to EObjects (Via a TextReferenceHelper) + * + * @author Camille Letavernier + * + */ +public class StringEditorWithReferences extends org.eclipse.papyrus.infra.widgets.editors.StringEditor implements SelectionListener { + + protected Composite buttonsBar; + + protected Button insertReferenceButton; + + protected IStaticContentProvider referenceContentProvider = EmptyContentProvider.instance; + + protected ILabelProvider labelProvider = new LabelProvider(); + + protected TextReferencesHelper referenceHelper; + + public StringEditorWithReferences(Composite parent, int style) { + super(parent, style | SWT.MULTI); + setLayout(new GridLayout(2, false)); + createButtonsBar(this); + } + + @Override + protected GridData getDefaultLayoutData() { + GridData defaultData = super.getDefaultLayoutData(); + defaultData.horizontalSpan = 2; + return defaultData; + } + + protected void createButtonsBar(Composite wrapper) { + buttonsBar = new Composite(wrapper, SWT.NONE); + GridLayout buttonsBarLayout = new GridLayout(1, true); + + buttonsBarLayout.marginWidth = 0; + buttonsBarLayout.marginHeight = 0; + + buttonsBar.setLayout(buttonsBarLayout); + buttonsBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); + buttonsBar.moveAbove(label); + createButtons(buttonsBar); + } + + protected void createButtons(Composite buttonsBar) { + createInsertReferenceButton(buttonsBar); + } + + protected void createInsertReferenceButton(Composite buttonsBar) { + insertReferenceButton = new Button(buttonsBar, SWT.PUSH); + insertReferenceButton.setToolTipText("Insert a dynamic reference to an Element"); + insertReferenceButton.setImage(org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage("/icons/hyperlink_16x16.gif")); //$NON-NLS-1$ + insertReferenceButton.addSelectionListener(this); + insertReferenceButton.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false)); + } + + public void setReferenceBrowserContentProvider(IStaticContentProvider provider) { + this.referenceContentProvider = provider; + } + + public void setTextReferencesHelper(TextReferencesHelper helper) { + this.referenceHelper = helper; + } + + public void widgetSelected(SelectionEvent e) { + if (e.widget == insertReferenceButton) { + insertReferenceAction(); + } + } + + protected void insertReferenceAction() { + if (referenceHelper == null) { + // The widget is not properly set. We cannot handle references + Activator.log.warn("This widget is not properly configured. It cannot handle reference insertion"); + return; + } + + TreeSelectorDialog dialog = new TreeSelectorDialog(getShell()); + + dialog.setContentProvider(new EncapsulatedContentProvider(referenceContentProvider)); + dialog.setLabelProvider(labelProvider); + + if (dialog.open() == Window.OK) { + Object[] result = dialog.getResult(); + if (result.length == 0) { + return; + } + + Object resultElement = result[0]; + if (!(resultElement instanceof EObject)) { + return; + } + + EObject objectToReference = (EObject) resultElement; + + String currentText = text.getText(); + int caretPosition = text.getCaretPosition(); + + String newText = referenceHelper.insertReference(objectToReference, currentText, caretPosition); + if (newText.length() == currentText.length()) { + return; + } + + int caretShift = newText.length() - currentText.length(); + int newCaretPosition = caretPosition + caretShift; + + // This should not happen with the standard ReferenceHelper as it is supposed to insert additional text into the current text + // However, some ReferenceHelper implementations might replace the current text + if (newCaretPosition < 0) { + newCaretPosition = 0; + } + + if (newCaretPosition > newText.length()) { + newCaretPosition = newText.length(); + } + + text.setText(newText); + text.setFocus(); + text.setSelection(newCaretPosition); + commit(); + } + } + + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + public void setLabelProvider(ILabelProvider labelProvider) { + this.labelProvider = labelProvider; + } + + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelector.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelector.java new file mode 100644 index 00000000000..aa2bb9dd01f --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelector.java @@ -0,0 +1,146 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A Widget for selecting Files on the workspace or on the file system. + * The widgets only edits String values : it uses the path of the files + * + * @author Camille Letavernier + */ +public class StringFileSelector extends AbstractPropertyEditor { + + /** + * The StringFileSelector widget used by this property editor + */ + protected org.eclipse.papyrus.infra.widgets.editors.StringFileSelector selector; + + /** + * The filtered extensions + * This should be a 1-1 mapping with {@link #filterNames} + */ + protected String[] filterExtensions; + + /** + * The name of the filters. + * This should be a 1-1 mapping with {@link #filterExtensions} + */ + protected String[] filterNames; + + /** + * Enables the "browse workspace" feature + */ + protected boolean allowWorkspace = true; + + /** + * Enables the "browse file system" feature + */ + protected boolean allowFileSystem = true; + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public StringFileSelector(Composite parent, int style) { + selector = createSelector(parent, style); + super.setEditor(selector); + } + + /** + * Creates the selector + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the selector + */ + protected org.eclipse.papyrus.infra.widgets.editors.StringFileSelector createSelector(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.StringFileSelector(parent, style); + } + + /** + * + * @param filterExtensions + */ + public void setFilterExtensions(String[] filterExtensions) { + this.filterExtensions = filterExtensions; + checkFilters(); + } + + public String[] getFilterExtensions() { + return this.filterExtensions; + } + + /** + * + * @param filterNames + */ + public void setFilterNames(String[] filterNames) { + this.filterNames = filterNames; + checkFilters(); + } + + public String[] getFilterNames() { + return this.filterNames; + } + + /** + * Checks if the filters are valid + */ + protected void checkFilters() { + if (filterExtensions != null && filterNames != null) { + selector.setFilters(filterExtensions, filterNames); + } + } + + /** + * Indicates whether the editor should allow browsing the workspace or not + * + * @param allowWorkspace + */ + public void setAllowWorkspace(boolean allowWorkspace) { + this.allowWorkspace = allowWorkspace; + selector.setAllowWorkspace(allowWorkspace); + } + + /** + * + * @return true if the editor can browse the workspace + */ + public boolean getAllowWorkspace() { + return allowWorkspace; + } + + /** + * Indicates whether the editor should allow browsing the file system or not + * + * @param allowFileSystem + */ + public void setAllowFileSystem(boolean allowFileSystem) { + this.allowFileSystem = allowFileSystem; + selector.setAllowFileSystem(allowFileSystem); + } + + /** + * + * @return true if the editor can browse the fileSystem + */ + public boolean getAllowFileSystem() { + return allowFileSystem; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelectorEMF.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelectorEMF.java new file mode 100644 index 00000000000..da526765234 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringFileSelectorEMF.java @@ -0,0 +1,58 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tessier (CEA LIST) - Initial API and implementation + /*****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import java.io.File; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.common.util.URI; +import org.eclipse.papyrus.infra.emf.utils.EMFFileUtil; +import org.eclipse.papyrus.infra.widgets.editors.StringFileSelector; +import org.eclipse.swt.widgets.Composite; + + +public class StringFileSelectorEMF extends StringFileSelector { + + public StringFileSelectorEMF(Composite parent, int style) { + super(parent, style); + } + + @Override + protected void setResult(IFile file) { + text.setText(EMFFileUtil.getPath(file)); + notifyChange(); + } + + @Override + protected void setResult(File file) { + setResult(file.getAbsolutePath()); + } + + @Override + protected void setResult(String path) { + URI uri = URI.createFileURI(path); + text.setText(uri.toString()); + notifyChange(); + } + + // @Override + protected IFile getIFile(String path) { + return EMFFileUtil.getIFile(path); + } + + // @Override + protected File getFile(String path) { + return EMFFileUtil.getFile(path); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringLabel.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringLabel.java new file mode 100644 index 00000000000..c193c5c9b94 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringLabel.java @@ -0,0 +1,61 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for displaying strings as a CLabel + * This editor is read-only + * + * @see org.eclipse.papyrus.infra.widgets.editors.StringLabel + * + * @author Camille Letavernier + */ +public class StringLabel extends AbstractPropertyEditor { + + private org.eclipse.papyrus.infra.widgets.editors.StringLabel editor; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public StringLabel(Composite parent, int style) { + editor = createStringLabel(parent, style); + setEditor(editor); + } + + /** + * Creates the string label dialog. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return The string label dialog. + */ + protected org.eclipse.papyrus.infra.widgets.editors.StringLabel createStringLabel(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.StringLabel(parent, style); + } + + @Override + protected void doBinding() { + ILabelProvider labelProvider = input.getLabelProvider(propertyPath); + editor.setLabelProvider(labelProvider); + super.doBinding(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMask.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMask.java new file mode 100644 index 00000000000..271a62662a1 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMask.java @@ -0,0 +1,114 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.papyrus.infra.properties.ui.providers.XWTCompliantMaskProvider; +import org.eclipse.papyrus.infra.properties.ui.providers.XWTCompliantMaskProviderListener; +import org.eclipse.swt.widgets.Composite; + +/** + * A widget to edit mask-based Integer values + * The integer value is interpreted as a list of boolean values + * The widget cannot use more than 32 masks + * + * @author Camille Letavernier + */ +public class StringMask extends AbstractPropertyEditor implements XWTCompliantMaskProviderListener { + + private org.eclipse.papyrus.infra.widgets.editors.StringMask editor; + + private XWTCompliantMaskProvider maskProvider; + + private boolean maskProviderReady = false; + + /** + * + * Constructor. + * + * @param parent + * The composite in which this widget will be created + * @param style + */ + public StringMask(Composite parent, int style) { + editor = createStringMask(parent, style); + setEditor(editor); + } + + /** + * Creates the integer mask. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the integer mask. + */ + protected org.eclipse.papyrus.infra.widgets.editors.StringMask createStringMask(Composite parent, int style) { + return new org.eclipse.papyrus.infra.widgets.editors.StringMask(parent, style); + } + + @Override + protected void checkInput() { + if (maskProvider != null && maskProviderReady) { + super.checkInput(); + } + } + + /** + * @return the number of columns for this editor + * + */ + public int getNumColumns() { + return editor.getNumColumns(); + } + + /** + * Sets the number of columns for this editor. The mask checkboxes will be + * distributed according to this number + * + * @param numColumns + */ + public void setNumColumns(int numColumns) { + editor.setNumColumns(numColumns); + } + + /** + * Sets the MaskProvider for this editor + * + * @param provider + */ + public void setMaskProvider(XWTCompliantMaskProvider provider) { + if (this.maskProvider != null) { + maskProvider.removeMaskProviderListener(this); + } + + maskProviderReady = false; + this.maskProvider = provider; + provider.addMaskProviderListener(this); + checkInput(); + } + + /** + * + * @return the MaskProvider associated to this editor + */ + public XWTCompliantMaskProvider getMaskProvider() { + return maskProvider; + } + + public void notifyReady(XWTCompliantMaskProvider provider) { + this.maskProviderReady = true; + editor.setMasks(maskProvider.getMasks()); + provider.removeMaskProviderListener(this); + checkInput(); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultiline.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultiline.java new file mode 100644 index 00000000000..51a5dc3578a --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultiline.java @@ -0,0 +1,38 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +/** + * A PropertyEditor for editing multiline strings through a Text field + * + * @see org.eclipse.papyrus.infra.widgets.editors.StringEditor + * + * @author Camille Letavernier + */ +public class StringMultiline extends AbstractPropertyEditor { + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public StringMultiline(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.StringEditor(parent, style | SWT.MULTI | SWT.V_SCROLL | SWT.WRAP)); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultilineWithReferences.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultilineWithReferences.java new file mode 100644 index 00000000000..87a30a6816e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/StringMultilineWithReferences.java @@ -0,0 +1,183 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import java.util.Iterator; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.emf.utils.TextReferencesHelper; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.DropTargetListener; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +/** + * + * A StringMultiline property editor with support for TextReferences + * + * @author Camille Letavernier + * + * @see {@link org.eclipse.papyrus.infra.emf.utils.TextReferencesHelper} + */ +public class StringMultilineWithReferences extends AbstractPropertyEditor { + + protected TextReferencesHelper textReferencesHelper; + + protected StringEditorWithReferences editor; + + public void setTextReferencesHelper(TextReferencesHelper helper) { + this.textReferencesHelper = helper; + editor.setTextReferencesHelper(helper); + installDropListener(); + } + + @Override + protected void doBinding() { + super.doBinding(); + IStaticContentProvider provider = input.getContentProvider(propertyPath); + if (provider != null) { + editor.setReferenceBrowserContentProvider(provider); + } + + if (getInputObservableValue() instanceof ICommitListener) { + editor.addCommitListener((ICommitListener) getInputObservableValue()); + } + } + + public StringMultilineWithReferences(Composite parent, int style) { + super(); + setEditor(editor = new StringEditorWithReferences(parent, style)); + } + + protected void installDropListener() { + DropTarget target = new DropTarget(getStringEditor().getText(), DND.DROP_LINK); + LocalSelectionTransfer selectionTransfer = LocalSelectionTransfer.getTransfer(); + target.setTransfer(new Transfer[] { selectionTransfer }); + target.addDropListener(new DropTargetListener() { + + public void dropAccept(DropTargetEvent event) { + } + + public void drop(DropTargetEvent event) { + IStructuredSelection dropSelection = getSelection(event); + if (dropSelection == null) { + return; + } + + Iterator selectionIterator = dropSelection.iterator(); + + Text textWidget = getStringEditor().getText(); + String textToEdit = textWidget.getText(); + int caretPosition = textWidget.getCaretPosition(); + while (selectionIterator.hasNext()) { + EObject selectedEObject = EMFHelper.getEObject(selectionIterator.next()); + if (selectedEObject == null) { + continue; + } + textToEdit = textReferencesHelper.insertReference(selectedEObject, textToEdit, caretPosition); + } + + textWidget.setText(textToEdit); + getStringEditor().setFocus(); + } + + public void dragOver(DropTargetEvent event) { + verifyDrop(event); + } + + public void dragOperationChanged(DropTargetEvent event) { + verifyDrop(event); + } + + public void dragLeave(DropTargetEvent event) { + } + + public void dragEnter(DropTargetEvent event) { + verifyDrop(event); + } + + private void verifyDrop(DropTargetEvent event) { + IStructuredSelection selection = getSelection(event); + if (isValidSelection(selection)) { + event.feedback = DND.FEEDBACK_INSERT_AFTER; + event.detail = DND.DROP_LINK; + } else { + event.detail = DND.DROP_NONE; + } + } + + private IStructuredSelection getSelection(DropTargetEvent event) { + if (!(event.getSource() instanceof DropTarget)) { + return null; + } + + DropTarget target = (DropTarget) event.getSource(); + + for (Transfer transfer : target.getTransfer()) { + if (transfer instanceof LocalSelectionTransfer) { + LocalSelectionTransfer selectionTransfer = (LocalSelectionTransfer) transfer; + ISelection selection = selectionTransfer.getSelection(); + if (selection instanceof IStructuredSelection) { + return (IStructuredSelection) selection; + } + } + } + + return null; + } + + private boolean isValidSelection(IStructuredSelection dropSelection) { + if (textReferencesHelper == null) { + return false; + } + if (dropSelection.isEmpty()) { + return false; + } + + IStructuredSelection structuredSelection = dropSelection; + Iterator selectionIterator = structuredSelection.iterator(); + while (selectionIterator.hasNext()) { + EObject selectedElement = EMFHelper.getEObject(selectionIterator.next()); + if (selectedElement == null) { + return false; + } + } + + return true; + } + }); + } + + protected org.eclipse.papyrus.infra.widgets.editors.StringEditor getStringEditor() { + return (org.eclipse.papyrus.infra.widgets.editors.StringEditor) valueEditor; + } + + protected void setContentProvider(IStaticContentProvider provider) { + editor.setReferenceBrowserContentProvider(provider); + } + + protected void setLabelProvider(ILabelProvider labelProvider) { + editor.setLabelProvider(labelProvider); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/UnlimitedNaturalEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/UnlimitedNaturalEditor.java new file mode 100644 index 00000000000..160fc1b4454 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/UnlimitedNaturalEditor.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Thibault Le Ouay t.leouay@sherpa-eng.com - Initial API and implementation + *****************************************************************************/ + +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +public class UnlimitedNaturalEditor extends AbstractPropertyEditor { + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public UnlimitedNaturalEditor(Composite parent, int style) { + super(new org.eclipse.papyrus.infra.widgets.editors.UnlimitedNaturalEditor(parent, style)); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ViewEditor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ViewEditor.java new file mode 100644 index 00000000000..193572fb0fa --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/ViewEditor.java @@ -0,0 +1,415 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 443417 + * Christian W. Damus (CEA) - bug 444227 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.properties.contexts.Context; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSourceChangedEvent; +import org.eclipse.papyrus.infra.properties.ui.modelelement.IDataSourceListener; +import org.eclipse.papyrus.infra.properties.ui.runtime.DefaultDisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.papyrus.infra.properties.ui.widgets.layout.PropertiesLayout; +import org.eclipse.papyrus.infra.properties.ui.xwt.XWTSection; +import org.eclipse.papyrus.infra.tools.databinding.IMultipleObservableValue; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ScrollBar; + +/** + * An Editor for displaying a whole property {@link View} on a sub-object. + * If the property is a list, there will be one view per element in the list. + * + * The view's tabs will be ignored : the sections are embedded in the caller's + * tab. + */ +public class ViewEditor extends AbstractPropertyEditor { + + private String viewPath; + + private Composite self; + + private Map sections = new HashMap(); + + private DisplayEngine displayEngine; + + private IDataSourceListener dataSourceListener; + + /** + * Constructor. + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + */ + public ViewEditor(Composite parent, int style) { + self = new Composite(parent, SWT.NONE); + PropertiesLayout layout = new PropertiesLayout(1, true); + layout.horizontalSpacing = 0; + layout.marginWidth = 0; + self.setLayout(layout); + + addDisposeListener(self); + } + + private void addDisposeListener(Control control) { + control.addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + disposeDisplayEngine(); + } + }); + } + + private void disposeDisplayEngine() { + if (displayEngine != null) { + displayEngine.dispose(); + displayEngine = null; + sections.clear(); + } + } + + @Override + public void checkInput() { + if (propertyPath != null && input != null && viewPath != null) { + display(); + } + } + + @Override + protected void unhookDataSourceListener(DataSource oldInput) { + oldInput.removeDataSourceListener(getDataSourceListener()); + super.unhookDataSourceListener(oldInput); + } + + @Override + protected void hookDataSourceListener(DataSource newInput) { + super.hookDataSourceListener(newInput); + newInput.addDataSourceListener(getDataSourceListener()); + } + + private IDataSourceListener getDataSourceListener() { + if (dataSourceListener == null) { + dataSourceListener = new IDataSourceListener() { + + @Override + public void dataSourceChanged(DataSourceChangedEvent event) { + // The data source's selection changed. Re-display our nested sections, if appropriate + if ((self != null) && !self.isDisposed()) { + self.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if (!self.isDisposed()) { + checkInput(); + } + } + }); + } + } + }; + } + + return dataSourceListener; + } + + /** + * Sets the number of columns for this editor. If the property is a list, + * there will be one view per element in the list : these views will be + * distributed in the given number of columns. + * + * @param numColumns + */ + public void setNumColumns(int numColumns) { + ((PropertiesLayout) self.getLayout()).numColumns = numColumns; + } + + /** + * @return the number of columns for this editor. + */ + public int getNumColumns() { + return ((PropertiesLayout) self.getLayout()).numColumns; + } + + /** + * Sets the view for this editor. The view is represented by its viewPath, which is + * of form ContextName:ViewName + * e.g. : UML:Class + * The Context should be registered in the ConfigurationManager + * + * @param viewPath + * The path of the view used to display the given property + */ + public void setView(String viewPath) { + this.viewPath = viewPath; + checkInput(); + } + + /** + * @return the qualified name of the view associated to this editor + */ + public String getView() { + return viewPath; + } + + private View resolveView() { + String contextName = viewPath.substring(0, viewPath.indexOf(":")); //$NON-NLS-1$ + String viewName = viewPath.substring(viewPath.indexOf(":") + 1); //$NON-NLS-1$ + Context context = PropertiesRuntime.getConfigurationManager().getContext(contextName); + for (View view : context.getViews()) { + if (view.getName().equals(viewName)) { + return view; + } + } + return null; + } + + private void display() { + View view = resolveView(); + + if (view == null) { + Activator.log.warn("Unabled to resolve view : " + viewPath); //$NON-NLS-1$ + return; + } + + IObservable observable = getInputObservable(); + if (observable == null) { + return; + } + + if (displayEngine == null) { + displayEngine = new DefaultDisplayEngine(false); + } + + // We need to be able to repeat sections, so use an arbitrary discriminator to + // present the same section multiple times as distinct sections + int index = 0; + if (observable instanceof IObservableValue) { + IObservableValue observableValue = (IObservableValue) observable; + if (observableValue instanceof IMultipleObservableValue) { + IMultipleObservableValue multipleObservable = (IMultipleObservableValue) observableValue; + display(displayEngine, multipleObservable.getObservedValues(), view, index++); + } else { + Object value = observableValue.getValue(); + display(displayEngine, value, view, index++); + } + } else if (observable instanceof IObservableList) { + IObservableList observableList = (IObservableList) observable; + for (Object value : observableList) { + display(displayEngine, value, view, index++); + } + } + + // Any repeated sections that we had created for a previous selection and no longer need must be destroyed + purgeUnusedSections(index); + + // A hack to force the containing scroll pane, if any (we expect to have one in the property sheet), to + // recompute its client area and scrollbars + for (Composite next = self; (next != null); next = next.getParent()) { + if (next.getParent() instanceof ScrolledComposite) { + final ScrolledComposite scrolled = (ScrolledComposite) next.getParent(); + next.layout(); + scrolled.layout(); + scrolled.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if (scrolled.isDisposed()) { + return; + } + resizeScrolledComposite(scrolled); + } + }); + } + } + + updateControls(); + } + + private void purgeUnusedSections(int maxDiscriminator) { + for (Iterator
iter = sections.keySet().iterator(); iter.hasNext();) { + Section section = iter.next(); + Object discriminator = DefaultDisplayEngine.getDiscriminator(section); + if ((discriminator instanceof Number) && (((Number) discriminator).intValue() >= maxDiscriminator)) { + sections.get(section).dispose(); + iter.remove(); + } + } + } + + /** + * Recompute the size of a {@code scrolled} composite's client area and adjust its scroll bars accordingly. + * + * @param scrolled + * a scrolled composite to force to adapt to a new layout + */ + private void resizeScrolledComposite(ScrolledComposite scrolled) { + Point sizeConstraint = scrolled.getContent().getSize(); + sizeConstraint = scrolled.getContent().computeSize(SWT.DEFAULT, SWT.DEFAULT); + scrolled.setMinSize(sizeConstraint); + + Rectangle clientArea = scrolled.getClientArea(); + + ScrollBar vbar = scrolled.getVerticalBar(); + if (vbar != null) { + vbar.setPageIncrement(clientArea.height - 5); + } + + ScrollBar hbar = scrolled.getHorizontalBar(); + if (hbar != null) { + hbar.setPageIncrement(clientArea.width - 5); + } + } + + /** + * Displays the given view in the display engine, with the given object. + * + * @param display + * The Display engine used to display the view. It should allow duplication, + * as for list properties, the same section will be displayed for each element + * in the list. + * @param data + * The raw object for which we are displaying the view. + * @param view + * The view to display + */ + protected void display(DisplayEngine display, Object data, View view, Object discriminator) { + display(display, Collections.singletonList(data), view, discriminator); + } + + /** + * Displays the given view in the display engine, with the given object. + * + * @param display + * The Display engine used to display the view. It should allow duplication, + * as for list properties, the same section will be displayed for each element + * in the list. + * @param selectedElements + * The list of objects for which we are displaying the view + * @param view + * The view to display + */ + protected void display(DisplayEngine display, List selectedElements, View view, Object discriminator) { + for (Section section : view.getSections()) { + // Distinguish this occurrence of the section + section = DefaultDisplayEngine.discriminate(section, discriminator); + + EditorSection editorSection = sections.get(section); + if (editorSection == null) { + editorSection = new EditorSection(new XWTSection(section, view, display)); + sections.put(section, editorSection); + } + + ISelection selection = new StructuredSelection(selectedElements); + + editorSection.setInput(selection); + } + } + + /** + * Updates the displayed widgets to mark them as readOnly if needed. + */ + protected void updateControls() { + for (Control container : self.getChildren()) { + // TODO : Browse recursively ? + if (container instanceof Composite) { + for (Control control : ((Composite) container).getChildren()) { + if (control instanceof AbstractEditor) { + AbstractEditor editor = (AbstractEditor) control; + editor.setReadOnly(getReadOnly() || editor.isReadOnly()); + } + } + } + } + + self.setEnabled(!getReadOnly()); + } + + @Override + protected IObservable getInputObservable() { + // Override the generic behavior: ViewEditor doesn't rely on an AbstractEditor + return input.getObservable(propertyPath); + } + + @Override + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + updateControls(); + } + + @Override + protected void doBinding() { + // Nothing to do here + } + + @Override + public Control getControl() { + return self; + } + + // + // Nested types + // + + /** + * An encapsulation of an XWT section with the composite that contains it within the {@link ViewEditor}'s parent composite. + */ + private class EditorSection { + private final XWTSection xwt; + private final Composite sectionComposite; + + EditorSection(XWTSection xwt) { + this.xwt = xwt; + this.sectionComposite = new Composite(self, SWT.NONE); + + xwt.createControls(sectionComposite, null); + } + + void dispose() { + if (!sectionComposite.isDisposed()) { + xwt.dispose(); + sectionComposite.dispose(); + } + } + + void setInput(ISelection selection) { + xwt.setInput(null, selection); + xwt.refresh(); + } + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/XWTStringFileSelectorEMF.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/XWTStringFileSelectorEMF.java new file mode 100644 index 00000000000..d83afe860ea --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/XWTStringFileSelectorEMF.java @@ -0,0 +1,48 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets; + +import org.eclipse.swt.widgets.Composite; + +/** + * A Widget for selecting Files on the workspace or on the file system. + * The widgets only edits String values : it uses the path of the files + * + * @author Camille Letavernier + */ +public class XWTStringFileSelectorEMF extends StringFileSelector { + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public XWTStringFileSelectorEMF(Composite parent, int style) { + super(parent, style); + } + + /** + * Creates the selector + * + * @param parent + * The composite in which the widget will be displayed + * @param style + * The style for the widget + * @return the selector + */ + @Override + protected StringFileSelectorEMF createSelector(Composite parent, int style) { + return new StringFileSelectorEMF(parent, style); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/GridData.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/GridData.java new file mode 100644 index 00000000000..95c7248ef18 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/GridData.java @@ -0,0 +1,651 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation (org.eclipse.swt.layout.GridData) + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr + *******************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets.layout; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; + +/** + * GridData is the layout data object associated with GridLayout. To set a GridData object into a + * control, you use the Control.setLayoutData(Object) method. + *

+ * There are two ways to create a GridData object with certain fields set. The first is to set the fields directly, like this: + * + *

+ * GridData gridData = new GridData();
+ * gridData.horizontalAlignment = GridData.FILL;
+ * gridData.grabExcessHorizontalSpace = true;
+ * button1.setLayoutData(gridData);
+ *
+ * gridData = new GridData();
+ * gridData.horizontalAlignment = GridData.FILL;
+ * gridData.verticalAlignment = GridData.FILL;
+ * gridData.grabExcessHorizontalSpace = true;
+ * gridData.grabExcessVerticalSpace = true;
+ * gridData.horizontalSpan = 2;
+ * button2.setLayoutData(gridData);
+ * 
+ * + * The second is to take advantage of GridData convenience constructors, for example: + * + *
+ * button1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ * button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+ * 
+ * + *

+ *

+ * NOTE: Do not reuse GridData objects. Every control in a Composite that is managed by a GridLayout must have a unique GridData object. If the layout data for a control in a GridLayout is null + * at layout time, a unique GridData object is created for it. + *

+ * + * @see PropertiesLayout + * @see Control#setLayoutData + * @see Sample code and further information + * @see org.eclipse.swt.layout.GridData + */ +public final class GridData { + + /** + * verticalAlignment specifies how controls will be positioned + * vertically within a cell. + * + * The default value is CENTER. + * + * Possible values are: + *
    + *
  • SWT.BEGINNING (or SWT.TOP): Position the control at the top of the cell
  • + *
  • SWT.CENTER: Position the control in the vertical center of the cell
  • + *
  • SWT.END (or SWT.BOTTOM): Position the control at the bottom of the cell
  • + *
  • SWT.FILL: Resize the control to fill the cell vertically
  • + *
+ */ + public int verticalAlignment = CENTER; + + /** + * horizontalAlignment specifies how controls will be positioned + * horizontally within a cell. + * + * The default value is BEGINNING. + * + * Possible values are: + *
    + *
  • SWT.BEGINNING (or SWT.LEFT): Position the control at the left of the cell
  • + *
  • SWT.CENTER: Position the control in the horizontal center of the cell
  • + *
  • SWT.END (or SWT.RIGHT): Position the control at the right of the cell
  • + *
  • SWT.FILL: Resize the control to fill the cell horizontally
  • + *
+ */ + public int horizontalAlignment = BEGINNING; + + /** + * widthHint specifies the preferred width in pixels. This value + * is the wHint passed into Control.computeSize(int, int, boolean) + * to determine the preferred size of the control. + * + * The default value is SWT.DEFAULT. + * + * @see Control#computeSize(int, int, boolean) + */ + public int widthHint = SWT.DEFAULT; + + /** + * heightHint specifies the preferred height in pixels. This value + * is the hHint passed into Control.computeSize(int, int, boolean) + * to determine the preferred size of the control. + * + * The default value is SWT.DEFAULT. + * + * @see Control#computeSize(int, int, boolean) + */ + public int heightHint = SWT.DEFAULT; + + /** + * horizontalIndent specifies the number of pixels of indentation + * that will be placed along the left side of the cell. + * + * The default value is 0. + */ + public int horizontalIndent = 0; + + /** + * verticalIndent specifies the number of pixels of indentation + * that will be placed along the top side of the cell. + * + * The default value is 0. + * + * @since 3.1 + */ + public int verticalIndent = 0; + + /** + * horizontalSpan specifies the number of column cells that the control + * will take up. + * + * The default value is 1. + */ + public int horizontalSpan = 1; + + /** + * verticalSpan specifies the number of row cells that the control + * will take up. + * + * The default value is 1. + */ + public int verticalSpan = 1; + + /** + *

+ * grabExcessHorizontalSpace specifies whether the width of the cell changes depending on the size of the parent Composite. If grabExcessHorizontalSpace is true, the following rules apply to the width of the cell: + *

+ *
    + *
  • If extra horizontal space is available in the parent, the cell will grow to be wider than its preferred width. The new width will be "preferred width + delta" where delta is the extra horizontal space divided by the number of grabbing columns.
  • + *
  • If there is not enough horizontal space available in the parent, the cell will shrink until it reaches its minimum width as specified by GridData.minimumWidth. The new width will be the maximum of "minimumWidth" and "preferred width - delta", where + * delta is the amount of space missing divided by the number of grabbing columns.
  • + *
  • If the parent is packed, the cell will be its preferred width as specified by GridData.widthHint.
  • + *
  • If the control spans multiple columns and there are no other grabbing controls in any of the spanned columns, the last column in the span will grab the extra space. If there is at least one other grabbing control in the span, the grabbing will be + * spread over the columns already marked as grabExcessHorizontalSpace.
  • + *
+ * + *

+ * The default value is false. + *

+ * + * @see GridData#minimumWidth + * @see GridData#widthHint + */ + public boolean grabExcessHorizontalSpace = false; + + /** + *

+ * grabExcessVerticalSpace specifies whether the height of the cell changes depending on the size of the parent Composite. If grabExcessVerticalSpace is true, the following rules apply to the height of the cell: + *

+ *
    + *
  • If extra vertical space is available in the parent, the cell will grow to be taller than its preferred height. The new height will be "preferred height + delta" where delta is the extra vertical space divided by the number of grabbing rows.
  • + *
  • If there is not enough vertical space available in the parent, the cell will shrink until it reaches its minimum height as specified by GridData.minimumHeight. The new height will be the maximum of "minimumHeight" and "preferred height - delta", + * where delta is the amount of space missing divided by the number of grabbing rows.
  • + *
  • If the parent is packed, the cell will be its preferred height as specified by GridData.heightHint.
  • + *
  • If the control spans multiple rows and there are no other grabbing controls in any of the spanned rows, the last row in the span will grab the extra space. If there is at least one other grabbing control in the span, the grabbing will be spread over + * the rows already marked as grabExcessVerticalSpace.
  • + *
+ * + *

+ * The default value is false. + *

+ * + * @see GridData#minimumHeight + * @see GridData#heightHint + */ + public boolean grabExcessVerticalSpace = false; + + /** + * minimumWidth specifies the minimum width in pixels. This value + * applies only if grabExcessHorizontalSpace is true. A value of + * SWT.DEFAULT means that the minimum width will be the result + * of Control.computeSize(int, int, boolean) where wHint is + * determined by GridData.widthHint. + * + * The default value is 0. + * + * @since 3.1 + * @see Control#computeSize(int, int, boolean) + * @see GridData#widthHint + */ + public int minimumWidth = 0; + + /** + * minimumHeight specifies the minimum height in pixels. This value + * applies only if grabExcessVerticalSpace is true. A value of + * SWT.DEFAULT means that the minimum height will be the result + * of Control.computeSize(int, int, boolean) where hHint is + * determined by GridData.heightHint. + * + * The default value is 0. + * + * @since 3.1 + * @see Control#computeSize(int, int, boolean) + * @see GridData#heightHint + */ + public int minimumHeight = 0; + + /** + * exclude informs the layout to ignore this control when sizing + * and positioning controls. If this value is true, + * the size and position of the control will not be managed by the + * layout. If this value is false, the size and + * position of the control will be computed and assigned. + * + * The default value is false. + * + * @since 3.1 + */ + public boolean exclude = false; + + /** + * Value for horizontalAlignment or verticalAlignment. + * Position the control at the top or left of the cell. + * Not recommended. Use SWT.BEGINNING, SWT.TOP or SWT.LEFT instead. + */ + public static final int BEGINNING = SWT.BEGINNING; + + /** + * Value for horizontalAlignment or verticalAlignment. + * Position the control in the vertical or horizontal center of the cell + * Not recommended. Use SWT.CENTER instead. + */ + public static final int CENTER = 2; + + /** + * Value for horizontalAlignment or verticalAlignment. + * Position the control at the bottom or right of the cell + * Not recommended. Use SWT.END, SWT.BOTTOM or SWT.RIGHT instead. + */ + public static final int END = 3; + + /** + * Value for horizontalAlignment or verticalAlignment. + * Resize the control to fill the cell horizontally or vertically. + * Not recommended. Use SWT.FILL instead. + */ + public static final int FILL = SWT.FILL; + + /** + * Style bit for new GridData(int). + * Position the control at the top of the cell. + * Not recommended. Use new GridData(int, SWT.BEGINNING, boolean, boolean) instead. + */ + public static final int VERTICAL_ALIGN_BEGINNING = 1 << 1; + + /** + * Style bit for new GridData(int) to position the + * control in the vertical center of the cell. + * Not recommended. Use new GridData(int, SWT.CENTER, boolean, boolean) instead. + */ + public static final int VERTICAL_ALIGN_CENTER = 1 << 2; + + /** + * Style bit for new GridData(int) to position the + * control at the bottom of the cell. + * Not recommended. Use new GridData(int, SWT.END, boolean, boolean) instead. + */ + public static final int VERTICAL_ALIGN_END = 1 << 3; + + /** + * Style bit for new GridData(int) to resize the + * control to fill the cell vertically. + * Not recommended. Use new GridData(int, SWT.FILL, boolean, boolean) instead + */ + public static final int VERTICAL_ALIGN_FILL = 1 << 4; + + /** + * Style bit for new GridData(int) to position the + * control at the left of the cell. + * Not recommended. Use new GridData(SWT.BEGINNING, int, boolean, boolean) instead. + */ + public static final int HORIZONTAL_ALIGN_BEGINNING = 1 << 5; + + /** + * Style bit for new GridData(int) to position the + * control in the horizontal center of the cell. + * Not recommended. Use new GridData(SWT.CENTER, int, boolean, boolean) instead. + */ + public static final int HORIZONTAL_ALIGN_CENTER = 1 << 6; + + /** + * Style bit for new GridData(int) to position the + * control at the right of the cell. + * Not recommended. Use new GridData(SWT.END, int, boolean, boolean) instead. + */ + public static final int HORIZONTAL_ALIGN_END = 1 << 7; + + /** + * Style bit for new GridData(int) to resize the + * control to fill the cell horizontally. + * Not recommended. Use new GridData(SWT.FILL, int, boolean, boolean) instead. + */ + public static final int HORIZONTAL_ALIGN_FILL = 1 << 8; + + /** + * Style bit for new GridData(int) to resize the + * control to fit the remaining horizontal space. + * Not recommended. Use new GridData(int, int, true, boolean) instead. + */ + public static final int GRAB_HORIZONTAL = 1 << 9; + + /** + * Style bit for new GridData(int) to resize the + * control to fit the remaining vertical space. + * Not recommended. Use new GridData(int, int, boolean, true) instead. + */ + public static final int GRAB_VERTICAL = 1 << 10; + + /** + * Style bit for new GridData(int) to resize the + * control to fill the cell vertically and to fit the remaining + * vertical space. + * FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL + * Not recommended. Use new GridData(int, SWT.FILL, boolean, true) instead. + */ + public static final int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL; + + /** + * Style bit for new GridData(int) to resize the + * control to fill the cell horizontally and to fit the remaining + * horizontal space. + * FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL + * Not recommended. Use new GridData(SWT.FILL, int, true, boolean) instead. + */ + public static final int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL; + + /** + * Style bit for new GridData(int) to resize the + * control to fill the cell horizontally and vertically and + * to fit the remaining horizontal and vertical space. + * FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL + * Not recommended. Use new GridData(SWT.FILL, SWT.FILL, true, true) instead. + */ + public static final int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL; + + protected int cacheWidth = -1, cacheHeight = -1; + + protected int defaultWhint, defaultHhint, defaultWidth = -1, defaultHeight = -1; + + public int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1; + + /** + * Constructs a new instance of GridData using + * default values. + */ + public GridData() { + super(); + } + + /** + * Constructs a new instance based on the GridData style. + * This constructor is not recommended. + * + * @param style + * the GridData style + */ + public GridData(int style) { + super(); + if ((style & VERTICAL_ALIGN_BEGINNING) != 0) { + verticalAlignment = BEGINNING; + } + if ((style & VERTICAL_ALIGN_CENTER) != 0) { + verticalAlignment = CENTER; + } + if ((style & VERTICAL_ALIGN_FILL) != 0) { + verticalAlignment = FILL; + } + if ((style & VERTICAL_ALIGN_END) != 0) { + verticalAlignment = END; + } + if ((style & HORIZONTAL_ALIGN_BEGINNING) != 0) { + horizontalAlignment = BEGINNING; + } + if ((style & HORIZONTAL_ALIGN_CENTER) != 0) { + horizontalAlignment = CENTER; + } + if ((style & HORIZONTAL_ALIGN_FILL) != 0) { + horizontalAlignment = FILL; + } + if ((style & HORIZONTAL_ALIGN_END) != 0) { + horizontalAlignment = END; + } + grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) != 0; + grabExcessVerticalSpace = (style & GRAB_VERTICAL) != 0; + } + + /** + * Constructs a new instance of GridData according to the parameters. + * + * @param horizontalAlignment + * how control will be positioned horizontally within a cell, + * one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL + * @param verticalAlignment + * how control will be positioned vertically within a cell, + * one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL + * @param grabExcessHorizontalSpace + * whether cell will be made wide enough to fit the remaining horizontal space + * @param grabExcessVerticalSpace + * whether cell will be made high enough to fit the remaining vertical space + * + * @since 3.0 + */ + public GridData(int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace) { + this(horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1); + } + + /** + * Constructs a new instance of GridData according to the parameters. + * + * @param horizontalAlignment + * how control will be positioned horizontally within a cell, + * one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL + * @param verticalAlignment + * how control will be positioned vertically within a cell, + * one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL + * @param grabExcessHorizontalSpace + * whether cell will be made wide enough to fit the remaining horizontal space + * @param grabExcessVerticalSpace + * whether cell will be made high enough to fit the remaining vertical space + * @param horizontalSpan + * the number of column cells that the control will take up + * @param verticalSpan + * the number of row cells that the control will take up + * + * @since 3.0 + */ + public GridData(int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) { + super(); + this.horizontalAlignment = horizontalAlignment; + this.verticalAlignment = verticalAlignment; + this.grabExcessHorizontalSpace = grabExcessHorizontalSpace; + this.grabExcessVerticalSpace = grabExcessVerticalSpace; + this.horizontalSpan = horizontalSpan; + this.verticalSpan = verticalSpan; + } + + /** + * Constructs a new instance of GridData according to the parameters. + * A value of SWT.DEFAULT indicates that no minimum width or + * no minimum height is specified. + * + * @param width + * a minimum width for the column + * @param height + * a minimum height for the row + * + * @since 3.0 + */ + public GridData(int width, int height) { + super(); + this.widthHint = width; + this.heightHint = height; + } + + /** + * Creates a new Properties GridData from a SWT GridData + * + * @param layoutData + * The SWT GridData to copy + */ + public GridData(org.eclipse.swt.layout.GridData layoutData) { + this.exclude = layoutData.exclude; + this.grabExcessHorizontalSpace = layoutData.grabExcessHorizontalSpace; + this.grabExcessVerticalSpace = layoutData.grabExcessVerticalSpace; + this.heightHint = layoutData.heightHint; + this.horizontalAlignment = layoutData.horizontalAlignment; + this.horizontalIndent = layoutData.horizontalIndent; + this.horizontalSpan = layoutData.horizontalSpan; + this.minimumHeight = layoutData.minimumHeight; + this.minimumWidth = layoutData.minimumWidth; + this.verticalAlignment = layoutData.verticalAlignment; + this.verticalIndent = layoutData.verticalIndent; + this.verticalSpan = layoutData.verticalSpan; + this.widthHint = layoutData.widthHint; + + } + + protected void computeSize(Control control, int wHint, int hHint, boolean flushCache) { + if (cacheWidth != -1 && cacheHeight != -1) { + return; + } + if (wHint == this.widthHint && hHint == this.heightHint) { + if (defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != defaultHhint) { + Point size = control.computeSize(wHint, hHint, flushCache); + defaultWhint = wHint; + defaultHhint = hHint; + defaultWidth = size.x; + defaultHeight = size.y; + } + cacheWidth = defaultWidth; + cacheHeight = defaultHeight; + return; + } + if (currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != currentHhint) { + Point size = control.computeSize(wHint, hHint, flushCache); + currentWhint = wHint; + currentHhint = hHint; + currentWidth = size.x; + currentHeight = size.y; + } + cacheWidth = currentWidth; + cacheHeight = currentHeight; + } + + protected void flushCache() { + cacheWidth = cacheHeight = -1; + defaultWidth = defaultHeight = -1; + currentWidth = currentHeight = -1; + } + + protected String getName() { + String string = getClass().getName(); + int index = string.lastIndexOf('.'); + if (index == -1) { + return string; + } + return string.substring(index + 1, string.length()); + } + + /** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the GridData object + */ + @Override + public String toString() { + String hAlign = ""; //$NON-NLS-1$ + switch (horizontalAlignment) { + case SWT.FILL: + hAlign = "SWT.FILL"; //$NON-NLS-1$ + break; + case SWT.BEGINNING: + hAlign = "SWT.BEGINNING"; //$NON-NLS-1$ + break; + case SWT.LEFT: + hAlign = "SWT.LEFT"; //$NON-NLS-1$ + break; + case SWT.END: + hAlign = "SWT.END"; //$NON-NLS-1$ + break; + case END: + hAlign = "GridData.END"; //$NON-NLS-1$ + break; + case SWT.RIGHT: + hAlign = "SWT.RIGHT"; //$NON-NLS-1$ + break; + case SWT.CENTER: + hAlign = "SWT.CENTER"; //$NON-NLS-1$ + break; + case CENTER: + hAlign = "GridData.CENTER"; //$NON-NLS-1$ + break; + default: + hAlign = "Undefined " + horizontalAlignment; //$NON-NLS-1$ + break; + } + String vAlign = ""; //$NON-NLS-1$ + switch (verticalAlignment) { + case SWT.FILL: + vAlign = "SWT.FILL"; //$NON-NLS-1$ + break; + case SWT.BEGINNING: + vAlign = "SWT.BEGINNING"; //$NON-NLS-1$ + break; + case SWT.TOP: + vAlign = "SWT.TOP"; //$NON-NLS-1$ + break; + case SWT.END: + vAlign = "SWT.END"; //$NON-NLS-1$ + break; + case END: + vAlign = "GridData.END"; //$NON-NLS-1$ + break; + case SWT.BOTTOM: + vAlign = "SWT.BOTTOM"; //$NON-NLS-1$ + break; + case SWT.CENTER: + vAlign = "SWT.CENTER"; //$NON-NLS-1$ + break; + case CENTER: + vAlign = "GridData.CENTER"; //$NON-NLS-1$ + break; + default: + vAlign = "Undefined " + verticalAlignment; //$NON-NLS-1$ + break; + } + String string = getName() + " {"; //$NON-NLS-1$ + string += "horizontalAlignment=" + hAlign + " "; //$NON-NLS-1$ //$NON-NLS-2$ + if (horizontalIndent != 0) { + string += "horizontalIndent=" + horizontalIndent + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (horizontalSpan != 1) { + string += "horizontalSpan=" + horizontalSpan + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (grabExcessHorizontalSpace) { + string += "grabExcessHorizontalSpace=" + grabExcessHorizontalSpace + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (widthHint != SWT.DEFAULT) { + string += "widthHint=" + widthHint + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (minimumWidth != 0) { + string += "minimumWidth=" + minimumWidth + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + string += "verticalAlignment=" + vAlign + " "; //$NON-NLS-1$ //$NON-NLS-2$ + if (verticalIndent != 0) { + string += "verticalIndent=" + verticalIndent + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (verticalSpan != 1) { + string += "verticalSpan=" + verticalSpan + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (grabExcessVerticalSpace) { + string += "grabExcessVerticalSpace=" + grabExcessVerticalSpace + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (heightHint != SWT.DEFAULT) { + string += "heightHint=" + heightHint + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (minimumHeight != 0) { + string += "minimumHeight=" + minimumHeight + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (exclude) { + string += "exclude=" + exclude + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + string = string.trim(); + string += "}"; //$NON-NLS-1$ + return string; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/PropertiesLayout.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/PropertiesLayout.java new file mode 100644 index 00000000000..67f76691729 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/widgets/layout/PropertiesLayout.java @@ -0,0 +1,961 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation (org.eclipse.swt.layout.GridLayout) + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Default values for GridData + *******************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.widgets.layout; + +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Scrollable; + +/** + * Layout based on {@link org.eclipse.swt.layout.GridLayout} This layout is basically the same as GridLayout, except for default values (Especially + * the default GridData) + * If an element doesn't have a GridData, a default one is created, which takes as much horizontal space as possible. + * The goal is to enable a nice layout for the Property View, without requiring each Control to have an explicit GridData + * However, explicit GridData are still supported. + * + * Instances of this class lay out the control children of a Composite in a grid. + *

+ * GridLayout has a number of configuration fields, and the controls it lays out can have an associated layout data object, called GridData. The power of GridLayout lies in the ability to configure GridData + * for each control in the layout. + *

+ *

+ * The following code creates a shell managed by a GridLayout with 3 columns: + * + *

+ * Display display = new Display();
+ * Shell shell = new Shell(display);
+ * GridLayout gridLayout = new GridLayout();
+ * gridLayout.numColumns = 3;
+ * shell.setLayout(gridLayout);
+ * 
+ * + * The numColumns field is the most important field in a GridLayout. Widgets are laid out in columns from left to right, and a new row is created when numColumns + 1 controls are added to the Composite. + *

+ * + * @see GridData + * @see GridLayout snippets + * @see SWT Example: LayoutExample + * @see Sample code and further information + * @see org.eclipse.swt.layout.GridLayout + */ +public class PropertiesLayout extends Layout { + + /** + * numColumns specifies the number of cell columns in the layout. + * If numColumns has a value less than 1, the layout will not + * set the size and position of any controls. + * + * The default value is 1. + */ + public int numColumns = 1; + + /** + * The adjusted number of columns + * If the number of controls is lower than the number of columns, + * some columns will be removed to let these controls take all + * the available space + * GridData#horizontalSpan is taken into account + */ + private int adjustedNumColumns = 1; + + /** + * makeColumnsEqualWidth specifies whether all columns in the layout + * will be forced to have the same width. + * + * The default value is true. + */ + public boolean makeColumnsEqualWidth = true; + + /** + * marginWidth specifies the number of pixels of horizontal margin + * that will be placed along the left and right edges of the layout. + * + * The default value is 5. + */ + public int marginWidth = 5; + + /** + * marginHeight specifies the number of pixels of vertical margin + * that will be placed along the top and bottom edges of the layout. + * + * The default value is 0. + */ + public int marginHeight = 0; + + /** + * marginLeft specifies the number of pixels of horizontal margin + * that will be placed along the left edge of the layout. + * + * The default value is 0. + * + * @since 3.1 + */ + public int marginLeft = 0; + + /** + * marginTop specifies the number of pixels of vertical margin + * that will be placed along the top edge of the layout. + * + * The default value is 0. + * + * @since 3.1 + */ + public int marginTop = 0; + + /** + * marginRight specifies the number of pixels of horizontal margin + * that will be placed along the right edge of the layout. + * + * The default value is 0. + * + * @since 3.1 + */ + public int marginRight = 0; + + /** + * marginBottom specifies the number of pixels of vertical margin + * that will be placed along the bottom edge of the layout. + * + * The default value is 0. + * + * @since 3.1 + */ + public int marginBottom = 0; + + /** + * horizontalSpacing specifies the number of pixels between the right + * edge of one cell and the left edge of its neighbouring cell to + * the right. + * + * The default value is 5. + */ + public int horizontalSpacing = 5; + + /** + * verticalSpacing specifies the number of pixels between the bottom + * edge of one cell and the top edge of its neighbouring cell underneath. + * + * The default value is 0. + */ + public int verticalSpacing = 0; + + /** + * Constructs a new instance of this class. + */ + public PropertiesLayout() { + this(false); + } + + /** + * + * Constructor. + * + * @param useMargins + * If false, there won't be any margin. If true, default margins + * will be used + */ + public PropertiesLayout(boolean useMargins) { + if (!useMargins) { + marginHeight = 0; + marginWidth = 0; + } + } + + /** + * Constructs a new instance of this class given the + * number of columns, and whether or not the columns + * should be forced to have the same width. + * If numColumns has a value less than 1, the layout will not + * set the size and position of any controls. + * + * @param numColumns + * the number of columns in the grid + * @param makeColumnsEqualWidth + * whether or not the columns will have equal width + * + * @since 2.0 + */ + public PropertiesLayout(int numColumns, boolean makeColumnsEqualWidth) { + this(numColumns, makeColumnsEqualWidth, false); + } + + /** + * + * Constructor. + * + * @param numColumns + * the number of columns in the grid + * @param makeColumnsEqualWidth + * whether or not the columns will have equal width + * @param useMargins + * If false, there won't be any margin. If true, default margins + * will be used + */ + public PropertiesLayout(int numColumns, boolean makeColumnsEqualWidth, boolean useMargins) { + this(useMargins); + this.numColumns = numColumns; + this.makeColumnsEqualWidth = makeColumnsEqualWidth; + } + + @Override + protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { + Point size = layout(composite, false, 0, 0, wHint, hHint, flushCache); + if (wHint != SWT.DEFAULT) { + size.x = wHint; + } + if (hHint != SWT.DEFAULT) { + size.y = hHint; + } + return size; + } + + @Override + protected boolean flushCache(Control control) { + GridData data = getLayoutData(control); + if (data != null) { + data.flushCache(); + } + return true; + } + + protected GridData getData(Control[][] grid, int row, int column, int rowCount, int columnCount, boolean first) { + Control control = grid[row][column]; + if (control != null) { + GridData data = getLayoutData(control); + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + int vSpan = Math.max(1, data.verticalSpan); + int i = first ? row + vSpan - 1 : row - vSpan + 1; + int j = first ? column + hSpan - 1 : column - hSpan + 1; + if (0 <= i && i < rowCount) { + if (0 <= j && j < columnCount) { + if (control == grid[i][j]) { + return data; + } + } + } + } + return null; + } + + @Override + protected void layout(Composite composite, boolean flushCache) { + Rectangle rect = composite.getClientArea(); + layout(composite, true, rect.x, rect.y, rect.width, rect.height, flushCache); + } + + /** + * Removes columns when there are less controls than columns, + * to take all the available space + * + * @param composite + */ + protected void adjustColumns(Composite composite) { + int numChildren = composite.getChildren().length; + adjustedNumColumns = numColumns; + + if (numChildren < numColumns) { + int totalColumns = 0; + + for (Control child : composite.getChildren()) { + GridData data = getLayoutData(child); + totalColumns += data.horizontalSpan; + } + + if (totalColumns < numColumns) { + adjustedNumColumns = totalColumns; + } + } + + if (adjustedNumColumns < 1) { + adjustedNumColumns = 1; + } + } + + protected Point layout(Composite composite, boolean move, int x, int y, int width, int height, boolean flushCache) { + adjustColumns(composite); + + Control[] children = composite.getChildren(); + int count = 0; + + for (int i = 0; i < children.length; i++) { + Control control = children[i]; + GridData data = getLayoutData(control); + if (data == null || !data.exclude) { + children[count++] = children[i]; + } + } + + if (count == 0) { + return new Point(marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom); + } + for (int i = 0; i < count; i++) { + Control child = children[i]; + GridData data = getLayoutData(child); + if (data == null) { + child.setLayoutData(data = new GridData()); + } + if (flushCache) { + data.flushCache(); + } + data.computeSize(child, data.widthHint, data.heightHint, flushCache); + if (data.grabExcessHorizontalSpace && data.minimumWidth > 0) { + if (data.cacheWidth < data.minimumWidth) { + int trim = 0; + // TEMPORARY CODE + if (child instanceof Scrollable) { + Rectangle rect = ((Scrollable) child).computeTrim(0, 0, 0, 0); + trim = rect.width; + } else { + trim = child.getBorderWidth() * 2; + } + data.cacheWidth = data.cacheHeight = SWT.DEFAULT; + data.computeSize(child, Math.max(0, data.minimumWidth - trim), data.heightHint, false); + } + } + if (data.grabExcessVerticalSpace && data.minimumHeight > 0) { + data.cacheHeight = Math.max(data.cacheHeight, data.minimumHeight); + } + } + + /* Build the grid */ + int row = 0, column = 0, rowCount = 0, columnCount = adjustedNumColumns; + Control[][] grid = new Control[4][columnCount]; + for (int i = 0; i < count; i++) { + Control child = children[i]; + GridData data = getLayoutData(child); + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + int vSpan = Math.max(1, data.verticalSpan); + while (true) { + int lastRow = row + vSpan; + if (lastRow >= grid.length) { + Control[][] newGrid = new Control[lastRow + 4][columnCount]; + System.arraycopy(grid, 0, newGrid, 0, grid.length); + grid = newGrid; + } + if (grid[row] == null) { + grid[row] = new Control[columnCount]; + } + while (column < columnCount && grid[row][column] != null) { + column++; + } + int endCount = column + hSpan; + if (endCount <= columnCount) { + int index = column; + while (index < endCount && grid[row][index] == null) { + index++; + } + if (index == endCount) { + break; + } + column = index; + } + if (column + hSpan >= columnCount) { + column = 0; + row++; + } + } + for (int j = 0; j < vSpan; j++) { + if (grid[row + j] == null) { + grid[row + j] = new Control[columnCount]; + } + for (int k = 0; k < hSpan; k++) { + grid[row + j][column + k] = child; + } + } + rowCount = Math.max(rowCount, row + vSpan); + column += hSpan; + } + + /* Column widths */ + int availableWidth = width - horizontalSpacing * (columnCount - 1) - (marginLeft + marginWidth * 2 + marginRight); + int expandCount = 0; + int[] widths = new int[columnCount]; + int[] minWidths = new int[columnCount]; + boolean[] expandColumn = new boolean[columnCount]; + for (int j = 0; j < columnCount; j++) { + for (int i = 0; i < rowCount; i++) { + GridData data = getData(grid, i, j, rowCount, columnCount, true); + if (data != null) { + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + if (hSpan == 1) { + int w = data.cacheWidth + data.horizontalIndent; + widths[j] = Math.max(widths[j], w); + if (data.grabExcessHorizontalSpace) { + if (!expandColumn[j]) { + expandCount++; + } + expandColumn[j] = true; + } + if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) { + w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; + w += data.horizontalIndent; + minWidths[j] = Math.max(minWidths[j], w); + } + } + } + } + for (int i = 0; i < rowCount; i++) { + GridData data = getData(grid, i, j, rowCount, columnCount, false); + if (data != null) { + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + if (hSpan > 1) { + int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0; + for (int k = 0; k < hSpan; k++) { + spanWidth += widths[j - k]; + spanMinWidth += minWidths[j - k]; + if (expandColumn[j - k]) { + spanExpandCount++; + } + } + if (data.grabExcessHorizontalSpace && spanExpandCount == 0) { + expandCount++; + expandColumn[j] = true; + } + int w = data.cacheWidth + data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing; + if (w > 0) { + if (makeColumnsEqualWidth) { + int equalWidth = (w + spanWidth) / hSpan; + int remainder = (w + spanWidth) % hSpan, last = -1; + for (int k = 0; k < hSpan; k++) { + widths[last = j - k] = Math.max(equalWidth, widths[j - k]); + } + if (last > -1) { + widths[last] += remainder; + } + } else { + if (spanExpandCount == 0) { + widths[j] += w; + } else { + int delta = w / spanExpandCount; + int remainder = w % spanExpandCount, last = -1; + for (int k = 0; k < hSpan; k++) { + if (expandColumn[j - k]) { + widths[last = j - k] += delta; + } + } + if (last > -1) { + widths[last] += remainder; + } + } + } + } + if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) { + w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; + w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing; + if (w > 0) { + if (spanExpandCount == 0) { + minWidths[j] += w; + } else { + int delta = w / spanExpandCount; + int remainder = w % spanExpandCount, last = -1; + for (int k = 0; k < hSpan; k++) { + if (expandColumn[j - k]) { + minWidths[last = j - k] += delta; + } + } + if (last > -1) { + minWidths[last] += remainder; + } + } + } + } + } + } + } + } + if (makeColumnsEqualWidth) { + int minColumnWidth = 0; + int columnWidth = 0; + for (int i = 0; i < columnCount; i++) { + minColumnWidth = Math.max(minColumnWidth, minWidths[i]); + columnWidth = Math.max(columnWidth, widths[i]); + } + columnWidth = width == SWT.DEFAULT || expandCount == 0 ? columnWidth : Math.max(minColumnWidth, availableWidth / columnCount); + for (int i = 0; i < columnCount; i++) { + expandColumn[i] = expandCount > 0; + widths[i] = columnWidth; + } + } else { + if (width != SWT.DEFAULT && expandCount > 0) { + int totalWidth = 0; + for (int i = 0; i < columnCount; i++) { + totalWidth += widths[i]; + } + int c = expandCount; + int delta = (availableWidth - totalWidth) / c; + int remainder = (availableWidth - totalWidth) % c; + int last = -1; + while (totalWidth != availableWidth) { + for (int j = 0; j < columnCount; j++) { + if (expandColumn[j]) { + if (widths[j] + delta > minWidths[j]) { + widths[last = j] = widths[j] + delta; + } else { + widths[j] = minWidths[j]; + expandColumn[j] = false; + c--; + } + } + } + if (last > -1) { + widths[last] += remainder; + } + + for (int j = 0; j < columnCount; j++) { + for (int i = 0; i < rowCount; i++) { + GridData data = getData(grid, i, j, rowCount, columnCount, false); + if (data != null) { + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + if (hSpan > 1) { + if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) { + int spanWidth = 0, spanExpandCount = 0; + for (int k = 0; k < hSpan; k++) { + spanWidth += widths[j - k]; + if (expandColumn[j - k]) { + spanExpandCount++; + } + } + int w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; + w += data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing; + if (w > 0) { + if (spanExpandCount == 0) { + widths[j] += w; + } else { + int delta2 = w / spanExpandCount; + int remainder2 = w % spanExpandCount, last2 = -1; + for (int k = 0; k < hSpan; k++) { + if (expandColumn[j - k]) { + widths[last2 = j - k] += delta2; + } + } + if (last2 > -1) { + widths[last2] += remainder2; + } + } + } + } + } + } + } + } + if (c == 0) { + break; + } + totalWidth = 0; + for (int i = 0; i < columnCount; i++) { + totalWidth += widths[i]; + } + delta = (availableWidth - totalWidth) / c; + remainder = (availableWidth - totalWidth) % c; + last = -1; + } + } + } + + /* Wrapping */ + GridData[] flush = null; + int flushLength = 0; + if (width != SWT.DEFAULT) { + for (int j = 0; j < columnCount; j++) { + for (int i = 0; i < rowCount; i++) { + GridData data = getData(grid, i, j, rowCount, columnCount, false); + if (data != null) { + if (data.heightHint == SWT.DEFAULT) { + Control child = grid[i][j]; + // TEMPORARY CODE + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + int currentWidth = 0; + for (int k = 0; k < hSpan; k++) { + currentWidth += widths[j - k]; + } + currentWidth += (hSpan - 1) * horizontalSpacing - data.horizontalIndent; + if ((currentWidth != data.cacheWidth && data.horizontalAlignment == SWT.FILL) || (data.cacheWidth > currentWidth)) { + int trim = 0; + if (child instanceof Scrollable) { + Rectangle rect = ((Scrollable) child).computeTrim(0, 0, 0, 0); + trim = rect.width; + } else { + trim = child.getBorderWidth() * 2; + } + data.cacheWidth = data.cacheHeight = SWT.DEFAULT; + data.computeSize(child, Math.max(0, currentWidth - trim), data.heightHint, false); + if (data.grabExcessVerticalSpace && data.minimumHeight > 0) { + data.cacheHeight = Math.max(data.cacheHeight, data.minimumHeight); + } + if (flush == null) { + flush = new GridData[count]; + } + flush[flushLength++] = data; + } + } + } + } + } + } + + /* Row heights */ + int availableHeight = height - verticalSpacing * (rowCount - 1) - (marginTop + marginHeight * 2 + marginBottom); + expandCount = 0; + int[] heights = new int[rowCount]; + int[] minHeights = new int[rowCount]; + boolean[] expandRow = new boolean[rowCount]; + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + GridData data = getData(grid, i, j, rowCount, columnCount, true); + if (data != null) { + int vSpan = Math.max(1, Math.min(data.verticalSpan, rowCount)); + if (vSpan == 1) { + int h = data.cacheHeight + data.verticalIndent; + heights[i] = Math.max(heights[i], h); + if (data.grabExcessVerticalSpace) { + if (!expandRow[i]) { + expandCount++; + } + expandRow[i] = true; + } + if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) { + h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; + h += data.verticalIndent; + minHeights[i] = Math.max(minHeights[i], h); + } + } + } + } + for (int j = 0; j < columnCount; j++) { + GridData data = getData(grid, i, j, rowCount, columnCount, false); + if (data != null) { + int vSpan = Math.max(1, Math.min(data.verticalSpan, rowCount)); + if (vSpan > 1) { + int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0; + for (int k = 0; k < vSpan; k++) { + spanHeight += heights[i - k]; + spanMinHeight += minHeights[i - k]; + if (expandRow[i - k]) { + spanExpandCount++; + } + } + if (data.grabExcessVerticalSpace && spanExpandCount == 0) { + expandCount++; + expandRow[i] = true; + } + int h = data.cacheHeight + data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing; + if (h > 0) { + if (spanExpandCount == 0) { + heights[i] += h; + } else { + int delta = h / spanExpandCount; + int remainder = h % spanExpandCount, last = -1; + for (int k = 0; k < vSpan; k++) { + if (expandRow[i - k]) { + heights[last = i - k] += delta; + } + } + if (last > -1) { + heights[last] += remainder; + } + } + } + if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) { + h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; + h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing; + if (h > 0) { + if (spanExpandCount == 0) { + minHeights[i] += h; + } else { + int delta = h / spanExpandCount; + int remainder = h % spanExpandCount, last = -1; + for (int k = 0; k < vSpan; k++) { + if (expandRow[i - k]) { + minHeights[last = i - k] += delta; + } + } + if (last > -1) { + minHeights[last] += remainder; + } + } + } + } + } + } + } + } + if (height != SWT.DEFAULT && expandCount > 0) { + int totalHeight = 0; + for (int i = 0; i < rowCount; i++) { + totalHeight += heights[i]; + } + int c = expandCount; + int delta = (availableHeight - totalHeight) / c; + int remainder = (availableHeight - totalHeight) % c; + int last = -1; + while (totalHeight != availableHeight) { + for (int i = 0; i < rowCount; i++) { + if (expandRow[i]) { + if (heights[i] + delta > minHeights[i]) { + heights[last = i] = heights[i] + delta; + } else { + heights[i] = minHeights[i]; + expandRow[i] = false; + c--; + } + } + } + if (last > -1) { + heights[last] += remainder; + } + + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + GridData data = getData(grid, i, j, rowCount, columnCount, false); + if (data != null) { + int vSpan = Math.max(1, Math.min(data.verticalSpan, rowCount)); + if (vSpan > 1) { + if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) { + int spanHeight = 0, spanExpandCount = 0; + for (int k = 0; k < vSpan; k++) { + spanHeight += heights[i - k]; + if (expandRow[i - k]) { + spanExpandCount++; + } + } + int h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; + h += data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing; + if (h > 0) { + if (spanExpandCount == 0) { + heights[i] += h; + } else { + int delta2 = h / spanExpandCount; + int remainder2 = h % spanExpandCount, last2 = -1; + for (int k = 0; k < vSpan; k++) { + if (expandRow[i - k]) { + heights[last2 = i - k] += delta2; + } + } + if (last2 > -1) { + heights[last2] += remainder2; + } + } + } + } + } + } + } + } + if (c == 0) { + break; + } + totalHeight = 0; + for (int i = 0; i < rowCount; i++) { + totalHeight += heights[i]; + } + delta = (availableHeight - totalHeight) / c; + remainder = (availableHeight - totalHeight) % c; + last = -1; + } + } + + /* Position the controls */ + if (move) { + int gridY = y + marginTop + marginHeight; + for (int i = 0; i < rowCount; i++) { + int gridX = x + marginLeft + marginWidth; + for (int j = 0; j < columnCount; j++) { + GridData data = getData(grid, i, j, rowCount, columnCount, true); + if (data != null) { + int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount)); + int vSpan = Math.max(1, data.verticalSpan); + int cellWidth = 0, cellHeight = 0; + for (int k = 0; k < hSpan; k++) { + cellWidth += widths[j + k]; + } + for (int k = 0; k < vSpan; k++) { + cellHeight += heights[i + k]; + } + cellWidth += horizontalSpacing * (hSpan - 1); + int childX = gridX + data.horizontalIndent; + int childWidth = Math.min(data.cacheWidth, cellWidth); + switch (data.horizontalAlignment) { + case SWT.CENTER: + case GridData.CENTER: + childX += Math.max(0, (cellWidth - data.horizontalIndent - childWidth) / 2); + break; + case SWT.RIGHT: + case SWT.END: + case GridData.END: + childX += Math.max(0, cellWidth - data.horizontalIndent - childWidth); + break; + case SWT.FILL: + childWidth = cellWidth - data.horizontalIndent; + break; + } + cellHeight += verticalSpacing * (vSpan - 1); + int childY = gridY + data.verticalIndent; + int childHeight = Math.min(data.cacheHeight, cellHeight); + switch (data.verticalAlignment) { + case SWT.CENTER: + case GridData.CENTER: + childY += Math.max(0, (cellHeight - data.verticalIndent - childHeight) / 2); + break; + case SWT.BOTTOM: + case SWT.END: + case GridData.END: + childY += Math.max(0, cellHeight - data.verticalIndent - childHeight); + break; + case SWT.FILL: + childHeight = cellHeight - data.verticalIndent; + break; + } + Control child = grid[i][j]; + if (child != null) { + child.setBounds(childX, childY, childWidth, childHeight); + } + } + gridX += widths[j] + horizontalSpacing; + } + gridY += heights[i] + verticalSpacing; + } + } + + // clean up cache + for (int i = 0; i < flushLength; i++) { + flush[i].cacheWidth = flush[i].cacheHeight = -1; + } + + int totalDefaultWidth = 0; + int totalDefaultHeight = 0; + for (int i = 0; i < columnCount; i++) { + totalDefaultWidth += widths[i]; + } + for (int i = 0; i < rowCount; i++) { + totalDefaultHeight += heights[i]; + } + totalDefaultWidth += horizontalSpacing * (columnCount - 1) + marginLeft + marginWidth * 2 + marginRight; + totalDefaultHeight += verticalSpacing * (rowCount - 1) + marginTop + marginHeight * 2 + marginBottom; + return new Point(totalDefaultWidth, totalDefaultHeight); + } + + protected String getName() { + String string = getClass().getName(); + int index = string.lastIndexOf('.'); + if (index == -1) { + return string; + } + return string.substring(index + 1, string.length()); + } + + /** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the layout + */ + @Override + public String toString() { + String string = getName() + " {"; //$NON-NLS-1$ + if (numColumns != 1) { + string += "numColumns=" + numColumns + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (makeColumnsEqualWidth) { + string += "makeColumnsEqualWidth=" + makeColumnsEqualWidth + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (marginWidth != 0) { + string += "marginWidth=" + marginWidth + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (marginHeight != 0) { + string += "marginHeight=" + marginHeight + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (marginLeft != 0) { + string += "marginLeft=" + marginLeft + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (marginRight != 0) { + string += "marginRight=" + marginRight + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (marginTop != 0) { + string += "marginTop=" + marginTop + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (marginBottom != 0) { + string += "marginBottom=" + marginBottom + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (horizontalSpacing != 0) { + string += "horizontalSpacing=" + horizontalSpacing + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + if (verticalSpacing != 0) { + string += "verticalSpacing=" + verticalSpacing + " "; //$NON-NLS-1$ //$NON-NLS-2$ + } + string = string.trim(); + string += "}"; //$NON-NLS-1$ + return string; + } + + protected GridData getLayoutData(Control control) { + Object layoutData = control.getLayoutData(); + + GridData data = null; + if (layoutData == null) { // We create a new default GridData + data = createDefaultLayoutData(); + } else if (layoutData instanceof org.eclipse.swt.layout.GridData) { // We convert it to our own GridData class (For visibility matters) + data = new GridData((org.eclipse.swt.layout.GridData) layoutData); + } else if (layoutData instanceof GridData) { + data = (GridData) layoutData; + } else { + data = createDefaultLayoutData(); + Activator.log.warn("Unknown LayoutData : " + layoutData); //$NON-NLS-1$ + } + + control.setLayoutData(data); + + return data; + } + + protected GridData createDefaultLayoutData() { + return new GridData(SWT.FILL, SWT.BEGINNING, true, false); + } + + /** + * Sets the number of columns for this layout + * + * @param numColumns + */ + public void setNumColumns(int numColumns) { + this.numColumns = numColumns; + } + + /** + * + * @return the number of columns for this layout + */ + public int getNumColumns() { + return numColumns; + } + + /** + * Indicates if all columns should have the same width + * + * @param makeColumnsEqualWidth + */ + public void setMakeColumnsEqualWidth(boolean makeColumnsEqualWidth) { + this.makeColumnsEqualWidth = makeColumnsEqualWidth; + } + + /** + * + * @return true if all columns should have the same width + */ + public boolean getMakeColumnsEqualWidth() { + return makeColumnsEqualWidth; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSection.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSection.java new file mode 100644 index 00000000000..71c403b7e36 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSection.java @@ -0,0 +1,247 @@ +/***************************************************************************** + * Copyright (c) 2010, 2016 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bugs 435420, 417409 + * Christian W. Damus - bug 485220 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.xwt; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.constraints.ConstraintDescriptor; +import org.eclipse.papyrus.infra.constraints.constraints.Constraint; +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintFactory; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; +import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSourceFactory; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.papyrus.infra.widgets.editors.EditorParentComposite; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * An Implementation of ISection for the TabbedPropertyView framework. + * The XWTSection uses an XWT File to display the SWT Controls, and + * a DataSource for DataBinding + * + * @author Camille Letavernier + */ +public class XWTSection extends AbstractPropertySection implements IChangeListener { + + private Section section; + + private DataSource source; + + private View view; + + private Composite self; + + private DisplayEngine display; + + private Set constraints; + + /** + * Constructor. + * + * @param section + * The Section object containing the Metadata for the XWTSection + * @param view + * The view this section belongs to + * @param display + * The display engine that will generate the SWT Controls + */ + public XWTSection(Section section, View view, DisplayEngine display) { + this.section = section; + this.view = view; + this.display = display; + } + + @Override + public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) { + self = new EditorParentComposite(parent, SWT.NONE); + + GridLayout layout = new GridLayout(1, false); + layout.marginHeight = 0; + layout.marginWidth = 0; + self.setLayout(layout); + + layout = new GridLayout(1, false); + layout.verticalSpacing = 0; + layout.marginHeight = 0; + layout.marginWidth = 5; + parent.setLayout(layout); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + self.setLayoutData(data); + + self.setBackground(parent.getBackground()); + self.setBackgroundMode(SWT.INHERIT_DEFAULT); + } + + @Override + public void setInput(IWorkbenchPart part, ISelection selection) { + if (selection == getSelection()) { + return; + } + + // Sets the initial input, *or* changes the input for the same view : we need to clean the cache + DataSourceFactory.instance.removeFromCache(getSelection(), view); + + super.setInput(part, selection); + + if (selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = (IStructuredSelection) selection; + + setSource(DataSourceFactory.instance.createDataSourceFromSelection(structuredSelection, view)); + } + } + + private void setSource(DataSource source) { + final DataSource oldSource = this.source; + + if (oldSource != source) { + if (oldSource != null) { + oldSource.removeChangeListener(this); + } + + this.source = source; + + if (section.getConstraints().size() > 0) { + source.addChangeListener(this); + } + } + } + + /** + * Displays the section + * + * @param refresh + * If true, and the section has already been displayed, the controls will be + * regenerated. If false, the section will only be displayed if it hasn't been + * displayed yet, or if the display engine allows duplication of sections + */ + public void display(boolean refresh) { + if (self.isDisposed()) { + Activator.log.debug("Error : widget is disposed"); //$NON-NLS-1$ + dispose(); + return; + } + + if (!isApplied()) { + hide(); + return; + } + + self.setRedraw(false); // Avoid flickering during refresh + if (refresh) { + display.refreshSection(self, section, source); + } else { + display.createSection(self, section, source); + } + self.setRedraw(true); + } + + private void hide() { + display.removeSection(self); + } + + @Override + public void refresh() { + display(false); + } + + /** + * Tests if this section is applied. A section is applied if it doesn't have + * any constraint, or if at least one of its constraints match the current selection + * + * @return + * True if the section should be displayed + */ + protected boolean isApplied() { + if (getConstraints().isEmpty()) { + return true; + } + + ISelection selection = getSelection(); + List selectionList = ((IStructuredSelection) selection).toList(); + + // Return true only if at least one constraint matches the selection + + for (Constraint constraint : getConstraints()) { + if (constraint.match(selectionList)) { + return true; + } + } + + return false; + } + + protected Set getConstraints() { + if (constraints == null) { + constraints = new HashSet(); + for (ConstraintDescriptor constraintDescriptor : section.getConstraints()) { + Constraint constraint = ConstraintFactory.getInstance().createFromModel(constraintDescriptor); + if (constraint != null) { + constraints.add(constraint); + } + } + } + + return constraints; + } + + @Override + public void dispose() { + // Dispose the DataSource + if (source != null) { + source.removeChangeListener(this); + source.dispose(); + } + + // Dispose the SWT Composite + if (self != null) { + self.dispose(); + } + + // Clean the DataSource cache + DataSourceFactory.instance.removeFromCache(getSelection(), view); + super.dispose(); + } + + @Override + public IStructuredSelection getSelection() { + return (IStructuredSelection) super.getSelection(); + } + + @Override + public String toString() { + return "XWTSection : " + section.getName(); //$NON-NLS-1$ + } + + @Override + public void handleChange(ChangeEvent event) { + display(true); + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSectionDescriptor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSectionDescriptor.java new file mode 100644 index 00000000000..d2e703d25a5 --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTSectionDescriptor.java @@ -0,0 +1,109 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.xwt; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.properties.tabbed.AbstractSectionDescriptor; +import org.eclipse.ui.views.properties.tabbed.ISection; + +/** + * An XWTSectionDescriptor contains Metadata for the XWTSection. + * It is similar to the {@link Section} class, but in the TabbedPropertyView context. + * + * @author Camille Letavernier + */ +public class XWTSectionDescriptor extends AbstractSectionDescriptor { + + private Section section; + + private View view; + + private DisplayEngine display; + + /** + * + * Constructs a new XWTSectionDescriptor from the given section and view. + * The XWTSections will be displayed in the given DisplayEngine. + * + * @param section + * The Section model object containing the section metadata + * @param view + * The view the section belongs to + * @param display + * The display engine that will be used to display the XWTSection + */ + public XWTSectionDescriptor(Section section, View view, DisplayEngine display) { + this.section = section; + this.view = view; + this.display = display; + } + + public String getId() { + return section.getName(); + } + + public ISection getSectionClass() { + return new XWTSection(section, view, display); + } + + public String getTargetTab() { + return section.getTab().getId(); + } + + @Override + public String toString() { + return "Section " + getId(); //$NON-NLS-1$ + } + + @Override + public boolean appliesTo(IWorkbenchPart part, ISelection selection) { + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + System.identityHashCode(display); + result = prime * result + System.identityHashCode(section); + result = prime * result + System.identityHashCode(view); + return result; + } + + /** + * XWT section descriptors are equal if they have the same (identical) references to the section and view from the property-sheet model + * and are associated with the same display engine. + */ + @Override + public boolean equals(Object obj) { + boolean result; + + if (this == obj) { + result = true; + } else if ((obj == null) || (obj.getClass() != this.getClass())) { + result = false; + } else { + XWTSectionDescriptor other = (XWTSectionDescriptor) obj; + + result = (other.section == this.section) && (other.view == this.view) && (other.display == this.display); + } + + return result; + } + +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptor.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptor.java new file mode 100644 index 00000000000..ae84d71ddaa --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptor.java @@ -0,0 +1,144 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.xwt; + +import java.util.List; + +import org.eclipse.papyrus.infra.properties.contexts.Section; +import org.eclipse.papyrus.infra.properties.contexts.Tab; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.views.properties.tabbed.AbstractTabDescriptor; + +/** + * A Tab descriptor implementation for the TabbedPropertyView. + * The property view is described by XWT files. + * + * @author Camille Letavernier + */ +public class XWTTabDescriptor extends AbstractTabDescriptor { + + private Tab tab; + + /** + * Constructor. + * + * @param tab + * The Tab model object containing the Metadata for the tab + */ + public XWTTabDescriptor(Tab tab) { + this.tab = tab; + } + + /** + * Adds a section to this tab + * + * @param section + * The Section model object + * @param view + * The View model object to which the section belongs + * @param display + * The display engine that will be used to display the section + */ + @SuppressWarnings("unchecked") + public void addSection(Section section, View view, DisplayEngine display) { + super.getSectionDescriptors().add(new XWTSectionDescriptor(section, view, display)); + } + + public String getCategory() { + String category = tab.getCategory(); + return category == null ? "" : category; //$NON-NLS-1$ + } + + public String getId() { + return tab.getId(); + } + + public String getLabel() { + return tab.getLabel(); + } + + @Override + public Image getImage() { + String imagePath = tab.getImage(); + + if (imagePath == null || imagePath.trim().equals("")) { //$NON-NLS-1$ + return null; + } + + return Activator.getDefault().getImageFromPlugin(imagePath); + } + + @Override + public boolean isIndented() { + return tab.isIndented(); + } + + @Override + public String getAfterTab() { + if (tab.getAfterTab() != null) { + return tab.getAfterTab().getId(); + } + return super.getAfterTab(); + } + + @Override + public String toString() { + return "Tab " + getLabel() + " => " + getSectionDescriptors(); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * @return this tab's priority. The tabs should be ordered by ascending + * priority (i.e. the lower the priority int value, the higher + * the actual priority) + */ + public int getPriority() { + return tab.getPriority(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + List sectionDescriptors = getSectionDescriptors(); + result = prime * result + ((tab == null) ? 0 : tab.hashCode()); + result = prime * result + ((sectionDescriptors == null) ? 0 : sectionDescriptors.hashCode()); + return result; + } + + /** + * XWT tab descriptors are equal if they have the same ID and an equal list (in order) of section descriptors. + */ + @Override + public boolean equals(Object obj) { + boolean result; + + if (this == obj) { + result = true; + } else if ((obj == null) || (obj.getClass() != this.getClass())) { + result = false; + } else { + XWTTabDescriptor other = (XWTTabDescriptor) obj; + + result = (other.getId() == null) ? this.getId() == null : (other.getId().equals(this.getId())); + if (result) { + result = (other.getSectionDescriptors() == null) ? this.getSectionDescriptors() == null : other.getSectionDescriptors().equals(this.getSectionDescriptors()); + } + } + + return result; + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptorProvider.java b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptorProvider.java new file mode 100644 index 00000000000..4897ef3ba0e --- /dev/null +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties.ui/src/org/eclipse/papyrus/infra/properties/ui/xwt/XWTTabDescriptorProvider.java @@ -0,0 +1,284 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.properties.ui.xwt; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.Collator; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintEngineListener; +import org.eclipse.papyrus.infra.constraints.runtime.ConstraintsChangedEvent; +import org.eclipse.papyrus.infra.properties.contexts.View; +import org.eclipse.papyrus.infra.properties.internal.ui.Activator; +import org.eclipse.papyrus.infra.properties.ui.runtime.DefaultDisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.DisplayEngine; +import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistry; +import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistryFactory; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptor; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptorProvider; +import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; + +/** + * An implementation of ITabDescriptorProvider, which displays the Property view + * from XWT files. + * + * @author Camille Letavernier + */ +public class XWTTabDescriptorProvider implements ITabDescriptorProvider { + + private ITabDescriptor[] cachedResult; + + private ISelection previousSelection; + + private IWorkbenchPart previousPart; + + private final Map displays = new HashMap(); + + + public XWTTabDescriptorProvider() { + PropertiesRuntime.getConstraintEngine().addConstraintEngineListener(new ConstraintEngineListener() { + + @Override + public void constraintsChanged(ConstraintsChangedEvent event) { + // Purge the caches of all display engines because the XML view descriptions + // they cached are out of date + for (DisplayEngine next : displays.values()) { + ((DefaultDisplayEngine) next).invalidate(); + } + } + }); + } + + private DisplayEngine getDisplay(final IWorkbenchPart part) { + if (!displays.containsKey(part)) { + displays.put(part, new DefaultDisplayEngine()); + part.getSite().getPage().addPartListener(new IPartListener() { + + @Override + public void partClosed(IWorkbenchPart part) { + part.getSite().getPage().removePartListener(this); + DisplayEngine display = displays.get(part); + if (display != null) { + display.dispose(); + displays.remove(part); + } + + // We remove pointers to the cached IWorkbenchPart, to avoid Memory Leaks. + // Even if the closed part is not the previousPart, both parts may share the same objects (e.g. ModelExplorer & DiagramEditor). + // We'd better not retain the selection at all. In such a case, we won't receive a SelectionChangedEvent from the ModelExplorer. + previousPart = null; + previousSelection = null; + } + + @Override + public void partActivated(IWorkbenchPart part) { + // Nothing + } + + @Override + public void partBroughtToTop(IWorkbenchPart part) { + // Nothing + } + + @Override + public void partDeactivated(IWorkbenchPart part) { + // Nothing + } + + @Override + public void partOpened(IWorkbenchPart part) { + // Nothing + } + + }); + } + + return displays.get(part); + } + + @Override + public ITabDescriptor[] getTabDescriptors(final IWorkbenchPart part, final ISelection selection) { + if (selection != this.previousSelection || part != previousPart) { + this.previousSelection = selection; + this.previousPart = part; + + List descriptors = new LinkedList(); + + Set views = PropertiesRuntime.getConstraintEngine().getDisplayUnits(selection); + if (!views.isEmpty()) { + descriptors.addAll(getDisplay(part).getTabDescriptors(views)); + } + + // FIXME: In some cases (e.g. Selection in the Papyrus Tree outline), the IWorkbenchPart is not an ITabbedPropertySheetPageContributor + // TODO: Investigate on this case and fix the issue (contributor == null in this case) + ITabbedPropertySheetPageContributor contributor; + if (part instanceof ITabbedPropertySheetPageContributor) { + contributor = (ITabbedPropertySheetPageContributor) part; + } else { + contributor = (part.getAdapter(ITabbedPropertySheetPageContributor.class)); + } + + if (contributor != null) { + // get all tab descriptors for the registered extension points + // Memory leak here + TabbedPropertyRegistry registry = TabbedPropertyRegistryFactory.getInstance().createRegistry(contributor); + + // invoke dynamically on the tab registry, as method is private + // problem of implementation of tabbed properties tabbed registry. Either contribution using extension points, either a tabprovider + // both contribution can not exist together, the only solution is to make a workaround. + try { + Method method = TabbedPropertyRegistry.class.getDeclaredMethod("getAllTabDescriptors"); //$NON-NLS-1$ + method.setAccessible(true); + ITabDescriptor[] registeredTabDesriptors; + + registeredTabDesriptors = (ITabDescriptor[]) method.invoke(registry); + + if (registeredTabDesriptors != null) { + for (ITabDescriptor descriptor : registeredTabDesriptors) { + if (descriptor.getSectionDescriptors().size() > 0) { + descriptors.add(descriptor); + } + } + } + } catch (IllegalArgumentException e) { + Activator.log.error(e); + } catch (IllegalAccessException e) { + Activator.log.error(e); + } catch (InvocationTargetException e) { + Activator.log.error(e); + } catch (SecurityException e) { + Activator.log.error(e); + } catch (NoSuchMethodException e) { + Activator.log.error(e); + } + } + + orderTabDescriptors(descriptors); + + cachedResult = descriptors.toArray(new ITabDescriptor[descriptors.size()]); + + // Workaround for memory leak + TabbedPropertyRegistryFactory.getInstance().disposeRegistry((ITabbedPropertySheetPageContributor) part); + } + + return cachedResult; + } + + /** + * Order the tab descriptors in the given list, given the afterTab comparator + * + * @param descriptors + * tab descriptor list to order + */ + protected void orderTabDescriptors(final List descriptors) { + + Collections.sort(descriptors, new Comparator() { + + /** + * compares two tab descriptors each other + * + * @param tabDescriptor1 + * first tab to compare + * @param tabDescriptor2 + * second tab to compare + * @return an integer lesser than -1 if the first tab should be placed before the second tab + */ + @Override + public int compare(ITabDescriptor tabDescriptor1, ITabDescriptor tabDescriptor2) { + int priority1 = getPriority(tabDescriptor1); + int priority2 = getPriority(tabDescriptor2); + + if (priority1 < priority2) { + return -1; + } + + if (priority1 > priority2) { + return 1; + } + + // p1 == p2 + + priority1 = getXWTTabPriority(tabDescriptor1); + priority2 = getXWTTabPriority(tabDescriptor2); + + if (priority1 < priority2) { + return -1; + } + + if (priority1 > priority2) { + return 1; + } + + // p1 == p2 + + String label1 = tabDescriptor1.getLabel(); + String label2 = tabDescriptor2.getLabel(); + + return Collator.getInstance().compare(label1, label2); + } + + /** + * Returns the tab descriptor before tab + * + * @param tab + * the tab to test + * @return the tab descriptor before tab + */ + private ITabDescriptor getPreviousTab(ITabDescriptor tab) { + String afterId = tab.getAfterTab(); + if (!(ITabDescriptor.TOP.equals(afterId))) { + for (ITabDescriptor descriptor : descriptors) { + String id = descriptor.getId(); + if (id != null && id.equals(afterId)) { + return descriptor; + } + } + + } + // not found. Return null + return null; + } + + private int getPriority(ITabDescriptor tab) { + ITabDescriptor previousTab = getPreviousTab(tab); + if (previousTab != null) { + return getPriority(previousTab) + 1; + } + + return getXWTTabPriority(tab); + } + + private int getXWTTabPriority(ITabDescriptor tab) { + if (tab instanceof XWTTabDescriptor) { + XWTTabDescriptor xwtTab = (XWTTabDescriptor) tab; + return xwtTab.getPriority(); + } else { + return 100; // This tab is not handled by our framework + } + } + + }); + } +} diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties/META-INF/MANIFEST.MF b/plugins/infra/properties/org.eclipse.papyrus.infra.properties/META-INF/MANIFEST.MF index e144c0631e0..f3c88e1b574 100644 --- a/plugins/infra/properties/org.eclipse.papyrus.infra.properties/META-INF/MANIFEST.MF +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties/META-INF/MANIFEST.MF @@ -1,12 +1,12 @@ Manifest-Version: 1.0 -Export-Package: org.eclipse.papyrus.infra.properties.contexts, +Export-Package: org.eclipse.papyrus.infra.properties.catalog, + org.eclipse.papyrus.infra.properties.contexts, org.eclipse.papyrus.infra.properties.contexts.impl, org.eclipse.papyrus.infra.properties.contexts.util, org.eclipse.papyrus.infra.properties.environment, org.eclipse.papyrus.infra.properties.environment.impl, org.eclipse.papyrus.infra.properties.environment.util, - org.eclipse.papyrus.infra.properties.catalog, - org.eclipse.papyrus.infra.properties.internal;x-friends:="org.eclipse.papyrus.views.properties", + org.eclipse.papyrus.infra.properties.internal;x-friends:="org.eclipse.papyrus.infra.properties.ui,org.eclipse.papyrus.views.properties", org.eclipse.papyrus.infra.properties.spi, org.eclipse.papyrus.infra.properties.ui, org.eclipse.papyrus.infra.properties.ui.impl, diff --git a/plugins/infra/properties/org.eclipse.papyrus.infra.properties/pom.xml b/plugins/infra/properties/org.eclipse.papyrus.infra.properties/pom.xml index 5d0386a803d..e7570a844e1 100644 --- a/plugins/infra/properties/org.eclipse.papyrus.infra.properties/pom.xml +++ b/plugins/infra/properties/org.eclipse.papyrus.infra.properties/pom.xml @@ -2,13 +2,11 @@ 4.0.0 - org.eclipse.papyrus.releng + org.eclipse.papyrus.infra-properties org.eclipse.papyrus - 1.2.0-SNAPSHOT - ../../../../releng/main + 0.0.1-SNAPSHOT org.eclipse.papyrus.infra.properties - org.eclipse.papyrus 1.2.0-SNAPSHOT eclipse-plugin - \ No newline at end of file + diff --git a/plugins/infra/properties/pom.xml b/plugins/infra/properties/pom.xml new file mode 100644 index 00000000000..68a871512ce --- /dev/null +++ b/plugins/infra/properties/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + org.eclipse.papyrus.infra-properties + pom + + org.eclipse.papyrus + org.eclipse.papyrus.infra + 0.0.1-SNAPSHOT + + Papyrus Infra Properties Framework + The model and UI framework for dynamic Properties View content. + + + org.eclipse.papyrus.infra.properties + org.eclipse.papyrus.infra.properties.edit + org.eclipse.papyrus.infra.properties.editor + org.eclipse.papyrus.infra.properties.ui + + -- cgit v1.2.3