StackPane based wizard : StackPane « JavaFX « Java






StackPane based wizard

 

import java.util.Stack;

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextAreaBuilder;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPaneBuilder;
import javafx.scene.layout.VBox;
import javafx.scene.layout.VBoxBuilder;
import javafx.stage.Stage;

public class Main extends Application {
  public static void main(String[] args) throws Exception {
    launch(args);
  }

  @Override
  public void start(Stage stage) throws Exception {

    stage.setScene(new Scene(new SurveyWizard(stage), 400, 250));
    stage.show();
  }
}

class Wizard extends StackPane {
  private static final int UNDEFINED = -1;
  private ObservableList<WizardPage> pages = FXCollections
      .observableArrayList();
  private Stack<Integer> history = new Stack<Integer>();
  private int curPageIdx = UNDEFINED;

  Wizard(WizardPage... nodes) {
    pages.addAll(nodes);
    navTo(0);
    setStyle("-fx-padding: 10; -fx-background-color: cornsilk;");
  }

  void nextPage() {
    if (hasNextPage()) {
      navTo(curPageIdx + 1);
    }
  }

  void priorPage() {
    if (hasPriorPage()) {
      navTo(history.pop(), false);
    }
  }

  boolean hasNextPage() {
    return (curPageIdx < pages.size() - 1);
  }

  boolean hasPriorPage() {
    return !history.isEmpty();
  }

  void navTo(int nextPageIdx, boolean pushHistory) {
    if (nextPageIdx < 0 || nextPageIdx >= pages.size())
      return;
    if (curPageIdx != UNDEFINED) {
      if (pushHistory) {
        history.push(curPageIdx);
      }
    }

    WizardPage nextPage = pages.get(nextPageIdx);
    curPageIdx = nextPageIdx;
    getChildren().clear();
    getChildren().add(nextPage);
    nextPage.manageButtons();
  }

  void navTo(int nextPageIdx) {
    navTo(nextPageIdx, true);
  }

  void navTo(String id) {
    Node page = lookup("#" + id);
    if (page != null) {
      int nextPageIdx = pages.indexOf(page);
      if (nextPageIdx != UNDEFINED) {
        navTo(nextPageIdx);
      }
    }
  }

  public void finish() {
  }

  public void cancel() {
  }
}

/** basic wizard page class */
abstract class WizardPage extends VBox {
  Button priorButton = new Button("_Previous");
  Button nextButton = new Button("N_ext");
  Button cancelButton = new Button("Cancel");
  Button finishButton = new Button("_Finish");

  WizardPage(String title) {
    getChildren().add(
        LabelBuilder.create().text(title)
            .style("-fx-font-weight: bold; -fx-padding: 0 0 5 0;").build());
    setId(title);
    setSpacing(5);
    setStyle("-fx-padding:10; -fx-background-color: honeydew; -fx-border-color: derive(honeydew, -30%); -fx-border-width: 3;");

    Region spring = new Region();
    VBox.setVgrow(spring, Priority.ALWAYS);
    getChildren().addAll(getContent(), spring, getButtons());

    priorButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent actionEvent) {
        priorPage();
      }
    });
    nextButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent actionEvent) {
        nextPage();
      }
    });
    cancelButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent actionEvent) {
        getWizard().cancel();
      }
    });
    finishButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent actionEvent) {
        getWizard().finish();
      }
    });
  }

  HBox getButtons() {
    Region spring = new Region();
    HBox.setHgrow(spring, Priority.ALWAYS);
    HBox buttonBar = new HBox(5);
    cancelButton.setCancelButton(true);
    finishButton.setDefaultButton(true);
    buttonBar.getChildren().addAll(spring, priorButton, nextButton,
        cancelButton, finishButton);
    return buttonBar;
  }

  abstract Parent getContent();

  boolean hasNextPage() {
    return getWizard().hasNextPage();
  }

  boolean hasPriorPage() {
    return getWizard().hasPriorPage();
  }

  void nextPage() {
    getWizard().nextPage();
  }

  void priorPage() {
    getWizard().priorPage();
  }

  void navTo(String id) {
    getWizard().navTo(id);
  }

  Wizard getWizard() {
    return (Wizard) getParent();
  }

  public void manageButtons() {
    if (!hasPriorPage()) {
      priorButton.setDisable(true);
    }

    if (!hasNextPage()) {
      nextButton.setDisable(true);
    }
  }
}

/** This class shows a satisfaction survey */
class SurveyWizard extends Wizard {
  Stage owner;

  public SurveyWizard(Stage owner) {
    super(new ComplaintsPage(), new MoreInformationPage(), new ThanksPage());
    this.owner = owner;
  }

  public void finish() {
    System.out.println("Had complaint? "
        + SurveyData.instance.hasComplaints.get());
    if (SurveyData.instance.hasComplaints.get()) {
      System.out.println("Complaints: "
          + (SurveyData.instance.complaints.get().isEmpty() ? "No Details"
              : "\n" + SurveyData.instance.complaints.get()));
    }
    owner.close();
  }

  public void cancel() {
    System.out.println("Cancelled");
    owner.close();
  }
}

/** Simple placeholder class for the customer entered survey response. */
class SurveyData {
  BooleanProperty hasComplaints = new SimpleBooleanProperty();
  StringProperty complaints = new SimpleStringProperty();
  static SurveyData instance = new SurveyData();
}

/**
 * This class determines if the user has complaints. If not, it jumps to the
 * last page of the wizard.
 */
class ComplaintsPage extends WizardPage {
  private RadioButton yes;
  private RadioButton no;
  private ToggleGroup options = new ToggleGroup();

  public ComplaintsPage() {
    super("Complaints");

    nextButton.setDisable(true);
    finishButton.setDisable(true);
    yes.setToggleGroup(options);
    no.setToggleGroup(options);
    options.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
      @Override
      public void changed(ObservableValue<? extends Toggle> observableValue,
          Toggle oldToggle, Toggle newToggle) {
        nextButton.setDisable(false);
        finishButton.setDisable(false);
      }
    });
  }

  Parent getContent() {
    yes = new RadioButton("Yes");
    no = new RadioButton("No");
    SurveyData.instance.hasComplaints.bind(yes.selectedProperty());
    return VBoxBuilder.create().spacing(5)
        .children(new Label("Do you have complaints?"), yes, no).build();
  }

  void nextPage() {
    // If they have complaints, go to the normal next page
    if (options.getSelectedToggle().equals(yes)) {
      super.nextPage();
    } else {
      // No complaints? Short-circuit the rest of the pages
      navTo("Thanks");
    }
  }
}

/** This page gathers more information about the complaint */
class MoreInformationPage extends WizardPage {
  public MoreInformationPage() {
    super("More Info");
  }

  Parent getContent() {
    TextArea textArea = TextAreaBuilder.create().wrapText(true).build();
    nextButton.setDisable(true);
    textArea.textProperty().addListener(new ChangeListener<String>() {
      @Override
      public void changed(ObservableValue<? extends String> observableValue,
          String oldValue, String newValue) {
        nextButton.setDisable(newValue.isEmpty());
      }
    });
    SurveyData.instance.complaints.bind(textArea.textProperty());
    return VBoxBuilder.create().spacing(5)
        .children(new Label("Please enter your complaints."), textArea).build();
  }
}

/** This page thanks the user for taking the survey */
class ThanksPage extends WizardPage {
  public ThanksPage() {
    super("Thanks");
  }

  Parent getContent() {
    StackPane stack = StackPaneBuilder.create().children(new Label("Thanks!"))
        .build();
    VBox.setVgrow(stack, Priority.ALWAYS);
    return stack;
  }
}

   
  








Related examples in the same category

1.Add Control to StackPane
2.Add StackPane to a Scene and then add Scene to Stage
3.Using StackPane to hold controls
4.Align the title Label at the bottom-center of the stackpane
5.Create an 8 pixel margin around a listview in the stackpane
6.Adding components to StackPane