org.eclipse.rcptt.ui.editors.EditorHeader.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.rcptt.ui.editors.EditorHeader.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2015 Xored Software Inc and others.
 * 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:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.ui.editors;

import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.eclipse.rcptt.ui.launching.LaunchUtils.runResource;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.window.Window;
import org.eclipse.rcptt.core.model.IQ7NamedElement;
import org.eclipse.rcptt.core.model.ModelException;
import org.eclipse.rcptt.core.scenario.NamedElement;
import org.eclipse.rcptt.core.scenario.ScenarioPackage;
import org.eclipse.rcptt.core.tags.Tag;
import org.eclipse.rcptt.core.utils.TagsUtil;
import org.eclipse.rcptt.internal.ui.Images;
import org.eclipse.rcptt.internal.ui.Messages;
import org.eclipse.rcptt.launching.IExecutable;
import org.eclipse.rcptt.launching.ILaunchListener;
import org.eclipse.rcptt.launching.LaunchAdapter;
import org.eclipse.rcptt.launching.Q7Launcher;
import org.eclipse.rcptt.ui.commons.OneSelectionListener;
import org.eclipse.rcptt.ui.launching.LaunchUtils;
import org.eclipse.rcptt.ui.tags.SelectTagDialog;
import org.eclipse.rcptt.util.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.internal.forms.widgets.FormImages;

@SuppressWarnings("restriction")
public abstract class EditorHeader {

    protected DataBindingContext dbc = new DataBindingContext();
    protected StyledText nameText;
    protected ControlDecoration nameDecoration;
    protected Button addTag;
    protected StyledText tagsControl;

    private Button recordButton;
    private Button replayButton;

    private IQ7NamedElement model;
    private NamedElement element;
    private Binding nameBinding;
    private Binding tagsBinging;

    public EditorHeader(IQ7NamedElement model, NamedElement element) {
        this.model = model;
        this.element = element;
    }

    public IQ7NamedElement getModel() {
        return model;
    }

    public NamedElement getElement() {
        return element;
    }

    public DataBindingContext getDataBindingContext() {
        return dbc;
    }

    public StyledText getTagsControl() {
        return tagsControl;
    }

    public Button getRecordButton() {
        return recordButton;
    }

    public Button getReplayButton() {
        return replayButton;
    }

    public Composite createContent(Composite parent, FormToolkit toolkit) {
        GridLayoutFactory.fillDefaults().margins(0, 0).spacing(0, 0).equalWidth(true).applyTo(parent);

        createGeneral(parent, toolkit);

        Composite composite = toolkit.createComposite(parent);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
        GridLayoutFactory.fillDefaults().margins(5, 5).spacing(0, 0).equalWidth(true).applyTo(composite);
        update(this.model, this.element);

        return composite;
    }

    protected void createGeneral(Composite parent, FormToolkit toolkit) {
        Composite composite = toolkit.createComposite(parent);

        GridLayoutFactory.swtDefaults().numColumns(getTotalColumns()).spacing(10, 4).applyTo(composite);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).applyTo(composite);

        createNameControl(composite, toolkit);
        recordButton = createRecordButton(composite, toolkit);
        createTagControl(composite, toolkit);
        replayButton = createReplayButton(composite, toolkit);

        int height = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;

        Color top = toolkit.getColors().getColor(IFormColors.H_GRADIENT_END);
        Color bot = toolkit.getColors().getColor(IFormColors.H_GRADIENT_START);

        Image gradientImage = FormImages.getInstance().getGradient(new Color[] { top, bot }, new int[] { 100 },
                height, true, toolkit.getColors().getColor(IFormColors.TB_BG), composite.getDisplay());
        // No need to dispose the gradient image cause it's created and stored
        // in resource manager
        composite.setBackgroundImage(gradientImage);

        Composite c1 = toolkit.createComposite(parent);
        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 1).span(4, 1).grab(true, false).applyTo(c1);
        c1.setBackground(toolkit.getColors().getColor(IFormColors.H_BOTTOM_KEYLINE1));

        Composite c2 = toolkit.createComposite(parent);
        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 1).span(4, 1).grab(true, false).applyTo(c2);
        c2.setBackground(toolkit.getColors().getColor(IFormColors.H_BOTTOM_KEYLINE2));

        // if (!Platform.getOS().equals(Platform.OS_MACOSX)) {
        // // We need to simulate transparent background for labels
        // composite.layout();
        // setBackgroundToHeaderLabel(nameLabel, gradientImage);
        // setBackgroundToHeaderLabel(tagsLabel, gradientImage);
        // }
    }

    protected int getTotalColumns() {
        return 4;
    }

    public void focus() {
        nameText.setFocus();
    }

    protected void createNameControl(Composite parent, FormToolkit toolkit) {
        createLabel(parent, toolkit, Messages.NamedElementEditorPage_NameLabel);
        nameText = createWrappedText(parent, toolkit, element.getName(), 2);
        nameText.setBackground(null);

        nameDecoration = new ControlDecoration(nameText, SWT.TOP | SWT.LEFT);

        FieldDecoration errorFieldIndicator = FieldDecorationRegistry.getDefault()
                .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
        nameDecoration.setImage(errorFieldIndicator.getImage());

        nameDecoration.setMarginWidth(2);
        nameDecoration.setShowHover(true);
        nameDecoration.hide();
    }

    protected Menu createTextMenu(final StyledText text) {
        Menu menu = new Menu(text);

        MenuItem copy = new MenuItem(menu, SWT.PUSH);
        copy.setText("Copy");
        copy.addSelectionListener(new OneSelectionListener() {
            @Override
            public void selected(SelectionEvent e) {
                if (TextUtils.canCopy(text))
                    TextUtils.copy(text);
            }
        });

        MenuItem paste = new MenuItem(menu, SWT.PUSH);
        paste.setText("Paste");
        paste.addSelectionListener(new OneSelectionListener() {
            @Override
            public void selected(SelectionEvent e) {
                if (TextUtils.canPaste(text))
                    TextUtils.paste(text);
            }
        });

        MenuItem cut = new MenuItem(menu, SWT.PUSH);
        cut.setText("Cut");
        cut.addSelectionListener(new OneSelectionListener() {
            @Override
            public void selected(SelectionEvent e) {
                if (TextUtils.canCut(text))
                    TextUtils.cut(text);
            }
        });

        return menu;
    }

    protected StyledText createWrappedText(Composite parent, FormToolkit toolkit, String text, int hSpan) {
        Composite composite = toolkit.createComposite(parent);
        GridLayoutFactory.fillDefaults().equalWidth(true).applyTo(composite);
        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).span(hSpan, 1).grab(true, false)
                .applyTo(composite);
        StyledText textControl = new StyledText(composite,
                SWT.BORDER | SWT.SINGLE | toolkit.getBorderStyle() | toolkit.getOrientation());
        textControl.setText(text);
        toolkit.adapt(textControl);
        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).hint(111, SWT.DEFAULT)
                .applyTo(textControl);
        textControl.setBackground(null);

        textControl.setMenu(createTextMenu(textControl));

        return textControl;
    }

    protected void createTagControl(Composite parent, FormToolkit toolkit) {
        createLabel(parent, toolkit, Messages.NamedElementEditorPage_TagsLabel);
        Composite tags = toolkit.createComposite(parent, SWT.NONE);
        tags.setBackground(null);
        GridLayoutFactory.fillDefaults().spacing(3, 0).numColumns(2).margins(0, 0).applyTo(tags);
        GridDataFactory.fillDefaults().grab(true, false).span(getTagsSpacing(), 1).applyTo(tags);

        tagsControl = new StyledText(tags,
                SWT.BORDER | SWT.SINGLE | toolkit.getBorderStyle() | toolkit.getOrientation());
        toolkit.adapt(tagsControl);
        tagsControl.setBackground(null);
        tagsControl.setMenu(createTextMenu(tagsControl));
        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(tagsControl);
        addTag = toolkit.createButton(tags, "", SWT.PUSH); //$NON-NLS-1$
        addTag.setToolTipText(Messages.NamedElementEditorPage_AddTagButton);
        addTag.setBackground(null);
        GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(addTag);
        addTag.setImage(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJ_ADD)
                .createImage());
        addTag.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                final List<String> existingTags = TagsUtil.extractTags(element.getTags());
                final SelectTagDialog dialog = new SelectTagDialog(tagsControl.getShell(), existingTags);

                if (dialog.open() == SelectTagDialog.OK) {
                    final StringBuilder sb = new StringBuilder(element.getTags());
                    boolean first = existingTags.isEmpty();
                    if (!dialog.getResult().isEmpty()) {
                        for (final Tag tag : dialog.getResult()) {
                            if (!first) {
                                sb.append(", "); //$NON-NLS-1$
                            } else {
                                first = false;
                            }
                            sb.append(tag.getPath());
                        }
                        element.setTags(sb.toString());
                    } else if (dialog.getTagName() != null) {
                        if (sb.toString().length() != 0) {
                            sb.append(", "); //$NON-NLS-1$
                        }
                        sb.append(dialog.getTagName().trim());
                        element.setTags(sb.toString());
                    }
                }
            }
        });
    }

    protected int getTagsSpacing() {
        return 2;
    }

    protected Button createRecordButton(Composite composite, FormToolkit toolkit) {
        Button button = toolkit.createButton(composite, Messages.NamedElementEditorPage_RecordButton, SWT.PUSH);
        button.setImage(Images.getImageDescriptor(Images.RECORD).createImage());
        button.setBackground(null);
        GridDataFactory.fillDefaults().applyTo(button);
        button.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                record();
            }
        });
        return button;
    }

    protected Button createReplayButton(Composite composite, FormToolkit toolkit) {
        Button button = toolkit.createButton(composite, Messages.NamedElementEditorPage_ReplayButton, SWT.PUSH);
        button.setImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_ACT_RUN).createImage());
        button.setBackground(null);
        GridDataFactory.fillDefaults().applyTo(button);
        button.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                if ((e.stateMask & SWT.SHIFT) != 0)
                    multiReplay();
                else
                    replay();
            }
        });
        return button;
    }

    protected Label createLabel(Composite parent, FormToolkit toolkit, final String label) {
        Label labelControl = new Label(parent, SWT.NONE);
        labelControl.setText(label);
        labelControl.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
        GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(labelControl);
        labelControl.setBackground(null);
        return labelControl;
    }

    protected void setBackgroundToHeaderLabel(Label label, Image backgroundImage) {
        Rectangle bounds = label.getBounds();
        bounds.x = 0;
        bounds.width = 1;
        final Image image = new Image(label.getDisplay(), bounds);
        GC gc = new GC(image);
        gc.drawImage(backgroundImage, bounds.x, bounds.y, bounds.width, bounds.height, 0, 0, bounds.width,
                bounds.height);
        gc.dispose();
        label.setBackgroundImage(image);
        label.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                image.dispose();
            }
        });
    }

    protected abstract void record();

    protected void replay() {
        IResource res = model.getResource();
        if (res == null)
            return;
        LaunchUtils.launchContext(new IResource[] { res }, "run"); //$NON-NLS-1$
    }

    private static int getReplayCount() {
        InputDialog in = new InputDialog(null, Messages.NamedElementEditorPage_RunCounterDialogTitle,
                Messages.NamedElementEditorPage_RunCounterDialogLabel,
                Messages.NamedElementEditorPage_RunCounterDialogDefaultValue, new IInputValidator() {
                    public String isValid(String newText) {
                        try {
                            int value = Integer.parseInt(newText);
                            if (value <= 0) {
                                return Messages.NamedElementEditorPage_RunCounterDialogNeagtiveIntErrorMsg;
                            }
                        } catch (Throwable e) {
                            return Messages.NamedElementEditorPage_RunCounterDialogIncorrectIntErrorMsg;
                        }
                        return null;
                    }
                });
        if (in.open() != Window.OK) {
            return -1;
        }
        return Integer.parseInt(in.getValue());
    }

    private static boolean resourceSaved(IResource res) {
        try {
            return LaunchUtils.saveChanges(new IResource[] { res });
        } catch (ModelException e) {
            return false;
        }
    }

    protected void multiReplay() {
        final IResource res = model.getResource();
        if (res == null) {
            return;
        }
        int count = getReplayCount();
        if (count == -1) {
            return;
        }
        if (!resourceSaved(res)) {
            return;
        }

        final AtomicInteger countAtom = new AtomicInteger(count);
        final Job execJob = new Job("Times execute") { //$NON-NLS-1$
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                runResource(res);
                return Status.OK_STATUS;
            }
        };

        final ILaunchListener listener = new LaunchAdapter() {

            public void launchStatusChanged(IExecutable... executable) {
                for (IExecutable e : executable) {
                    if (!e.getResultStatus().isOK()) {
                        countAtom.set(0);
                    }
                }
            }

            public void finished() {
                if (countAtom.decrementAndGet() > 0) {
                    execJob.schedule(500);
                }
            }
        };

        Job cancelationJob = new Job("Times execution") { //$NON-NLS-1$
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                int count = countAtom.get();
                monitor.beginTask("Times", count); //$NON-NLS-1$
                while (!monitor.isCanceled() && (count = countAtom.get()) > 0) {
                    sleepUninterruptibly(100, MILLISECONDS);
                    monitor.worked(count - countAtom.get());
                }
                countAtom.set(0);
                Q7Launcher.getInstance().removeListener(listener);
                return Status.OK_STATUS;
            }
        };

        cancelationJob.schedule();
        cancelationJob.setPriority(Job.LONG);
        Q7Launcher.getInstance().addListener(listener);
        execJob.schedule();

    }

    public boolean isInFocus() {
        if (nameText.isFocusControl() || tagsControl.isFocusControl()) {
            return true;
        }
        return false;
    }

    public void doSelectAll() {
        if (nameText.isFocusControl()) {
            nameText.selectAll();
        } else if (tagsControl.isFocusControl()) {
            tagsControl.selectAll();
        }
    }

    public void copy() {
        if (nameText.isFocusControl()) {
            TextUtils.copy(nameText);
        } else if (tagsControl.isFocusControl()) {
            TextUtils.copy(tagsControl);
        }
    }

    public boolean canCopy() {
        if (nameText.isFocusControl()) {
            return TextUtils.canCopy(nameText);
        } else if (tagsControl.isFocusControl()) {
            return TextUtils.canCopy(tagsControl);
        }
        return false;
    }

    public boolean canPaste() {
        if (nameText.isFocusControl()) {
            return TextUtils.canPaste(nameText);
        } else if (tagsControl.isFocusControl()) {
            return TextUtils.canPaste(tagsControl);
        }
        return false;
    }

    public boolean canCut() {
        if (nameText.isFocusControl()) {
            return TextUtils.canCut(nameText);
        } else if (tagsControl.isFocusControl()) {
            return TextUtils.canCut(tagsControl);
        }
        return false;
    }

    public void paste() {
        if (nameText.isFocusControl()) {
            TextUtils.paste(nameText);
        } else if (tagsControl.isFocusControl()) {
            TextUtils.paste(tagsControl);
        }
    }

    public void cut() {
        if (nameText.isFocusControl()) {
            TextUtils.cut(nameText);
        } else if (tagsControl.isFocusControl()) {
            TextUtils.cut(tagsControl);
        }
    }

    private IStatus nameFail(String message) {
        nameDecoration.setDescriptionText(message);
        nameDecoration.show();
        return Status.CANCEL_STATUS;
    }

    private IStatus nameWin() {
        nameDecoration.hide();
        return Status.OK_STATUS;
    }

    public void update(final IQ7NamedElement model, NamedElement element) {
        this.model = model;
        this.element = element;
        if (nameText != null) {
            if (nameBinding != null) {
                nameBinding.dispose();
            }

            UpdateValueStrategy strategy = new UpdateValueStrategy();
            strategy.setBeforeSetValidator(new IValidator() {
                public IStatus validate(Object value) {
                    String text = (String) value;

                    if (StringUtils.isBlank(text))
                        return nameFail("Name must be non-blank string.");

                    // that is toooo slooooow
                    // IQ7NamedElement[] found = Q7SearchCore.findByName(text,
                    // new OneProjectScope(model.getQ7Project()),
                    // new NullProgressMonitor());
                    // for (IQ7NamedElement e : found)
                    // if (e != model && e.getClass() == model.getClass())
                    // return nameFail("Name is already in use.");

                    return nameWin();
                }
            });
            nameBinding = dbc.bindValue(SWTObservables.observeText(nameText, SWT.Modify),
                    EMFObservables.observeValue(element, ScenarioPackage.eINSTANCE.getNamedElement_Name()),
                    strategy, null);
        }

        if (tagsControl != null) {
            if (tagsBinging != null) {
                tagsBinging.dispose();
            }
            tagsBinging = dbc.bindValue(SWTObservables.observeText(tagsControl, SWT.Modify),
                    EMFProperties.value(ScenarioPackage.Literals.NAMED_ELEMENT__TAGS).observe(element));
        }
    }

    public void doTextCommand(int fAction) {

        if (nameText.isFocusControl()) {
            nameText.invokeAction(fAction);
        } else if (tagsControl.isFocusControl()) {
            tagsControl.invokeAction(fAction);
        }
    }

    public boolean canUndo() {
        return false;
    }

    public boolean canRedo() {
        return false;
    }

    public void undo() {
    }

    public void redo() {
    }

    protected StyledText getNameControl() {
        return nameText;
    }
}