/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.codegen.ui.internal;
import gov.redhawk.ide.codegen.CodegenFactory;
import gov.redhawk.ide.codegen.CodegenUtil;
import gov.redhawk.ide.codegen.IPortTemplateDesc;
import gov.redhawk.ide.codegen.PortRepToGeneratorMap;
import gov.redhawk.ide.codegen.RedhawkCodegenActivator;
import java.util.Collections;
import java.util.HashSet;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* The Class PropertyDialog.
*/
public class GeneratorDialog extends Dialog {
private static final int NUM_COLUMNS = 3;
/**
* The title of the dialog.
*/
private final String title;
/**
* The input value; the empty string by default.
*/
private PortRepToGeneratorMap value;
/**
* Ok button widget.
*/
private Button okButton;
/**
* Viewer for selecting the RepID.
*/
private ComboViewer repIdViewer;
/**
* Viewer for selecting the code generator.
*/
private ComboViewer generatorViewer;
/**
* Error message label widget.
*/
private Text errorMessageText;
/**
* Error message string.
*/
private String errorMessage;
private Text descriptionText;
private final HashSet<String> repIds;
private final String language;
/**
* Creates an input dialog with OK and Cancel buttons. Note that the dialog
* will have no visual representation (no widgets) until it is told to open.
* <p>
* Note that the <code>open</code> method blocks for input dialogs.
* </p>
*
* @param parentShell the parent shell, or <code>null</code> to create a
* top-level shell
* @param dialogTitle the dialog title, or <code>null</code> if none
* @param curValue the initial input value, or <code>null</code> if none
* @param ports the Ports object of the SCD containing all the projects
* ports
* @param language the programming language of the base code generator
*/
public GeneratorDialog(final Shell parentShell, final String dialogTitle, final PortRepToGeneratorMap curValue, final HashSet<String> repIds,
final String language) {
super(parentShell);
this.title = dialogTitle;
this.language = language;
this.repIds = repIds;
this.value = curValue;
}
/**
* {@inheritDoc}
*/
@Override
protected void buttonPressed(final int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
final String selectedRep = (String) ((IStructuredSelection) this.repIdViewer.getSelection()).getFirstElement();
final IPortTemplateDesc selectedGen = (IPortTemplateDesc) ((IStructuredSelection) this.generatorViewer.getSelection()).getFirstElement();
final PortRepToGeneratorMap ref = CodegenFactory.eINSTANCE.createPortRepToGeneratorMap();
ref.setRepId(selectedRep);
ref.setGenerator(selectedGen.getId());
this.value = ref;
} else {
this.value = null;
}
super.buttonPressed(buttonId);
}
/**
* {@inheritDoc}
*/
@Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
if (this.title != null) {
shell.setText(this.title);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void createButtonsForButtonBar(final Composite parent) {
// create OK and Cancel buttons by default
this.okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
this.okButton.setEnabled(false);
// do this here because setting the text will set enablement on the ok
// button
this.repIdViewer.getControl().setFocus();
this.repIdViewer.setInput(this.repIds);
if (this.value != null) {
for (final String rep : this.repIds) {
if (this.value.getRepId().equals(rep)) {
this.repIdViewer.setSelection(new StructuredSelection(Collections.singletonList(rep)));
break;
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected Control createDialogArea(final Composite parent) {
// create composite
final Composite composite = (Composite) super.createDialogArea(parent);
final GridLayout layout = (GridLayout) composite.getLayout();
layout.numColumns = GeneratorDialog.NUM_COLUMNS;
Label label = new Label(composite, SWT.WRAP);
label.setText("Port RepID:");
label.setFont(parent.getFont());
this.repIdViewer = new ComboViewer(composite, getInputTextStyle() | SWT.READ_ONLY);
this.repIdViewer.getCombo().setEnabled(this.value == null);
this.repIdViewer.getCombo().addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
final String key = GeneratorDialog.this.repIdViewer.getCombo().getText();
IPortTemplateDesc gen = null;
// Get all the generators for this rep
final IPortTemplateDesc[] gens = RedhawkCodegenActivator.getCodeGeneratorPortTemplatesRegistry().findTemplatesByRepId(key,
GeneratorDialog.this.language);
GeneratorDialog.this.generatorViewer.setInput(gens);
// If we have a saved value, try to reselect it
if (GeneratorDialog.this.value != null) {
gen = CodegenUtil.getPortTemplate(GeneratorDialog.this.value.getGenerator(), null);
}
// If we couldn't find the value, or none is selected, choose the first
if ((gen == null) && (gens.length > 0)) {
gen = gens[0];
}
// If we have something to select, select it
if (gen != null) {
GeneratorDialog.this.generatorViewer.setSelection(new StructuredSelection(Collections.singletonList(gen)));
GeneratorDialog.this.descriptionText.setText((gen.getDescription() == null) ? "" : gen.getDescription().trim()); // SUPPRESS CHECKSTYLE AvoidInline
}
// Validate the dialog
validate();
}
});
this.repIdViewer.setContentProvider(new ArrayContentProvider());
this.repIdViewer.getControl().setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
this.descriptionText = new Text(composite, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL | SWT.BORDER);
this.descriptionText.setEditable(false);
this.descriptionText.setEnabled(false);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true, 1, GeneratorDialog.NUM_COLUMNS);
data.widthHint = 200; // SUPPRESS CHECKSTYLE MagicNumber
data.heightHint = (int) (data.widthHint * 0.75); // SUPPRESS CHECKSTYLE MagicNumber
this.descriptionText.setLayoutData(data);
label = new Label(composite, SWT.WRAP);
label.setText("Generator:");
label.setFont(parent.getFont());
this.generatorViewer = new ComboViewer(composite, getInputTextStyle() | SWT.READ_ONLY);
this.generatorViewer.getCombo().addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
widgetSelected(e);
}
@Override
public void widgetSelected(final SelectionEvent e) {
final IPortTemplateDesc gen = (IPortTemplateDesc) ((IStructuredSelection) GeneratorDialog.this.generatorViewer.getSelection())
.getFirstElement();
GeneratorDialog.this.descriptionText.setText((gen.getDescription() == null) ? "" : gen.getDescription().trim()); // SUPPRESS CHECKSTYLE AvoidInline
validate();
}
});
this.generatorViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(final Object element) {
return ((IPortTemplateDesc) element).getName();
}
});
this.generatorViewer.setContentProvider(new ArrayContentProvider());
this.generatorViewer.getControl().setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
this.errorMessageText = new Text(composite, SWT.READ_ONLY | SWT.WRAP);
data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
data.horizontalSpan = GeneratorDialog.NUM_COLUMNS;
this.errorMessageText.setLayoutData(data);
this.errorMessageText.setBackground(this.errorMessageText.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
// Set the error message text
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=66292
setErrorMessage(this.errorMessage);
Dialog.applyDialogFont(composite);
return composite;
}
/**
*
*/
protected void validate() {
if ("".equals(this.repIdViewer.getCombo().getText().trim())) {
setErrorMessage("Must select a RepID.");
} else if ("".equals(this.generatorViewer.getCombo().getText().trim())) {
setErrorMessage("Must select a generator.");
} else {
setErrorMessage(null);
}
}
/**
* Returns the ok button.
*
* @return the ok button
*/
protected Button getOkButton() {
return this.okButton;
}
/**
* Returns the string typed into this input dialog.
*
* @return the property value string
*/
public EObject getValue() {
return this.value;
}
/**
* Sets or clears the error message. If not <code>null</code>, the OK button
* is disabled.
*
* @param errorMessage the error message, or <code>null</code> to clear
*/
public void setErrorMessage(final String errorMessage) {
this.errorMessage = errorMessage;
if (this.errorMessageText != null && !this.errorMessageText.isDisposed()) {
this.errorMessageText.setText((errorMessage == null) ? " \n " : errorMessage); // SUPPRESS CHECKSTYLE AvoidInline //$NON-NLS-1$
// Disable the error message text control if there is no error, or
// no error text (empty or whitespace only). Hide it also to avoid
// color change.
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=130281
final boolean hasError = errorMessage != null && (StringConverter.removeWhiteSpaces(errorMessage)).length() > 0;
this.errorMessageText.setEnabled(hasError);
this.errorMessageText.setVisible(hasError);
this.errorMessageText.getParent().update();
// Access the ok button by id, in case clients have overridden
// button creation.
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=113643
final Control button = getButton(IDialogConstants.OK_ID);
if (button != null) {
button.setEnabled(errorMessage == null);
}
}
}
/**
* Returns the style bits that should be used for the input text field.
* Defaults to a single line entry. Subclasses may override.
*
* @return the integer style bits that should be used when creating the
* input text
*/
protected int getInputTextStyle() {
return SWT.SINGLE | SWT.BORDER;
}
}