Java tutorial
/******************************************************************************* * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * 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 *******************************************************************************/ package gov.redhawk.ide.codegen.ui; import gov.redhawk.common.ui.editor.FormLayoutFactory; import gov.redhawk.common.ui.parts.FormEntry; import gov.redhawk.ide.codegen.CodegenPackage; import gov.redhawk.ide.codegen.ICodeGeneratorDescriptor; import gov.redhawk.ide.codegen.ITemplateDesc; import gov.redhawk.ide.codegen.ImplementationSettings; import gov.redhawk.ide.codegen.PortRepToGeneratorMap; import gov.redhawk.ide.codegen.RedhawkCodegenActivator; import gov.redhawk.ide.codegen.ui.internal.GeneratorDialog; import gov.redhawk.ide.codegen.ui.internal.PortGeneratorComposite; import gov.redhawk.ui.editor.EMFTableViewerElementSelector; import gov.redhawk.ui.parts.FormEntryBindingFactory; import gov.redhawk.ui.util.EMFEmptyStringToNullUpdateValueStrategy; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import mil.jpeojtrs.sca.scd.Ports; import mil.jpeojtrs.sca.scd.Provides; import mil.jpeojtrs.sca.scd.Uses; import mil.jpeojtrs.sca.spd.Descriptor; import mil.jpeojtrs.sca.spd.Implementation; import mil.jpeojtrs.sca.spd.SoftPkg; import org.eclipse.core.databinding.Binding; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.databinding.EMFDataBindingContext; import org.eclipse.emf.databinding.EMFUpdateValueStrategy; import org.eclipse.emf.databinding.edit.EMFEditObservables; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.command.RemoveCommand; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.widgets.FormToolkit; /** * @since 6.0 */ public abstract class BaseGeneratorPropertiesComposite extends Composite implements ICodegenComposite { private static final int NUM_COLUMNS = 3; private final FormToolkit toolkit; private final int style; private FormEntry outputDirEntry; private ComboViewer generatorViewer; private ComboViewer templateViewer; private DataBindingContext context = new EMFDataBindingContext(); private ImplementationSettings implSettings; private ITemplateDesc selectedTemplate; private EditingDomain domain; private PortGeneratorComposite portMapComposite; private Implementation impl; private EMFTableViewerElementSelector portMapSelector; /** * @param parent * @param style * @param toolkit */ public BaseGeneratorPropertiesComposite(final Composite parent, final int style, final FormToolkit toolkit) { super(parent, style); this.style = style; this.toolkit = toolkit; setLayout(FormLayoutFactory.createSectionClientGridLayout(false, BaseGeneratorPropertiesComposite.NUM_COLUMNS)); } protected void initialize() { createGeneratorEntry(); createTemplateEntry(); createOutputDirEntry(); createPropertiesArea(); createExtraArea(this, this.style, this.toolkit); this.toolkit.paintBordersFor(this); } protected FormToolkit getToolkit() { return this.toolkit; } protected ImplementationSettings getImplSettings() { return this.implSettings; } protected EditingDomain getEditingDomain() { return this.domain; } public DataBindingContext getContext() { return this.context; } /** * Creates the generator entry. * * @param client the client * @param toolkit the toolkit * @param actionBars the action bars */ private void createGeneratorEntry() { final Label label = this.toolkit.createLabel(this, "Generator:"); label.setForeground(this.toolkit.getColors().getColor(IFormColors.TITLE)); this.generatorViewer = new ComboViewer(this, SWT.SINGLE | SWT.READ_ONLY | SWT.DROP_DOWN); this.generatorViewer.getControl().addListener(SWT.MouseVerticalWheel, new Listener() { @Override public void handleEvent(Event event) { event.doit = false; } }); this.generatorViewer.setContentProvider(new ArrayContentProvider()); this.generatorViewer.setLabelProvider(new LabelProvider() { @Override public String getText(final Object element) { final ICodeGeneratorDescriptor desc = (ICodeGeneratorDescriptor) element; return desc.getName(); } }); this.generatorViewer.getControl() .setLayoutData(GridDataFactory.fillDefaults().span(2, 1).grab(true, false).create()); this.generatorViewer.setInput(RedhawkCodegenActivator.getCodeGeneratorsRegistry().getCodegens()); this.generatorViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final ICodeGeneratorDescriptor desc = (ICodeGeneratorDescriptor) ((IStructuredSelection) event .getSelection()).getFirstElement(); if (desc == null) { BaseGeneratorPropertiesComposite.this.templateViewer.setInput(Collections.EMPTY_LIST); } else { ITemplateDesc[] templates = RedhawkCodegenActivator.getCodeGeneratorTemplatesRegistry() .findTemplatesByCodegen(desc.getId()); BaseGeneratorPropertiesComposite.this.templateViewer.setInput(templates); } } }); } /** * Creates the output dir entry. * * @param client the client * @param toolkit the toolkit * @param actionBars the action bars */ private void createOutputDirEntry() { this.outputDirEntry = new FormEntry(this, this.toolkit, "Output Dir:", SWT.SINGLE, "Browse...", false); this.outputDirEntry.getText().setToolTipText("Directory where generated code will be created."); } /** * Creates the template entry. * * @param client the client * @param toolkit the toolkit * @param actionBars the action bars */ private void createTemplateEntry() { final Label label = this.toolkit.createLabel(this, "Template:"); label.setForeground(this.toolkit.getColors().getColor(IFormColors.TITLE)); label.setLayoutData(GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.TOP).create()); this.templateViewer = new ComboViewer(this, SWT.READ_ONLY | SWT.SINGLE | SWT.DROP_DOWN); this.templateViewer.getControl().addListener(SWT.MouseVerticalWheel, new Listener() { @Override public void handleEvent(Event event) { event.doit = false; } }); this.templateViewer.getControl() .setLayoutData(GridDataFactory.fillDefaults().span(2, 1).grab(true, false).create()); this.templateViewer.getControl().setToolTipText("Template for the code generator"); this.templateViewer.setContentProvider(new ArrayContentProvider()); this.templateViewer.setLabelProvider(new LabelProvider() { @Override public String getText(final Object element) { final ITemplateDesc desc = (ITemplateDesc) element; return desc.getName(); } }); this.templateViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final ITemplateDesc desc = (ITemplateDesc) ((IStructuredSelection) event.getSelection()) .getFirstElement(); final EditingDomain dom = BaseGeneratorPropertiesComposite.this.domain; if ((dom != null) && (desc != null) && (desc != BaseGeneratorPropertiesComposite.this.selectedTemplate)) { // Save the selected Template and update the ImplementationSettings BaseGeneratorPropertiesComposite.this.selectedTemplate = desc; // Check if the template has actually changed // - this gets called when selecting implementations in the // implementation list and we don't want change properties // - this gets called when you actually click the dropdown, // here we actually want to change the properties if (!desc.getId().equals(BaseGeneratorPropertiesComposite.this.implSettings.getTemplate())) { final Command command = SetCommand.create(dom, BaseGeneratorPropertiesComposite.this.implSettings, CodegenPackage.Literals.IMPLEMENTATION_SETTINGS__TEMPLATE, desc.getId()); dom.getCommandStack().execute(command); // Change the enablement of the port map if the new // template supports it BaseGeneratorPropertiesComposite.this.portMapComposite .setEnabled(BaseGeneratorPropertiesComposite.this.getEnablePortMap()); // Update the properties display and rebind templateSelected(desc); } } } }); } /** * {@inheritDoc} */ @Override public void dispose() { if ((this.implSettings != null) && this.implSettings.eAdapters().contains(this.portMapSelector)) { this.implSettings.eAdapters().remove(this.portMapSelector); } this.context.dispose(); super.dispose(); } /** * This method is used to add extra Generator Settings information for * subclasses. * * @param parent the parent composite * @param style this composite's style * @param toolkit the toolkit to use */ protected void createExtraArea(final Composite parent, final int style, final FormToolkit toolkit) { this.portMapComposite = new PortGeneratorComposite(parent, SWT.NONE, toolkit); this.portMapComposite.setLayoutData(GridDataFactory.fillDefaults() .span(BaseGeneratorPropertiesComposite.NUM_COLUMNS, 1).grab(true, false).create()); this.portMapComposite.getAddPropertyButton().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleAddPortMapping(); } }); this.portMapComposite.getEditPropertyButton().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleEditPortMapping(); } }); this.portMapComposite.getRemovePropertyButton().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleRemovePortMapping(); } }); this.portMapComposite.getPortMapViewer().addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final boolean enabled = BaseGeneratorPropertiesComposite.this.portMapComposite.isEnabled(); BaseGeneratorPropertiesComposite.this.portMapComposite.getRemovePropertyButton() .setEnabled(enabled && !event.getSelection().isEmpty()); BaseGeneratorPropertiesComposite.this.portMapComposite.getEditPropertyButton() .setEnabled(enabled && !event.getSelection().isEmpty()); BaseGeneratorPropertiesComposite.this.portMapComposite.getAddPropertyButton().setEnabled( enabled && BaseGeneratorPropertiesComposite.this.getUnmappedRepIds(null).size() > 0); } }); } /** * This returns the outputDirEntry field * * @return the outputDirEntry field * @since 7.0 */ @Override public FormEntry getOutputDirEntry() { return this.outputDirEntry; } /** * This returns the selected generator. * * @return the currently selected code generator descriptor */ public ICodeGeneratorDescriptor getSelectedGenerator() { return (ICodeGeneratorDescriptor) ((IStructuredSelection) this.generatorViewer.getSelection()) .getFirstElement(); } /** * This returns the selected template. * * @return the currently selected template descriptor */ public ITemplateDesc getSelectedTemplate() { return (ITemplateDesc) ((IStructuredSelection) this.templateViewer.getSelection()).getFirstElement(); } @Override public void bind(final ArrayList<Binding> bindList, final EditingDomain editingDomain, final DataBindingContext context, final Implementation impl, final ImplementationSettings implSettings) { this.impl = impl; this.implSettings = implSettings; this.context = context; this.domain = editingDomain; preBind(this.impl, this.implSettings, bindList); bindList.add(context.bindValue(ViewersObservables.observeSingleSelection(this.generatorViewer), EMFEditObservables.observeValue(editingDomain, implSettings, CodegenPackage.Literals.IMPLEMENTATION_SETTINGS__GENERATOR_ID), createGeneratorTargetToModel(), createGeneratorModelToTarget())); bindList.add(FormEntryBindingFactory.bind(context, this.outputDirEntry, editingDomain, CodegenPackage.Literals.IMPLEMENTATION_SETTINGS__OUTPUT_DIR, implSettings, null, null)); bindList.add(context.bindValue(ViewersObservables.observeSingleSelection(this.templateViewer), EMFEditObservables.observeValue(editingDomain, implSettings, CodegenPackage.Literals.IMPLEMENTATION_SETTINGS__TEMPLATE), createTemplateTargetToModel(), createTemplateModelToTarget())); this.portMapComposite.setEnabled(this.getEnablePortMap()); this.portMapComposite.getPortMapViewer().setInput(implSettings); if (this.portMapSelector == null) { this.portMapSelector = new EMFTableViewerElementSelector(this.portMapComposite.getPortMapViewer()); } if (!this.implSettings.eAdapters().contains(this.portMapSelector)) { this.implSettings.eAdapters().add(this.portMapSelector); } this.createPropertyBinding(); this.portMapComposite.getAddPropertyButton() .setEnabled((getUnmappedRepIds(null).size() > 0) && (this.portMapComposite.isEnabled())); } private boolean getEnablePortMap() { return ((this.getSelectedTemplate() != null) && this.getSelectedTemplate().delegatePortGeneration()); } /** * @return */ private UpdateValueStrategy createTemplateModelToTarget() { final EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(String.class, ITemplateDesc.class) { @Override public Object convert(final Object fromObject) { if (fromObject == null) { return null; } final String templateId = fromObject.toString(); final ITemplateDesc template = RedhawkCodegenActivator.getCodeGeneratorTemplatesRegistry() .findTemplate(templateId); return template; } }); return strategy; } /** * @return */ private UpdateValueStrategy createTemplateTargetToModel() { final EMFEmptyStringToNullUpdateValueStrategy strategy = new EMFEmptyStringToNullUpdateValueStrategy(); strategy.setConverter(new Converter(ITemplateDesc.class, String.class) { @Override public Object convert(final Object fromObject) { if (fromObject == null) { return null; } final ITemplateDesc desc = (ITemplateDesc) fromObject; return desc.getId(); } }); return strategy; } /** * @return */ private UpdateValueStrategy createGeneratorTargetToModel() { final EMFEmptyStringToNullUpdateValueStrategy strategy = new EMFEmptyStringToNullUpdateValueStrategy(); strategy.setConverter(new Converter(ICodeGeneratorDescriptor.class, String.class) { @Override public Object convert(final Object fromObject) { if (fromObject == null) { return null; } final ICodeGeneratorDescriptor desc = (ICodeGeneratorDescriptor) fromObject; return desc.getId(); } }); return strategy; } /** * @return */ private UpdateValueStrategy createGeneratorModelToTarget() { final EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(String.class, ICodeGeneratorDescriptor.class) { @Override public Object convert(final Object fromObject) { if (fromObject == null) { return null; } final String generatorId = fromObject.toString(); final ICodeGeneratorDescriptor generator = RedhawkCodegenActivator.getCodeGeneratorsRegistry() .findCodegen(generatorId); return generator; } }); return strategy; } /** * This returns the template specified in the ImplementationSettings or the * default one that corresponds to the generator passed in * * @param generator the generator to get templates for * @return the specified template or a default one if it's not found */ protected ITemplateDesc getTemplateDesc(final ICodeGeneratorDescriptor generator) { if (generator == null) { return null; } String templateId = this.implSettings.getTemplate(); // If the templateId is null or old style, select the legacy code // generator template if the implementationSettings has existing props if (((templateId == null) || ("src/".equals(templateId))) && (this.implSettings.getProperties().size() > 0)) { templateId = this.implSettings.getGeneratorId(); } ITemplateDesc template = null; ITemplateDesc genTemplate = null; final ITemplateDesc[] temps = RedhawkCodegenActivator.getCodeGeneratorTemplatesRegistry() .findTemplatesByCodegen(generator.getId()); for (final ITemplateDesc temp : temps) { // Keep track of the default generator template if (temp.getId().equals(generator.getId())) { genTemplate = temp; } if (temp.getId().equals(templateId)) { template = temp; break; } } // If we didn't find the template for some reason, return the default // generator template return (template != null) ? template : genTemplate; // SUPPRESS CHECKSTYLE AvoidInline } /** * Handle add mapping. */ private void handleAddPortMapping() { final HashSet<String> repIds = getUnmappedRepIds(null); final GeneratorDialog dialog = new GeneratorDialog(getShell(), "Add Generator Mapping", null, repIds, this.impl.getProgrammingLanguage().getName()); if (dialog.open() == Window.OK) { final EObject ref = dialog.getValue(); this.domain.getCommandStack().execute(AddCommand.create(this.domain, this.implSettings, CodegenPackage.Literals.IMPLEMENTATION_SETTINGS__PORT_GENERATORS, ref)); } } /** * Handle edit mapping. */ private void handleEditPortMapping() { final PortRepToGeneratorMap curProp = (PortRepToGeneratorMap) ((IStructuredSelection) this.portMapComposite .getPortMapViewer().getSelection()).getFirstElement(); final HashSet<String> repIds = getUnmappedRepIds(curProp.getRepId()); final GeneratorDialog dialog = new GeneratorDialog(getShell(), "Edit Generator Mapping", curProp, repIds, this.impl.getProgrammingLanguage().getName()); if (dialog.open() == Window.OK) { final PortRepToGeneratorMap ref = (PortRepToGeneratorMap) dialog.getValue(); this.domain.getCommandStack().execute(SetCommand.create(this.domain, curProp, CodegenPackage.Literals.PORT_REP_TO_GENERATOR_MAP__GENERATOR, ref.getGenerator())); } } /** * Handle remove mapping. */ private void handleRemovePortMapping() { final PortRepToGeneratorMap curProp = (PortRepToGeneratorMap) ((IStructuredSelection) this.portMapComposite .getPortMapViewer().getSelection()).getFirstElement(); this.domain.getCommandStack().execute(RemoveCommand.create(this.domain, this.implSettings, CodegenPackage.Literals.IMPLEMENTATION_SETTINGS__PORT_GENERATORS, curProp)); } /** * This returns a set of repIds representing all the ports for the current * implementation that do not have a generator assigned. If currentRep is * not null, it adds it to the list. * * @param currentRep the repId to add to the set, or null if none should be * added * @return set of repIds without generators */ private HashSet<String> getUnmappedRepIds(final String currentRep) { final HashSet<String> repIds = new HashSet<String>(); final Descriptor descriptor = ((SoftPkg) this.impl.eContainer()).getDescriptor(); if ((descriptor != null) && (descriptor.getComponent() != null)) { final Ports ports = descriptor.getComponent().getComponentFeatures().getPorts(); // Store the current RepIds for (final Provides p : ports.getProvides()) { repIds.add(p.getRepID()); } for (final Uses u : ports.getUses()) { repIds.add(u.getRepID()); } // filter out the used ones for (final PortRepToGeneratorMap r : this.implSettings.getPortGenerators()) { repIds.remove(r.getRepId()); } // Add the passed in rep if necessary if (currentRep != null) { repIds.add(currentRep); } } return repIds; } public void setEditable(final boolean canEdit) { this.portMapComposite.getAddPropertyButton() .setEnabled(canEdit && (getUnmappedRepIds(null).size() > 0) && this.portMapComposite.isEnabled()); this.portMapComposite.setEditable(canEdit); } /** * This is called after a new template is selected that doesn't match the * previously selected one. When this is called, the stored template has * been updated. * * @param desc the newly selected template descriptor */ protected abstract void templateSelected(ITemplateDesc desc); /** * Creates the properties entry. */ protected abstract void createPropertiesArea(); /** * This is called when bind is called on the composite, but before any * bindings are created. * * @param impl the current implementation * @param implSettings the current implementation settings * @param bindList the binding list used by the bind() method */ protected abstract void preBind(final Implementation impl, final ImplementationSettings implSettings, final List<Binding> bindList); /** * Creates the property binding. */ protected abstract void createPropertyBinding(); }