view com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/CommandEditPage.java @ 98:c3002fd38e27

Fix dirty state handling for edit pages
author Omair Majid <omajid@redhat.com>
date Fri, 07 Feb 2014 12:57:54 -0500
parents 1c835942f3c2
children 4dfa549ca00c
line wrap: on
line source

package com.redhat.thermostat.tools.eclipse.plugin.editor;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;

import com.redhat.thermostat.tools.eclipse.plugin.BundleInformation;
import com.redhat.thermostat.tools.eclipse.plugin.Messages;
import com.redhat.thermostat.tools.eclipse.plugin.model.Bundle;
import com.redhat.thermostat.tools.eclipse.plugin.model.Command;
import com.redhat.thermostat.tools.eclipse.plugin.model.Environments;
import com.redhat.thermostat.tools.eclipse.plugin.model.Plugin;

/**
 * The page shown for editing aspects of a specific command.
 * <p>
 * The details area of the master-details block.
 */
class CommandEditPage implements IDetailsPage, IChangeListener {

    private FormToolkit toolkit;
    private Plugin model;

    private boolean isDirty = false;
    private boolean isStale = false;

    private Command commandModel;

    private Text commandName;
    private Text commandUsage;
    private Text commandDescription;
    private Button cli;
    private Button shell;

    // uses a List<Bundle> as the backing model
    private TableViewer bundlesTableViewer;

    private DataBindingContext bindingContext;

    private FormPage form;

    public CommandEditPage(FormPage formPage) {
        this.form = formPage;
    }

    public void setModel(Plugin model) {
        this.model = model;
    }

    @Override
    public void initialize(IManagedForm form) {
        toolkit = form.getToolkit();
    }

    @Override
    public void dispose() {
        if (bindingContext != null) {
            DataBindingChangeSupport.removeChangeListener(bindingContext, this);
            bindingContext.dispose();
        }
    }

    @Override
    public boolean isDirty() {
        return isDirty;
    }

    @Override
    public void commit(boolean onSave) {
        // model is always kept in sync

        if (onSave) {
            isDirty = false;
        }
    }

    @Override
    public boolean setFormInput(Object input) {
        // TODO fix this
        return false;
    }

    @Override
    public void setFocus() {
        // TODO what is this?
    }

    @Override
    public boolean isStale() {
        // FIXME check from model?
        return false;
    }

    @Override
    public void refresh() {
        // no-op: model is always kept in sync
    }

    @Override
    public void selectionChanged(IFormPart part, ISelection selection) {
        if (bindingContext != null) {
            DataBindingChangeSupport.removeChangeListener(bindingContext, this);
            bindingContext.dispose();
        }

        String commandName = (String) ((IStructuredSelection)selection).getFirstElement();
        commandModel = model.getCommand(commandName);
        if (commandModel == null) {
            return;
        }

        bindingContext = initDataBindings();
        DataBindingChangeSupport.addChangeListener(bindingContext, this);
    }

    @Override
    public void createContents(Composite parent) {
        TableWrapLayout parentLayout = new TableWrapLayout();
        parentLayout.topMargin = 0;
        parentLayout.bottomMargin = 0;
        parentLayout.leftMargin = 0;
        parentLayout.rightMargin = 0;
        parent.setLayout(parentLayout);

        Section section = toolkit.createSection(parent, Section.TITLE_BAR);

        TableWrapData tableData = new TableWrapData(TableWrapData.FILL, TableWrapData.TOP);
        tableData.grabHorizontal = true;

        section.setLayoutData(tableData);

        section.setText(Messages.CommandEditPage_commandDetailsSectionTitle);

        Composite sectionContents = toolkit.createComposite(section);
        section.setClient(sectionContents);

        sectionContents.setLayout(new GridLayout());

        createBasicSection(sectionContents);
        createArgumentsAndOptionsSection(sectionContents);
        createBundlesSection(sectionContents);
    }

    private void createBasicSection(Composite sectionContents) {
        Section basics = toolkit.createSection(sectionContents, Section.TITLE_BAR);
        basics.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        basics.setText(Messages.CommandEditPage_basicsSectionTitle);

        Composite basicContents = toolkit.createComposite(basics);
        basics.setClient(basicContents);
        basicContents.setLayout(new GridLayout(2, false));

        toolkit.createLabel(basicContents, Messages.CommandEditPage_nameLabel);
        commandName = toolkit.createText(basicContents, "<command name here>"); //$NON-NLS-1$
        commandName.setEditable(false);
        commandName.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        toolkit.createLabel(basicContents, Messages.CommandEditPage_usageLabel);
        commandUsage = toolkit.createText(basicContents, "<usage>"); //$NON-NLS-1$
        commandUsage.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        toolkit.createLabel(basicContents, Messages.CommandEditPage_descriptionLabel);
        commandDescription = toolkit.createText(basicContents, "<description>"); //$NON-NLS-1$
        commandDescription.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        toolkit.createLabel(basicContents, Messages.CommandEditPage_environmentsTitle);
        Composite environmentsComposite = toolkit.createComposite(basicContents);
        environmentsComposite.setLayout(new RowLayout());
        cli = toolkit.createButton(environmentsComposite, Messages.CommandEditPage_cliCheckTitle, SWT.CHECK);
        shell = toolkit.createButton(environmentsComposite, Messages.CommandEditPage_shellCheckTitle, SWT.CHECK);
    }

    private void createArgumentsAndOptionsSection(Composite sectionContents) {
        // TODO Auto-generated method stub
    }

    private void createBundlesSection(final Composite sectionContents) {
        Section bundles = toolkit.createSection(sectionContents, Section.TITLE_BAR);
        bundles.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        bundles.setText(Messages.CommandEditPage_bundlesToLoadsectionTitle);

        Composite bundleContents = toolkit.createComposite(bundles);
        bundles.setClient(bundleContents);
        bundleContents.setLayout(new GridLayout(2, false));

        Table list = toolkit.createTable(bundleContents, SWT.BORDER | SWT.V_SCROLL);
        list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        bundlesTableViewer = new TableViewer(list);
        IStructuredContentProvider contentProvider = ArrayContentProvider.getInstance();
        bundlesTableViewer.setContentProvider(contentProvider);

        Composite buttonComposite = toolkit.createComposite(bundleContents);
        buttonComposite.setLayout(new GridLayout(1, false));

        Button add = toolkit.createButton(buttonComposite, Messages.CommandEditPage_addButton, SWT.NONE);
        add.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
        add.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                NewBundleDialog dialog = new NewBundleDialog(sectionContents.getShell());
                dialog.create();
                if (dialog.open() == Window.OK) {
                    BundleInformation bundleInfo = dialog.getBundleInformation();
                    commandModel.addBundle(new Bundle(bundleInfo.getName(), bundleInfo.getVersion()));
                }
            }
        });

        Button remove = toolkit.createButton(buttonComposite, Messages.CommandEditPage_removeButton, SWT.NONE);
        remove.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
        remove.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Bundle selectedItem = (Bundle)
                        ((IStructuredSelection)bundlesTableViewer.getSelection()).getFirstElement();
                commandModel.removeBundle(selectedItem);
            }
        });
    }

    private DataBindingContext initDataBindings() {
        DataBindingContext bindingContext = new DataBindingContext();

        IObservableValue nameWidgetValue = WidgetProperties.text(SWT.Modify).observe(commandName);
        IObservableValue nameModelValue = BeanProperties.value(Command.class, "name").observe(commandModel); //$NON-NLS-1$
        bindingContext.bindValue(nameWidgetValue, nameModelValue);

        IObservableValue usageWidgetValue = WidgetProperties.text(SWT.Modify).observe(commandUsage);
        IObservableValue usageModelValue = BeanProperties.value(Command.class, "usage").observe(commandModel); //$NON-NLS-1$
        bindingContext.bindValue(usageWidgetValue, usageModelValue);

        IObservableValue descriptionWidgetValue = WidgetProperties.text(SWT.Modify).observe(commandDescription);
        IObservableValue descriptionModelValue = BeanProperties.value(Command.class, "description").observe(commandModel); //$NON-NLS-1$
        UpdateValueStrategy descriptionStrategy = new UpdateValueStrategy();
        descriptionStrategy.setBeforeSetValidator(new Validators.NonEmptyStringRequired("Description can not be empty"));
        Binding descriptionBinding = bindingContext.bindValue(descriptionWidgetValue, descriptionModelValue, descriptionStrategy, null);
        ControlDecorationSupport.create(descriptionBinding, SWT.LEFT | SWT.TOP);

        IObservableValue environmentsModelValue = BeanProperties.value(Command.class, "environments").observe(commandModel); //$NON-NLS-1$

        IObservableValue cliWidgetValue = WidgetProperties.selection().observe(cli);
        IObservableValue cliModelValue = BeanProperties.value(Environments.class, "cli").observeDetail(environmentsModelValue); //$NON-NLS-1$
        bindingContext.bindValue(cliWidgetValue, cliModelValue);

        IObservableValue shellWidgetValue = WidgetProperties.selection().observe(shell);
        IObservableValue shellModelValue = BeanProperties.value(Environments.class, "shell").observeDetail(environmentsModelValue); //$NON-NLS-1$
        bindingContext.bindValue(shellWidgetValue, shellModelValue);

        ObservableListContentProvider listContentProvider = new ObservableListContentProvider();
        bundlesTableViewer.setContentProvider(listContentProvider);

        IObservableList bundlesModel = BeanProperties.list(Command.class, "bundles").observe(commandModel); //$NON-NLS-1$
        bundlesTableViewer.setInput(bundlesModel);

        return bindingContext;
    }

    @Override
    public void handleChange(ChangeEvent event) {
        isDirty = true;

        form.getEditor().editorDirtyStateChanged();
    }
}