au.gov.ga.earthsci.discovery.ui.preferences.DiscoveryServicesPreferencePage.java Source code

Java tutorial

Introduction

Here is the source code for au.gov.ga.earthsci.discovery.ui.preferences.DiscoveryServicesPreferencePage.java

Source

/*******************************************************************************
 * Copyright 2013 Geoscience Australia
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package au.gov.ga.earthsci.discovery.ui.preferences;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
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.TextCellEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import au.gov.ga.earthsci.common.ui.dialogs.StackTraceDialog;
import au.gov.ga.earthsci.common.ui.preferences.PreferencePage;
import au.gov.ga.earthsci.discovery.DiscoveryServiceManager;
import au.gov.ga.earthsci.discovery.IDiscoveryService;
import au.gov.ga.earthsci.discovery.IDiscoveryServiceProperty;
import au.gov.ga.earthsci.discovery.ui.Activator;
import au.gov.ga.earthsci.discovery.ui.ILayoutConstants;
import au.gov.ga.earthsci.discovery.ui.Messages;

/**
 * PreferencePage for editing discovery services.
 * 
 * @author Michael de Hoog (michael.dehoog@ga.gov.au)
 */
public class DiscoveryServicesPreferencePage extends PreferencePage {
    private Table table;
    private CheckboxTableViewer viewer;
    private DiscoveryServiceComparator comparator = new DiscoveryServiceComparator();
    private final Set<IDiscoveryService> stagingSet = new HashSet<IDiscoveryService>();
    private final Map<IDiscoveryService, Boolean> originalEnablement = new HashMap<IDiscoveryService, Boolean>();

    private Button addButton;
    private Button editButton;
    private Button removeButton;
    private Button disableButton;
    private Button selectAllButton;
    private Button exportButton;

    public DiscoveryServicesPreferencePage() {
        noDefaultAndApplyButton();
        setTitle(Messages.DiscoveryServicesPreferencePage_Title);
        setDescription(Messages.DiscoveryServicesPreferencePage_Description);
    }

    @Override
    protected Control createContents(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        composite.setLayoutData(gd);

        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        composite.setLayout(layout);

        table = new Table(composite,
                SWT.CHECK | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
        data.widthHint = convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH);
        data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT);
        table.setLayoutData(data);

        viewer = new CheckboxTableViewer(table);

        // Key listener for delete
        table.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == SWT.DEL) {
                    removeSelected();
                }
            }
        });
        setTableColumns();

        viewer.setComparator(comparator);
        viewer.setContentProvider(new ArrayContentProvider());
        viewer.setLabelProvider(new DiscoveryServiceLabelProvider());

        stagingSet.clear();
        stagingSet.addAll(DiscoveryServiceManager.getServices());
        viewer.setInput(stagingSet);

        viewer.setCellModifier(new ICellModifier() {
            @Override
            public boolean canModify(Object element, String property) {
                return element instanceof IDiscoveryService;
            }

            @Override
            public Object getValue(Object element, String property) {
                String name = ((IDiscoveryService) element).getName();
                return name != null ? name : ""; //$NON-NLS-1$
            }

            @Override
            public void modify(Object element, String prop, Object value) {
                if (value != null && value.toString().length() >= 0) {
                    IDiscoveryService service;
                    if (element instanceof Item) {
                        service = (IDiscoveryService) ((Item) element).getData();
                    } else if (element instanceof IDiscoveryService) {
                        service = (IDiscoveryService) element;
                    } else {
                        return;
                    }
                    if (!value.toString().equals(service.getName())) {
                        Map<IDiscoveryServiceProperty<?>, Object> propertyValues = new HashMap<IDiscoveryServiceProperty<?>, Object>();
                        IDiscoveryServiceProperty<?>[] properties = service.getProvider().getProperties();
                        if (properties != null) {
                            for (IDiscoveryServiceProperty<?> property : properties) {
                                propertyValues.put(property, property.getValue(service));
                            }
                        }

                        IDiscoveryService replacement = service.getProvider().createService(value.toString(),
                                service.getServiceURL(), propertyValues);
                        replacement.setEnabled(service.isEnabled());
                        stagingSet.remove(service);
                        stagingSet.add(replacement);
                        viewer.refresh();
                    }
                }
            }
        });
        viewer.setColumnProperties(new String[] { "name" }); //$NON-NLS-1$
        viewer.setCellEditors(new CellEditor[] { new TextCellEditor(table) });

        viewer.setCheckStateProvider(new ICheckStateProvider() {
            @Override
            public boolean isChecked(Object element) {
                return ((IDiscoveryService) element).isEnabled();
            }

            @Override
            public boolean isGrayed(Object element) {
                return false;
            }
        });

        viewer.addCheckStateListener(new ICheckStateListener() {
            @Override
            public void checkStateChanged(CheckStateChangedEvent event) {
                IDiscoveryService service = (IDiscoveryService) event.getElement();
                if (!originalEnablement.containsKey(service)) {
                    originalEnablement.put(service, service.isEnabled());
                }
                service.setEnabled(event.getChecked());
                viewer.refresh();
                validateButtons();
            }
        });

        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                validateButtons();
            }
        });

        Composite verticalButtonBar = createVerticalButtonBar(composite);
        data = new GridData(SWT.FILL, SWT.FILL, false, false);
        data.verticalAlignment = SWT.TOP;
        data.verticalIndent = 0;
        verticalButtonBar.setLayoutData(data);
        validateButtons();

        return composite;
    }

    private void setTableColumns() {
        table.setHeaderVisible(true);

        DiscoveryServiceViewerColumn[] columns = DiscoveryServiceViewerColumn.values();
        for (int i = 0; i < columns.length; i++) {
            final DiscoveryServiceViewerColumn column = columns[i];
            TableColumn tc = new TableColumn(table, SWT.NONE, i);
            tc.setResizable(true);
            tc.setText(column.getLabel());
            if (column == DiscoveryServiceViewerColumn.ENABLED) {
                tc.setWidth(convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_SMALL_COLUMN_WIDTH));
                tc.setAlignment(SWT.CENTER);
            } else if (column == DiscoveryServiceViewerColumn.URL) {
                tc.setWidth(convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH));
            } else {
                tc.setWidth(convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_COLUMN_WIDTH));
            }
            tc.addSelectionListener(new SelectionListener() {
                @Override
                public void widgetDefaultSelected(SelectionEvent e) {
                    columnSelected((TableColumn) e.widget, column);
                }

                @Override
                public void widgetSelected(SelectionEvent e) {
                    columnSelected((TableColumn) e.widget, column);
                }

            });
            // First column only
            if (i == 0) {
                table.setSortColumn(tc);
                table.setSortDirection(SWT.UP);
                comparator.setColumn(column);
            }
        }
    }

    private void columnSelected(TableColumn tc, DiscoveryServiceViewerColumn column) {
        if (comparator.getColumn() == column) {
            comparator.setDescending(!comparator.isDescending());
            table.setSortDirection(comparator.isDescending() ? SWT.DOWN : SWT.UP);
        } else {
            comparator.setColumn(column);
            comparator.setDescending(false);
            table.setSortColumn(tc);
            table.setSortDirection(SWT.UP);
        }
        viewer.refresh();
    }

    private IDiscoveryService[] getSelected() {
        IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        List<IDiscoveryService> list = new ArrayList<IDiscoveryService>();
        for (Object selected : selection.toList()) {
            if (selected instanceof IDiscoveryService) {
                list.add((IDiscoveryService) selected);
            }
        }
        return list.toArray(new IDiscoveryService[list.size()]);
    }

    private Composite createVerticalButtonBar(Composite parent) {
        // Create composite.
        Composite composite = new Composite(parent, SWT.NONE);
        initializeDialogUnits(composite);

        // create a layout with spacing and margins appropriate for the font
        // size.
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        layout.marginWidth = 5;
        layout.marginHeight = 0;
        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        composite.setLayout(layout);

        createVerticalButtons(composite);
        return composite;
    }

    private void createVerticalButtons(Composite parent) {
        addButton = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_AddButton, false);
        addButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                addService();
            }
        });

        editButton = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_EditButton, false);
        editButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                editSelected();
            }
        });

        removeButton = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_RemoveButton, false);
        removeButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                removeSelected();
            }
        });

        disableButton = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_DisableButton, false);
        disableButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                toggleSelected();
            }
        });

        selectAllButton = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_SelectAllButton,
                false);
        selectAllButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                selectAll();
            }
        });

        Button button = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_ImportButton, false);
        button.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                importServices();
            }
        });

        exportButton = createVerticalButton(parent, Messages.DiscoveryServicesPreferencePage_ExportButton, false);
        exportButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                exportServices();
            }
        });
    }

    private Button createVerticalButton(Composite parent, String label, boolean defaultButton) {
        Button button = new Button(parent, SWT.PUSH);
        button.setText(label);

        GridData data = setVerticalButtonLayoutData(button);
        data.horizontalAlignment = GridData.FILL;

        button.setToolTipText(label);
        if (defaultButton) {
            Shell shell = parent.getShell();
            if (shell != null) {
                shell.setDefaultButton(button);
            }
        }
        return button;
    }

    private GridData setVerticalButtonLayoutData(Button button) {
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
        data.widthHint = Math.max(widthHint, minSize.x);
        button.setLayoutData(data);
        return data;
    }

    private void validateButtons() {
        IDiscoveryService[] selected = getSelected();
        exportButton.setEnabled(selected.length > 0);
        removeButton.setEnabled(selected.length > 0);
        disableButton.setEnabled(selected.length > 0);
        selectAllButton.setEnabled(table.getItemCount() > 0);
        editButton.setEnabled(selected.length == 1);
        if (selected.length >= 1 && toggleMeansDisable(selected)) {
            disableButton.setText(Messages.DiscoveryServicesPreferencePage_Disable);
        } else {
            disableButton.setText(Messages.DiscoveryServicesPreferencePage_Enable);
        }
    }

    private boolean toggleMeansDisable(IDiscoveryService[] elements) {
        int count = 0;
        for (int i = 0; i < elements.length; i++) {
            if (elements[i].isEnabled()) {
                count++;
            }
        }
        return count * 2 >= elements.length;
    }

    private void addService() {
        EditDiscoveryServiceDialog dialog = new EditDiscoveryServiceDialog(getShell());
        dialog.setTitle(Messages.DiscoveryServicesPreferencePage_AddDialogTitle);
        if (dialog.open() == Window.OK) {
            IDiscoveryService service = dialog.getService();
            if (service != null) {
                service.setEnabled(true);
                stagingSet.add(service);
                viewer.refresh();
                validateButtons();
            }
        }
    }

    private void editSelected() {
        IDiscoveryService[] selected = getSelected();
        if (selected.length != 1) {
            return;
        }

        IDiscoveryService oldService = selected[0];
        EditDiscoveryServiceDialog dialog = new EditDiscoveryServiceDialog(getShell());
        dialog.setTitle(Messages.DiscoveryServicesPreferencePage_EditDialogTitle);
        dialog.setService(oldService);
        if (dialog.open() == Window.OK) {
            IDiscoveryService newService = dialog.getService();
            if (newService != null) {
                newService.setEnabled(oldService.isEnabled());

                stagingSet.remove(oldService);
                stagingSet.add(newService);

                viewer.refresh();
                viewer.setSelection(new StructuredSelection(newService));
                validateButtons();
            }
        }
    }

    private void removeSelected() {
        IDiscoveryService[] selected = getSelected();
        for (IDiscoveryService s : selected) {
            stagingSet.remove(s);
        }
        viewer.refresh();
        validateButtons();
    }

    private void toggleSelected() {
        IDiscoveryService[] selected = getSelected();
        boolean enabled = !toggleMeansDisable(selected);
        for (IDiscoveryService s : selected) {
            s.setEnabled(enabled);
        }
        viewer.refresh();
        validateButtons();
    }

    private void selectAll() {
        table.setSelection(0, table.getItemCount() - 1);
        validateButtons();
    }

    private void importServices() {
        FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
        dialog.setFilterExtensions(new String[] { "*.xml", "*.*" }); //$NON-NLS-1$ //$NON-NLS-2$
        String filename = dialog.open();
        if (filename != null) {
            File file = new File(filename);
            try {
                List<IDiscoveryService> services = DiscoveryServiceManager.loadServices(file);
                stagingSet.addAll(services);
            } catch (Exception e) {
                IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e);
                StackTraceDialog.openError(getShell(), Messages.DiscoveryServicesPreferencePage_Error,
                        Messages.DiscoveryServicesPreferencePage_ImportError, status);
            }

            viewer.refresh();
            validateButtons();
        }
    }

    private void exportServices() {
        FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
        dialog.setFilterExtensions(new String[] { "*.xml", "*.*" }); //$NON-NLS-1$ //$NON-NLS-2$
        String filename = dialog.open();
        if (filename != null) {
            File file = new File(filename);
            try {
                DiscoveryServiceManager.saveServices(stagingSet, file);
            } catch (Exception e) {
                IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e);
                StackTraceDialog.openError(getShell(), Messages.DiscoveryServicesPreferencePage_Error,
                        Messages.DiscoveryServicesPreferencePage_ExportError, status);
            }
        }
    }

    @Override
    public boolean performOk() {
        //create a copy to prevent modification during iteration:
        Set<IDiscoveryService> services = new HashSet<IDiscoveryService>(DiscoveryServiceManager.getServices());
        for (IDiscoveryService existingService : services) {
            if (!stagingSet.contains(existingService)) {
                DiscoveryServiceManager.removeService(existingService);
            }
        }
        for (IDiscoveryService newService : stagingSet) {
            if (!services.contains(newService)) {
                DiscoveryServiceManager.addService(newService);
            }
        }
        return super.performOk();
    }

    @Override
    public boolean performCancel() {
        //revert enablement changes:
        for (Entry<IDiscoveryService, Boolean> entry : originalEnablement.entrySet()) {
            entry.getKey().setEnabled(entry.getValue());
        }
        return super.performCancel();
    }
}