blob: 2dc19158f66c98b5a6aeb2e33d5af9b23ebaf6df [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.nico.ui.util;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.jface.databinding.swt.WidgetProperties;
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.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.statet.ecommons.databinding.IntegerValidator;
import org.eclipse.statet.ecommons.databinding.NotEmptyValidator;
import org.eclipse.statet.ecommons.databinding.core.observable.ComputedOnChangeValue;
import org.eclipse.statet.ecommons.databinding.jface.DataBindingSupport;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.util.VariableFilterUtils;
import org.eclipse.statet.ecommons.ui.workbench.ResourceInputComposite;
import org.eclipse.statet.internal.nico.ui.Messages;
import org.eclipse.statet.nico.core.runtime.SubmitType;
import org.eclipse.statet.nico.core.util.TrackingConfiguration;
/**
* Composite to configure a track configuration.
*/
public class TrackingConfigurationComposite extends Composite {
public static class SaveTemplate {
private final String label;
private final String filePath;
public SaveTemplate(final String label, final String path) {
this.label= label;
this.filePath= path;
}
public String getLabel() {
return this.label;
}
public String getFilePath() {
return this.filePath;
}
}
private Text nameControl;
private Button streamInfoControl;
private Button streamInputControl;
private Button streamInputHistoryOnlyControl;
private Button streamOutputErrorControl;
private Button streamOutputErrorTruncateControl;
private Text streamOutputErrorTruncateLinesControl;
private SubmitTypeSelectionComposite submitTypeControl;
private ResourceInputComposite filePathControl;
private Button fileAppendControl;
private Button fileOverwriteControl;
private Button prependTimestampControl;
private final List<SaveTemplate> saveTemplates= new ArrayList<>();
private TrackingConfiguration input;
public TrackingConfigurationComposite(final Composite parent) {
super(parent, SWT.NONE);
configure();
create();
}
protected boolean enableFullMode() {
return true;
}
protected boolean enableFilePathAsCombo() {
return false;
}
protected EnumSet<SubmitType> getEditableSubmitTypes() {
return EnumSet.allOf(SubmitType.class);
}
protected void configure() {
}
protected void addSaveTemplate(final SaveTemplate template) {
this.saveTemplates.add(template);
}
protected void create() {
setLayout(LayoutUtils.newCompositeGrid(1));
if (enableFullMode()) {
final Composite topComposite= createTopOptions(this);
if (topComposite != null) {
topComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
}
final Composite contentComposite= createContentOptions(this);
if (contentComposite != null) {
contentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
final Composite saveComposite= createSaveOptions(this);
if (saveComposite != null) {
saveComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
final Composite additionalComposite= createAdditionalOptions(this);
if (additionalComposite != null) {
additionalComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
}
private Composite createTopOptions(final Composite parent) {
final Composite composite= new Composite(parent, SWT.NONE);
composite.setLayout(LayoutUtils.newCompositeGrid(2));
{ final Label label= new Label(composite, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
label.setText(Messages.Tracking_Name_label);
}
{ final Text text= new Text(composite, SWT.BORDER);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint= LayoutUtils.hintWidth(text, 80);
text.setLayoutData(gd);
this.nameControl= text;
}
return composite;
}
private Composite createContentOptions(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Tracking_Content_label+':');
composite.setLayout(LayoutUtils.newGroupGrid(1));
{ this.streamInfoControl= new Button(composite, SWT.CHECK);
this.streamInfoControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.streamInfoControl.setText(Messages.Tracking_InfoStream_label);
}
{ this.streamInputControl= new Button(composite, SWT.CHECK);
this.streamInputControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.streamInputControl.setText(Messages.Tracking_InputStream_label);
}
if (enableFullMode()) {
this.streamInputHistoryOnlyControl= new Button(composite, SWT.CHECK);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.horizontalIndent= LayoutUtils.defaultIndent();
this.streamInputHistoryOnlyControl.setLayoutData(gd);
this.streamInputHistoryOnlyControl.setText(Messages.Tracking_InputStream_OnlyHistory_label);
this.streamInputHistoryOnlyControl.setEnabled(false);
}
{ this.streamOutputErrorControl= new Button(composite, SWT.CHECK);
this.streamOutputErrorControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.streamOutputErrorControl.setText(Messages.Tracking_OutputStream_label);
}
{ final Composite truncateRow;
{ truncateRow= new Composite(composite, SWT.NONE);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.horizontalIndent= LayoutUtils.defaultIndent();
truncateRow.setLayoutData(gd);
truncateRow.setLayout(LayoutUtils.newCompositeGrid(2));
}
{ this.streamOutputErrorTruncateControl= new Button(truncateRow, SWT.CHECK);
this.streamOutputErrorTruncateControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
this.streamOutputErrorTruncateControl.setText(Messages.Tracking_OutputStream_TruncateLines_label);
this.streamOutputErrorTruncateControl.setEnabled(false);
}
{ this.streamOutputErrorTruncateLinesControl= new Text(truncateRow, SWT.RIGHT | SWT.BORDER);
final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, false, false);
gd.widthHint= LayoutUtils.hintWidth(this.streamOutputErrorTruncateLinesControl, 10);
this.streamOutputErrorTruncateLinesControl.setLayoutData(gd);
this.streamOutputErrorTruncateLinesControl.setEnabled(false);
}
}
{ final Label label= new Label(composite, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
label.setText(Messages.Tracking_Sources_label);
this.submitTypeControl= new SubmitTypeSelectionComposite(composite);
this.submitTypeControl.setEditable(getEditableSubmitTypes());
this.submitTypeControl.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
}
return composite;
}
private Composite createSaveOptions(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Tracking_File_label+':');
composite.setLayout(LayoutUtils.newGroupGrid(1));
this.filePathControl= new ResourceInputComposite(composite,
enableFilePathAsCombo() ? ResourceInputComposite.STYLE_COMBO : ResourceInputComposite.STYLE_TEXT,
ResourceInputComposite.MODE_FILE | ResourceInputComposite.MODE_SAVE,
Messages.Tracking_File_label) {
@Override
protected void fillMenu(final Menu menu) {
super.fillMenu(menu);
if (!TrackingConfigurationComposite.this.saveTemplates.isEmpty()) {
new MenuItem(menu, SWT.SEPARATOR);
for (final SaveTemplate template : TrackingConfigurationComposite.this.saveTemplates) {
final MenuItem item= new MenuItem(menu, SWT.PUSH);
item.setText(template.getLabel());
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
setText(template.getFilePath());
getTextControl().setFocus();
}
});
}
}
}
};
this.filePathControl.setShowInsertVariable(true, VariableFilterUtils.DEFAULT_NON_ITERACTIVE_FILTERS, null);
this.filePathControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.fileAppendControl= new Button(composite, SWT.CHECK);
this.fileAppendControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
this.fileAppendControl.setText(Messages.Tracking_File_Append_label);
this.fileOverwriteControl= new Button(composite, SWT.CHECK);
this.fileOverwriteControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
this.fileOverwriteControl.setText(Messages.Tracking_File_Overwrite_label);
return composite;
}
protected ResourceInputComposite getPathInput() {
return this.filePathControl;
}
/**
* Extended or overwritten this method to add additional options.
*
* @return the composite containing the additional options
*/
protected Composite createAdditionalOptions(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Tracking_Actions_label+':');
composite.setLayout(LayoutUtils.newGroupGrid(1));
addDefaultAdditionalOptions(composite);
return composite;
}
protected Control addDefaultAdditionalOptions(final Composite composite) {
final int columns= ((GridLayout) composite.getLayout()).numColumns;
this.prependTimestampControl= new Button(composite, SWT.CHECK);
this.prependTimestampControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columns, 1));
this.prependTimestampControl.setText(Messages.Tracking_Actions_PrependTimestamp_label);
return this.prependTimestampControl;
}
protected void addBindings(final DataBindingSupport db) {
if (this.nameControl != null) {
db.getContext().bindValue(
WidgetProperties.text(SWT.Modify).observe(this.nameControl),
BeanProperties.value(TrackingConfiguration.class, "name") //$NON-NLS-1$
.observe(this.input),
new UpdateValueStrategy().setAfterGetValidator(new NotEmptyValidator(Messages.Tracking_Name_error_Missing_message)),
null );
}
final IObservableValue<Boolean> infoTargetObs= WidgetProperties.selection()
.observe(this.streamInfoControl);
db.getContext().bindValue(
infoTargetObs,
BeanProperties.value(TrackingConfiguration.class, "trackStreamInfo") //$NON-NLS-1$
.observe(this.input) );
final IObservableValue<Boolean> inputTargetObs= WidgetProperties.selection()
.observe(this.streamInputControl);
db.getContext().bindValue(inputTargetObs,
BeanProperties.value(TrackingConfiguration.class, "trackStreamInput") //$NON-NLS-1$
.observe(this.input) );
if (this.streamInputHistoryOnlyControl != null) {
db.getContext().bindValue(
WidgetProperties.enabled().observe(this.streamInputHistoryOnlyControl),
inputTargetObs );
db.getContext().bindValue(
WidgetProperties.selection().observe(this.streamInputHistoryOnlyControl),
BeanProperties.value(TrackingConfiguration.class, "trackStreamInputHistoryOnly") //$NON-NLS-1$
.observe(this.input) );
}
final IObservableValue<Boolean> outputTargetObj= WidgetProperties.selection()
.observe(this.streamOutputErrorControl);
final IObservableValue<Boolean> outputModelObs= BeanProperties.value(TrackingConfiguration.class, "trackStreamOutput") //$NON-NLS-1$
.observe(this.input);
db.getContext().bindValue(outputTargetObj, outputModelObs);
if (this.streamOutputErrorTruncateControl != null) {
final IObservableValue<Boolean> outputTruncateTargetObs= WidgetProperties.selection()
.observe(this.streamOutputErrorTruncateControl);
final IObservableValue<Boolean> outputTruncateModelObs= BeanProperties.value(TrackingConfiguration.class, "trackStreamOutputTruncate") //$NON-NLS-1$
.observe(this.input);
db.getContext().bindValue(
WidgetProperties.enabled().observe(this.streamOutputErrorTruncateControl),
outputTargetObj );
db.getContext().bindValue(
outputTruncateTargetObs,
outputTruncateModelObs );
db.getContext().bindValue(
WidgetProperties.enabled().observe(this.streamOutputErrorTruncateLinesControl),
new ComputedOnChangeValue<Boolean>(Boolean.class, outputModelObs, outputTruncateModelObs) {
@Override
protected Boolean calculate() {
final Boolean one= outputModelObs.getValue();
final Boolean two= outputTruncateModelObs.getValue();
return Boolean.valueOf(one.booleanValue() && two.booleanValue());
}
});
db.getContext().bindValue(
WidgetProperties.text(SWT.Modify).observe(this.streamOutputErrorTruncateLinesControl),
BeanProperties.value(TrackingConfiguration.class, "trackStreamOutputTruncateLines") //$NON-NLS-1$
.observe(this.input),
new UpdateValueStrategy().setAfterGetValidator(new IntegerValidator(2, 1000000,
Messages.Tracking_OutputStream_TruncateLines_error_Invalid_message )),
null );
}
if (this.submitTypeControl != null) {
db.getContext().bindValue(
this.submitTypeControl.getObservable(),
BeanProperties.value(TrackingConfiguration.class, "submitTypes") //$NON-NLS-1$
.observe(this.input) );
}
db.getContext().bindValue(
this.filePathControl.getObservable(),
BeanProperties.value(TrackingConfiguration.class, "filePath") //$NON-NLS-1$
.observe(this.input),
new UpdateValueStrategy().setAfterGetValidator(this.filePathControl.getValidator()),
null );
final IObservableValue<Integer> fileModeModelObs= BeanProperties.value(TrackingConfiguration.class, "fileMode") //$NON-NLS-1$
.observe(this.input);
db.getContext().bindValue(
WidgetProperties.selection().observe(this.fileAppendControl),
new ComputedOnChangeValue<Boolean>(Boolean.class, fileModeModelObs) {
@Override
protected Boolean calculate() {
final Integer mode= fileModeModelObs.getValue();
return Boolean.valueOf((mode.intValue() & EFS.APPEND) == EFS.APPEND);
}
@Override
protected void extractAndSet(final Object value) {
final Boolean selected= (Boolean) value;
fileModeModelObs.setValue(selected.booleanValue() ? EFS.APPEND : EFS.NONE);
}
});
db.getContext().bindValue(
WidgetProperties.selection().observe(this.fileOverwriteControl),
new ComputedOnChangeValue<Boolean>(Boolean.class, fileModeModelObs) {
@Override
protected Boolean calculate() {
final Integer mode= fileModeModelObs.getValue();
return Boolean.valueOf((mode.intValue() & EFS.OVERWRITE) == EFS.OVERWRITE);
}
@Override
protected void extractAndSet(final Object value) {
final Boolean selected= (Boolean) value;
fileModeModelObs.setValue(selected.booleanValue() ? EFS.OVERWRITE : EFS.NONE);
}
});
if (this.prependTimestampControl != null) {
db.getContext().bindValue(
WidgetProperties.selection().observe(this.prependTimestampControl),
BeanProperties.value(TrackingConfiguration.class, "prependTimestamp") //$NON-NLS-1$
.observe(this.input) );
}
}
public void setLabelEnabled(final boolean enabled) {
this.nameControl.setEnabled(enabled);
}
public void setStreamsEnabled(final boolean enabled) {
this.streamInfoControl.setEnabled(enabled);
this.streamInputControl.setEnabled(enabled);
if (this.streamInputHistoryOnlyControl != null) {
this.streamInputHistoryOnlyControl.setEnabled(enabled);
}
this.streamOutputErrorControl.setEnabled(enabled);
}
public boolean getStreamsEnabled() {
return this.streamInfoControl.getEnabled();
}
public void setSubmitTypesEnabled(final boolean enabled) {
this.submitTypeControl.setEnabled(enabled);
}
public boolean getSubmitTypesEnabled() {
return this.submitTypeControl.getEnabled();
}
public void setInput(final TrackingConfiguration config) {
this.input= config;
}
public TrackingConfiguration getInput() {
return this.input;
}
}