/* * Copyright 2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.eclipse.dsl.inferencing.suggestions.ui; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.codehaus.groovy.eclipse.dsl.GroovyDSLCoreActivator; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; /** * * @author Nieraj Singh * @created 2011-05-13 */ public abstract class AbstractDialogue extends TitleAreaDialog { private Map<IDialogueControlDescriptor, SetValue> invalidValues; protected static final String EMPTY_ERROR_MESSAGE = " "; public AbstractDialogue(Shell parentShell) { super(parentShell); } /** * Must not be null * * @return */ abstract protected DialogueDescriptor getDialogueDescriptor(); protected boolean isResizable() { return true; } protected String iconLocation() { return null; } protected Control createDialogArea(Composite parent) { invalidValues = new HashMap<IDialogueControlDescriptor, SetValue>(); DialogueDescriptor descriptor = getDialogueDescriptor(); setTitle(descriptor.getTitle()); setMessage(descriptor.getMessage()); String iconLocation = descriptor.getIconLocation(); if (iconLocation != null && iconLocation.length() > 0) { setTitleImage(GroovyDSLCoreActivator.getImageDescriptor(iconLocation).createImage()); } Composite composite = new Composite(parent, SWT.NONE); GridLayoutFactory .fillDefaults() .margins(getDefaultCompositeHMargin(), getDefaultCompositeVMargin()) .spacing(convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING), convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING)).applyTo(composite); Dialog.applyDialogFont(composite); GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); createCommandArea(composite); return composite; } protected Control createContents(Composite parent) { Control control = super.createContents(parent); // Set "OK" button state after all dialogue contents are created to // ensure the // dialogue buttons have already been created. if (invalidValues != null) { for (SetValue setValue : invalidValues.values()) { if (setValue.getValue() == null) { enableOKButton(false); } } } return control; } protected Point getOffsetLabelLocation(String[] labels) { int length = SWT.DEFAULT; int charLength = 0; for (String label : labels) { int nameLength = label.length(); if (nameLength > charLength) { charLength = nameLength; } } if (charLength > 0) { Control control = getShell(); GC gc = new GC(control); Font requiredLabelFont = getRequiredParameterFont(); gc.setFont(requiredLabelFont != null ? requiredLabelFont : control.getFont()); FontMetrics fontMetrics = gc.getFontMetrics(); length = Dialog.convertWidthInCharsToPixels(fontMetrics, charLength); gc.dispose(); } Point longestLabelWidth = new Point(length, -1); longestLabelWidth.x += getLabelNameSeparatorOffset(); return longestLabelWidth; } protected int getLabelNameSeparatorOffset() { return 5; } protected Font getRequiredParameterFont() { return JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT); } protected int getDefaultCompositeVMargin() { return convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); } protected int getDefaultCompositeHMargin() { return convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); } abstract protected void createCommandArea(Composite parent); /** * Control listener to be used if the dialogue has required values that * determine if * the user can click "OK" on the dialogue. Two options exist: * 1. The value is not initially required (i.e. value is empty or null), but * once a value is set, it needs * to be verified before enabling the OK button * 2. The value is required, and an empty or null value is not acceptable. * * @author Nieraj Singh * @created 2011-08-06 */ abstract protected class ValidatedValueSelectionListener implements IControlSelectionListener { /** * User this only if values should not be initially marked as required * until a value is actually set */ public ValidatedValueSelectionListener() { } public ValidatedValueSelectionListener(IDialogueControlDescriptor descriptor, Object initialValue) { // Add any instances of the listener to the list of descriptors that // need to // be observed for value validation if (descriptor != null) { invalidValues.put(descriptor, new SetValue(initialValue, null)); } } public void handleSelection(ControlSelectionEvent event) { handleValidatedValue(event); notifyValidValueSet(event.getControlDescriptor(), event.getSelectionData()); } public void handleInvalidSelection(ControlSelectionEvent event) { IDialogueControlDescriptor descriptor = event.getControlDescriptor(); invalidValues.put(descriptor, new SetValue(event.getSelectionData(), event.getErrorMessage())); displayInvalidValueError(descriptor, event.getErrorMessage(), true); } abstract protected void handleValidatedValue(ControlSelectionEvent event); } protected void notifyValidValueSet(IDialogueControlDescriptor descriptor, Object value) { invalidValues.remove(descriptor); // Check if there are any remaining inValid values and display the next // error if (invalidValues != null) { for (Entry<IDialogueControlDescriptor, SetValue> entry : invalidValues.entrySet()) { if (entry.getValue().getValue() == null) { displayInvalidValueError(entry.getKey(), entry.getValue().getErrorMessage(), true); return; } } } setErrorMessage(null); enableOKButton(true); } /** * Checks if any required values are set with valid values before enabling * the "OK" button. */ protected void displayInvalidValueError(IDialogueControlDescriptor descriptor, String errorMessage, boolean displayErrorMessage) { StringBuffer missingFields = new StringBuffer(); missingFields.append("Value ("); missingFields.append(descriptor.getLabel()); missingFields.append(')'); if (errorMessage != null && errorMessage.length() > 0) { missingFields.append(':'); missingFields.append(' '); missingFields.append(errorMessage); } else { missingFields.append(" is missing"); } if (displayErrorMessage) { setErrorMessage(missingFields.toString()); } enableOKButton(false); } /** * Should only be called once the button bars have been created for the * dialogue * * @param enable */ protected void enableOKButton(boolean enable) { Button okButton = getButton(IDialogConstants.OK_ID); if (okButton != null && !okButton.isDisposed()) { okButton.setEnabled(enable); } } protected class SetValue { private Object value; private String errorMessage; public SetValue(Object value, String errorMessage) { this.value = value; this.errorMessage = errorMessage; } public Object getValue() { return value; } public String getErrorMessage() { return errorMessage; } } }