package nl.uva.sc.encoders.qlruntime.ui;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import nl.uva.sc.encoders.ql.ast.expression.Expression;
import nl.uva.sc.encoders.ql.ast.statement.Question;
import nl.uva.sc.encoders.ql.ast.type.DataType;
import nl.uva.sc.encoders.qlruntime.evaluator.ExpressionEvaluator;
import nl.uva.sc.encoders.qlruntime.model.RuntimeQuestion;
import nl.uva.sc.encoders.qlruntime.model.value.BooleanValue;
import nl.uva.sc.encoders.qlruntime.model.value.Value;
import nl.uva.sc.encoders.qlruntime.ui.control.ControlGenerator;
import nl.uva.sc.encoders.qlruntime.ui.control.ControlPropertyChangeWrapper;
public class QuestionnaireGridPane extends GridPane {
public QuestionnaireGridPane() {
setAlignment(Pos.CENTER);
setHgap(10);
setVgap(10);
setPadding(new Insets(25, 25, 25, 25));
}
public void showQuestions(final List<RuntimeQuestion> allRuntimeQuestions, final List<RuntimeQuestion> runtimeQuestionsToShow) {
getChildren().clear();
int y = 1;
for (RuntimeQuestion runtimeQuestion : runtimeQuestionsToShow) {
Question question = runtimeQuestion.getQuestion();
Label label = new Label(question.getQuestionLabel());
add(label, 0, y);
Expression condition = runtimeQuestion.getCondition();
boolean visible = condition == null;
label.setVisible(visible);
ControlPropertyChangeWrapper controlPropertyChangeWrapper = generateControl(runtimeQuestion);
Control control = controlPropertyChangeWrapper.getControl();
control.setVisible(visible);
if (condition != null) {
addChangeListeners(runtimeQuestionsToShow, runtimeQuestion, condition, evt -> {
ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(runtimeQuestionsToShow);
// The cast to BooleanValue should be safe, because the
// types should already be checked at this point.
BooleanValue value = (BooleanValue) condition.accept(expressionEvaluator);
Boolean visible1 = value.getValue();
control.setVisible(visible1);
label.setVisible(visible1);
});
}
Expression computed = question.getComputed();
if (computed != null) {
runtimeQuestion.addPropertyChangeListener(controlPropertyChangeWrapper);
control.setDisable(true);
addChangeListeners(allRuntimeQuestions, runtimeQuestion, computed, evt -> {
ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(allRuntimeQuestions);
Value value = computed.accept(expressionEvaluator);
runtimeQuestion.setValue(value);
});
}
add(control, 1, y);
y++;
}
}
protected ControlPropertyChangeWrapper generateControl(RuntimeQuestion runtimeQuestion) {
Question question = runtimeQuestion.getQuestion();
DataType dataType = question.getDataType();
ControlGenerator controlGenerator = new ControlGenerator(runtimeQuestion);
return dataType.accept(controlGenerator);
}
private void addChangeListeners(final List<RuntimeQuestion> allRuntimeQuestions, final RuntimeQuestion runtimeQuestion,
final Expression expression, final PropertyChangeListener listener) {
Set<String> relatedQuestionNames = new HashSet<>();
expression.collectQuestionNames(relatedQuestionNames);
for (String relatedQuestionName : relatedQuestionNames) {
RuntimeQuestion relatedQuestion = RuntimeQuestion.getRuntimeQuestion(relatedQuestionName, allRuntimeQuestions);
relatedQuestion.addPropertyChangeListener(listener);
}
}
}