Java tutorial
/** * Copyright (C) 2014 BonitaSoft S.A. * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.studio.contract.ui.property; import javax.inject.Inject; import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables; import org.bonitasoft.studio.common.properties.AbstractBonitaDescriptionSection; import org.bonitasoft.studio.common.repository.RepositoryAccessor; import org.bonitasoft.studio.contract.core.mapping.expression.FieldToContractInputMappingExpressionBuilder; import org.bonitasoft.studio.contract.core.mapping.operation.FieldToContractInputMappingOperationBuilder; import org.bonitasoft.studio.contract.i18n.Messages; import org.bonitasoft.studio.contract.ui.property.constraint.ContractConstraintController; import org.bonitasoft.studio.contract.ui.property.constraint.ContractConstraintsTableViewer; import org.bonitasoft.studio.contract.ui.property.input.ContractInputController; import org.bonitasoft.studio.contract.ui.property.input.ContractInputTreeViewer; import org.bonitasoft.studio.contract.ui.wizard.AddInputContractFromDataWizardDialog; import org.bonitasoft.studio.contract.ui.wizard.ContractInputGenerationInfoDialogFactory; import org.bonitasoft.studio.contract.ui.wizard.ContractInputGenerationWizard; import org.bonitasoft.studio.contract.ui.wizard.ContractInputGenerationWizardPagesFactory; import org.bonitasoft.studio.designer.ui.contribution.CreateAndEditFormContributionItem; import org.bonitasoft.studio.groovy.ui.viewer.GroovySourceViewerFactory; import org.bonitasoft.studio.model.process.Contract; import org.bonitasoft.studio.model.process.ContractConstraint; import org.bonitasoft.studio.model.process.ContractContainer; import org.bonitasoft.studio.model.process.ContractInput; import org.bonitasoft.studio.model.process.ContractInputType; import org.bonitasoft.studio.model.process.ProcessPackage; import org.bonitasoft.studio.model.process.Task; import org.bonitasoft.studio.preferences.BonitaStudioPreferencesPlugin; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.list.IListChangeListener; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.ListChangeEvent; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.databinding.EMFDataBindingContext; import org.eclipse.emf.databinding.EMFObservables; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.databinding.swt.ISWTObservableValue; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.progress.IProgressService; /** * @author Romain Bioteau */ public class ContractPropertySection extends AbstractBonitaDescriptionSection { private EMFDataBindingContext context; private ContractInputController inputController; private ContractConstraintController constraintController; private final ContractContainerAdaptableSelectionProvider selectionProvider; private final IEclipseContext eclipseContext; private final IProgressService progressService; private final ISharedImages sharedImages; private final RepositoryAccessor repositoryAccessor; private final FieldToContractInputMappingOperationBuilder fieldToContractInputMappingOperationBuilder; private final FieldToContractInputMappingExpressionBuilder fieldToContractInputMappingExpressionBuilder; @Inject public ContractPropertySection(final ISharedImages sharedImages, final IEclipseContext eclipseContext, final ContractContainerAdaptableSelectionProvider selectionProvider, final RepositoryAccessor repositoryAccessor, final FieldToContractInputMappingOperationBuilder fieldToContractInputMappingOperationBuilder, final FieldToContractInputMappingExpressionBuilder fieldToContractInputMappingExpressionBuilder, final IProgressService progressService) { this.eclipseContext = eclipseContext; this.repositoryAccessor = repositoryAccessor; this.selectionProvider = selectionProvider; this.progressService = progressService; this.sharedImages = sharedImages; this.fieldToContractInputMappingOperationBuilder = fieldToContractInputMappingOperationBuilder; this.fieldToContractInputMappingExpressionBuilder = fieldToContractInputMappingExpressionBuilder; } @Override public String getSectionDescription() { return selectionProvider.getAdapter(EObject.class) instanceof Task ? Messages.stepContractSectionDescription : Messages.processContractSectionDescription; } @Override public String getSectionTitle() { return selectionProvider.getAdapter(EObject.class) instanceof Task ? Messages.taskInputs : Messages.processInstantiationInputs; } protected void init(final IObservableValue observeContractValue) { inputController = new ContractInputController(progressService); constraintController = new ContractConstraintController(observeContractValue); context = new EMFDataBindingContext(); } @Override protected void updateToolbar(final IToolBarManager toolbarManager) { final CreateAndEditFormContributionItem newFormContributionItem = newContributionItem( CreateAndEditFormContributionItem.class); newFormContributionItem.setSelectionProvider(selectionProvider); toolbarManager.add(newFormContributionItem); } protected <T> T newContributionItem(final Class<T> clazz) { return ContextInjectionFactory.make(clazz, eclipseContext); } @Override public void refresh() { super.refresh(); for (final IContributionItem object : form.getToolBarManager().getItems()) { object.update(); } } @Override protected void createContent(final Composite parent) { final IObservableValue observeContractValue = CustomEMFEditObservables.observeDetailValue( Realm.getDefault(), ViewersObservables.observeSingleSelection(selectionProvider), ProcessPackage.Literals.CONTRACT_CONTAINER__CONTRACT); init(observeContractValue); final CTabFolder tabFolder = getWidgetFactory().createTabFolder(parent, SWT.TOP); tabFolder.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); getWidgetFactory().adapt(tabFolder); final CTabItem inputTabItem = getWidgetFactory().createTabItem(tabFolder, SWT.NULL); inputTabItem.setText(Messages.inputTabLabel); final Composite inputComposite = getWidgetFactory().createComposite(tabFolder); inputComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); inputComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0) .extendedMargins(15, 0, 10, 5).create()); createInputTabContent(inputComposite, observeContractValue); inputTabItem.setControl(inputComposite); final Composite constraintComposite = getWidgetFactory().createComposite(tabFolder); constraintComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); constraintComposite .setLayout(GridLayoutFactory.fillDefaults().numColumns(2).extendedMargins(15, 0, 10, 5).create()); createConstraintTabContent(constraintComposite, observeContractValue); final CTabItem constraintTabItem = getWidgetFactory().createTabItem(tabFolder, SWT.NULL); constraintTabItem.setText(Messages.constraintsTabLabel); constraintTabItem.setControl(constraintComposite); tabFolder.setSelection(0); } private void createConstraintTabContent(final Composite parent, final IObservableValue observeContractValue) { final Composite buttonsComposite = createButtonContainer(parent); final Button addButton = createButton(buttonsComposite, Messages.add); final Button upButton = createButton(buttonsComposite, Messages.up); final Button downButton = createButton(buttonsComposite, Messages.down); final Button removeButton = createButton(buttonsComposite, Messages.remove); final ContractConstraintsTableViewer constraintsTableViewer = new ContractConstraintsTableViewer(parent, getWidgetFactory()); constraintsTableViewer.getControl() .setLayoutData(GridDataFactory.fillDefaults().grab(true, true).hint(500, SWT.DEFAULT).create()); constraintsTableViewer.initialize(constraintController, getMessageManager(), context); constraintsTableViewer.setInput(CustomEMFEditObservables.observeDetailList(Realm.getDefault(), observeContractValue, ProcessPackage.Literals.CONTRACT__CONSTRAINTS)); constraintsTableViewer.createAddListener(addButton); constraintsTableViewer.createMoveUpListener(upButton); constraintsTableViewer.createMoveDownListener(downButton); constraintsTableViewer.createRemoveListener(removeButton); bindAddConstraintButtonEnablement(addButton, observeContractValue); bindRemoveButtonEnablement(removeButton, constraintsTableViewer); bindUpButtonEnablement(upButton, constraintsTableViewer); bindDownButtonEnablement(downButton, constraintsTableViewer); } private void createInputTabContent(final Composite parent, final IObservableValue observeContractValue) { final Composite buttonsComposite = createButtonContainer(parent); createGenerateButton(buttonsComposite); final Button addButton = createButton(buttonsComposite, Messages.add); final Button addChildButton = createButton(buttonsComposite, Messages.addChild); final Button removeButton = createButton(buttonsComposite, Messages.remove); final ContractInputTreeViewer inputsTableViewer = new ContractInputTreeViewer(parent, getWidgetFactory(), progressService, sharedImages); inputsTableViewer.getControl() .setLayoutData(GridDataFactory.fillDefaults().grab(true, true).hint(500, SWT.DEFAULT).create()); inputsTableViewer.initialize(inputController, getMessageManager(), context); inputsTableViewer.setInput(observeContractValue); inputsTableViewer.createAddListener(addButton); inputsTableViewer.createAddChildListener(addChildButton); inputsTableViewer.createRemoveListener(removeButton); bindRemoveButtonEnablement(removeButton, inputsTableViewer); bindAddChildButtonEnablement(addChildButton, inputsTableViewer); } private void createGenerateButton(final Composite buttonsComposite) { final Button generateButton = createButton(buttonsComposite, Messages.generate); generateButton.addSelectionListener(new SelectionAdapter() { /* * (non-Javadoc) * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(final SelectionEvent e) { openAddInputWizardDialog(); } }); } public void openAddInputWizardDialog() { final AddInputContractFromDataWizardDialog dialog = new AddInputContractFromDataWizardDialog( Display.getCurrent().getActiveShell(), new ContractInputGenerationWizard((ContractContainer) selectionProvider.getAdapter(EObject.class), getEditingDomain(), repositoryAccessor, fieldToContractInputMappingOperationBuilder, fieldToContractInputMappingExpressionBuilder, BonitaStudioPreferencesPlugin.getDefault().getPreferenceStore(), sharedImages, new ContractInputGenerationInfoDialogFactory(), new ContractInputGenerationWizardPagesFactory(), new GroovySourceViewerFactory()), this, true); dialog.open(); } private Button createButton(final Composite buttonsComposite, final String label) { final Button button = getWidgetFactory().createButton(buttonsComposite, label, SWT.PUSH); button.setLayoutData(GridDataFactory.fillDefaults().grab(true, false) .minSize(IDialogConstants.BUTTON_WIDTH, SWT.DEFAULT).create()); return button; } private Composite createButtonContainer(final Composite parent) { final Composite buttonsComposite = getWidgetFactory().createComposite(parent); buttonsComposite .setLayoutData(GridDataFactory.fillDefaults().grab(false, true).align(SWT.LEFT, SWT.TOP).create()); buttonsComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).spacing(0, 3).create()); return buttonsComposite; } protected void bindAddConstraintButtonEnablement(final Button button, final IObservableValue contractObservable) { final ISWTObservableValue observeEnabled = SWTObservables.observeEnabled(button); final IObservableList observeDetailList = CustomEMFEditObservables.observeDetailList(Realm.getDefault(), contractObservable, ProcessPackage.Literals.CONTRACT__INPUTS); observeDetailList.addListChangeListener(new IListChangeListener() { @Override public void handleListChange(final ListChangeEvent event) { if (!button.isDisposed()) { observeEnabled.setValue(!event.getObservableList().isEmpty()); } } }); } protected void bindRemoveButtonEnablement(final Button button, final Viewer viewer) { context.bindValue(SWTObservables.observeEnabled(button), ViewersObservables.observeSingleSelection(viewer), new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), emptySelectionToBooleanStrategy()); } protected void bindUpButtonEnablement(final Button button, final Viewer viewer) { context.bindValue(SWTObservables.observeEnabled(button), ViewersObservables.observeSingleSelection(viewer), new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), isFirstElementToBooleanStrategy()); } protected void bindDownButtonEnablement(final Button button, final Viewer viewer) { context.bindValue(SWTObservables.observeEnabled(button), ViewersObservables.observeSingleSelection(viewer), new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), isLastElementToBooleanStrategy()); } protected void bindAddChildButtonEnablement(final Button button, final Viewer viewer) { context.bindValue(SWTObservables.observeEnabled(button), ViewersObservables.observeSingleSelection(viewer), new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), emptySelectionAndComplexTypeToBooleanStrategy()); context.bindValue(SWTObservables.observeEnabled(button), EMFObservables.observeDetailValue(Realm.getDefault(), ViewersObservables.observeSingleSelection(viewer), ProcessPackage.Literals.CONTRACT_INPUT__TYPE), new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), complexTypeToBooleanStrategy()); } private UpdateValueStrategy emptySelectionToBooleanStrategy() { final UpdateValueStrategy modelStrategy = new UpdateValueStrategy(); modelStrategy.setConverter(new Converter(Object.class, Boolean.class) { @Override public Object convert(final Object from) { return from != null; } }); return modelStrategy; } private UpdateValueStrategy isLastElementToBooleanStrategy() { final UpdateValueStrategy strategy = new UpdateValueStrategy(); strategy.setConverter(new Converter(Object.class, Boolean.class) { @Override public Object convert(final Object from) { if (from instanceof ContractConstraint) { final Contract contract = (Contract) ((ContractConstraint) from).eContainer(); final EList<ContractConstraint> constraints = contract.getConstraints(); return constraints.size() > 1 && constraints.indexOf(from) < constraints.size() - 1; } return false; } }); return strategy; } private UpdateValueStrategy isFirstElementToBooleanStrategy() { final UpdateValueStrategy strategy = new UpdateValueStrategy(); strategy.setConverter(new Converter(Object.class, Boolean.class) { @Override public Object convert(final Object from) { if (from instanceof ContractConstraint) { final Contract contract = (Contract) ((ContractConstraint) from).eContainer(); final EList<ContractConstraint> constraints = contract.getConstraints(); return constraints.size() > 1 && constraints.indexOf(from) > 0; } return false; } }); return strategy; } private UpdateValueStrategy emptySelectionAndComplexTypeToBooleanStrategy() { final UpdateValueStrategy modelStrategy = new UpdateValueStrategy(); modelStrategy.setConverter(new Converter(Object.class, Boolean.class) { @Override public Object convert(final Object from) { if (from instanceof ContractInput) { return ((ContractInput) from).getType() == ContractInputType.COMPLEX; } return false; } }); return modelStrategy; } private UpdateValueStrategy complexTypeToBooleanStrategy() { final UpdateValueStrategy modelStrategy = new UpdateValueStrategy(); modelStrategy.setConverter(new Converter(ContractInputType.class, Boolean.class) { @Override public Object convert(final Object from) { if (from instanceof ContractInputType) { return from == ContractInputType.COMPLEX; } return false; } }); return modelStrategy; } @Override public void setInput(final IWorkbenchPart part, final ISelection selection) { super.setInput(part, selection); selectionProvider.setSelection(selection); } @Override public void dispose() { super.dispose(); if (context != null) { context.dispose(); } } }