/** * 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.core.graphiti.sad.ui.editor; import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CommandStack; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.URI; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.statushandlers.StatusManager; import gov.redhawk.core.graphiti.sad.ui.GraphitiSadUIPlugin; import gov.redhawk.core.graphiti.sad.ui.diagram.providers.WaveformExplorerDiagramTypeProvider; import gov.redhawk.core.graphiti.sad.ui.modelmap.GraphitiSADModelAdapter; import gov.redhawk.core.graphiti.sad.ui.modelmap.GraphitiSADModelMap; import gov.redhawk.core.graphiti.sad.ui.modelmap.GraphitiSADModelMapInitializerCommand; import gov.redhawk.core.graphiti.sad.ui.modelmap.ScaWaveformModelAdapter; import gov.redhawk.core.graphiti.ui.editor.AbstractGraphitiDiagramEditor; import gov.redhawk.core.graphiti.ui.util.DUtil; import gov.redhawk.model.sca.RefreshDepth; import gov.redhawk.model.sca.ScaComponent; import gov.redhawk.model.sca.ScaWaveform; import gov.redhawk.model.sca.commands.NonDirtyingCommand; import gov.redhawk.model.sca.commands.ScaModelCommand; import gov.redhawk.sca.ui.ScaFileStoreEditorInput; import mil.jpeojtrs.sca.sad.SoftwareAssembly; import mil.jpeojtrs.sca.util.CorbaUtils; /** * The multi-page explorer editor for waveforms ({@link ScaWaveform}). Includes a Graphiti diagram. */ public class GraphitiWaveformExplorerEditor extends AbstractGraphitiSADEditor { private ScaWaveform waveform; private GraphitiSADModelMap modelMap; private ScaWaveformModelAdapter scaListener; private GraphitiSADModelAdapter sadlistener; protected ScaWaveform getWaveform() { return waveform; } protected void setWaveform(ScaWaveform waveform) { this.waveform = waveform; } @Override public < T > T getAdapter(Class<T> adapter) { if (adapter.isInstance(this.waveform)) { return adapter.cast(this.waveform); } return super.getAdapter(adapter); } @Override protected void setInput(IEditorInput input) { if (input instanceof ScaFileStoreEditorInput) { ScaFileStoreEditorInput scaInput = (ScaFileStoreEditorInput) input; if (scaInput.getScaObject() instanceof ScaWaveform) { setWaveform((ScaWaveform) scaInput.getScaObject()); } else { throw new IllegalStateException("Diagram opened with invalid input: " + scaInput.getScaObject()); } } super.setInput(input); } @Override protected void addPages() { super.addPages(); getEditingDomain().getCommandStack().removeCommandStackListener(getCommandStackListener()); // reflect runtime aspects here modelMap.reflectRuntimeStatus(); // set layout for sandbox editors DUtil.layout(getDiagramEditor()); // Adjust the text editor's title to the profile file name if possible IEditorPart textEditor = getTextEditor(); if (textEditor != null) { int pageIndex = getPages().indexOf(textEditor); URI profileURI = waveform.getProfileURI(); if (profileURI != null) { setPageText(pageIndex, profileURI.lastSegment()); } } // Hide the grid for the explorer diagram final Diagram diagram = this.getDiagramEditor().getDiagramBehavior().getDiagramTypeProvider().getDiagram(); if (DUtil.isDiagramExplorer(diagram)) { NonDirtyingCommand.execute(diagram, new NonDirtyingCommand() { @Override public void execute() { diagram.setGridUnit(-1); // hide grid on diagram by setting grid units to -1 } }); } } //////////////////////////////////////////////////// // 1. createDiagramEditor() //////////////////////////////////////////////////// @Override protected AbstractGraphitiDiagramEditor createDiagramEditor() { return new GraphitiWaveformExplorerDiagramEditor(getEditingDomain()); } //////////////////////////////////////////////////// // 2. initModelMap() //////////////////////////////////////////////////// @Override protected void initModelMap() throws CoreException { if (waveform == null) { throw new IllegalStateException("Can not initialize the model map without a waveform"); } SoftwareAssembly sad = getSoftwareAssembly(); if (sad == null) { throw new IllegalStateException("Can not initialize the model map without a software assembly (SAD)"); } if (!waveform.isSetComponents()) { if (Display.getCurrent() != null) { ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getCurrent().getActiveShell()); try { dialog.run(true, true, new IRunnableWithProgress() { @Override public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { CorbaUtils.invoke(new Callable<Object>() { @Override public Object call() throws Exception { waveform.refresh(monitor, RefreshDepth.FULL); return null; } }, monitor); } catch (CoreException e) { throw new InvocationTargetException(e); } } }); } catch (InvocationTargetException | InterruptedException e) { // PASS } } else { try { waveform.refresh(null, RefreshDepth.FULL); } catch (InterruptedException e) { // PASS } } } try { ProgressMonitorDialog loadCompDialog = new ProgressMonitorDialog(Display.getCurrent().getActiveShell()); final int numOfLoadingItems = waveform.getComponents().size() * 2; // for getProfile and getStarted calls loadCompDialog.run(true, true, new IRunnableWithProgress() { @Override public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Loading Waveform Components...", numOfLoadingItems); ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Object> future = executor.submit(new Callable<Object>() { @Override public Object call() throws Exception { int totalProgress = 0; while (totalProgress < numOfLoadingItems && !monitor.isCanceled()) { int newProgress = 0; for (ScaComponent component : waveform.getComponents()) { if (component.getProfile() != null) { newProgress++; } if (component.getStarted() != null) { newProgress++; } } if (newProgress > totalProgress) { monitor.worked(newProgress - totalProgress); totalProgress = newProgress; } Thread.sleep(250); } return null; } }); try { future.get(30, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { monitor.setCanceled(true); StatusManager.getManager().handle(new Status(IStatus.ERROR, GraphitiSadUIPlugin.PLUGIN_ID, "Waveform components failed to load", e), StatusManager.SHOW | StatusManager.LOG); } finally { monitor.done(); } } }); } catch (final Exception e) { // SUPPRESS CHECKSTYLE Logged Catch all exception StatusManager.getManager().handle(new Status(IStatus.ERROR, GraphitiSadUIPlugin.PLUGIN_ID, "Errors occured while loading waveform components", e), StatusManager.SHOW | StatusManager.LOG); } modelMap = createModelMapInstance(); this.sadlistener = new GraphitiSADModelAdapter(modelMap); this.scaListener = new ScaWaveformModelAdapter(modelMap) { @Override public void notifyChanged(Notification notification) { super.notifyChanged(notification); if (notification.getNotifier() == waveform) { if (waveform.isDisposed() && !isDisposed()) { getEditorSite().getPage().getWorkbenchWindow().getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (!isDisposed()) { getEditorSite().getPage().closeEditor(GraphitiWaveformExplorerEditor.this, false); } } }); } } } }; // Initialize the model map, then begin listening to the model CommandStack stack = getEditingDomain().getCommandStack(); CompoundCommand command = new CompoundCommand(); command.append(createModelInitializeCommand()); command.append(new ScaModelCommand() { @Override public void execute() { scaListener.addAdapter(waveform); } }); stack.execute(command); stack.flush(); // Listen to the SAD for changes sad.eAdapters().add(this.sadlistener); } /** * Creates the model map (SAD <-> ScaWaveform). * @return */ protected GraphitiSADModelMap createModelMapInstance() { return new GraphitiSADModelMap(this, waveform); } /** * Creates an EMF {@link Command} to initialize the model map. * @return */ protected Command createModelInitializeCommand() { SoftwareAssembly sad = getSoftwareAssembly(); return new GraphitiSADModelMapInitializerCommand(modelMap, sad, waveform); } //////////////////////////////////////////////////// // 3. createDiagramInput() //////////////////////////////////////////////////// @Override public String getDiagramTypeProviderID() { return WaveformExplorerDiagramTypeProvider.PROVIDER_ID; } @Override public String getDiagramContext() { return DUtil.DIAGRAM_CONTEXT_EXPLORER; } @Override protected void addDiagramLinks(Diagram diagram) { diagram.getLink().getBusinessObjects().add(waveform); } //////////////////////////////////////////////////// // Other //////////////////////////////////////////////////// @Override public void dispose() { if (this.sadlistener != null) { SoftwareAssembly sad = getSoftwareAssembly(); if (sad != null) { sad.eAdapters().remove(this.sadlistener); } this.sadlistener = null; } if (this.scaListener != null) { ScaModelCommand.execute(waveform, new ScaModelCommand() { @Override public void execute() { waveform.eAdapters().remove(GraphitiWaveformExplorerEditor.this.scaListener); } }); this.scaListener = null; } super.dispose(); } @Override public void doSave(final IProgressMonitor monitor) { doSaveAs(); } @Override public List<Object> getOutlineItems() { return Collections.emptyList(); } @Override public void updateTitle() { final String name; if (waveform != null) { name = (waveform.getName() != null) ? waveform.getName() : "Waveform"; } else { name = "Waveform"; } if (Display.getCurrent() != null) { setPartName(name); } else { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (!isDisposed()) { setPartName(name); } } }); } } }