All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.imunity.vaadin.elements.wizard.Wizard Maven / Gradle / Ivy

/*
 * Copyright (c) 2021 Bixbit - Krzysztof Benedyczak. All rights reserved.
 * See LICENCE.txt file for licensing information.
 */

package io.imunity.vaadin.elements.wizard;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.FlexComponent.JustifyContentMode;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.progressbar.ProgressBar;

import io.imunity.vaadin.elements.CssClassNames;

public class Wizard extends Dialog
{
	private final Button finishButton = new Button();
	private final Button nextButton = new Button();
	private final Button backButton = new Button();
	private final ProgressBar progressBar = new ProgressBar();
	private final double progressBarIncrementer;
	private final VerticalLayout contentLayout = new VerticalLayout();
	private final UI ui = UI.getCurrent();
	private final WizardStepController wizardStepController;


	public Wizard(List steps, List> stepPreparers, Function msg,
			Runnable cancelTask, String title)
	{
		setModal(true);
		setWidth("80%");
		setHeight("60%");
		setCloseOnOutsideClick(false);
		
		contentLayout.addClassName(CssClassNames.WIZARD.getName());
		
		this.wizardStepController = new WizardStepController(steps, stepPreparers);
		List labels = steps.stream()
				.map(step -> step.label).toList();
		this.progressBarIncrementer = 1.0/(steps.size() - 1);

		HorizontalLayout labelsLayout = new HorizontalLayout();

		initLabelsLayout(labels, labelsLayout);

		Button cancelButton = new Button(msg.apply("Wizard.cancel"), e -> {cancelTask.run(); close();});
		cancelButton.setId("Wizard.cancel");

		nextButton.setText(msg.apply("Wizard.next"));
		nextButton.setId("Wizard.next");
		nextButton.addClickListener(event -> nextStep());
		nextButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);

		backButton.setText(msg.apply("Wizard.back"));
		backButton.setId("Wizard.back");
		backButton.addClickListener(event -> prevStep());

		finishButton.setText(msg.apply("Wizard.finish"));
		finishButton.setId("Wizard.finish");
		finishButton.addClickListener(e ->
		{
			nextButton.setEnabled(false);
			finishButton.setEnabled(false);
			backButton.setEnabled(false);
			progressBar.setValue(1.0);
			contentLayout.removeAll();
			contentLayout.add(wizardStepController.getNext());
		});
		finishButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		
		getFooter().add(cancelButton, backButton, nextButton, finishButton);
		getHeader().add(labelsLayout, progressBar);
		add(contentLayout);
	
		if (title != null)
			setHeaderTitle(title);
		init();
	}

	private void initLabelsLayout(List labels, HorizontalLayout labelsLayout)
	{
		labelsLayout.setWidthFull();
		labels.forEach(label ->
		{
			if(label == null)
				return;
			HorizontalLayout labelComponent = new HorizontalLayout(new Span(label));
			labelComponent.setWidthFull();
			labelComponent.setJustifyContentMode(JustifyContentMode.CENTER);
			labelsLayout.add(labelComponent);
		});
	}

	private void init()
	{
		wizardStepController.startAgain();
		contentLayout.removeAll();
		progressBar.setValue(progressBarIncrementer / 2);
		contentLayout.add(wizardStepController.getCurrent());
		nextButton.setEnabled(true);
		nextButton.setVisible(true);
		backButton.setEnabled(false);
		finishButton.setEnabled(false);
		finishButton.setVisible(false);
	}

	private void showDisableFinishButton()
	{
		finishButton.setVisible(true);
		finishButton.setEnabled(false);
		nextButton.setVisible(false);
	}

	private void nextStep()
	{
		if(wizardStepController.hasFinished())
		{
			finishButton.setEnabled(true);
			finishButton.setVisible(true);
			nextButton.setVisible(false);
			return;
		}
		contentLayout.removeAll();
		contentLayout.add(wizardStepController.getNext());

		if(progressBar.getValue() == 0)
			progressBar.setValue(progressBarIncrementer / 2);
		else
		{
			double value = progressBar.getValue() + progressBarIncrementer;
			progressBar.setValue(Math.min(value, 1.0));
		}
		nextButton.setEnabled(false);
		backButton.setEnabled(true);
	}
	void prevStep()
	{
		contentLayout.removeAll();
		contentLayout.add(wizardStepController.getPrev());
		if(progressBar.getValue() == 1.0)
			progressBar.setValue(1.0 - (progressBarIncrementer / 2));
		else
		{
			double value = progressBar.getValue() - progressBarIncrementer;
			progressBar.setValue(Math.max(value, 0));
		}

		backButton.setEnabled(wizardStepController.hasPrev());
		finishButton.setVisible(false);
		nextButton.setVisible(true);
	}

	void refresh()
	{
		WizardStep current = wizardStepController.getCurrent();
		if(current.getStatus() == WizardStepStatus.COMPLITED)
			stepComplited();
		else if (current.getStatus() == WizardStepStatus.NEXT_STEP_REQUIRED)
			ui.access(this::nextStep);
		else if (current.getStatus() == WizardStepStatus.PREV_STEP_REQUIRED)
			ui.access(this::prevStep);
	}

	void interrupt()
	{
		ui.access(this::showDisableFinishButton);
	}

	private void stepComplited()
	{
		ui.access(() ->
		{
			if(wizardStepController.hasFinished())
			{
				finishButton.setVisible(true);
				finishButton.setEnabled(true);
				nextButton.setVisible(false);
			}
			else
				nextButton.setEnabled(true);
		});
	}

	public static WizardBuilder builder()
	{
		return new WizardBuilder();
	}

	public static final class WizardBuilder
	{
		private final List wizardSteps = new ArrayList<>();
		private final List> stepPreparers = new ArrayList<>();
		private Runnable cancelTask = () -> {};
		private Function msg;
		private String title;

		private WizardBuilder()
		{
		}

		public WizardBuilder addStep(WizardStep wizardStep)
		{
			wizardSteps.add(wizardStep);
			return this;
		}

		public WizardBuilder addNextStepPreparer(WizardStepPreparer preparer)
		{
			stepPreparers.add(preparer);
			return this;
		}

		public WizardBuilder addMessageSource(Function  msg)
		{
			this.msg = msg;
			return this;
		}

		public WizardBuilder addCancelTask(Runnable cancelTask)
		{
			this.cancelTask = cancelTask;
			return this;
		}

		public WizardBuilder title(String title)
		{
			this.title = title;
			return this;
		}

		public Wizard build()
		{
			Wizard wizard = new Wizard(wizardSteps, stepPreparers, msg, cancelTask, title);
			wizardSteps.forEach(wizardStep -> wizardStep.setWizard(wizard));
			return wizard;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy