org.eclipse.ice.reflectivity.ui.ReflectivityPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ice.reflectivity.ui.ReflectivityPage.java

Source

/*******************************************************************************
 * Copyright (c) 2015 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 -
 *   Kasper Gammeltoft, Jay Jay Billings
 *******************************************************************************/
package org.eclipse.ice.reflectivity.ui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.ice.client.widgets.ElementSourceDialog;
import org.eclipse.ice.client.widgets.ICEResourcePage;
import org.eclipse.ice.client.widgets.ListComponentNattable;
import org.eclipse.ice.datastructures.ICEObject.ListComponent;
import org.eclipse.ice.datastructures.form.DataComponent;
import org.eclipse.ice.datastructures.form.Material;
import org.eclipse.ice.reflectivity.MaterialSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.window.Window;
import org.eclipse.nebula.widgets.nattable.selection.RowSelectionProvider;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.ManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;

/**
 * This is the custom reflectivity section page used to render the reflectivity
 * model. It sets up the <code>ListComponentNattable</code> in the top of a
 * <code>SashForm</code>, with an <code>ICEResourcePage</code> on the bottom. It
 * uses the tabbed properties view to display information about the model as a
 * whole and about the cells for the table. <br>
 * The tabbed properties view contains three tabs, info, cell editor, and
 * output. These describe the input values such as the wave vector on the info
 * tab, allow for editing and containing the table's cells such as thickness on
 * the cell editor tab, and display the output from the chi squared analysis on
 * the output tab. This class provides selections to the eclipse environment to
 * give the data to the properties view. It implements the
 * {@link ISelectionProvider} interface to do so, always having the data
 * component, the output data component, and the list component in it's
 * selection, along with the material selection describing the selected cell if
 * one is selected (not null).
 *
 * @author Kasper Gammeltoft
 * @author Jay Billings
 *
 */
public class ReflectivityPage extends ICEResourcePage
        implements ITabbedPropertySheetPageContributor, ISelectionProvider {

    public static final String ID = "org.eclipse.ice.reflectivity.ui.ReflectivityPage";

    /**
     * The shell of the page, used to create the element source dialog for
     * adding materials to the list component
     */
    private Shell shell;

    /**
     * The list component, displays the layer data in the top of the sash form
     */
    private ListComponent<Material> list;

    /**
     * The section client for the list component
     */
    private Composite sectionClient;

    /**
     * THe List component nattable that displays the list data
     */
    private ListComponentNattable listTable;

    /**
     * The data component that should have its entries displayed in the
     * properties tab
     */
    private DataComponent data;

    /**
     * The output data, namely the chi squared analysis, should be presented
     * with this component
     */
    private DataComponent output;

    /**
     * The sash form that is the base composite for the editor in this page
     */
    private SashForm sashForm;

    /**
     * Represents the selected cell in the nat table, holds the data from that
     * cell
     */
    private MaterialSelection selectedCell;

    /**
     * The selection changed listeners that are responsible for noting when the
     * selection changes on this page
     */
    private ArrayList<ISelectionChangedListener> listeners;

    /**
     * The constructor
     *
     * @param editor
     *            The ICEFormEditor to use. Should always be an instance of
     *            ReflectivityFormEditor.
     * @param id
     *            The id of this section page.
     * @param title
     *            The title of this section page.
     */
    public ReflectivityPage(FormEditor editor, String id, String title) {
        super(editor, id, title);
        listeners = new ArrayList<ISelectionChangedListener>();
    }

    /**
     * Creates the content of the composite and instantiates the graphics
     * widgets. Calls super for the resource component on the bottom of the sash
     * form, and constructs the NatTable on the top.
     *
     * @see org.eclipse.ui.forms.editor.FormPage#createFormContent(org.eclipse.ui
     *      .forms.IManagedForm)
     */
    @Override
    protected void createFormContent(IManagedForm managedForm) {

        // Get the parent form and the toolkit
        final ScrolledForm scrolledForm = managedForm.getForm();
        final FormToolkit formToolkit = managedForm.getToolkit();

        // Set a GridLayout with a single column. Remove the default margins.
        GridLayout layout = new GridLayout(1, false);
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        scrolledForm.getBody().setLayout(layout);

        // Get the parent
        Composite parent = managedForm.getForm().getBody();

        // Get the shell
        shell = parent.getShell();

        // Create the sashForm
        sashForm = new SashForm(parent, SWT.VERTICAL);
        sashForm.setLayout(new GridLayout());
        sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
        sashForm.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));

        // Create the list's section and set its layout info
        Section listSection = formToolkit.createSection(sashForm,
                Section.TITLE_BAR | Section.DESCRIPTION | Section.TWISTIE | Section.EXPANDED | Section.COMPACT);

        listSection.setLayout(new GridLayout(1, false));
        listSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

        // Create the section client, which is the client area of the
        // section that will actually render data.
        sectionClient = new Composite(listSection, SWT.FLAT);
        sectionClient.setLayout(new GridLayout(2, false));
        sectionClient.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
        // Fixes section header bug where label color is spammed
        sectionClient.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
        // Fixes background color bug for NatTable
        sectionClient.setBackgroundMode(SWT.INHERIT_FORCE);

        // Draws the table and sets that instance variable
        listTable = new ListComponentNattable(sectionClient, list, true, true, false);
        // Nothing is selected by default
        selectedCell = null;

        // Add the buttons to the table
        createButtons();

        // Set the section client.
        listSection.setClient(sectionClient);

        // Enable a new selection listener to listen to the table's selection
        // events

        // FIXME: Does not listen to changes in selection on the same row. This
        // means that the user can select a different column on the same row and
        // nothing will update as this listener is specifically for rows. Needs
        // to find a more general selection listener or create on if necessary!
        RowSelectionProvider provider = listTable.getSelectionProvider();
        provider.addSelectionChangedListener(new ISelectionChangedListener() {

            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                ISelection selection = event.getSelection();
                IStructuredSelection structSelect = (IStructuredSelection) selection;
                Material selected = (Material) structSelect.getFirstElement();

                // Get the selection layer to find the exact cell that was last
                // selected
                SelectionLayer layer = listTable.getSelectionLayer();
                int col = layer.getLastSelectedCellPosition().columnPosition;
                // Get the property from the table
                String property = listTable.getColumnName(col);
                // Set the selected cell from the material and property
                MaterialSelection newSelection = new MaterialSelection(selected, property);
                // If this selection is a new one (different from the current
                // one), then set the new selected cell and update the selection
                // listeners
                if (!newSelection.equals(selectedCell)) {
                    selectedCell = newSelection;
                    for (ISelectionChangedListener listener : listeners) {
                        listener.selectionChanged(new SelectionChangedEvent(ReflectivityPage.this,
                                ReflectivityPage.this.getSelection()));
                    }
                }
            }
        });

        // Create the scrolled and managed forms to pass to
        // super.createFormContent() to create the resource page in the sash
        // form
        ScrolledForm form = formToolkit.createScrolledForm(sashForm);
        IManagedForm resourceForm = new ManagedForm(formToolkit, form);

        // Set this page as a selection provider (for the whole page)
        getSite().setSelectionProvider(this);

        // Create the resource form page contents
        super.createFormContent(resourceForm);

        //Open the properties view and set the focuse on this view to force the correct properties to display. 
        try {
            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                    .showView("org.eclipse.ui.propertiesView");
        } catch (PartInitException e) {
            e.printStackTrace();
        }
        setFocus();

        return;

    }

    /**
     * This operation creates the add and delete buttons that are used to add
     * layers to the table. Also creates buttons for moving layers around and
     * clearing the table.
     */
    private void createButtons() {

        // Create a composite for holding Add/Delete buttons to manipulate
        // the table and lay it out.
        Composite listButtonComposite = new Composite(sectionClient, SWT.NONE);
        listButtonComposite.setLayout(new GridLayout(1, false));
        listButtonComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, true, 1, 1));

        // Create the add button to add a new element to the list.
        Button addMaterialButton = new Button(listButtonComposite, SWT.PUSH);
        addMaterialButton.setText("Add");
        addMaterialButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                // We need to add the element based on whether or not the
                // IElementSource is available to provide selections.
                if (list.getElementSource() == null) {
                    // If it is not available, just duplicate the last one
                    // on the list. I'm not entirely sure if this will work
                    // because it will just be adding the same element twice
                    // and may result in both being updated. We don't have a
                    // good test case for it at the moment, so we will have
                    // to cross that bridge when we get to it.
                    int index = list.size() - 1;
                    // Lock the list before adding the selction
                    list.getReadWriteLock().writeLock().lock();
                    try {
                        list.add(list.get(index));
                    } finally {
                        // Unlock it
                        list.getReadWriteLock().writeLock().unlock();
                    }
                } else {
                    // Otherwise, if the IElementSource is available, throw
                    // up the source selection dialog
                    ElementSourceDialog<Material> dialog = new ElementSourceDialog<Material>(shell,
                            list.getElementSource());
                    if (dialog.open() == Window.OK) {
                        // Lock the list to avoid concurrent modifications
                        list.getReadWriteLock().writeLock().lock();
                        try {
                            // Get the selection and add it if they actually
                            // selected something.
                            list.add(dialog.getSelection());
                        } finally {
                            // Unlock the list
                            list.getReadWriteLock().writeLock().unlock();
                        }
                    }

                }

                listTable.getTable().refresh();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
            }

        });

        // Create the delete button to delete the currently selected element
        // from the list.
        Button deleteMaterialButton = new Button(listButtonComposite, SWT.PUSH);
        deleteMaterialButton.setText("Delete");
        deleteMaterialButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetDefaultSelected(SelectionEvent arg0) {
            }

            @Override
            public void widgetSelected(SelectionEvent arg0) {

                // checks if list has something to delete
                if (list.size() > 0) {
                    ListComponent<Material> selected = listTable.getSelectedObjects();
                    if (selected.size() > 0) {

                        // removes that material from the list
                        // lock the list before removing the selection
                        list.getReadWriteLock().writeLock().lock();
                        try {
                            for (Object o : selected) {
                                list.remove(o);
                            }
                        } finally {
                            // Unlock it
                            list.getReadWriteLock().writeLock().unlock();
                        }
                    }
                }

                listTable.getTable().refresh();
            }

        });

        // Move up button, moves the selected rows up one index.
        Button moveUpButton = new Button(listButtonComposite, SWT.PUSH);
        moveUpButton.setText("^");
        moveUpButton.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetDefaultSelected(SelectionEvent arg0) {
            }

            @SuppressWarnings("unchecked")
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                // Makes sure there is actually data in the list to manipulate
                if (list.size() > 0) {
                    // Gets selected rows
                    ListComponent<Material> selected = listTable.getSelectedObjects();
                    // Makes sure there are selected rows
                    if (selected.size() > 0) {
                        int numSelected = selected.size();
                        // Makes sure that the user does not move the cell at
                        // position 0 to position -1 (past top of table)
                        if (!(selected.get(0).equals(list.get(0)))) {

                            list.getReadWriteLock().writeLock().lock();

                            // Gets the object in the list that will be
                            // overridden
                            int index = 0;
                            Material toMove = list.get(0);

                            // Overrides the list entries to move the selected
                            // rows up by one row
                            for (int i = 0; i < numSelected; i++) {
                                index = list.indexOf(selected.get(i)) - 1;
                                toMove = list.get(index);
                                list.set(index, selected.get(i));
                                list.set(index + 1, toMove);

                            }

                            // Resets the overridden row to be at the end of the
                            // selected rows
                            list.set(index + 1, toMove);

                            // Unlocks the list
                            list.getReadWriteLock().writeLock().unlock();
                            listTable.setSelection(selected);

                        }

                    }

                    listTable.getTable().refresh();
                }
            }

        });

        // Move down button, moves the currently selected rows down one index.
        Button moveDownButton = new Button(listButtonComposite, SWT.PUSH);
        moveDownButton.setText("v");
        moveDownButton.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetDefaultSelected(SelectionEvent arg0) {
            }

            @SuppressWarnings("unchecked")
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                // makes sure there is actually data in the list to manipulate
                if (list.size() > 0) {
                    // Gets selected rows
                    ListComponent<Material> selected = listTable.getSelectedObjects();
                    // Makes sure there are selected rows
                    if (selected.size() > 0) {
                        int numSelected = selected.size();
                        // Makes sure that the user does not move the selected
                        // cell past the end of the table.
                        if (!(selected.get(numSelected - 1).equals(list.get(list.size() - 1)))) {

                            list.getReadWriteLock().writeLock().lock();

                            // Gets the object in the list that will be
                            // overridden
                            int index = 0;
                            Material toMove = list.get(0);

                            // Overrides the list entries to move the selected
                            // rows up by one row
                            for (int i = numSelected - 1; i >= 0; i--) {
                                index = list.indexOf(selected.get(i)) + 1;
                                toMove = list.get(index);
                                list.set(index, selected.get(i));
                                list.set(index - 1, toMove);

                            }

                            // Resets the overridden row to be at the end of the
                            // selected rows
                            list.set(index - 1, toMove);

                            // Unlocks the list
                            list.getReadWriteLock().writeLock().unlock();
                            listTable.setSelection(selected);
                        }
                    }

                    listTable.getTable().refresh();
                }
            }

        });

        // Clear button- removes all entries from the list.
        Button clearButton = new Button(listButtonComposite, SWT.PUSH);
        clearButton.setText("clear");
        clearButton.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetDefaultSelected(SelectionEvent arg0) {
            }

            @SuppressWarnings("unchecked")
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                // makes sure there is actually data in the list to manipulate
                if (list.size() > 0) {

                    // Now just clear the list.
                    list.getReadWriteLock().writeLock().lock();
                    list.clear();
                    list.getReadWriteLock().writeLock().unlock();
                }

                listTable.getTable().refresh();
            }

        });

        return;
    }

    /**
     * Sets the data component to use as the inputs for this model.
     *
     * @param dataComp
     *            The data component to use.
     */
    public void setDataComponent(DataComponent dataComp) {
        data = dataComp;
    }

    /**
     * Sets the output component used to display the chi squared analysis
     *
     * @param outputComp
     *            The output component to use.
     */
    public void setOutputComponent(DataComponent outputComp) {
        output = outputComp;
    }

    /**
     * Sets the list component to use for this page. The list is displayed at
     * the top of the page in the upper part of the sash form.
     *
     * @param listComp
     *            The list component to display.
     */
    public void setList(ListComponent listComp) {
        list = listComp;
    }

    /**
     * Needed for the properties tab attributes to be registered for this page.
     * Makes sure that the IPropertySheetPage class returns this as a new
     * TabbedPropertySheetPage so that the properties tab uses the Reflectivity
     * properties rather than the standard eclipse properties view
     */
    @Override
    public Object getAdapter(Class adapter) {
        if (adapter == IPropertySheetPage.class) {
            return new TabbedPropertySheetPage(this);
        }
        return super.getAdapter(adapter);
    }

    /**
     * Also needed for the properties view to work. Must return the same thing
     * as denoted for the tabbed property contributor ID in the plugin.xml
     */
    @Override
    public String getContributorId() {
        return getSite().getId();
    }

    /**
     * Adds a selection changed listener. Part of the ISelectionProvider
     * interface.
     */
    @Override
    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        listeners.add(listener);
    }

    /**
     * Gets the current selection for this page. This selection is a structured
     * selection that should always contain, in order, a data component for the
     * inputs, a data component for the outputs, a list component containing the
     * table data, and a material selection if and only if one is present (not
     * null, meaning the user has selected a cell in the table)
     *
     * Part of the ISelectionProvider interface.
     */
    @Override
    public ISelection getSelection() {
        // Create the new selection
        return new IStructuredSelection() {

            @Override
            public boolean isEmpty() {
                // It is never empty- always has data component at least
                return false;
            }

            @Override
            public Object getFirstElement() {
                // Get the data
                return data;
            }

            @Override
            public Iterator iterator() {
                // Create an iterator over a list containing the selection
                List<Object> lst = new ArrayList<Object>();
                lst.add(data);
                lst.add(output);
                lst.add(list);
                if (selectedCell != null) {
                    lst.add(selectedCell);
                }
                return lst.iterator();
            }

            @Override
            public int size() {
                return selectedCell == null ? 3 : 4;
            }

            @Override
            public Object[] toArray() {
                // An array containing the selection
                if (selectedCell != null) {
                    return new Object[] { data, output, list, selectedCell };
                } else {
                    return new Object[] { data, output, list };
                }
            }

            @Override
            public List<Object> toList() {
                // A list containing the selection
                List<Object> lst = new ArrayList<Object>();
                lst.add(data);
                lst.add(output);
                lst.add(list);
                if (selectedCell != null) {
                    lst.add(selectedCell);
                }
                return lst;
            }

        };
    }

    /**
     * Removes a selection changed listener. Part of the ISelectionProvider
     * interface
     */
    @Override
    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        listeners.remove(listener);
    }

    /**
     * Sets the current selection. Not used as of now. Part of the
     * ISelectionProvider interface.
     */
    @Override
    public void setSelection(ISelection selection) {
        // Do nothing, as we do not want this capability
    }

}