package edu.uva.softwarecons.ui; import edu.uva.softwarecons.checker.TypeChecker; import edu.uva.softwarecons.checker.warning.QuestionnaireWarning; import edu.uva.softwarecons.evaluator.ExpressionEvaluator; import edu.uva.softwarecons.evaluator.QuestionEvalVisitor; import edu.uva.softwarecons.grammar.QuestionnaireBuilderVisitor; import edu.uva.softwarecons.model.Form; import edu.uva.softwarecons.model.question.BasicQuestion; import edu.uva.softwarecons.model.question.ComputedQuestion; import edu.uva.softwarecons.model.question.IfQuestion; import edu.uva.softwarecons.model.question.Question; import edu.uva.softwarecons.model.type.BooleanType; import edu.uva.softwarecons.model.type.DateType; import edu.uva.softwarecons.model.type.IntegerType; import edu.uva.softwarecons.model.value.BooleanValue; import edu.uva.softwarecons.model.value.DateValue; import edu.uva.softwarecons.model.value.IntegerValue; import edu.uva.softwarecons.ui.dialog.DialogFactory; import edu.uva.softwarecons.ui.question.BooleanQuestionHBox; import edu.uva.softwarecons.ui.question.ComputedQuestionHBox; import edu.uva.softwarecons.ui.question.DateQuestionHBox; import edu.uva.softwarecons.ui.question.NumericQuestionHBox; import edu.uva.softwarecons.ui.question.QuestionHBox; import edu.uva.softwarecons.ui.widget.TitleHBox; import edu.uva.softwarecons.util.ParserBuilder; import edu.uva.softwarecons.util.StringUtil; import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.ScrollPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Text; import javafx.stage.FileChooser; import javafx.stage.Stage; import org.antlr.v4.runtime.tree.ParseTree; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.List; /** * Falconlabs * * @author Santiago Carrillo * Date: 3/6/14 */ public class MainApplication extends Application implements EventHandler<ActionEvent> { private HashMap<String, QuestionHBox> questions = new HashMap<String, QuestionHBox>(); private final VBox questionsVBox = new VBox(); private final VBox mainVBox = new VBox(); private final ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(); private Form form; public static void main( String[] args ) { launch( args ); } @Override public void start( final Stage primaryStage ) { primaryStage.setTitle( "Questionnaire Language" ); mainVBox.getChildren().add( getTopMenuBar( primaryStage ) ); Scene scene = new Scene( mainVBox, 600, 700 ); primaryStage.setScene( scene ); primaryStage.show(); } private MenuBar getTopMenuBar( final Stage stage ) { MenuBar menuBar = new MenuBar(); Menu menuFile = new Menu( "File" ); MenuItem menuItemOpen = new MenuItem( "Open" ); MenuItem menuItemExit = new MenuItem( "Exit" ); menuItemOpen.setOnAction( new EventHandler<ActionEvent>() { @Override public void handle( ActionEvent e ) { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle( "Open Questionnaire" ); File selectedFile = fileChooser.showOpenDialog( stage ); try { if ( null != selectedFile ) { loadForm( selectedFile ); } } catch ( FileNotFoundException e1 ) { DialogFactory.showErrorDialog( "File Not Found", "The specified file: " + selectedFile.getName() + "was not found" ); } catch ( IOException e1 ) { DialogFactory.showErrorDialog( "System Error", "Error loading file: " + selectedFile.getName() ); } } } ); menuItemExit.setOnAction( new EventHandler<ActionEvent>() { @Override public void handle( ActionEvent actionEvent ) { Platform.exit(); } } ); menuFile.getItems().add( menuItemOpen ); menuFile.getItems().add( menuItemExit ); menuBar.getMenus().add( menuFile ); return menuBar; } private void loadForm( File selectedFile ) throws IOException { ParserBuilder parserBuilder = new ParserBuilder(); ParseTree tree = parserBuilder.buildParseTree( new FileInputStream( selectedFile ) ); QuestionnaireBuilderVisitor questionnaireBuilderVisitor = new QuestionnaireBuilderVisitor(); form = (Form) questionnaireBuilderVisitor.visit( tree ); TypeChecker typeChecker = new TypeChecker(); typeChecker.checkForm( form ); if ( !typeChecker.getErrors().isEmpty() ) { DialogFactory.showQuestionnaireErrorDialog( typeChecker.getErrors() ); } else { ScrollPane scrollPane = new ScrollPane(); VBox.setVgrow( scrollPane, Priority.ALWAYS ); scrollPane.setContent( questionsVBox ); mainVBox.getChildren().add( new TitleHBox( form.getId(), "#336699", Color.WHITE ) ); mainVBox.getChildren().addAll( scrollPane, getSubmitFormPanel(), getWarningsPanel( typeChecker ) ); addQuestions( form.getQuestions() ); updateModel(); } } private HBox getSubmitFormPanel() { HBox hBox = new HBox( 10 ); hBox.setPadding( new Insets( 12, 12, 12, 12 ) ); hBox.setAlignment( Pos.CENTER ); Button button = new Button( "Submit" ); button.setOnAction( new EventHandler<ActionEvent>() { @Override public void handle( ActionEvent actionEvent ) { System.out.println( StringUtil.formToJson( form, questions ) ); } } ); hBox.getChildren().add( button ); return hBox; } private ScrollPane getWarningsPanel( TypeChecker typeChecker ) { HBox infoHBox = new HBox( 10 ); infoHBox.setPadding( new Insets( 12, 12, 12, 12 ) ); infoHBox.setAlignment( Pos.CENTER ); StringBuilder warnings = new StringBuilder(); for ( QuestionnaireWarning warning : typeChecker.getWarnings() ) { warnings.append( warning.toString() ).append( "\n" ); } infoHBox.getChildren().add( new Text( warnings.toString() ) ); ScrollPane scrollPane = new ScrollPane(); scrollPane.setContent( infoHBox ); return scrollPane; } private void addQuestions( List<Question> questions ) { for ( Question question : questions ) { if ( new IfQuestion( null, null, null, null ).equals( question ) ) { IfQuestion ifQuestion = (IfQuestion) question; addQuestions( ifQuestion.getQuestions() ); if ( null != ifQuestion.getElseQuestion() ) { addQuestions( ifQuestion.getElseQuestion().getQuestions() ); } } else { createQuestionLayout( question ); } } } private void updateIfQuestion( IfQuestion ifQuestion ) { boolean display = ( (BooleanValue) ifQuestion.getExpression().accept( expressionEvaluator ) ).getValue(); ifQuestion.accept( new QuestionEvalVisitor( display, questions, expressionEvaluator ) ); } private void createQuestionLayout( Question question ) { if ( new ComputedQuestion( null, null, null, null ).equals( question ) ) { ComputedQuestion computedQuestion = (ComputedQuestion) question; QuestionHBox questionHBox = new ComputedQuestionHBox( computedQuestion ); questions.put( computedQuestion.getId(), questionHBox ); } else if ( new BasicQuestion( null, null, null ).equals( question ) ) { BasicQuestion basicQuestion = (BasicQuestion) question; QuestionHBox questionHBox = null; if ( basicQuestion.getType().equals( new BooleanType() ) ) { questionHBox = new BooleanQuestionHBox( basicQuestion, this ); expressionEvaluator.addContextValue( basicQuestion.getId(), new BooleanValue( false ) ); } else if ( basicQuestion.getType().equals( new IntegerType() ) ) { questionHBox = new NumericQuestionHBox( basicQuestion, this ); expressionEvaluator.addContextValue( basicQuestion.getId(), new IntegerValue( 0 ) ); } else if ( basicQuestion.getType().equals( new DateType() ) ) { questionHBox = new DateQuestionHBox( basicQuestion, this ); expressionEvaluator.addContextValue( basicQuestion.getId(), new DateValue( new Date() ) ); } questions.put( basicQuestion.getId(), questionHBox ); } } private void addRemoveQuestions() { for ( QuestionHBox questionHBox : questions.values() ) { if ( questionHBox.isVisible() && !questionsVBox.getChildren().contains( questionHBox ) ) { questionsVBox.getChildren().add( questionHBox ); } else if ( !questionHBox.isVisible() && questionsVBox.getChildren().contains( questionHBox ) ) { questionsVBox.getChildren().remove( questionHBox ); } } } private void updateModel() { for ( Question question : form.getQuestions() ) { if ( new ComputedQuestion( null, null, null, null ).equals( question ) ) { ComputedQuestion computedQuestion = (ComputedQuestion) question; questions.get( computedQuestion.getId() ). updateValue( computedQuestion.getExpression().accept( expressionEvaluator ) ); } else if ( new IfQuestion( null, null, null, null ).equals( question ) ) { updateIfQuestion( (IfQuestion) question ); } } addRemoveQuestions(); } @Override public void handle( ActionEvent actionEvent ) { Node node = (Node) actionEvent.getSource(); expressionEvaluator.addContextValue( node.getId(), questions.get( node.getId() ).getValue() ); updateModel(); } }