package waelti.statistics.views;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import waelti.statistics.actions.NewQueryAction;
import waelti.statistics.queries.AbstractQuery;
import waelti.statistics.queries.annotations.GetProperty;
import waelti.statistics.queries.annotations.SetProperty;
import ch.elexis.util.SWTHelper;
/**
* View of the metamodel. All label textfield pairs are obtained by reflecting
* on the given AbtractQuery object. At the moment, all query classes are
* represented in a map containing an object of each query class. Might be
* changed in the future and done by reflecting on the whole query package.
*
* @author michael waelti
* @see SetProperty
* @see GetProperty
* @see AbstractQuery
*/
public class OptionPanel extends Composite implements ModifyListener {
/** Map containing query objects and their title retrieved by getTitle */
private Map<String, Text> fieldMap;
/**
* The query which is selected at the moment and will be configured by the
* user input.
*/
private AbstractQuery query;
/**
* The action which needs the query in the end. This field may be deleted
* when a better and more elegant way is found to hand the query down.
*/
private NewQueryAction action;
/** Should not be used since the action is not set. */
public OptionPanel(Composite parent) {
super(parent, SWT.BORDER);
this.fieldMap = new TreeMap<String, Text>();
GridLayout layout = new GridLayout();
layout.numColumns = 2;
this.setLayout(layout);
this.initDefault();
}
/** Constructor normally used. */
public OptionPanel(Composite parent, NewQueryAction action) {
this(parent);
this.action = action;
}
private void initDefault() {
this.createLabel("keine Query ausgewählt. Wählen Sie "
+ "bitte eine Query aus.");
}
/** {@inheritDoc} */
public void updateContent(AbstractQuery selectedQuery) {
this.query = selectedQuery;
// clear this composite
for (Control child : this.getChildren()) {
if (child.getClass().equals(Text.class)) {
this.fieldMap.remove(child); // the map is not valid anymore.
}
child.dispose();
}
// populate again
populatePanel(selectedQuery);
this.layout();
this.getParent().getShell().pack();
this.setQueryFields();
}
/** Populates this composite via reflection using the getProperty annotation. */
private void populatePanel(AbstractQuery selectedQuery) {
for (Method method : selectedQuery.getClass().getMethods()) {
if (method.isAnnotationPresent(GetProperty.class)) {
GetProperty getter = method.getAnnotation(GetProperty.class);
this.createLabel(getter.value());
String value = this.getValue(selectedQuery, method);
Text field = this.createTextField(value);
field.addModifyListener(this);
fieldMap.put(getter.value(), field);
}
}
}
private String getValue(AbstractQuery selectedQuery, Method method) {
try {
return (String) method.invoke(selectedQuery);
} catch (Exception e) {
// TODO: log
}
return "error";
}
private Text createTextField(String value) {
Text text = new Text(this, SWT.BORDER);
text.setText(value);
return text;
}
private Label createLabel(String text) {
Label lab = new Label(this, SWT.WRAP);
lab.setLayoutData(SWTHelper.getFillGridData(1, false, 1, false));
lab.setText(text);
return lab;
}
/**
* Reads all fields, sets them via the meta model and returns the configured
* query.
*/
public AbstractQuery getQuery() {
this.setQueryFields();
return this.query;
}
/** Sets all fields via the meta model in the given query. */
private void setQueryFields() {
assert (this.query != null);
for (Method method : query.getClass().getMethods()) {
if (method.isAnnotationPresent(SetProperty.class)) {
SetProperty setter = method.getAnnotation(SetProperty.class);
Text field = this.fieldMap.get(setter.value());
String value = field.getText();
this.setValue(query, method, value);
}
}
this.action.setConfiguredQuery(this.query);
}
private void setValue(AbstractQuery query, Method method, String value) {
try {
method.invoke(query, value);
} catch (Exception e) {
// TODO: log
System.out.println("error setting values in query");
}
}
public void modifyText(ModifyEvent e) {
this.setQueryFields();
}
}