net.sf.eclipsefp.haskell.ui.internal.preferences.hsimpls.ImplementationsBlock.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.eclipsefp.haskell.ui.internal.preferences.hsimpls.ImplementationsBlock.java

Source

// Copyright (c) 2006-2008 by Leif Frenzel - see http://leiffrenzel.de
// This code is made available under the terms of the Eclipse Public License,
// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
package net.sf.eclipsefp.haskell.ui.internal.preferences.hsimpls;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.sf.eclipsefp.haskell.core.compiler.CompilerManager;
import net.sf.eclipsefp.haskell.core.compiler.HsImplementation;
import net.sf.eclipsefp.haskell.core.compiler.HsImplementationPersister;
import net.sf.eclipsefp.haskell.core.compiler.IHsImplementation;
import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
import net.sf.eclipsefp.haskell.ui.util.SWTUtil;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
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.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
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.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

/** <p>A composite that displays installed Haskell implementations in a
  * table. Implementations can be added, removed and edited.</p>
  *
  * @author Leif Frenzel
  */
class ImplementationsBlock implements ISelectionProvider {

    private static final String KEY_COLUMN_WIDTH = ".columnWidth"; //$NON-NLS-1$
    private static final String KEY_SORT_COLUMN = ".sortColumn"; //$NON-NLS-1$
    private static final int DEFAULT_WIDTH = 100;

    private final List<IHsImplementation> installations = new ArrayList<>();

    private CheckboxTableViewer viewer;
    private Table table;
    private Button btnAdd;
    private Button btnRemove;
    private Button btnEdit;
    private Button btnAutoDetect;

    // index of column used for sorting
    private int sortColumn = 0;
    private final ListenerList selectionListeners = new ListenerList();
    private ISelection lastSelection = new StructuredSelection();

    Composite createControl(final Composite parent) {
        Composite composite = SWTUtil.createMainComposite(parent);

        Label tableLabel = new Label(composite, SWT.NONE);
        tableLabel.setText(UITexts.implementationsBlock_installed);
        GridData data = new GridData();
        data.horizontalSpan = 2;
        tableLabel.setLayoutData(data);
        tableLabel.setFont(parent.getFont());

        table = SWTUtil.createTable(composite);
        table.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(final KeyEvent event) {
                if (event.character == SWT.DEL && event.stateMask == 0) {
                    removeSelectedInstallations();
                }
            }
        });
        createColumns();
        createViewer();

        Composite buttonsComp = createButtonsComposite(composite);
        createButtons(buttonsComp);
        createSpacer(buttonsComp);

        enableButtons();
        return composite;
    }

    private void sortByType() {
        viewer.setComparator(new Comparator_TypeName());
        sortColumn = 3;
    }

    private void sortByName() {
        viewer.setComparator(new Comparator_Name());
        sortColumn = 1;
    }

    private void sortByVersion() {
        viewer.setComparator(new Comparator_Version());
        sortColumn = 2;
    }

    void applyPref(final String prefValue) {
        HsImplementationPersister.fromXML(prefValue, installations);
        viewer.setInput(installations);
        viewer.refresh();
    }

    String getPref() {
        return HsImplementationPersister.toXML(installations);
    }

    public List<IHsImplementation> getInstallations() {
        return installations;
    }

    void add(final HsImplementation impl) {
        installations.add(impl);
        viewer.setInput(installations);
        viewer.refresh();
    }

    boolean isDuplicateName(final String name, final HsImplementation impl) {
        return CompilerManager.isDuplicateName(installations, name, impl);
        //    boolean result = false;
        //    if( name != null && name.trim().length() > 0 ) {
        //      for( IHsImplementation inst: installations ) {
        //        result |= inst!=impl && name.equals( inst.getName() );
        //      }
        //    }
        //    return result;
    }

    void setCheckedHsImplementation(final String name) {
        IHsImplementation impl = findImpl(name);
        if (impl == null) {
            setSelection(new StructuredSelection());
        } else {
            setSelection(new StructuredSelection(impl));
        }
    }

    private IHsImplementation findImpl(final String name) {
        IHsImplementation result = null;
        for (IHsImplementation impl : installations) {
            if (impl.getName().equals(name)) {
                result = impl;
            }
        }
        return result;
    }

    IHsImplementation getCheckedHsImplementation() {
        IHsImplementation result = null;
        Object[] objects = viewer.getCheckedElements();
        if (objects.length > 0) {
            result = (IHsImplementation) objects[0];
        }
        return result;
    }

    void setInstallations(final IHsImplementation[] insts) {
        installations.clear();
        for (int i = 0; i < insts.length; i++) {
            installations.add(insts[i]);
        }
        viewer.setInput(installations);
        viewer.refresh();
    }

    void saveColumnSettings(final IDialogSettings settings, final String qualifier) {
        int columnCount = table.getColumnCount();
        for (int i = 0; i < columnCount; i++) {
            int width = table.getColumn(i).getWidth();
            settings.put(qualifier + KEY_COLUMN_WIDTH + i, width);
        }
        settings.put(qualifier + KEY_SORT_COLUMN, sortColumn);
    }

    void restoreColumnSettings(final IDialogSettings settings, final String qualifier) {
        viewer.getTable().layout(true);
        restoreColumnWidths(settings, qualifier);
        try {
            sortColumn = settings.getInt(qualifier + KEY_SORT_COLUMN);
        } catch (final NumberFormatException numfex) {
            sortColumn = 1;
        }
        switch (sortColumn) {
        case 1:
            sortByName();
            break;
        case 2:
            sortByVersion();
            break;
        case 3:
            sortByType();
            break;
        }
    }

    // interface methods of ISelectionProvider
    //////////////////////////////////////////

    @Override
    public void addSelectionChangedListener(final ISelectionChangedListener li) {
        selectionListeners.add(li);
    }

    @Override
    public ISelection getSelection() {
        return new StructuredSelection(viewer.getCheckedElements());
    }

    @Override
    public void removeSelectionChangedListener(final ISelectionChangedListener li) {
        selectionListeners.remove(li);
    }

    @Override
    public void setSelection(final ISelection selection) {
        if (selection instanceof IStructuredSelection) {
            if (!selection.equals(lastSelection)) {
                lastSelection = selection;
                Object elem = ((IStructuredSelection) selection).getFirstElement();
                if (elem == null) {
                    viewer.setCheckedElements(new Object[0]);
                } else {
                    viewer.setCheckedElements(new Object[] { elem });
                    viewer.reveal(elem);
                }
                fireSelectionChanged();
            }
        }
    }

    // helping functions
    ////////////////////

    private void fireSelectionChanged() {
        SelectionChangedEvent evt = new SelectionChangedEvent(this, getSelection());
        Object[] lis = selectionListeners.getListeners();
        for (int i = 0; i < lis.length; i++) {
            ISelectionChangedListener li = (ISelectionChangedListener) lis[i];
            li.selectionChanged(evt);
        }
    }

    private void enableButtons() {
        IStructuredSelection ssel = (IStructuredSelection) viewer.getSelection();
        btnEdit.setEnabled(ssel.size() == 1);
        boolean moreThanSelectedItem = ssel.size() > 0 && ssel.size() < viewer.getTable().getItemCount();
        btnRemove.setEnabled(moreThanSelectedItem);
    }

    private void createColumns() {
        createColumn(UITexts.implementationsBlock_colName, new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent evt) {
                sortByName();
            }
        });

        createColumn(UITexts.implementationsBlock_colType, new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent evt) {
                sortByType();
            }
        });

        createColumn(UITexts.implementationsBlock_colVersion, new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent evt) {
                sortByVersion();
            }
        });
    }

    private TableColumn createColumn(final String text, final SelectionListener listener) {
        TableColumn result = new TableColumn(table, SWT.NONE);
        result.setText(text);
        result.addSelectionListener(listener);
        return result;
    }

    private Composite createButtonsComposite(final Composite parent) {
        Composite result = new Composite(parent, SWT.NULL);
        result.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
        GridLayout gridLayout = new GridLayout();
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        result.setLayout(gridLayout);
        result.setFont(parent.getFont());
        return result;
    }

    private void createButtons(final Composite buttonsComp) {
        String sAdd = UITexts.implementationsBlock_btnAdd;
        btnAdd = SWTUtil.createPushButton(buttonsComp, sAdd);
        btnAdd.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(final Event evt) {
                addHsImplementation();
            }
        });

        String sEdit = UITexts.implementationsBlock_btnEdit;
        btnEdit = SWTUtil.createPushButton(buttonsComp, sEdit);
        btnEdit.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(final Event evt) {
                editHsImplementation();
            }
        });

        String sRemove = UITexts.implementationsBlock_btnRemove;
        btnRemove = SWTUtil.createPushButton(buttonsComp, sRemove);
        btnRemove.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(final Event evt) {
                removeSelectedInstallations();
            }
        });

        String sDetect = UITexts.cabalImplsBlock_btnAutoDetect;
        btnAutoDetect = SWTUtil.createPushButton(buttonsComp, sDetect);
        btnAutoDetect.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(final Event ev) {
                autoDetectGHCImpls();
            }

        });
    }

    private void createViewer() {
        viewer = new CheckboxTableViewer(table);
        viewer.setLabelProvider(new HsImplementationsLP());
        viewer.setContentProvider(new HsImplementationsCP(installations));
        // by default, sort by name
        sortByName();

        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent evt) {
                enableButtons();
            }
        });

        viewer.addCheckStateListener(new ICheckStateListener() {
            @Override
            public void checkStateChanged(final CheckStateChangedEvent event) {
                if (event.getChecked()) {
                    IHsImplementation element = (IHsImplementation) event.getElement();
                    setCheckedHsImplementation(element.getName());
                } else {
                    setCheckedHsImplementation(null);
                }
            }
        });

        viewer.addDoubleClickListener(new IDoubleClickListener() {
            @Override
            public void doubleClick(final DoubleClickEvent e) {
                if (!viewer.getSelection().isEmpty()) {
                    editHsImplementation();
                }
            }
        });
    }

    private void restoreColumnWidths(final IDialogSettings settings, final String qualifier) {
        int columnCount = table.getColumnCount();
        for (int i = 0; i < columnCount; i++) {
            int width = -1;

            try {
                width = settings.getInt(qualifier + KEY_COLUMN_WIDTH + i);
            } catch (final NumberFormatException numfex) {
                // ignored
            }

            if (width <= 0) {
                //table.getColumn( i ).pack();
                table.getColumn(i).setWidth(DEFAULT_WIDTH);
            } else {
                table.getColumn(i).setWidth(width);
            }
        }
    }

    private void createSpacer(final Composite buttonsComp) {
        Label separator = new Label(buttonsComp, SWT.NONE);
        separator.setVisible(false);
        GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
        gd.heightHint = 4;
        separator.setLayoutData(gd);
    }

    private void removeSelectedInstallations() {
        IStructuredSelection ssel = (IStructuredSelection) viewer.getSelection();
        IHsImplementation[] insts = new IHsImplementation[ssel.size()];
        @SuppressWarnings("unchecked")
        Iterator<IHsImplementation> iter = ssel.iterator();
        int i = 0;
        while (iter.hasNext()) {
            insts[i] = iter.next();
            i++;
        }
        removeHsImplementations(insts);
    }

    private void removeHsImplementations(final IHsImplementation[] insts) {
        IStructuredSelection prev = (IStructuredSelection) getSelection();
        for (int i = 0; i < insts.length; i++) {
            installations.remove(insts[i]);
        }
        viewer.refresh();
        autoSelectSingle(prev);
    }

    private void addHsImplementation() {
        IStructuredSelection prev = (IStructuredSelection) getSelection();
        HsImplementationDialog dialog = new HsImplementationDialog(table.getShell(), this, null);
        dialog.setTitle(UITexts.implementationsBlock_dlgAdd);
        if (dialog.open() == Window.OK) {
            add(dialog.getResult());
            autoSelectSingle(prev);
        }
    }

    private void editHsImplementation() {
        IStructuredSelection ssel = (IStructuredSelection) viewer.getSelection();
        if (!ssel.isEmpty()) {
            HsImplementation impl = (HsImplementation) ssel.getFirstElement();
            Shell shell = table.getShell();
            HsImplementationDialog dlg = new HsImplementationDialog(shell, this, impl);
            dlg.setTitle(UITexts.implementationsBlock_dlgEdit);
            if (dlg.open() == Window.OK) {
                installations.remove(impl);
                add(dlg.getResult());
                autoSelectSingle(ssel);
            }
        }
    }

    private void autoSelectSingle(final IStructuredSelection prev) {
        IStructuredSelection curr = (IStructuredSelection) getSelection();
        if (!curr.equals(prev) || curr.isEmpty()) {
            if (curr.size() == 0 && installations.size() == 1) {
                // pick a default automatically
                setSelection(new StructuredSelection(installations.get(0)));
            }
        } else {
            fireSelectionChanged();
        }
    }

    private void autoDetectGHCImpls() {
        IHsImplementation def = getCheckedHsImplementation();
        List<IHsImplementation> detect = CompilerManager.autodetectGHCImpls();
        installations.clear();
        installations.addAll(detect);
        viewer.refresh();
        if (def != null) {
            setCheckedHsImplementation(def.getName());
        }
    }

    private final class Comparator_Version extends ViewerComparator {

        // interface methods of ViewerComparator
        ////////////////////////////////////////

        @Override
        public int compare(final Viewer viewer, final Object e1, final Object e2) {
            int result = super.compare(viewer, e1, e2);
            if ((e1 instanceof IHsImplementation) && (e2 instanceof IHsImplementation)) {
                IHsImplementation left = (IHsImplementation) e1;
                IHsImplementation right = (IHsImplementation) e2;
                result = left.getVersion().compareTo(right.getVersion());
            }
            return result;
        }

        @Override
        public boolean isSorterProperty(final Object element, final String property) {
            return true;
        }
    }

    private final class Comparator_Name extends ViewerComparator {

        // interface methods of ViewerComparator
        ////////////////////////////////////////

        @Override
        public int compare(final Viewer viewer, final Object e1, final Object e2) {
            int result = super.compare(viewer, e1, e2);
            if ((e1 instanceof IHsImplementation) && (e2 instanceof IHsImplementation)) {
                IHsImplementation left = (IHsImplementation) e1;
                IHsImplementation right = (IHsImplementation) e2;
                result = left.getName().compareToIgnoreCase(right.getName());
            }
            return result;
        }

        @Override
        public boolean isSorterProperty(final Object element, final String property) {
            return true;
        }
    }

    private final class Comparator_TypeName extends ViewerComparator {

        // interface methods of ViewerComparator
        ////////////////////////////////////////

        @Override
        public int compare(final Viewer viewer, final Object e1, final Object e2) {
            int result = super.compare(viewer, e1, e2);
            if (e1 instanceof IHsImplementation && e2 instanceof IHsImplementation) {
                IHsImplementation left = (IHsImplementation) e1;
                IHsImplementation right = (IHsImplementation) e2;
                String leftType = left.getType().name();
                String rightType = right.getType().name();
                if (leftType.compareToIgnoreCase(rightType) != 0) {
                    result = leftType.compareToIgnoreCase(rightType);
                } else {
                    result = left.getName().compareToIgnoreCase(right.getName());
                }
            }
            return result;
        }

        @Override
        public boolean isSorterProperty(final Object elem, final String prop) {
            return true;
        }
    }

    /** The internal content provider class */
    class HsImplementationsCP implements IStructuredContentProvider {
        /** Initialization */
        HsImplementationsCP(final List<IHsImplementation> installations) {
            // Currently unused.
        }

        // interface methods of IStructuredContentProvider
        //////////////////////////////////////////////////

        @Override
        public Object[] getElements(final Object input) {
            return installations.toArray();
        }

        @Override
        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
            // unused
        }

        @Override
        public void dispose() {
            // unused
        }
    }

    /** The internal label provider class */
    class HsImplementationsLP extends LabelProvider implements ITableLabelProvider {
        @Override
        public String getColumnText(final Object elem, final int column) {
            String result = null;
            if (elem instanceof IHsImplementation) {
                IHsImplementation impl = (IHsImplementation) elem;
                switch (column) {
                case 0:
                    result = impl.getName();
                    break;
                case 1:
                    result = impl.getType().toString();
                    break;
                case 2:
                    result = impl.getVersion();
                    break;
                }
            } else {
                result = elem.toString();
            }
            return result;
        }

        @Override
        public Image getColumnImage(final Object elem, final int column) {
            return null;
        }
    }
}