/******************************************************************************* * 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.frontend.ui.internal; import gov.redhawk.frontend.FrontendPackage; import gov.redhawk.frontend.ListenerAllocation; import gov.redhawk.frontend.TunerStatus; import gov.redhawk.frontend.ui.FrontEndUIActivator; import gov.redhawk.frontend.ui.internal.section.FrontendSection; import gov.redhawk.frontend.util.TunerProperties.ListenerAllocationProperties; import gov.redhawk.frontend.util.TunerUtils; import gov.redhawk.model.sca.RefreshDepth; import gov.redhawk.model.sca.ScaDevice; import gov.redhawk.model.sca.ScaDomainManagerRegistry; import gov.redhawk.model.sca.ScaFactory; import gov.redhawk.model.sca.ScaPort; import gov.redhawk.model.sca.ScaSimpleProperty; import gov.redhawk.model.sca.ScaStructProperty; import gov.redhawk.model.sca.ScaUsesPort; import gov.redhawk.model.sca.commands.ScaModelCommand; import gov.redhawk.model.sca.provider.ScaItemProviderAdapterFactory; import gov.redhawk.ui.port.nxmplot.IPlotView; import gov.redhawk.ui.port.nxmplot.PlotActivator; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import mil.jpeojtrs.sca.prf.PrfFactory; import mil.jpeojtrs.sca.prf.PrfPackage; import mil.jpeojtrs.sca.prf.Simple; import mil.jpeojtrs.sca.util.CorbaUtils; import mil.jpeojtrs.sca.util.ScaEcoreUtils; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.expressions.EvaluationContext; 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.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.provider.IItemLabelProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.ISources; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.dialogs.ListSelectionDialog; import org.eclipse.ui.progress.UIJob; import CF.DataType; import CF.PropertiesHelper; import CF.DevicePackage.InsufficientCapacity; import CF.DevicePackage.InvalidCapacity; import CF.DevicePackage.InvalidState; /** * */ public class FeiPlotAction extends FrontendAction { private static final AtomicInteger SECONDARY_ID = new AtomicInteger(); // private IEvaluationContext context; public FeiPlotAction(FrontendSection theSection) { super(theSection, "Plot", "gov.redhawk.frontend.actions.plot", "gov.redhawk.ui.port.nxmplot.command.plot", "icons/plot.gif"); } @Override public void run() { EObject obj = getSection().getInput(); if (obj instanceof TunerStatus) { final TunerStatus tuner = (TunerStatus) obj; final ScaDevice< ? > device = ScaEcoreUtils.getEContainerOfType(tuner, ScaDevice.class); final DataType[] props = createAllocationProperties(tuner); Job job = new Job("Plotting tuner " + tuner.getAllocationID()) { @Override protected IStatus run(IProgressMonitor parentMonitor) { final SubMonitor subMonitor = SubMonitor.convert(parentMonitor, "Plotting tuner " + tuner.getAllocationID(), IProgressMonitor.UNKNOWN); try { IStatus status = CorbaUtils.invoke(new Callable<IStatus>() { @Override public IStatus call() throws Exception { try { subMonitor.subTask("Allocating capacity..."); if (device.allocateCapacity(props)) { return Status.OK_STATUS; } else { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Allocation failed, plot could not launch.", null); } } catch (InvalidCapacity e) { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Invalid Capacity in plot allocation: " + e.msg, e); } catch (InvalidState e) { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Invalid State in plot allocation: " + e.msg, e); } catch (InsufficientCapacity e) { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Insufficient Capacity in plot allocation: " + e.msg, e); } } }, subMonitor.newChild(1)); if (!status.isOK()) { return status; } subMonitor.subTask("Refeshing device..."); device.refresh(subMonitor.newChild(1), RefreshDepth.SELF); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } catch (CoreException e) { return new Status(e.getStatus().getSeverity(), FrontEndUIActivator.PLUGIN_ID, "Failed to plot allocation", e); } finally { subMonitor.done(); } UIJob uiJob = new UIJob("Launching Plot View...") { @Override public IStatus runInUIThread(IProgressMonitor monitor) { try { IStatus retVal = createPlotView(props, device, tuner); if (!retVal.isOK()) { deallocate(tuner, props, device); } return retVal; } catch (ExecutionException e) { deallocate(tuner, props, device); return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Failed to open plot view", e); } } }; uiJob.setUser(false); uiJob.setSystem(true); uiJob.schedule(); return Status.OK_STATUS; } }; job.setUser(true); job.schedule(); } } private DataType[] createAllocationProperties(TunerStatus tuner) { List<DataType> listenerCapacity = new ArrayList<DataType>(); ScaStructProperty struct; DataType dt = new DataType(); struct = ScaFactory.eINSTANCE.createScaStructProperty(); for (ListenerAllocationProperties allocProp : ListenerAllocationProperties.values()) { ScaSimpleProperty simple = ScaFactory.eINSTANCE.createScaSimpleProperty(); Simple definition = (Simple) PrfFactory.eINSTANCE.create(PrfPackage.Literals.SIMPLE); definition.setType(allocProp.getType()); definition.setId(allocProp.getType().getLiteral()); definition.setName(allocProp.getType().getName()); simple.setDefinition(definition); simple.setId(allocProp.getId()); switch (allocProp) { case EXISTING_ALLOCATION_ID: simple.setValue(TunerUtils.getControlId(tuner)); break; case LISTENER_ALLOCATION_ID: String listenerAllocationID = "Plot_" + System.getProperty("user.name") + ":" + System.currentTimeMillis(); simple.setValue(listenerAllocationID); break; default: } struct.getFields().add(simple); } dt.id = "FRONTEND::listener_allocation"; dt.value = struct.toAny(); listenerCapacity.add(dt); return listenerCapacity.toArray(new DataType[0]); } private IStatus createPlotView(final DataType[] props, final ScaDevice< ? > device, final TunerStatus tuner) throws ExecutionException { List<ScaPort< ? , ? >> devicePorts = device.getPorts(); List<ScaUsesPort> usesPorts = new ArrayList<ScaUsesPort>(); for (ScaPort< ? , ? > port : devicePorts) { if (port instanceof ScaUsesPort) { usesPorts.add((ScaUsesPort) port); } } final ScaItemProviderAdapterFactory factory = new ScaItemProviderAdapterFactory(); final ScaUsesPort usesPort; if (usesPorts.size() == 1) { usesPort = usesPorts.get(0); } else if (usesPorts.size() > 1) { ListSelectionDialog dialog = new ListSelectionDialog(Display.getCurrent().getActiveShell(), usesPorts, new ArrayContentProvider(), new AdapterFactoryLabelProvider(factory), "Select output port to use:"); if (dialog.open() == Window.OK) { Object[] result = dialog.getResult(); if (result.length >= 1) { usesPort = (ScaUsesPort) result[0]; } else { usesPort = null; } } else { usesPort = null; } } else { usesPort = null; } if (usesPort == null) { return Status.CANCEL_STATUS; } final StringBuilder name = new StringBuilder(); final StringBuilder tooltip = new StringBuilder(); createTooltip(factory, name, tooltip, usesPort); factory.dispose(); // Connect the port final List<ScaUsesPort> ports = new ArrayList<ScaUsesPort>(); ports.add(usesPort); // IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); // IHandlerService handlerService = (IHandlerService) window.getService(IHandlerService.class); // ICommandService svc = (ICommandService) window.getService(ICommandService.class); // Command comm = svc.getCommand(IPlotView.COMMAND_ID); // final ExecutionEvent evt; // evt = handlerService.createExecutionEvent(comm, null); // // EvaluationContext exContext = new EvaluationContext((IEvaluationContext) evt.getApplicationContext(), ports); EvaluationContext exContext = new EvaluationContext(null, ports); exContext.addVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME, new StructuredSelection(ports)); exContext.addVariable(ISources.ACTIVE_MENU_SELECTION_NAME, new StructuredSelection(ports)); exContext.addVariable(ISources.ACTIVE_WORKBENCH_WINDOW_NAME, PlatformUI.getWorkbench().getActiveWorkbenchWindow()); Map<String, Object> exParam = new HashMap<String, Object>(); exParam.put(IPlotView.PARAM_PLOT_TYPE, "LINE"); exParam.put(IPlotView.PARAM_ISFFT, "false"); final String listenerID = getListenerID(props); exParam.put(IPlotView.PARAM_CONNECTION_ID, listenerID); exParam.put(IPlotView.PARAM_SECONDARY_ID, createSecondaryId()); IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); ICommandService svc = (ICommandService) window.getService(ICommandService.class); Command comm = svc.getCommand(IPlotView.COMMAND_ID); ExecutionEvent ex = new ExecutionEvent(comm, exParam, null, exContext); final IPlotView view = PlotActivator.getDefault().showPlotView(ex); if (view != null) { view.setPartName(name.toString()); view.setTitleToolTip(tooltip.toString()); view.getPlotPageBook().addDisposeListener(getDisposeListener(tuner, props, device)); ScaModelCommand.execute(tuner, new ScaModelCommand() { @Override public void execute() { for (ListenerAllocation a : tuner.getListenerAllocations()) { if (a.getListenerID().equals(listenerID)) { a.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(org.eclipse.emf.common.notify.Notification msg) { if (msg.isTouch()) { return; } switch (msg.getFeatureID(ListenerAllocation.class)) { case FrontendPackage.LISTENER_ALLOCATION__TUNER_STATUS: if (msg.getNewValue() == null) { ((Notifier) msg.getNotifier()).eAdapters().remove(this); if (view.getPlotPageBook().isDisposed()) { return; } view.getPlotPageBook().getDisplay().asyncExec(new Runnable() { @Override public void run() { view.getPlotPageBook().dispose(); } }); } break; default: } } }); } } } }); } else { return Status.CANCEL_STATUS; } return Status.OK_STATUS; } private DisposeListener getDisposeListener(final TunerStatus tuner, final DataType[] props, final ScaDevice< ? > device) { DisposeListener disposeListener = new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { if (containsListener(tuner, props)) { deallocate(tuner, props, device); } } }; return disposeListener; } private boolean containsListener(TunerStatus tuner, DataType[] props) { String listenerId = getListenerID(props); for (ListenerAllocation a : tuner.getListenerAllocations()) { if (a.getListenerID().equals(listenerId)) { return true; } } return false; } private void deallocate(final TunerStatus tuner, final DataType[] props, final ScaDevice< ? > device) { if (!containsListener(tuner, props)) { return; } Job job = new Job("Fei Deallocate Listener") { @Override protected IStatus run(IProgressMonitor parentMonitor) { if (!containsListener(tuner, props)) { return Status.CANCEL_STATUS; } try { SubMonitor subMonitor = SubMonitor.convert(parentMonitor, "Deallocating listener...", 2); if (device != null && !device.isDisposed()) { CorbaUtils.invoke(new Callable<IStatus>() { @Override public IStatus call() throws Exception { try { device.deallocateCapacity(props); return Status.OK_STATUS; } catch (InvalidCapacity e) { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Invalid Capacity in plot deallocation: " + e.msg, e); } catch (InvalidState e) { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Invalid State in plot deallocation: " + e.msg, e); } } }, subMonitor.newChild(1)); device.refresh(subMonitor.newChild(1), RefreshDepth.SELF); } } catch (InterruptedException e) { return new Status(IStatus.ERROR, FrontEndUIActivator.PLUGIN_ID, "Interrupted Exception during plot deallocation", e); } catch (CoreException e) { return new Status(e.getStatus().getSeverity(), FrontEndUIActivator.PLUGIN_ID, "Failed to deallocate", e); } return Status.OK_STATUS; } }; job.setUser(false); job.setSystem(true); job.schedule(); } private String getListenerID(DataType[] props) { for (DataType prop : props) { DataType[] dt = PropertiesHelper.extract(prop.value); for (DataType d : dt) { if (d.id.equals(ListenerAllocationProperties.LISTENER_ALLOCATION_ID.getId())) { return (d.value.toString()); } } } return ""; } private String createSecondaryId() { return "FEI" + SECONDARY_ID.incrementAndGet(); } private void createTooltip(final ScaItemProviderAdapterFactory factory, final StringBuilder name, final StringBuilder tooltip, ScaUsesPort usesPort) { List<String> tmpList4Tooltip = new LinkedList<String>(); for (EObject eObj = usesPort; !(eObj instanceof ScaDomainManagerRegistry) && eObj != null; eObj = eObj.eContainer()) { Adapter adapter = factory.adapt(eObj, IItemLabelProvider.class); if (adapter instanceof IItemLabelProvider) { IItemLabelProvider lp = (IItemLabelProvider) adapter; String text = lp.getText(eObj); if (text != null && !text.isEmpty()) { tmpList4Tooltip.add(0, text); } } } String nameStr = usesPort.getName(); if (nameStr != null && !nameStr.isEmpty()) { name.append(nameStr).append(" "); } if (!tmpList4Tooltip.isEmpty()) { for (Iterator<String> i = tmpList4Tooltip.iterator(); i.hasNext();) { tooltip.append(i.next()); if (i.hasNext()) { tooltip.append(" -> "); } } tooltip.append("\n"); } } }