FaultSourceEditorDialog.java
/**
* Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
* All Rights Reserved.
*
* NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
* OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
* MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*
* 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/
* SPDX-License-Identifier: EPL-2.0
*
* Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
*
* This program includes and/or can make use of certain third party source code, object code, documentation and other
* files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
* configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
* conditions contained in any such Third Party Software or separate license file distributed with such Third Party
* Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
* aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
* censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
*/
package org.osate.ge.errormodel.ui.swt;
import java.util.Arrays;
import java.util.Collections;
import java.util.Objects;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.osate.ge.StringUtil;
import org.osate.ge.errormodel.ui.viewmodels.BasicTypeTokenListEditorModel;
import org.osate.ge.swt.SwtUtil;
import org.osate.ge.swt.selectors.CollectionSingleSelectorModel;
import org.osate.ge.swt.selectors.FilteringListSelectorField;
import org.osate.ge.swt.selectors.LabelFilteringListSelectorModel;
import org.osate.ge.swt.selectors.RadioSelector;
import org.osate.ge.swt.selectors.SingleSelectorModel;
import org.osate.xtext.aadl2.errormodel.errorModel.ErrorBehaviorState;
import org.osate.xtext.aadl2.errormodel.errorModel.ErrorModelFactory;
import org.osate.xtext.aadl2.errormodel.errorModel.TypeSet;
import com.google.common.base.Strings;
/**
* Dialog for editing a {@link FaultSource} provided by a {@link FaultSourceEditorModel}
*
*/
public final class FaultSourceEditorDialog {
private static final String WIDGET_ID_PREFIX = FaultSourceEditorDialog.class.getCanonicalName() + ".";
/**
* Testing ID of the label displaying the fault source's error behavior state
* @see SwtUtil#getTestingId(org.eclipse.swt.widgets.Widget)
*/
public static final String WIDGET_ID_STATE_VALUE_LABEL = WIDGET_ID_PREFIX + "stateValue";
/**
* Testing ID of the button for modifying the fault source's error behavior state
* @see SwtUtil#getTestingId(org.eclipse.swt.widgets.Widget)
*/
public static final String WIDGET_ID_STATE_MODIFY_BUTTON = WIDGET_ID_PREFIX + "stateModify";
/**
* Testing ID of the label displaying the fault source's type set
* @see SwtUtil#getTestingId(org.eclipse.swt.widgets.Widget)
*/
public static final String WIDGET_ID_TYPE_SET_VALUE_LABEL = WIDGET_ID_PREFIX + "typeSetValue";
/**
* Testing ID of the button for modifying the fault source's type set
* @see SwtUtil#getTestingId(org.eclipse.swt.widgets.Widget)
*/
public static final String WIDGET_ID_TYPE_SET_MODIFY_BUTTON = WIDGET_ID_PREFIX + "typeSetModify";
/**
* Testing ID of the text field for the fault source's failure mode description
* @see SwtUtil#getTestingId(org.eclipse.swt.widgets.Widget)
*/
public static final String WIDGET_ID_DESCRIPTION_TEXT = WIDGET_ID_PREFIX + "description";
private static enum FaultSourceType {
ERROR_TYPE_SET, DESCRIPTION
}
/**
* Private constructor to prevent instantiation.
*/
private FaultSourceEditorDialog() {
}
/**
* Opens a dialog to edit a fault condition.
* @param parent the parent of the dialog
* @param title the dialog's title
* @param model is the model to use to edit the fault condition.
* Will call {@link FaultSourceEditorModel#setFaultSource(FaultSource)} if OK was selected.
*/
public static void open(final Shell parent, final String title, final FaultSourceEditorModel model) {
Objects.requireNonNull(model, "model must not be null");
final InnerDialog dlg = new InnerDialog(parent, title, model);
if (dlg.open() == Window.OK) {
model.setFaultSource(dlg.getValue());
}
}
private static class InnerDialog extends TitleAreaDialog {
private final Runnable changeListener = this::refresh;
private final String title;
private final SingleSelectorModel<FaultSourceType> typeSelectorModel;
private final FaultSourceEditorModel model;
private CollectionSingleSelectorModel<ErrorBehaviorState> stateModel;
private Control stateLabel;
private FilteringListSelectorField<ErrorBehaviorState> stateField;
private BasicTypeTokenListEditorModel typeTokensModel;
private Control typeTokensLabel;
private TypeTokenListField typeTokensField;
private Control descriptionLabel;
private Text descriptionField;
private String description;
public InnerDialog(final Shell parentShell, final String title, final FaultSourceEditorModel model) {
super(parentShell);
this.title = Objects.requireNonNull(title, "title must not be null");
this.model = Objects.requireNonNull(model, "mode must not be null");
setShellStyle(getShellStyle() | SWT.RESIZE);
typeSelectorModel = new CollectionSingleSelectorModel<FaultSourceType>(
Arrays.asList(FaultSourceType.values())) {
@Override
public String getLabel(final FaultSourceType element) {
return StringUtil.snakeCaseToTitleCase(element.name());
}
};
final FaultSourceType type;
if (model.getFaultSource().getFailureModeDescription() != null) {
type = FaultSourceType.DESCRIPTION;
} else {
type = FaultSourceType.ERROR_TYPE_SET;
}
typeSelectorModel.setSelectedElement(type);
typeSelectorModel.changed().addListener(changeListener);
}
@Override
public void create() {
super.create();
setTitle(getShell().getText());
refresh();
}
@Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
shell.setText(title);
}
@Override
protected Control createDialogArea(final Composite parent) {
final Composite dialogArea = (Composite) super.createDialogArea(parent);
final Composite container = new Composite(dialogArea, SWT.NONE);
container.setLayoutData(GridDataFactory.swtDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).create());
container.setLayout(GridLayoutFactory.swtDefaults().numColumns(2).create());
final RadioSelector<FaultSourceType> typeSelector = new RadioSelector<>(container, typeSelectorModel);
typeSelector.setLayoutData(
GridDataFactory.swtDefaults().span(2, 1).grab(true, false).align(SWT.FILL, SWT.FILL).create());
//
// Error Behavior State
//
stateLabel = createLabel(container, "Error Behavior State:");
stateModel = new CollectionSingleSelectorModel<ErrorBehaviorState>(
model.getStateOptions()) {
@Override
public String getLabel(final ErrorBehaviorState element) {
return element == null ? "<None>" : element.getName();
}
};
stateModel.setSelectedElement(model.getFaultSource().getErrorBehaviorState());
stateField = new FilteringListSelectorField<>(container,
new LabelFilteringListSelectorModel<>(stateModel));
stateField.setValueLabelTestingId(WIDGET_ID_STATE_VALUE_LABEL);
stateField.setModifyButtonTestingId(WIDGET_ID_STATE_MODIFY_BUTTON);
stateField
.setLayoutData(GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.FILL).create());
//
// Type Tokens
//
typeTokensLabel = createLabel(container, "Type Set:");
typeTokensModel = new BasicTypeTokenListEditorModel(model.getErrorTypeOptions(),
model.getFaultSource().getErrorTypeSet() == null ? Collections.emptyList()
: model.getFaultSource().getErrorTypeSet().getTypeTokens(),
true);
typeTokensField = new TypeTokenListField(container, typeTokensModel);
typeTokensField.setValueLabelTestingId(WIDGET_ID_TYPE_SET_VALUE_LABEL);
typeTokensField.setModifyButtonTestingId(WIDGET_ID_TYPE_SET_MODIFY_BUTTON);
typeTokensField
.setLayoutData(GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.FILL).create());
//
// Failure Mode Description
//
descriptionLabel = createLabel(container, "Description:");
descriptionField = new Text(container, SWT.SINGLE | SWT.BORDER);
SwtUtil.setTestingId(descriptionField, WIDGET_ID_DESCRIPTION_TEXT);
descriptionField
.setLayoutData(GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.FILL).create());
description = model.getFaultSource().getFailureModeDescription();
descriptionField.setText(Strings.nullToEmpty(description));
descriptionField.addModifyListener(e -> {
description = descriptionField.getText();
refresh();
});
refresh();
return dialogArea;
}
private Control createLabel(final Composite container, final String txt) {
final Label label = new Label(container, SWT.NONE);
label.setText(txt);
label.setLayoutData(GridDataFactory.swtDefaults().grab(false, false).align(SWT.FILL, SWT.CENTER).create());
return label;
}
private void refresh() {
// Refresh error message and state of buttons
if (this.getShell() != null && !this.getShell().isDisposed()) {
final FaultSourceType type = typeSelectorModel.getSelectedElement();
final boolean showState = type == FaultSourceType.ERROR_TYPE_SET;
SwtUtil.setVisibilityAndExclusion(stateLabel, showState);
SwtUtil.setVisibilityAndExclusion(stateField, showState);
final boolean showTypeTokens = type == FaultSourceType.ERROR_TYPE_SET;
SwtUtil.setVisibilityAndExclusion(typeTokensLabel, showTypeTokens);
SwtUtil.setVisibilityAndExclusion(typeTokensField, showTypeTokens);
final boolean showDescription = type == FaultSourceType.DESCRIPTION;
SwtUtil.setVisibilityAndExclusion(descriptionLabel, showDescription);
SwtUtil.setVisibilityAndExclusion(descriptionField, showDescription);
}
}
public FaultSource getValue() {
final TypeSet typeSet = ErrorModelFactory.eINSTANCE.createTypeSet();
typeTokensModel.getTypeTokens().forEachOrdered(typeSet.getTypeTokens()::add);
if (typeSelectorModel.getSelectedElement() == FaultSourceType.DESCRIPTION) {
return new FaultSource(description);
} else {
return new FaultSource(stateModel.getSelectedElement(), typeSet);
}
}
}
/**
* Entry point for a test application.
* @param args command line arguments
* @noreference This method is not intended to be referenced by clients.
*/
public static void main(String[] args) {
SwtUtil.runDialog(
() -> FaultSourceEditorDialog.open(null, "Edit Fault Source", new TestFaultSourceEditorModel()));
}
}