carisma.ui.eclipse.editors.AdfEditorMasterDetailsBlock.java Source code

Java tutorial

Introduction

Here is the source code for carisma.ui.eclipse.editors.AdfEditorMasterDetailsBlock.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Software Engineering Institute, TU Dortmund.
 * 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:
 *    {SecSE group} - initial API and implementation and/or initial documentation
 *******************************************************************************/
package carisma.ui.eclipse.editors;

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

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
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.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
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.Combo;
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.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.DetailsPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.MasterDetailsBlock;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.FormToolkit;

import carisma.core.analysis.CheckReference;
import carisma.core.checks.CheckDescriptor;
import carisma.core.models.ModelTypeRegistry;
import carisma.ui.eclipse.CarismaGUI;
import carisma.ui.eclipse.editors.AdfEditorCheckSelectionDialog.CheckSelectionContentProvider;
import carisma.ui.eclipse.editors.AdfEditorCheckSelectionDialog.CheckSelectionLabelProvider;
import carisma.ui.eclipse.editors.descriptions.EditorDescriptor;
import carisma.ui.eclipse.preferences.Constants;
import carisma.ui.eclipse.preferences.pages.EditorPriorityList;

/**
 * Structure and behavior of the adf editor GUI.
 */
public class AdfEditorMasterDetailsBlock extends MasterDetailsBlock {

    /**
     * The controller between model (analysis) and view (adf editor).
     */
    AdfEditorController controller;

    /**
     * The open model button.
     */
    private Button openModel;

    /**
     * Combo menu for selected editor.
     */
    Combo selectedEditorCombo;

    /**
     * The corresponding table viewer.
     */
    CheckboxTableViewer viewer;

    /**
     * The del-button.
     */
    private Button del;

    /**
     * The up-button.
     */
    private Button up;

    /**
     * The down-button.
     */
    private Button down;

    /**
     * The run-button.
     */
    private Button run;

    /**
     * The show problems link.
     */
    private Link problemLink;

    /**
     * A boolean which indicates if the editor priority queue is used.
     */
    boolean selectedEditorPriorityListEnabled;

    /**
     * A static name of the default editor selection.
     */
    private static final String DEFAULT_EDITOR = "Default Eclipse Editor";

    /**
     * A red cross as a decoration for the model file name text box.
     */
    private ControlDecoration modelFileNameDecoration;

    /**
     * A information sign as a decoration for the selected editor combo box.
     */
    private ControlDecoration selectedEditorDecoration;

    /**
     * The last selection in the list of checks.
     */
    private ISelection lastSelection;

    /**
     * A listener which is registered to every GUI element which has an
     * influence on the validation of the analysis.
     */
    private Listener masterListener;

    /**
     * Constructor.
     * 
     * @param controller
     *            the corresponding AdfEditorController instance
     */
    public AdfEditorMasterDetailsBlock(final AdfEditorController controller) {
        this.controller = controller;
    }

    /**
     * Constructs the whole GUI of the adf editor.
     * 
     * @param managedForm
     *            managedForm for MasterDetailsBlock
     * @param parent
     *            the parent Composite
     */
    @Override
    protected final void createMasterPart(final IManagedForm managedForm, final Composite parent) {
        FormToolkit toolkit;
        this.controller.loadAnalysis();
        toolkit = managedForm.getToolkit();

        createMasterValidationModifyListener();

        // Master composite
        final Composite masterComposite = toolkit.createComposite(parent);
        GridLayout masterCompositeLayout = new GridLayout(3, false);
        masterCompositeLayout.marginHeight = 2;
        masterCompositeLayout.marginWidth = 10;
        masterComposite.setLayout(masterCompositeLayout);
        masterComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        // Analysis name
        createAnalysisNameText(toolkit, masterComposite);

        // Model file name and browse button
        createModelfileArea(toolkit, masterComposite);

        // Selected editor combo box and open model button
        createSelectedEditorCombo(toolkit, masterComposite);
        createOpenModelButton(toolkit, masterComposite);

        // Create model type informations
        toolkit.createLabel(masterComposite, "Modeltype:");
        Label modeltypeLabel = toolkit.createLabel(masterComposite, this.controller.getModelType());
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.horizontalSpan = 2;
        gridData.horizontalIndent = 6;
        modeltypeLabel.setLayoutData(gridData);

        // Separator
        Composite separator = toolkit.createCompositeSeparator(masterComposite);
        gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
        gridData.horizontalSpan = 3;
        gridData.heightHint = 2;
        separator.setLayoutData(gridData);

        // Composite for selected check list and buttons
        Composite checkListComposite = toolkit.createComposite(masterComposite);
        GridLayout checkListCompositeLayout = new GridLayout(2, false);
        checkListCompositeLayout.marginHeight = 0;
        checkListCompositeLayout.marginWidth = 0;
        checkListComposite.setLayout(checkListCompositeLayout);
        GridData checkListCompositeGridData = new GridData(GridData.FILL_BOTH);
        checkListCompositeGridData.horizontalSpan = 3;
        checkListComposite.setLayoutData(checkListCompositeGridData);

        // Label 'selected checks'
        Label label = toolkit.createLabel(checkListComposite, "Selected checks:");
        gridData = new GridData();
        gridData.horizontalSpan = 2;
        label.setLayoutData(gridData);

        // Check list table and viewer
        createTableAndViewer(toolkit, checkListComposite, managedForm);

        // Create add-, delete-, up- and down-buttons and their listeners
        createAddButton(toolkit, checkListComposite);
        createDelButton(toolkit, checkListComposite);
        createUpButton(toolkit, checkListComposite);
        createDownButton(toolkit, checkListComposite);

        // Create Run-Button and the Listener
        createRunButton(toolkit, masterComposite);

        // Update availability of Up-, Down- and Run-Button
        listSelectionChanged();

        // Update enable state of GUI elements referring amongst other to editor
        // selection art
        CarismaGUI.INSTANCE.getPreferenceStore().firePropertyChangeEvent(Constants.EDITOR_SELECTION_ART,
                CarismaGUI.INSTANCE.getPreferenceStore().getString(Constants.EDITOR_SELECTION_ART),
                CarismaGUI.INSTANCE.getPreferenceStore().getString(Constants.EDITOR_SELECTION_ART));
        updateRunButtonEnable();
    }

    /**
     * Creates the master listener.
     */
    private void createMasterValidationModifyListener() {
        this.masterListener = new Listener() {
            @Override
            public void handleEvent(final Event event) {
                updateRunButtonEnable();
            }
        };
    }

    /**
     * Creates the analysis name text and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding Composite
     */
    private void createAnalysisNameText(final FormToolkit toolkit, final Composite composite) {
        toolkit.createLabel(composite, "Name:", SWT.LEFT);
        final Text textAnalysisName = toolkit.createText(composite, this.controller.getAnalysisName(), SWT.SINGLE);
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.horizontalSpan = 2;
        gridData.horizontalIndent = 6;
        textAnalysisName.setLayoutData(gridData);
        textAnalysisName.setEditable(true);
        textAnalysisName.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(final ModifyEvent e) {
                AdfEditorMasterDetailsBlock.this.controller.setAnalysisName(textAnalysisName.getText());
            }
        });
    }

    /**
     * Creates the model file label, text, the browse button and the
     * corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding Composite
     */
    private void createModelfileArea(final FormToolkit toolkit, final Composite composite) {
        toolkit.createLabel(composite, "Modelfile:");

        final Text modelFileName = toolkit.createText(composite, "");
        GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
        gridData.horizontalIndent = 6;
        modelFileName.setLayoutData(gridData);
        modelFileName.setEditable(false);
        IFile iModelFile = this.controller.getModelIFile();
        IPath location = iModelFile.getLocation();
        final String modelfile;
        if (location != null) {
            modelfile = location.toString();
        } else {
            modelfile = iModelFile.toString();
        }
        modelFileName.setText(modelfile);

        // Red cross if model does not exist
        this.modelFileNameDecoration = new ControlDecoration(modelFileName, SWT.LEFT | SWT.TOP);
        Image errorDecoration = FieldDecorationRegistry.getDefault()
                .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR).getImage();
        this.modelFileNameDecoration.setImage(errorDecoration);
        this.modelFileNameDecoration.setShowHover(true);
        this.modelFileNameDecoration.setDescriptionText("The model file does not exist! Please\n"
                + "recover the selected file or use the\n" + "'Browse' button to choose a new one.");
        if (this.controller.isModelFileValid()) {
            this.modelFileNameDecoration.hide();
        } else {
            this.modelFileNameDecoration.show();
        }

        Button browse = toolkit.createButton(composite, "Browse...", SWT.PUSH);
        browse.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
        browse.setToolTipText("Browse for a\n" + "new model file");

        browse.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                FileDialog fileDialog = new FileDialog(composite.getShell(), SWT.OPEN);
                fileDialog.setText("Choose a model file");

                ModelTypeRegistry modelTypeRegistry = CarismaGUI.getModelTypeRegistry();
                String extensions = modelTypeRegistry
                        .getModelTypeWithName(AdfEditorMasterDetailsBlock.this.controller.getModelType())
                        .getFileExtension();

                // Delete whitespaces and add '*.' in front of the extension to
                // set up
                // extension filter correctly
                int iterate = 0;
                String[] extensionArray = extensions.split(",");
                for (String singleExtension : extensionArray) {
                    extensionArray[iterate++] = "*." + singleExtension.trim();
                }
                fileDialog.setFilterExtensions(extensionArray);

                // Determine initial path of file dialog
                IFile iModelFile = AdfEditorMasterDetailsBlock.this.controller.getModelIFile();
                String initialPath = iModelFile.getRawLocation().toOSString();
                // Cut off file name from path
                if (initialPath.contains("\\")) {
                    initialPath = initialPath.substring(0, initialPath.lastIndexOf('\\'));
                }
                if (initialPath.contains("/")) {
                    initialPath = initialPath.substring(0, initialPath.lastIndexOf('/'));
                }
                fileDialog.setFilterPath(initialPath);

                String filepath = fileDialog.open();
                if (filepath != null) {
                    try {
                        IFile modelIFile = AdfEditorController.getLinkedIFile(filepath);
                        modelFileName.setText(modelIFile.getFullPath().toString());
                        AdfEditorMasterDetailsBlock.this.controller.setModelIFile(modelIFile);
                        updateRunButtonEnable();
                        updateOpenModelButtonEnable();
                    } catch (Exception exc) {
                        exc.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * Creates the selected editor combo box.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding Composite
     */
    private void createSelectedEditorCombo(final FormToolkit toolkit, final Composite composite) {
        toolkit.createLabel(composite, "Associated Editor:");

        this.selectedEditorCombo = new Combo(composite, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);
        GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
        gridData.horizontalIndent = 6;
        this.selectedEditorCombo.setLayoutData(gridData);
        // The enable state will be updated later. Have to false for now
        // See updateGuiEnableState(..) for more information
        this.selectedEditorCombo.setEnabled(false);

        // Information icon if priority queue is used
        this.selectedEditorDecoration = new ControlDecoration(this.selectedEditorCombo, SWT.LEFT | SWT.TOP);
        Image questionDecoration = FieldDecorationRegistry.getDefault()
                .getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION).getImage();
        this.selectedEditorDecoration.setImage(questionDecoration);
        this.selectedEditorDecoration.setShowHover(true);

        // Change Listener for the EDITOR_SELECTION_ART property
        final IPropertyChangeListener propertyChangeListener = new IPropertyChangeListener() {
            @Override
            public void propertyChange(final PropertyChangeEvent event) {
                if (event.getProperty().equals(Constants.EDITOR_SELECTION_ART)) {
                    String editorSelectionArt = event.getNewValue().toString();
                    if (editorSelectionArt.equals(Constants.AUTO)) {
                        AdfEditorMasterDetailsBlock.this.selectedEditorPriorityListEnabled = true;
                    } else {
                        AdfEditorMasterDetailsBlock.this.selectedEditorPriorityListEnabled = false;
                    }
                    updateOpenModelButtonEnable();
                }
            }
        };
        CarismaGUI.INSTANCE.getPreferenceStore().addPropertyChangeListener(propertyChangeListener);

        // Selection Listener
        final EditorRegistry editorRegistry = CarismaGUI.INSTANCE.getEditorRegistry();
        this.selectedEditorCombo.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                String actualSelectedEditorName = AdfEditorMasterDetailsBlock.this.selectedEditorCombo
                        .getItem(AdfEditorMasterDetailsBlock.this.selectedEditorCombo.getSelectionIndex());
                if (!actualSelectedEditorName.equals(DEFAULT_EDITOR)) {
                    EditorDescriptor actualEditorDescriptor = editorRegistry
                            .getEditorDescriptorByName(actualSelectedEditorName);
                    AdfEditorMasterDetailsBlock.this.controller.setSelectedEditorId(actualEditorDescriptor.getId());
                } else {
                    AdfEditorMasterDetailsBlock.this.controller.setSelectedEditorId(DEFAULT_EDITOR);
                }
            }

            @Override
            public void widgetDefaultSelected(final SelectionEvent e) {
                //TODO: Why empty?
            }
        });

        // Add dispose listener to remove PropertyChangeListeners
        composite.getParent().addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(final DisposeEvent e) {
                CarismaGUI.INSTANCE.getPreferenceStore().removePropertyChangeListener(propertyChangeListener);
            }
        });
    }

    /**
     * Creates the open model button and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding Composite
     */
    private void createOpenModelButton(final FormToolkit toolkit, final Composite composite) {
        this.openModel = toolkit.createButton(composite, "Open Model", SWT.PUSH);
        this.openModel.setEnabled(this.controller.isModelFileValid());
        this.openModel.setToolTipText("Browse for a\n" + "new model file");

        this.openModel.setToolTipText("Open a model with an associated editor or an \n"
                + "editor, defined in the editor priority list.\n"
                + "Set CARiSMA's preferences to change the functionallity\n"
                + "of this button. Select \"Editor selection combo box\" to\n"
                + "save the choice in the analysis file.\n\n" + "Read the Help article for more information.");

        this.openModel.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                String selectedEditorName = AdfEditorMasterDetailsBlock.this.selectedEditorCombo
                        .getItem(AdfEditorMasterDetailsBlock.this.selectedEditorCombo.getSelectionIndex());
                AdfEditorMasterDetailsBlock.this.controller
                        .openModelEditor(selectedEditorName.equals(DEFAULT_EDITOR));
            }
        });
    }

    /**
     * Creates the table viewer.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding Composite
     * @param managedForm
     *            for MasterDetailsBlock
     */
    private void createTableAndViewer(final FormToolkit toolkit, final Composite composite,
            final IManagedForm managedForm) {
        Table table = toolkit.createTable(composite, SWT.CHECK);
        GridData gridData = new GridData(GridData.FILL_BOTH);
        gridData.heightHint = 20;
        gridData.widthHint = 100;
        gridData.verticalSpan = 4;
        table.setLayoutData(gridData);

        ISelectionChangedListener selectionChangeListener = new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                if (listSelectionChanged()) {
                    managedForm.fireSelectionChanged(new SectionPart(composite, toolkit, SWT.NONE),
                            event.getSelection());
                }
            }
        };

        this.viewer = new CheckboxTableViewer(table);
        this.viewer.addSelectionChangedListener(selectionChangeListener);

        this.viewer.addDoubleClickListener(new IDoubleClickListener() {
            @Override
            public void doubleClick(final DoubleClickEvent event) {
                Object selection = ((IStructuredSelection) AdfEditorMasterDetailsBlock.this.viewer.getSelection())
                        .getFirstElement();
                if (selection != null && selection instanceof CheckReference) {
                    boolean state = AdfEditorMasterDetailsBlock.this.viewer.getChecked(selection);
                    state = state ^ true; // XOR swaps
                    AdfEditorMasterDetailsBlock.this.viewer.setChecked(selection, state);
                    AdfEditorMasterDetailsBlock.this.viewer.refresh();
                    AdfEditorMasterDetailsBlock.this.controller.setCheckSelection((CheckReference) selection,
                            state);
                    updateRunButtonEnable();
                }
            }
        });

        this.viewer.addCheckStateListener(new ICheckStateListener() {
            @Override
            public void checkStateChanged(final CheckStateChangedEvent event) {
                Object obj = event.getElement();
                AdfEditorMasterDetailsBlock.this.controller.setCheckSelection((CheckReference) obj,
                        event.getChecked());
                listSelectionChanged();
                updateRunButtonEnable();
            }
        });

        this.viewer.getTable().addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(final KeyEvent e) {
                if (e.keyCode == SWT.DEL) {
                    deleteSelectedCheck();
                }
            }

            @Override
            public void keyReleased(final KeyEvent e) {
                // Do nothing
            }
        });

        this.viewer.setContentProvider(new SelectedChecksContentProvider());
        this.viewer.setLabelProvider(new SelectedChecksLabelProvider());
        this.viewer.setInput(this.controller.getSelectedChecksList());
        int dragAndDropOperations = DND.DROP_MOVE;
        Transfer[] transferTypes = new Transfer[] { LocalTransfer.getInstance() };
        this.viewer.addDragSupport(dragAndDropOperations, transferTypes,
                new SelectedChecksDragListener(this.viewer));
        this.viewer.addDropSupport(dragAndDropOperations, transferTypes,
                new SelectedChecksDropListener(this.viewer, this.controller));

        updateTable();
        this.viewer.getTable().select(0);
        //seems that selecting also works if there is no entry in the table
        //than nothing will be selected, but also no NullpointerException etc.
        initInvalidChecks();
    }

    /**
     * Creates the add button and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding composite
     */
    private void createAddButton(final FormToolkit toolkit, final Composite composite) {
        Button add = toolkit.createButton(composite, "", SWT.PUSH);
        add.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD));
        add.setToolTipText("Add checks\n" + "to the list");

        add.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                List<CheckDescriptor> fittingChecks = CarismaGUI.getCheckRegistry()
                        .findChecks(AdfEditorMasterDetailsBlock.this.controller.getModelType());

                AdfEditorCheckSelectionDialog dialog = new AdfEditorCheckSelectionDialog(composite.getShell(),
                        fittingChecks, new CheckSelectionContentProvider(), new CheckSelectionLabelProvider(),
                        "Choose from checks");

                List<CheckDescriptor> recChecks = CarismaGUI.getCheckRegistry()
                        .getRecommendedChecks(AdfEditorMasterDetailsBlock.this.controller.getModelIFile());
                if (recChecks != null && recChecks.size() > 0) {
                    dialog.setRecommendedChecks(recChecks);
                }

                dialog.open();

                if (dialog.getResult() != null) {
                    for (Object id : dialog.getResult()) {
                        AdfEditorMasterDetailsBlock.this.controller.createCheck(id.toString());
                        AdfEditorMasterDetailsBlock.this.viewer.refresh();
                        updateTable();
                        updateRunButtonEnable();
                    }
                }
                listSelectionChanged();
            }
        });
    }

    /**
     * Creates the delete button and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding composite
     */
    private void createDelButton(final FormToolkit toolkit, final Composite composite) {
        this.del = toolkit.createButton(composite, "", SWT.PUSH);
        this.del.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ETOOL_DELETE));
        this.del.setToolTipText("Delete the selected\n" + "check from the list");

        this.del.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                deleteSelectedCheck();
            }
        });
    }

    /**
     * Creates the up button and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding composite
     */
    private void createUpButton(final FormToolkit toolkit, final Composite composite) {
        this.up = toolkit.createButton(composite, "", SWT.PUSH);
        this.up.setImage(CarismaGUI.INSTANCE.getImageRegistry().get(CarismaGUI.IMG_UP));
        this.up.setToolTipText("Move the check upwards");
        this.up.setEnabled(false);

        this.up.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                if (AdfEditorMasterDetailsBlock.this.viewer.getTable().getSelectionIndex() > -1) {
                    Object entryToBeMoved = AdfEditorMasterDetailsBlock.this.viewer
                            .getElementAt(AdfEditorMasterDetailsBlock.this.viewer.getTable().getSelectionIndex());
                    AdfEditorMasterDetailsBlock.this.controller.removeCheck((CheckReference) entryToBeMoved);
                    AdfEditorMasterDetailsBlock.this.controller.getSelectedChecksList().add(
                            AdfEditorMasterDetailsBlock.this.viewer.getTable().getSelectionIndex() - 1,
                            (CheckReference) entryToBeMoved);
                }
                AdfEditorMasterDetailsBlock.this.viewer.refresh();
                listSelectionChanged();
            }
        });
    }

    /**
     * Creates the up button and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding composite
     */
    private void createDownButton(final FormToolkit toolkit, final Composite composite) {
        this.down = toolkit.createButton(composite, "", SWT.PUSH);
        this.down.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
        this.down.setImage(CarismaGUI.INSTANCE.getImageRegistry().get(CarismaGUI.IMG_DOWN));
        this.down.setToolTipText("Move the check downwards");
        this.down.setEnabled(false);

        this.down.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                if (AdfEditorMasterDetailsBlock.this.viewer.getTable().getSelectionIndex() > -1) {
                    Object entryToBeMoved = AdfEditorMasterDetailsBlock.this.viewer
                            .getElementAt(AdfEditorMasterDetailsBlock.this.viewer.getTable().getSelectionIndex());
                    AdfEditorMasterDetailsBlock.this.controller.removeCheck((CheckReference) entryToBeMoved);
                    AdfEditorMasterDetailsBlock.this.controller.getSelectedChecksList().add(
                            AdfEditorMasterDetailsBlock.this.viewer.getTable().getSelectionIndex() + 1,
                            (CheckReference) entryToBeMoved);
                }
                AdfEditorMasterDetailsBlock.this.viewer.refresh();
                listSelectionChanged();
            }
        });
    }

    /**
     * Creates the run-button and the corresponding listener.
     * 
     * @param toolkit
     *            The FormToolKit where the button is created
     * @param composite
     *            The corresponding composite
     */
    private void createRunButton(final FormToolkit toolkit, final Composite composite) {
        this.run = toolkit.createButton(composite, "RUN", SWT.PUSH);
        this.run.setEnabled(this.controller.isModelFileValid());
        //Bug #1518: Wie kann man die Position des Tooltips verndern?
        //http://stackoverflow.com/questions/11375250/set-tooltip-text-at-a-particular-location
        this.run.setToolTipText("Runs the analysis");

        this.run.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                listSelectionChanged();
                if (AdfEditorMasterDetailsBlock.this.controller.isEditorDirty()) {
                    MessageDialog messageDialog = new MessageDialog(composite.getShell(), "Save and Launch", null,
                            "Do you want to save the changes?", 0, new String[] { "OK", "Cancel" }, 0);
                    messageDialog.open();
                    if (messageDialog.getReturnCode() == 0) {
                        AdfEditorMasterDetailsBlock.this.controller.saveAnalysis();
                    }
                }
                if (AdfEditorMasterDetailsBlock.this.controller.hasAnalysisInvalidParameters()
                        || !AdfEditorMasterDetailsBlock.this.controller.isModelFileValid()
                        || !isOneCheckEnabled()) {
                    updateRunButtonEnable();
                    showProblems();
                } else {
                    AdfEditorMasterDetailsBlock.this.controller.runAnalysis();
                }
            }
        });

        this.problemLink = new Link(composite, SWT.NONE);
        this.problemLink.setText("<a>Show problems</a>");
        this.problemLink.setBackground(new Color(null, 255, 255, 255));
        this.problemLink.setVisible(false);
        this.problemLink.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                showProblems();
            }
        });
    }

    /**
     * Method checks for each check from the viewer if its enabled or disabled
     * and set then an enabled/disabled check box on the left of each row. This
     * method is called every time the table has to be drawn
     */
    void updateTable() {
        if (this.viewer != null) {
            if (this.viewer.getTable().getItemCount() > 0) {
                for (int i = 0; i < this.viewer.getTable().getItemCount(); i++) {
                    Object obj = this.viewer.getElementAt(i);
                    this.viewer.setChecked(obj, ((CheckReference) obj).isEnabled());
                }
            }
            this.viewer.refresh();
        }
    }

    /**
     * Returns true, if the list selection is not equal to the last selection.
     * This method also calls other methods to update the enable states of some
     * GUI elements and resizes the detail part if necessary.
     * 
     * @return A boolean which indicates if the selection really changed
     */
    boolean listSelectionChanged() {
        updateListButtonsEnable();
        if (!this.viewer.getSelection().equals(this.lastSelection)) {
            this.lastSelection = this.viewer.getSelection();
            resizeDetailPart();
            return true;
        }
        return false;
    }

    /**
     * Recalculates the ratio of the widths of the master and detail part.
     */
    private void resizeDetailPart() {
        // The weights must be positive values and there must
        // be an entry for each non-sash child of the SashForm
        int nonSashCount = 0;
        for (Control control : this.sashForm.getChildren()) {
            if (!(control instanceof Sash)) {
                nonSashCount++;
            } else {
                Sash sash = (Sash) control;
                sash.setEnabled(false);
            }
        }
        int[] weights = new int[nonSashCount];
        for (int counter = 0; counter < nonSashCount; counter++) {
            weights[counter] = 1;
        }
        this.sashForm.setWeights(weights);
    }

    /**
     * Check for invalid CheckReferences.
     */
    private void initInvalidChecks() {
        List<CheckReference> uninputs = new ArrayList<>();
        List<CheckReference> checks = this.controller.getSelectedChecksList();
        for (CheckReference checkReference : checks) {
            CheckDescriptor checkDescriptor = CarismaGUI.getCheckRegistry()
                    .getCheckDescriptor(checkReference.getCheckID());
            if (checkDescriptor == null) {
                uninputs.add(checkReference);
            }
        }
        if (uninputs.size() > 0) {
            StringBuffer warning = new StringBuffer();
            if (uninputs.size() == 1) {
                this.viewer.getTable()
                        .setToolTipText("Invalid CheckReference " + "\"" + uninputs.get(0).getCheckID() + "\"");
            } else {
                for (CheckReference cr : uninputs) {
                    warning.append("\n\"");
                    warning.append(cr.getCheckID());
                    warning.append("\"");
                }
                this.viewer.getTable().setToolTipText("Invalid CheckReferences: " + warning.toString());
            }
        }
    }

    /**
     * Displays a message box which contains a list of problems.
     */
    void showProblems() {
        StringBuffer message = new StringBuffer("");

        for (String line : this.controller.getProblems()) {
            message.append(line + System.getProperty("line.separator"));
        }
        MessageDialog messageDialog = new MessageDialog(this.sashForm.getShell(), "Analysis problems", null,
                message.toString(), MessageDialog.ERROR, new String[] { "OK" }, 0);
        messageDialog.open();
    }

    /**
     * Deletes the actual selected check from the list of checks.
     */
    void deleteSelectedCheck() {
        if (this.viewer.getTable().getSelectionIndex() > -1) {
            Object entryToBeDeleted = this.viewer.getElementAt(this.viewer.getTable().getSelectionIndex());
            this.controller.removeCheck((CheckReference) entryToBeDeleted);
        }
        this.viewer.refresh();
        initInvalidChecks();
        listSelectionChanged();
        updateRunButtonEnable();
    }

    /**
     * Returns true if at least one check is enabled.
     * 
     * @return true when at least one check is enabled
     */
    boolean isOneCheckEnabled() {
        List<CheckReference> checks = this.controller.getSelectedChecksList();
        int countEnabled = 0;
        for (CheckReference check : checks) {
            if (check.isEnabled()) {
                countEnabled++;
            }
        }
        return countEnabled == 0 ? false : true;
    }

    /**
     * Disables the open model button if necessary.
     */
    void updateOpenModelButtonEnable() {
        // Is model file valid?
        if (this.controller.isModelFileValid()) {
            this.openModel.setEnabled(true);
            updateSelectedEditorEnableState(!this.selectedEditorPriorityListEnabled,
                    "Editor priority list is used.\n" + "Change this setting in the CARiSMA preferences.");
            this.modelFileNameDecoration.hide();
        } else {
            this.openModel.setEnabled(false);
            updateSelectedEditorEnableState(false, "The referenced model file is invalid");
            this.modelFileNameDecoration.show();
        }
    }

    /**
     * Disables the delete button if no check is selected. Disables the up and
     * down button if they first or last check is selected.
     */
    private void updateListButtonsEnable() {
        if (this.viewer.getSelection().isEmpty()) {
            this.del.setEnabled(false);
        } else {
            this.del.setEnabled(true);
            int selectionIndex = this.viewer.getTable().getSelectionIndex();
            if (selectionIndex > 0) {
                this.up.setEnabled(true);
            } else {
                this.up.setEnabled(false);
            }
            if (this.viewer.getTable().getSelectionIndex() < (this.viewer.getTable().getItems().length - 1)) {
                this.down.setEnabled(true);
            } else {
                this.down.setEnabled(false);
            }
        }
    }

    /**
     * Disabled the run button if the model file is not valid or the list of
     * checks has no entry or if no check is enabled or if one of the parameters
     * is invalid.
     */
    void updateRunButtonEnable() {
        boolean hasInvalidParameters = this.controller.hasAnalysisInvalidParameters();
        if (this.controller.isModelFileValid()) {
            this.controller.removeProblem(AdfEditorController.PROBLEM_MODEL);
            if (isOneCheckEnabled()) {
                this.controller.removeProblem(AdfEditorController.PROBLEM_CHECK);
                if (!hasInvalidParameters) {
                    setEnableRunButton(true);
                    this.controller.clearProblems();
                } else {
                    setEnableRunButton(false);
                }
            } else {
                this.controller.addProblem(AdfEditorController.PROBLEM_CHECK,
                        "The list contains no check or none is enabled");
                setEnableRunButton(false);
            }
        } else {
            this.controller.addProblem(AdfEditorController.PROBLEM_MODEL, "File is invalid");
            if (isOneCheckEnabled()) {
                this.controller.removeProblem(AdfEditorController.PROBLEM_CHECK);
            } else {
                this.controller.addProblem(AdfEditorController.PROBLEM_CHECK,
                        "The list contains no check or none is enabled");
            }
            setEnableRunButton(false);
        }
    }

    /**
     * Dis-/Enables the run button and shows the show problem link if necessary.
     * 
     * @param enableState
     *            The new enable state of the run button
     */
    private void setEnableRunButton(final boolean enableState) {
        this.run.setEnabled(enableState);
        this.problemLink.setVisible(!enableState);
    }

    /**
     * This method activates or deactivates the editors combo box.
     * 
     * @param active
     *            True, if the combo box should be activated, false otherwise
     * @param message
     *            the message, which will be shown
     */
    private void updateSelectedEditorEnableState(final boolean active, final String message) {
        boolean validEditor = false;
        if (this.selectedEditorCombo.getEnabled() != active) {
            this.selectedEditorCombo.removeAll();
            if (active) {
                this.selectedEditorCombo.setEnabled(true);
                // Get the editors
                final EditorRegistry editorRegistry = CarismaGUI.INSTANCE.getEditorRegistry();
                List<EditorDescriptor> editorDescriptorList = editorRegistry.getRegisteredEditors();
                this.selectedEditorCombo.add(DEFAULT_EDITOR);
                // Add all applicable editors to the combo box
                for (EditorDescriptor editorDesc : editorDescriptorList) {
                    if (editorDesc.isAvailable() && editorDesc.isApplicable(this.controller.getModelIFile())) {
                        this.selectedEditorCombo.add(editorDesc.getName());
                    }
                }
                // Select 'Default Eclipse Editor' by default or the editor,
                // which is saved in the adf file
                this.selectedEditorCombo.select(0);
                EditorDescriptor savedEditorDescriptor = editorRegistry
                        .getEditorDescriptorById(this.controller.getSelectedEditorId());
                if (savedEditorDescriptor != null) {
                    int index = 0;
                    for (String item : this.selectedEditorCombo.getItems()) {
                        if (item.equals(savedEditorDescriptor.getName())) {
                            this.selectedEditorCombo.select(index);
                            validEditor = true;
                            break;
                        }
                        index++;
                    }
                } else {
                    if ((this.controller.getSelectedEditorId().equals(""))
                            || (this.controller.getSelectedEditorId().equals("Default Eclipse Editor"))) {
                        validEditor = true;
                    }
                }
                this.selectedEditorCombo.setToolTipText("Choose an editor to open the model.");
                this.selectedEditorDecoration.hide();
            } else {
                if (EditorPriorityList.getPriorityList(this.controller.getModelType()) != null
                        && EditorPriorityList.getPriorityList(this.controller.getModelType()).size() >= 1) {
                    this.selectedEditorCombo
                            .add(EditorPriorityList.getPriorityList(this.controller.getModelType()).get(0));
                } else {
                    this.selectedEditorCombo.add("Priority list is empty!");
                }
                this.selectedEditorCombo.select(0);
                this.selectedEditorCombo.setEnabled(false);
                this.selectedEditorDecoration.setDescriptionText(message);
                this.selectedEditorCombo.setToolTipText("");
                this.selectedEditorDecoration.show();
            }
            if (!validEditor) {
                //MessageBox if the stored editor is invalid
                MessageDialog messageDialog = new MessageDialog(this.selectedEditorCombo.getShell(),
                        "Invalid Model-Editor", null,
                        "The chosen editor for the modeltype of the CARiSMA analysis is invalid." + "\nThe ID is \""
                                + this.controller.getSelectedEditorId() + "\"."
                                + "\nThe default editor will be chosen."
                                + "\nClick \"OK && remove ID\" to change the editor to the default editor in the analysis file.",
                        MessageDialog.INFORMATION, new String[] { "OK", "OK && remove ID" }, 0);
                // && in strings results in &
                messageDialog.open();
                if (messageDialog.getReturnCode() == 1) {
                    //set the stored Editor to the default Editor and saves the analysis file
                    setEditorToDefault();
                }
            }
        }
    }

    /**
     * Sets the editor for the modeltype to the eclipse default editor.
     */
    private void setEditorToDefault() {
        String defaultEditor = "Default Eclipse Editor";
        this.controller.setSelectedEditorId(defaultEditor);
        this.controller.saveAnalysis();
    }

    @Override
    protected final void registerPages(final DetailsPart newDetailsPart) {
        AdfEditorCheckDetailsPage detailsPage = new AdfEditorCheckDetailsPage(this.controller, this.masterListener);
        newDetailsPart.registerPage(CheckReference.class, detailsPage);
    }

    @Override
    protected void createToolBarActions(final IManagedForm arg0) {
        // Auto-generated method stub
    }

}