/* ******************************************************************************
* Copyright (c) 2014 - 2015 Fabian Prasser.
* 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
*
* Contributors:
* Fabian Prasser - initial API and implementation
******************************************************************************/
package de.linearbits.swt.widgets;
import java.text.NumberFormat;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* An input dialog for the knob
*
* @author Fabian Prasser
*/
class KnobInputDialog<T> extends Dialog {
/** The formatter*/
private NumberFormat formatter;
/** The message*/
private String message;
/** The input text*/
private String input;
/** The scale*/
private KnobRange<T> scale;
/** The value*/
private T value;
/**
* Creates a new dialog
* @param parent
* @param language
* @param scale
* @param value
*/
public KnobInputDialog(Shell parent, KnobDialogProfile language, KnobRange<T> scale, T value) {
super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
this.setText(language.getTitle());
this.scale = scale;
this.value = value;
String message = language.getMessage();
if ((scale instanceof KnobRange.Character) || (scale instanceof KnobRange.Long) ||
(scale instanceof KnobRange.Integer)) {
message = message.replace("[type]", language.getInteger());
} else {
message = message.replace("[type]", language.getDecimal());
}
message = message.replace("[range]", "[" + toString(scale.getMinimum()) + ", " + toString(scale.getMaximum()) + "]");
this.message = message;
}
/**
* Opens the dialog. Returns null if canceled, the entered value otherwise
* @return
*/
public T open() {
Shell shell = new Shell(getParent(), getStyle());
shell.setText(getText());
createContents(shell);
shell.pack();
shell.open();
center(shell, getParent());
Display display = getParent().getDisplay();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
if (input == null) return null;
else return toT(input);
}
/**
* Centers the given shell.
*
* @param shell
* @param parent
*/
private void center(final Shell shell, final Shell parent) {
final Rectangle bounds = parent.getBounds();
final Point p = shell.getSize();
final int left = (bounds.width - p.x) / 2;
final int top = (bounds.height - p.y) / 2;
shell.setBounds(left + bounds.x, top + bounds.y, p.x, p.y);
}
/**
* Creates the dialogs contents
* @param shell
*/
private void createContents(final Shell shell) {
shell.setLayout(new GridLayout(2, true));
Label label = new Label(shell, SWT.NONE);
label.setText(message);
GridData data = new GridData();
data.horizontalSpan = 2;
label.setLayoutData(data);
final Text text = new Text(shell, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 2;
text.setLayoutData(data);
text.setText(toString(value));
final Button ok = new Button(shell, SWT.PUSH);
ok.setText("OK");
data = new GridData(GridData.FILL_HORIZONTAL);
ok.setLayoutData(data);
ok.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
input = text.getText();
shell.close();
}
});
Button cancel = new Button(shell, SWT.PUSH);
cancel.setText("Cancel");
data = new GridData(GridData.FILL_HORIZONTAL);
cancel.setLayoutData(data);
cancel.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
input = null;
shell.close();
}
});
text.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if (toT(text.getText()) != null) {
ok.setEnabled(true);
} else {
ok.setEnabled(false);
}
}
});
shell.setDefaultButton(ok);
}
/**
* Translates a value to a string
* @param value
*/
private String toString(T value) {
if (scale instanceof KnobRange.Long){
long lvalue = (Long)value;
if (formatter == null) return String.valueOf(lvalue);
else return formatter.format(lvalue);
} else if (scale instanceof KnobRange.Integer){
int lvalue = (Integer)value;
if (formatter == null) return String.valueOf(lvalue);
else return formatter.format(lvalue);
} else if (scale instanceof KnobRange.Character){
int lvalue = (int)((Character)value).charValue();
if (formatter == null) return String.valueOf(lvalue);
else return formatter.format(lvalue);
} else if (scale instanceof KnobRange.Float){
float lvalue =(Float)value;
if (formatter == null) return String.valueOf(lvalue);
else return formatter.format(lvalue);
} else if (scale instanceof KnobRange.Double){
double lvalue =(Double)value;
if (formatter == null) return String.valueOf(lvalue);
else return formatter.format(lvalue);
} else {
throw new IllegalStateException("Unknown type of scale: "+scale);
}
}
@SuppressWarnings("unchecked")
private T toT(String input) {
try {
if (scale instanceof KnobRange.Long){
long min = ((KnobRange.Long)scale).getMinimum();
long max = ((KnobRange.Long)scale).getMaximum();
long value = formatter == null ? Long.valueOf(input) : formatter.parse(input).longValue();
if (value < min || value > max) return null;
else return (T)Long.valueOf(value);
} else if (scale instanceof KnobRange.Integer){
int min = ((KnobRange.Integer)scale).getMinimum();
int max = ((KnobRange.Integer)scale).getMaximum();
int value = formatter == null ? Integer.valueOf(input) : formatter.parse(input).intValue();
if (value < min || value > max) return null;
else return (T)Integer.valueOf(value);
} else if (scale instanceof KnobRange.Character){
char min = ((KnobRange.Character)scale).getMinimum();
char max = ((KnobRange.Character)scale).getMaximum();
char value = formatter == null ? (char)Integer.valueOf(input).intValue() : (char)formatter.parse(input).intValue();
if (value < min || value > max) return null;
else return (T)Character.valueOf(value);
} else if (scale instanceof KnobRange.Float){
float min = ((KnobRange.Float)scale).getMinimum();
float max = ((KnobRange.Float)scale).getMaximum();
float value = formatter == null ? Float.valueOf(input) : formatter.parse(input).floatValue();
if (value < min || value > max) return null;
else return (T)Float.valueOf(value);
} else if (scale instanceof KnobRange.Double){
double min = ((KnobRange.Double)scale).getMinimum();
double max = ((KnobRange.Double)scale).getMaximum();
double value = formatter == null ? Double.valueOf(input) : formatter.parse(input).doubleValue();
if (value < min || value > max) return null;
else return (T)Double.valueOf(value);
}
} catch (Exception e){
/* Catch silently*/
}
return null;
}
}