/******************************************************************************* * 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.IPropertyDescriptor; import gov.redhawk.ide.codegen.ITemplateDesc; import gov.redhawk.ide.codegen.Property; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.resource.StringConverter; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; 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 PropertyDialog extends Dialog { /** * The title of the dialog. */ private final String title; /** * The input value; the empty string by default. */ private Property value; /** * Ok button widget. */ private Button okButton; /** * Input text widget. */ private ComboViewer idText; /** * Error message label widget. */ private Text errorMessageText; /** * Error message string. */ private String errorMessage; private Text valueText; private final ITemplateDesc desc; private Text descriptionText; /** * 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 initialValue the initial input value, or <code>null</code> if none * (equivalent to the empty string) */ public PropertyDialog(final Shell parentShell, final String dialogTitle, final Property initialValue, final ITemplateDesc desc) { super(parentShell); this.title = dialogTitle; this.desc = desc; if (initialValue == null) { this.value = CodegenFactory.eINSTANCE.createProperty(); } else { this.value = initialValue; } } /** * {@inheritDoc} */ @Override protected void buttonPressed(final int buttonId) { if (buttonId == IDialogConstants.OK_ID) { this.value.setId(this.idText.getCombo().getText()); this.value.setValue(this.valueText.getText()); } 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.idText.getControl().setFocus(); this.idText.setInput(this.desc.getPropertyDescriptors()); if (this.value != null) { String id = this.value.getId(); if (id == null) { id = ""; } this.idText.getCombo().setText(id); String valueStr = this.value.getValue(); if (valueStr == null) { valueStr = ""; } this.valueText.setText(valueStr); } } /** * {@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 = 3; // SUPPRESS CHECKSTYLE MagicNumber Label label = new Label(composite, SWT.WRAP); label.setText("ID:"); label.setFont(parent.getFont()); this.idText = new ComboViewer(composite, getInputTextStyle() | SWT.READ_ONLY); this.idText.getCombo().addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { final String key = PropertyDialog.this.idText.getCombo().getText(); String v = null; for (final IPropertyDescriptor pDesc : PropertyDialog.this.desc.getPropertyDescriptors()) { if (pDesc.getKey().equals(key)) { v = pDesc.getDescription(); if (PropertyDialog.this.valueText.getText().length() == 0) { PropertyDialog.this.valueText.setText(pDesc.getDefaultValue()); } break; } } if (v == null) { v = ""; } PropertyDialog.this.descriptionText.setText(v.trim()); validate(); } }); this.idText.setLabelProvider(new LabelProvider() { @Override public String getText(final Object element) { final IPropertyDescriptor prop = (IPropertyDescriptor) element; return prop.getKey(); } }); this.idText.setContentProvider(new ArrayContentProvider()); this.idText.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, 2); 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("Value:"); label.setFont(parent.getFont()); label.setLayoutData(GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.TOP).grab(false, true).create()); this.valueText = new Text(composite, getInputTextStyle()); this.valueText.setLayoutData(GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).create()); this.valueText.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { validate(); } }); this.errorMessageText = new Text(composite, SWT.READ_ONLY | SWT.WRAP); data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); data.horizontalSpan = layout.numColumns; 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() { boolean enabledOkay = false; if ("".equals(this.idText.getCombo().getText().trim())) { setErrorMessage("Must enter a property id."); } else if ("".equals(this.valueText.getText().trim())) { setErrorMessage("Must enter a property value."); } else { setErrorMessage(null); enabledOkay = true; } this.okButton.setEnabled(enabledOkay); } /** * Returns the ok button. * * @return the ok button */ protected Button getOkButton() { return this.okButton; } /** * Returns the string typed into this input dialog. * * @return the input string */ public Property 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(String errorMessage) { this.errorMessage = errorMessage; if (this.errorMessageText != null && !this.errorMessageText.isDisposed()) { if (errorMessage == null) { errorMessage = " \n "; //$NON-NLS-1$ } this.errorMessageText.setText(errorMessage); // 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 = (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(!hasError); } } } /** * 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; } }