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

org.dominokit.domino.ui.stepper.StepperTrack Maven / Gradle / Ivy

There is a newer version: 2.0.3
Show newest version
/*
 * Copyright © 2019 Dominokit
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dominokit.domino.ui.stepper;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.utils.Domino.*;

import elemental2.dom.HTMLDivElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import org.dominokit.domino.ui.config.HasComponentConfig;
import org.dominokit.domino.ui.config.StepperConfig;
import org.dominokit.domino.ui.elements.DivElement;
import org.dominokit.domino.ui.style.BooleanCssClass;
import org.dominokit.domino.ui.utils.BaseDominoElement;

/**
 * Represents a visual track within a stepper component.
 *
 * 

Usage: * *

 * StepperTrack track = StepperTrack.create();
 * 
* * @see BaseDominoElement */ public class StepperTrack extends BaseDominoElement implements StepperStyles, HasComponentConfig { private final DivElement root; private final List trackers = new ArrayList<>(); public BooleanCssClass textPosition = BooleanCssClass.of(dui_reversed); private StepTracker activeTracker; private int currentTrackerIndex; private boolean started = false; /** Constructor to create a new StepperTrack. */ public StepperTrack() { root = div().addCss(dui_stepper_track); init(this); } /** * Creates a new instance of {@link StepperTrack}. * * @return new instance of {@link StepperTrack} */ public static StepperTrack create() { return new StepperTrack(); } /** * Appends a {@link StepTracker} to the stepper track. * * @param stepTracker the {@link StepTracker} to be appended * @return this {@link StepperTrack} */ public StepperTrack appendChild(StepTracker stepTracker) { root.appendChild(stepTracker); trackers.add(stepTracker); return this; } /** * Removes a given {@link StepTracker} from the stepper track. * * @param stepTracker the {@link StepTracker} to be removed * @return this {@link StepperTrack} */ public StepperTrack removeTracker(StepTracker stepTracker) { if (trackers.contains(stepTracker)) { stepTracker.remove(); } return this; } /** * Moves to the next {@link StepTracker} without skipping any steps. * * @return this {@link StepperTrack} */ public StepperTrack next() { return next(0); } /** * Moves to the next {@link StepTracker} by skipping a specified number of steps. * * @param skip the number of steps to skip * @return this {@link StepperTrack} */ public StepperTrack next(int skip) { return next(skip, (deactivated, activated) -> {}); } /** * Moves to the next {@link StepTracker} without skipping any steps and provides a custom * callback. * * @param consumer callback to handle active step changes * @return this {@link StepperTrack} */ public StepperTrack next(StepTrackersConsumer consumer) { return next(0, consumer); } /** * Moves to the next {@link StepTracker} by skipping a specified number of steps and provides a * custom callback. * * @param skip the number of steps to skip * @param consumer callback to handle active step changes * @return this {@link StepperTrack} */ public StepperTrack next(int skip, StepTrackersConsumer consumer) { if (!started) { throw new IllegalStateException( "Stepper should be started before calling next, previous, or finish."); } int i = this.trackers.indexOf(this.activeTracker); int i1 = this.trackers.size() - 1; if (nonNull(this.activeTracker) && i == i1) { this.deactivateTracker(this.activeTracker); consumer.onActiveStepChanged(Optional.of(this.activeTracker), Optional.empty()); this.activeTracker = null; return this; } if (isNull(this.activeTracker)) { return this; } trackers.stream() .filter( tracker -> tracker.isEnabled() && tracker.isVisible() && trackers.indexOf(tracker) > (trackers.indexOf(this.activeTracker) + skip)) .findFirst() .ifPresent(stepTracker -> activateTracker(stepTracker, consumer)); return this; } /** * Initiates the {@link StepperTrack} with the default step state defined in the configuration. * * @return this {@link StepperTrack} * @see #getConfig() */ public StepperTrack start() { return start(getConfig().getDefaultStepState(), (deactivated, activated) -> {}); } /** * Initiates the {@link StepperTrack} with a given step state. * * @param startState the initial state for the starting step * @return this {@link StepperTrack} */ public StepperTrack start(StepState startState) { return start(startState, (deactivated, activated) -> {}); } /** * Initiates the {@link StepperTrack} with a given step state and provides a custom callback. * * @param startState the initial state for the starting step * @param consumer callback to handle active step changes * @return this {@link StepperTrack} */ public StepperTrack start(StepState startState, StepTrackersConsumer consumer) { this.started = true; int size = trackers.size(); trackers.stream() .filter( tracker -> { boolean enabled = tracker.isEnabled(); boolean visible = tracker.isVisible(); return enabled && visible; }) .findFirst() .ifPresent( tracker -> { activateTracker(tracker, consumer); tracker.setState(startState); }); return this; } /** * Finishes the {@link StepperTrack} and sets the active tracker to a given final state, then * invokes a custom callback. * * @param finishState the final state to set for the active tracker * @param consumer callback to handle active step changes * @return this {@link StepperTrack} * @throws IllegalStateException if the {@link StepperTrack} was not started */ public StepperTrack finish(StepState finishState, StepTrackersConsumer consumer) { if (!started) { throw new IllegalStateException( "Stepper should be started before calling next, previous, or finish."); } deactivateTracker(this.activeTracker); this.activeTracker.setState(finishState); consumer.onActiveStepChanged(Optional.of(this.activeTracker), Optional.empty()); this.activeTracker = null; this.started = false; return this; } /** * Finishes the {@link StepperTrack} and sets the active tracker to a given final state. * * @param finishState the final state to set for the active tracker * @return this {@link StepperTrack} * @throws IllegalStateException if the {@link StepperTrack} was not started */ public StepperTrack finish(StepState finishState) { return finish(finishState, (deactivated, activated) -> {}); } /** * Activates the given {@link StepTracker}, deactivating the currently active tracker if any, and * notifies the provided consumer of the change. * * @param stepTracker the {@link StepTracker} to activate * @param consumer callback to handle active step changes */ private void activateTracker(StepTracker stepTracker, StepTrackersConsumer consumer) { if (nonNull(stepTracker)) { StepTracker deactivated = this.activeTracker; if (nonNull(this.activeTracker)) { deactivateTracker(this.activeTracker); } stepTracker.activate(); this.activeTracker = stepTracker; if (isNull(deactivated) && this.currentTrackerIndex > 0 && !this.trackers.isEmpty()) { deactivated = trackers.get(this.currentTrackerIndex); } this.currentTrackerIndex = trackers.indexOf(this.activeTracker); consumer.onActiveStepChanged( Optional.ofNullable(deactivated), Optional.of(this.activeTracker)); } } /** * Deactivates the provided {@link StepTracker}. * * @param tracker the {@link StepTracker} to deactivate */ private void deactivateTracker(StepTracker tracker) { if (nonNull(tracker)) { tracker.deactivate(); } } /** * Moves to the previous step in the {@link StepperTrack}. * * @return this {@link StepperTrack} * @throws IllegalStateException if the {@link StepperTrack} was not started */ public StepperTrack prev() { return prev(0); } /** * Moves to the previous step in the {@link StepperTrack} and notifies the provided consumer of * the change. * * @param consumer callback to handle active step changes * @return this {@link StepperTrack} * @throws IllegalStateException if the {@link StepperTrack} was not started */ public StepperTrack prev(StepTrackersConsumer consumer) { return prev(0, consumer); } /** * Moves to the previous step in the {@link StepperTrack}, skipping a given number of steps. * * @param skip the number of steps to skip * @return this {@link StepperTrack} * @throws IllegalStateException if the {@link StepperTrack} was not started */ public StepperTrack prev(int skip) { return prev(skip, (deactivated, activated) -> {}); } /** * Moves to the previous step in the {@link StepperTrack}, skipping a given number of steps, and * notifies the provided consumer of the change. * * @param skip the number of steps to skip * @param consumer callback to handle active step changes * @return this {@link StepperTrack} * @throws IllegalStateException if the {@link StepperTrack} was not started */ public StepperTrack prev(int skip, StepTrackersConsumer consumer) { if (!started) { throw new IllegalStateException( "Stepper should be started before calling next, previous, or finish."); } if (isNull(this.activeTracker)) { if (this.currentTrackerIndex > 0 && !this.trackers.isEmpty()) { activateTracker(this.trackers.get(currentTrackerIndex - 1), consumer); } return this; } for (int i = trackers.size() - 1; i >= 0; i--) { StepTracker tracker = trackers.get(i); if (tracker.isEnabled() && tracker.isVisible() && trackers.indexOf(tracker) < (trackers.indexOf(this.activeTracker) - skip)) { activateTracker(tracker, consumer); return this; } } return this; } // ... other methods continue with similar documentation... /** * Resets the stepper track and starts with the given state. * * @param startState state to start with * @param trackersConsumer consumer accepting the list of trackers * @return this {@link StepperTrack} */ public StepperTrack reset(StepState startState, Consumer> trackersConsumer) { trackersConsumer.accept(this.trackers); start(startState); return this; } /** * Retrieves the next {@link StepTracker} in the {@link StepperTrack}. * * @return an {@link Optional} containing the next {@link StepTracker} if available, or an empty * {@link Optional} if there are no more steps or if the {@link StepperTrack} is empty */ public Optional getNextTracker() { if (this.trackers.isEmpty()) { return Optional.empty(); } if (nonNull(this.activeTracker)) { int currentTrackerIndex = this.trackers.indexOf(this.activeTracker); if (currentTrackerIndex < (this.trackers.size() - 1)) { return Optional.of(this.trackers.get(currentTrackerIndex + 1)); } else { return Optional.empty(); } } else { return Optional.of(this.trackers.get(0)); } } /** * Retrieves the previous {@link StepTracker} in the {@link StepperTrack}. * * @return an {@link Optional} containing the previous {@link StepTracker} if available, or an * empty {@link Optional} if there are no previous steps or if the {@link StepperTrack} is * empty */ public Optional getPreviousTracker() { if (this.trackers.isEmpty()) { return Optional.empty(); } if (nonNull(this.activeTracker)) { int currentTrackerIndex = this.trackers.indexOf(this.activeTracker); if (currentTrackerIndex > 0) { return Optional.of(this.trackers.get(currentTrackerIndex - 1)); } else { return Optional.empty(); } } else { return Optional.of(this.trackers.get(0)); } } /** * Retrieves the currently active {@link StepTracker} in the {@link StepperTrack}. * * @return an {@link Optional} containing the active {@link StepTracker} if available, or an empty * {@link Optional} if there is no active step */ public Optional getActiveTracker() { return Optional.ofNullable(activeTracker); } /** * Sets the text position within the {@link StepperTrack} to be reversed or not. * * @param reversed {@code true} to reverse the text position, {@code false} otherwise * @return this {@link StepperTrack} */ public StepperTrack setTextPositionReversed(boolean reversed) { textPosition.apply(this, reversed); return this; } /** {@inheritDoc} */ @Override public HTMLDivElement element() { return root.element(); } /** Functional interface to consume changes in active steps. */ @FunctionalInterface public interface StepTrackersConsumer { /** * Callback to notify when the active step has changed. * * @param deactivated previously active {@link StepTracker} * @param activated newly active {@link StepTracker} */ @SuppressWarnings("all") void onActiveStepChanged(Optional deactivated, Optional activated); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy