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

net.vectorpublish.desktop.vp.History Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2016, Peter Rader. All rights reserved.
 *  ___ ___               __                 ______         __     __  __         __
 * |   |   |.-----..----.|  |_ .-----..----.|   __ \.--.--.|  |--.|  ||__|.-----.|  |--.
 * |   |   ||  -__||  __||   _||  _  ||   _||    __/|  |  ||  _  ||  ||  ||__ --||     |
 *  \_____/ |_____||____||____||_____||__|  |___|   |_____||_____||__||__||_____||__|__|
 *
 * http://www.gnu.org/licenses/gpl-3.0.html
 */
package net.vectorpublish.desktop.vp;

import java.io.Serializable;
import java.util.Objects;

import javax.inject.Inject;

import net.vectorpublish.desktop.vp.api.InheritanceExclusion;
import net.vectorpublish.desktop.vp.api.history.ReadOnlyHistoryStepDataBean;
import net.vectorpublish.desktop.vp.api.io.Open;
import net.vectorpublish.desktop.vp.api.layer.Layer;
import net.vectorpublish.desktop.vp.api.ui.KeyframeSlider;
import net.vectorpublish.desktop.vp.api.vpd.DocumentNode;
import net.vectorpublish.desktop.vp.api.vpd.ModificationContext;

/**
 * The History of the work on the Document. Every {@link DocumentNode} has a
 * history, if you modify the {@link DocumentNode} the modifications are
 * 
    *
  • executed via the {@link HistoryStep} *
  • stored in a serializable {@link ReadOnlyHistoryStepDataBean} and *
  • rolled back via the {@link HistoryStep}. *
*/ public abstract class History implements InheritanceExclusion { /** * A {@link HistoryStep} holds all processes about what to do when the user * click undo or redo. Additionally there is a {@link #data field} to store * all Informations about what to store to a file on save. Store the * document to a file will store all {@link ReadOnlyHistoryStepDataBean * data-beans} to the File bound to the {@link DocumentNode}. *

* It has two essentail fields, the next step and the previous step just * like a double-linked-list. If the previous Step is null you * can not undo anymore, if the next step is null you can not * redo anymore. * *

* Rollback is the process of remove the work that has been done in the * {@link DocumentNode#getLastExecutedHistoryStep() last executed step}, and * point the * {@link DocumentNode#setLastExecutedHistoryStep(History.HistoryStep) last * executed} to the first previous step relative to the * {@link DocumentNode#getLastExecutedHistoryStep() old last executed step}. * Only if you {@link #canRollback() can rollback} the step, you are able to * undo the work. *

* Execute is the process of execute the work that must be done in the * {@link #next first next step} that is realtive to the * {@link DocumentNode#getLastExecutedHistoryStep() last executed step}. * After the {@link #execute(ModificationContext) execution} of the work * required in the next step, the * {@link DocumentNode#setLastExecutedHistoryStep(History.HistoryStep) last * step} will be set to the newly executed Step. Only if you * {@link #canExecuteNext() can redo} the step, you are able to redo the * work. */ public abstract class HistoryStep implements InheritanceExclusion { /** * The {@link HistoryStep} that comes right before this * {@link HistoryStep}. This field can be null in case of * the first HistorySteps. *

* To create a {@link DocumentNode} is not a history-point, so every * blank {@link DocumentNode} has not one {@link HistoryStep}. */ protected HistoryStep previous; /** * The {@link Serializable} data the {@link HistoryStep} needs to work. * How and what to do for the execution of the Step. */ protected final B data; /** * The {@link HistoryStep} that comes next. This field must be * null in the case that this is the last * {@link HistoryStep}. */ protected HistoryStep next; /** * Creates a new History. This instance is the very first * {@link HistoryStep} of the chain of many. * *

* This constructor must be executed when the {@link DocumentNode} has * no {@link HistoryStep}. * * @param data * The Data for this {@link HistoryStep}. */ @Deprecated public HistoryStep(B data) { this.data = Objects.requireNonNull(data); this.previous = null; } /** * Adds a {@link HistoryStep} to existing chain of HistorySteps. To * create a blank {@link DocumentNode} is not a {@link HistoryStep}. * * @param before * The {@link HistoryStep} who comes right before this step * would execute. * @param data * The Data for the HistoryStep. */ public HistoryStep(HistoryStep before, B data) { assert this.getClass().getDeclaredConstructors().length == 1 : "Should only have one constructor but has " + this.getClass().getDeclaredConstructors().length + "!"; this.previous = Objects.requireNonNull(before); this.previous.next = this; this.data = Objects.requireNonNull(data); notifyHistoryChanged(before, this, Thread.currentThread().getName().equals(Open.THREAD_NAME_FILE_LOAD)); } /** * Checks if a next step is available for execution. *

* After rollback this method returns true, even if the action who * produced the history step to execute-next is not available. * * @return true if a next step is available for execution, * false if not. */ public final boolean canExecuteNext() { return next != null; } /** * Returns if the last step executed can be rolled back. *

* If false is returned the document must be blank. If a * new document is created this method returns false. * * @return true if the last step executed can be rolled * back, false if not. */ public final boolean canRollback() { return previous != null; } /** * Executes internally the atomic next {@link HistoryStep} in the * {@link History}. *

* There is no garantuee that {@link #rollback(ModificationContext)} has * been called before! * * @param ctx * The context to make modifications for the {@link Layer * Layers}. */ protected abstract void execute(ModificationContext ctx); /** * Executes the complete next step in the {@link History}. */ public final void executeNext() { final DocumentNode currentDocument = getCurrentDocument(); final ModificationContext ctx = new ModificationContext(History.this, currentDocument, layer, slider); this.next.execute(ctx); ctx.cleanUp(); currentDocument.setLastExecutedHistoryStep(this.next); } protected final B getData() { return data; } /** * The work to do to have the status of the previous {@link HistoryStep} * . *

* You have the 100% garatuee that at least one * {@link #execute(ModificationContext)} has been called before! * * @param ctx * The {@link ModificationContext}. */ protected abstract void rollback(ModificationContext ctx); public final void rollbackToPrevious() { final ModificationContext ctx = new ModificationContext(History.this, getCurrentDocument(), layer, slider); rollback(ctx); getCurrentDocument().setLastExecutedHistoryStep(previous); ctx.cleanUp(); } } @Inject private final Layer layer = null; @Inject private final KeyframeSlider slider = null; public abstract DocumentNode getCurrentDocument(); protected abstract void notifyHistoryChanged(HistoryStep previous, HistoryStep newStep, boolean byFileRead); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy