package net.iplantevin.ql.gui.formcomponents;
import net.iplantevin.ql.ast.expressions.Expression;
import net.iplantevin.ql.evaluation.BoolVal;
import net.iplantevin.ql.evaluation.UndefinedVal;
import net.iplantevin.ql.evaluation.Value;
import net.iplantevin.ql.gui.main.FormFrame;
import net.iplantevin.ql.gui.main.IdentifierGatherer;
import javax.swing.*;
import java.util.Set;
/**
* Listens to changes in the values in its condition and manages the activation
* and deactivation of the AbstractFormComponents it contains.
*
* @author Ivan
*/
public abstract class ConditionalComponent extends AbstractFormComponent {
private final AbstractFormComponent ifBody;
private Expression condition;
private static BoolVal TRUE = new BoolVal(true);
/**
* Constructs a ConditionalComponent.
*
* @param ifBody the component of the if statement body.
* @param condition the Expression of this if statement.
* @param frame the FormFrame to manage changes.
*/
public ConditionalComponent(AbstractFormComponent ifBody, Expression condition,
FormFrame frame) {
super(frame);
this.ifBody = ifBody;
this.condition = condition;
subScribe();
}
private void subScribe() {
Set<String> identifiers = IdentifierGatherer.gather(condition);
getFormFrame().subscribe(this, identifiers);
}
protected void initUI() {
setAlignmentY(TOP_ALIGNMENT);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(ifBody);
}
/**
* Re-evaluates this ConditionalComponent if it is currently active.
*/
@Override
public void reEvaluate() {
if (!isActive()) {
return;
}
Value conditionValue = getFormFrame().evaluate(condition);
if (isNewConditionValue(conditionValue)) {
setValue(conditionValue);
setIfBodyActive();
}
}
/**
* Handles the fact that two UndefinedVals are considered different.
*/
private boolean isNewConditionValue(Value conditionValue) {
if (getValue().isUndefined() && conditionValue.isUndefined()) {
return false;
}
return !conditionValue.equals(getValue());
}
private void setIfBodyActive() {
if (getValue().equals(TRUE)) {
ifBody.setActive(true);
} else {
ifBody.setActive(false);
}
}
@Override
public void initValue() {
Value conditionValue = getFormFrame().evaluate(condition);
setValue(conditionValue);
setIfBodyActive();
}
@Override
protected void setActive(boolean active) {
super.setActive(active);
if (active) {
reEvaluate();
} else {
setValue(new UndefinedVal());
ifBody.setActive(false);
}
}
}