Java tutorial
/******************************************************************************* * Copyright (c) 2014 UT-Battelle, LLC. * 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: * Initial API and implementation and/or initial documentation - Jay Jay Billings, * Jordan H. Deyton, Dasha Gorin, Alexander J. McCaskey, Taylor Patterson, * Claire Saunders, Matthew Wang, Anna Wojtowicz *******************************************************************************/ package org.eclipse.ice.viz.csv.viewer; import java.util.ArrayList; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.ice.client.widgets.NextAction; import org.eclipse.ice.client.widgets.PlayAction; import org.eclipse.ice.client.widgets.PlayableViewPart; import org.eclipse.ice.client.widgets.PreviousAction; import org.eclipse.ice.datastructures.ICEObject.IUpdateable; import org.eclipse.ice.datastructures.ICEObject.IUpdateableListener; import org.eclipse.ice.datastructures.form.ResourceComponent; import org.eclipse.ice.datastructures.resource.VizResource; import org.eclipse.ice.viz.DeletePlotAction; import org.eclipse.ice.viz.IDeletePlotActionViewPart; import org.eclipse.ice.viz.VizFileViewer; import org.eclipse.ice.viz.service.csv.CSVPlotEditor; import org.eclipse.ice.viz.service.csv.PlotProvider; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPersistableElement; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.part.WorkbenchPart; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class extends the ViewPart class and provides a view in the * Visualization Perspective to display CSV plots that are currently available. * * @author Jay Jay Billings, Taylor Patterson, Jordan H. Deyton, Matthew Wang */ public class CSVPlotViewer extends PlayableViewPart implements IDeletePlotActionViewPart, IUpdateableListener, ISelectionChangedListener { /** * Logger for handling event messages and other information. */ private static final Logger logger = LoggerFactory.getLogger(CSVPlotViewer.class); /** * The ID for this view */ public static final String ID = "org.eclipse.ice.viz.plotviewer.CSVPlotViewer"; /** * The currently selected CSV file stored as a VizResource. */ private VizResource resource; /** * A List of all PlotProviders displayed in this view. */ private final ArrayList<PlotProvider> plottedProviders; /** * The active ResourceComponent */ private ResourceComponent resourceComponent; /** * The TreeViewer contained in this ViewPart used for managing resources in * the view. */ private TreeViewer plotTreeViewer; /** * The Action for selecting the next element in the list. */ private NextAction nextAction; /** * The Action for playing through the list of plots. */ private PlayAction playAction; /** * The Action for selecting the previous element in the list. */ private PreviousAction prevAction; /** * Creates a dialog that lets the user select from the available plots for * the currently selected CSV file from the {@link VizFileViewer}. */ private AddCSVPlotAction addPlotAction; /** * Removes the selected plot(s) from the PlotViewer. */ private DeletePlotAction deletePlotAction; /** * The default constructor. */ public CSVPlotViewer() { // Initialize the variables tied to the current CSV file stored as a // VizResource. resource = null; // Initialize the lists for the selected plots. plottedProviders = new ArrayList<PlotProvider>(); // This will always be a playable view, so set it that way. playable = true; return; } /** * Creates the widgets and controls for the PlotViewer. This includes * {@link #plotTreeViewer}. * * @param parent * The parent Composite that will contain this PlotViewer. * * @see ViewPart#createPartControl(Composite) */ @Override public void createPartControl(Composite parent) { // Create the tool bar buttons for the view createActions(); // Initialize the TreeViewer. plotTreeViewer = new TreeViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); plotTreeViewer.addSelectionChangedListener(this); // Create content and label providers initializeTreeViewer(plotTreeViewer); // Register this view's ListViewer as a SelectionProvider getSite().setSelectionProvider(plotTreeViewer); return; } /** * Does nothing yet. * * @see WorkbenchPart#setFocus() */ @Override public void setFocus() { return; } /** * This function is called by the NextAction and PlayAction to set the * selection to the next element in the list. * * @see PlayableViewPart#setToNextResource() */ @Override public void setToNextResource() { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { // Get the currently selected resource in the view. (Or the // first selected resource if multiple resources are // selected even though this has no effect.) TreeItem[] currSelection = plotTreeViewer.getTree().getSelection(); int currIndex = plotTreeViewer.getTree().indexOf(currSelection[0]); // Set the selection to the next resource in the tree or the // first resource if the last resource is currently selected. if (!plottedProviders.isEmpty()) { int nextIndex = (currIndex + 1) % plottedProviders.size(); plotTreeViewer.setSelection(new StructuredSelection(plottedProviders.get(nextIndex)), true); } } }); return; } /** * This function is called by the PreviousAction to set the selection to the * previous action in the list. * * @see PlayableViewPart#setToPreviousResource() */ @Override public void setToPreviousResource() { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { // Get the currently selected resource in the view. (Or the // first selected resource if multiple resources are // selected even though this has no effect.) TreeItem[] currSelection = plotTreeViewer.getTree().getSelection(); int currIndex = plotTreeViewer.getTree().indexOf(currSelection[0]); // Set the selection to the previous resource in the tree or the // last resource if the first resource is currently selected. if (!plottedProviders.isEmpty()) { int prevIndex = (currIndex - 1) % plottedProviders.size(); if (prevIndex < 0) { prevIndex = plottedProviders.size() - 1; } plotTreeViewer.setSelection(new StructuredSelection(plottedProviders.get(prevIndex)), true); } } }); return; } /** * Refreshes the content in the {@link #plotTreeViewer}. */ private void refreshPlotViewer() { // Sync with the display PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { // If possible, reset the plotTreeViewer's input. if (plotTreeViewer != null) { logger.info("CSVPlotViewer message: " + "Refreshing TreeViewer."); // Reset the input for the plotTreeViewer. The viewer just // takes an array of objects. plotTreeViewer.setInput(plottedProviders); plotTreeViewer.refresh(); plotTreeViewer.getTree().redraw(); } } }); return; } /** * Updates the PlotViewer (specifically, the {@link #plotTreeViewer}) when * the associated Component is updated. * * @param component * The Component that was just updated. */ @Override public void update(IUpdateable component) { logger.info("CSVPlotViewer Message: Incoming resource update."); // Sync with the display PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { // If possible, reset the plotTreeViewer's input. if (plotTreeViewer != null) { // TODO Reset the input for the plotTreeViewer. // plotTreeViewer.setInput(null); logger.info("CSVPlotViewer Message: " + "Updating resource table."); plotTreeViewer.refresh(); plotTreeViewer.getTree().redraw(); } } }); return; } /** * This operation sets the ResourceComponent that should be used by this * view. It also registers this view with the ResourceComponent so that it * can be notified of state changes through the IUpdateableListener * interface. * * @param component * The ResourceComponent */ public void setResourceComponent(ResourceComponent component) { // Make sure the ResourceComponent exists. if (component != null) { // If there was an associated ResourceComponent, unregister from it. if (resourceComponent != null) { resourceComponent.unregister(this); } // Set the component reference. resourceComponent = component; // Register this view with the Component to receive updates. component.register(this); // Update the view. update(component); } return; } /** * This operation retrieves the active ResourceComponent of this view or * null if the component does not exist. * * @return The ResourceComponent or null if the component was not previously * set. */ public ResourceComponent getResourceComponent() { // begin-user-code return resourceComponent; // end-user-code } /** * Creates the JFace Actions associated with this PlotViewer. */ private void createActions() { // Get the IToolBarManager IActionBars actionBars = getViewSite().getActionBars(); IToolBarManager toolBarManager = actionBars.getToolBarManager(); // Create a previous button and add it to the tool bar prevAction = new PreviousAction(this); toolBarManager.add(prevAction); prevAction.setEnabled(!plottedProviders.isEmpty()); // Create a play button and add it to the tool bar playAction = new PlayAction(this); toolBarManager.add(playAction); playAction.setEnabled(!plottedProviders.isEmpty()); // Create a next button and add it to the tool bar nextAction = new NextAction(this); toolBarManager.add(nextAction); nextAction.setEnabled(!plottedProviders.isEmpty()); // Create a delete button and add it to the tool bar deletePlotAction = new DeletePlotAction(this); toolBarManager.add(deletePlotAction); deletePlotAction.setEnabled(!plottedProviders.isEmpty()); // Create an add button and add it to the tool bar addPlotAction = new AddCSVPlotAction(this); toolBarManager.add(addPlotAction); addPlotAction.setEnabled(resource != null); return; } /** * Initializes the provided TreeViewer based on the current VizResource for * this PlotViewer. * * @param inputTreeViewer * The TreeViewer that should be configured to display the * currently selected plots for a CSV file. */ private void initializeTreeViewer(TreeViewer inputTreeViewer) { // Set the content provider, which determines how the input should // produce elements in the TreeViewer. inputTreeViewer.setContentProvider(new PlotTreeContentProvider()); // Set up the label provider, which determines what string is displayed // for each element in the tree. Currently, this only needs to produce // a string for each PlotProvider. inputTreeViewer.setLabelProvider(new PlotTreeLabelProvider()); return; } /** * Gets the current VizResource wrapping the CSV file that is being used by * this PlotViewer. * * @return A VizResource. */ public VizResource getResource() { return resource; } /** * Adds a plot to the current set of CSV plots. * * @param newPlotProvider * The PlotProvider for the plot that is to be added. */ public void addPlot(PlotProvider newPlotProvider) { // Make sure the PlotProvider and current resource are not null if (newPlotProvider != null && resource != null) { // Add this entry to our bookkeeping. plottedProviders.add(newPlotProvider); logger.info("CSVPlotViewer message: adding plot \"" + newPlotProvider.getPlotTitle() + "\"."); // Update the plotViewer. refreshPlotViewer(); } return; } /** * Removes a plot from the current set of CSV plots. * * @param newPlotProvider * The PlotProvider for the plot that is to be removed. */ public void removePlot(PlotProvider newPlotProvider) { // Make sure the entry is not null and that it is marked as plotted. if (newPlotProvider != null) { // Get the index of the entry in the list of plotted entries. int index = -1; for (int i = 0; i < plottedProviders.size(); i++) { if (newPlotProvider == plottedProviders.get(i)) { index = i; break; } } if (index > -1) { // Remove the resource and entry from our bookkeeping. plottedProviders.remove(index); logger.info("CSVPlotViewer message: Removing plot \"" + newPlotProvider.getPlotTitle() + "\"."); // Update the plotViewer. refreshPlotViewer(); } } return; } /** * This method draws the plot for the specified entry if it is one of the * selected plots. * * @param newPlotProvider * The PlotProvider to draw. */ public void drawPlot(PlotProvider newPlotProvider) { // Make sure the entry is not null and that it is marked as plotted. if (newPlotProvider != null) { // Get the index of the entry in the list of plotted entries. int index = -1; for (int i = 0; i < plottedProviders.size(); i++) { if (newPlotProvider == plottedProviders.get(i)) { index = i; break; } } if (index > -1) { logger.info("CSVPlotViewer message: Drawing plot \"" + newPlotProvider.getPlotTitle()); // Get the CSVPlotEditor. IEditorPart editorPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() .getActiveEditor(); CSVPlotEditor editor = (CSVPlotEditor) editorPart; // Display the plot in the editor. editor.showPlotProvider(newPlotProvider); } } return; } /** * Removes all plots selected in {@link #plotTreeViewer}. */ @Override public void removeSelection() { // Make sure the viewer's controls have been created. if (plotTreeViewer != null) { // Get the selection from the plotTreeViewer. It should at least be // an IStructuredSelection (a parent interface of TreeSelections). ISelection selection = plotTreeViewer.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; // Create a List of PlotProviders to be unplotted. List<PlotProvider> providers = new ArrayList<PlotProvider>(); // Loop over the selected elements and add any PlotProviders to // the List of PlotProviders to be unplotted. for (Iterator<?> iter = structuredSelection.iterator(); iter.hasNext();) { Object object = iter.next(); if (object instanceof PlotProvider) { providers.add((PlotProvider) object); } } // Remove all of the entries that were selected. for (PlotProvider provider : providers) { removePlot(provider); } } } return; } /** * Draws all plots selected in {@link #plotTreeViewer}. */ public void drawSelection() { // Get the selection from the plotTreeViewer. It should at least be // an IStructuredSelection (a parent interface of TreeSelections). ISelection selection = plotTreeViewer.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; // Create a List of PlotProviders to be unplotted. List<PlotProvider> providers = new ArrayList<PlotProvider>(); // Loop over the selected elements and add any PlotProviders to // the List of PlotProviders to be unplotted. for (Iterator<?> iter = structuredSelection.iterator(); iter.hasNext();) { Object object = iter.next(); if (object instanceof PlotProvider) { providers.add((PlotProvider) object); } } // Remove all of the entries that were selected. for (PlotProvider provider : providers) { drawPlot(provider); } } return; } /** * This method is called when the selection in the VizFileViewer has * changed. It is used to listen for changes to the currently selected * VizResource in the {@link VizFileViewer}. * * @param inResource * The VizResource in the VizFileViewer to set this object's * {@link #resource} to. */ public void setResource(VizResource inResource) { // Reset the VizResource resource = inResource; String fileName = ""; // Get the file set title or file name if (resource.getFileSet() != null && resource.getFileSetTitle() != null) { fileName = resource.getFileSetTitle(); } else { fileName = resource.getContents().getAbsolutePath(); } logger.info( "CSVPlotViewer message: The " + "selected file from the VizFileViewer is \"" + fileName + "\"."); // Enable the AddPlotAction. addPlotAction.setEnabled(true); return; } /** * A Map that keeps track of IEditorInputs for existing, opened PlotEditors * based on some key shared with the available plots in this PlotViewer. */ // FIXME - Change this from an IdentityHashMap on the PlotProviders! We // should use a regular HashMap and some key value shared with items in the // PlotViewer's list. private final Map<PlotProvider, IEditorInput> editorInputs = new IdentityHashMap<PlotProvider, IEditorInput>(); // ---- Implements ISelectionChangedListener ---- // /** * This method is called when the selection in the PlotViewer has changed. * It should either open a new plot or re-open an existing one. * * @param event * The SelectionChangedEvent that fired this method. */ @Override public void selectionChanged(SelectionChangedEvent event) { // Get the selection from the TreeViewer and see if it's empty. ISelection selection = plotTreeViewer.getSelection(); boolean notEmptySelection = !selection.isEmpty(); if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; Object firstElement = structuredSelection.getFirstElement(); // If a plot was selected from the list, we can try to open a // PlotEditor. if (notEmptySelection && firstElement instanceof PlotProvider) { PlotProvider provider = (PlotProvider) firstElement; // See if an IEditorInput has already been created for the // selected plot. IEditorInput editorInput = editorInputs.get(provider); boolean newEditor = false; if (editorInput == null) { editorInput = new IEditorInput() { @Override public Object getAdapter(Class adapter) { return null; } @Override public String getToolTipText() { return null; } @Override public IPersistableElement getPersistable() { return null; } @Override public String getName() { return null; } @Override public ImageDescriptor getImageDescriptor() { return null; } @Override public boolean exists() { return false; } }; newEditor = true; // Store the IEditorInput for reference later in case the // same item is selected again. editorInputs.put(provider, editorInput); } // Get the workbench page IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); // Open an editor with the specified IEditorInput. If it's a new // IEditorInput or the associated editor has been closed, the // workbench will automatically create a new editor. Otherwise, // an existing one is opened. try { page.openEditor(editorInput, CSVPlotEditor.ID); } catch (PartInitException e) { // Complain logger.error(getClass().getName() + " Exception!", e); Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); // Throw up an error dialog MessageBox errBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); errBox.setText("CSV Plot Editor Error!"); errBox.setMessage("Unable to open the CSV Plot Editor!"); errBox.open(); } // Draw the selection if (newEditor) { drawSelection(); } } } // Enable the other actions in this view if possible. deletePlotAction.setEnabled(notEmptySelection); prevAction.setEnabled(notEmptySelection); playAction.setEnabled(notEmptySelection); nextAction.setEnabled(notEmptySelection); return; } // ---------------------------------------------- // /** * Public method for retrieving the selection in this view. * * @return The PlotProvider selected in this view. */ public PlotProvider getSelection() { // Get the selection from the plotTreeViewer. It should at least be // an IStructuredSelection (a parent interface of TreeSelections). ISelection selection = plotTreeViewer.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; // Loop over the selected elements and add any PlotProviders to // the List of PlotProviders to be unplotted. for (Iterator<?> iter = structuredSelection.iterator(); iter.hasNext();) { Object object = iter.next(); return ((PlotProvider) object); } } return null; } }