Java tutorial
/******************************************************************************* * 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; } }