org.fxmisc.richtext.util.UndoUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richtextfx Show documentation
Show all versions of richtextfx Show documentation
Rich-text area for JavaFX
package org.fxmisc.richtext.util;
import org.fxmisc.richtext.GenericStyledArea;
import org.fxmisc.richtext.MultiChangeBuilder;
import org.fxmisc.richtext.model.PlainTextChange;
import org.fxmisc.richtext.model.RichTextChange;
import org.fxmisc.richtext.model.TextChange;
import org.fxmisc.undo.UndoManager;
import org.fxmisc.undo.UndoManagerFactory;
import org.reactfx.EventStream;
import java.time.Duration;
import java.util.List;
import java.util.function.Consumer;
/**
* A class filled with factory methods to help easily construct an {@link UndoManager} for a {@link GenericStyledArea}.
*/
public final class UndoUtils {
private UndoUtils() {
throw new IllegalStateException("UndoUtils cannot be instantiated");
}
public static final Duration DEFAULT_PREVENT_MERGE_DELAY = Duration.ofMillis(500);
/**
* Constructs an UndoManager with an unlimited history:
* if {@link GenericStyledArea#isPreserveStyle() the area's preserveStyle flag is true}, the returned UndoManager
* can undo/redo multiple {@link RichTextChange}s; otherwise, it can undo/redo multiple {@link PlainTextChange}s.
*/
public static UndoManager defaultUndoManager(GenericStyledArea area) {
return area.isPreserveStyle()
? richTextUndoManager(area)
: plainTextUndoManager(area);
}
/* ********************************************************************** *
* *
* UndoManager Factory Methods *
* *
* Code that constructs different kinds of UndoManagers for an area *
* *
* ********************************************************************** */
/**
* Returns an UndoManager with an unlimited history that can undo/redo {@link RichTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@link #DEFAULT_PREVENT_MERGE_DELAY}
*/
public static UndoManager>> richTextUndoManager(
GenericStyledArea area) {
return richTextUndoManager(area, UndoManagerFactory.unlimitedHistoryFactory());
}
/**
* Returns an UndoManager that can undo/redo {@link RichTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@code preventMergeDelay}
*/
public static UndoManager>> richTextUndoManager(
GenericStyledArea area, Duration preventMergeDelay) {
return richTextUndoManager(area, UndoManagerFactory.unlimitedHistoryFactory(), preventMergeDelay);
};
/**
* Returns an UndoManager that can undo/redo {@link RichTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@link #DEFAULT_PREVENT_MERGE_DELAY}
*/
public static UndoManager>> richTextUndoManager(
GenericStyledArea area, UndoManagerFactory factory) {
return richTextUndoManager(area, factory, DEFAULT_PREVENT_MERGE_DELAY);
};
/**
* Returns an UndoManager that can undo/redo {@link RichTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@code preventMergeDelay}
*/
public static UndoManager>> richTextUndoManager(
GenericStyledArea area, UndoManagerFactory factory, Duration preventMergeDelay) {
return factory.createMultiChangeUM(area.multiRichChanges(),
TextChange::invert,
applyMultiRichTextChange(area),
TextChange::mergeWith,
TextChange::isIdentity,
preventMergeDelay);
};
/**
* Returns an UndoManager with an unlimited history that can undo/redo {@link PlainTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@link #DEFAULT_PREVENT_MERGE_DELAY}
*/
public static UndoManager> plainTextUndoManager(
GenericStyledArea area) {
return plainTextUndoManager(area, DEFAULT_PREVENT_MERGE_DELAY);
}
/**
* Returns an UndoManager that can undo/redo {@link PlainTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@code preventMergeDelay}
*/
public static UndoManager> plainTextUndoManager(
GenericStyledArea area, Duration preventMergeDelay) {
return plainTextUndoManager(area, UndoManagerFactory.unlimitedHistoryFactory(), preventMergeDelay);
}
/**
* Returns an UndoManager that can undo/redo {@link PlainTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@link #DEFAULT_PREVENT_MERGE_DELAY}
*/
public static UndoManager> plainTextUndoManager(
GenericStyledArea area, UndoManagerFactory factory) {
return plainTextUndoManager(area, factory, DEFAULT_PREVENT_MERGE_DELAY);
}
/**
* Returns an UndoManager that can undo/redo {@link PlainTextChange}s. New changes
* emitted from the stream will not be merged with the previous change
* after {@code preventMergeDelay}
*/
public static UndoManager> plainTextUndoManager(
GenericStyledArea area, UndoManagerFactory factory, Duration preventMergeDelay) {
return factory.createMultiChangeUM(area.multiPlainChanges(),
TextChange::invert,
applyMultiPlainTextChange(area),
TextChange::mergeWith,
TextChange::isIdentity,
preventMergeDelay);
}
/* ********************************************************************** *
* *
* Change Appliers *
* *
* Code that handles how a change should be applied to the area *
* *
* ********************************************************************** */
/**
* Applies a {@link PlainTextChange} to the given area when the {@link UndoManager}'s change stream emits an event
* by {@code area.replaceText(change.getPosition(), change.getRemovalEnd(), change.getInserted()}.
*/
public static Consumer applyPlainTextChange(GenericStyledArea area) {
return change -> area.replaceText(change.getPosition(), change.getRemovalEnd(), change.getInserted());
}
/**
* Applies a {@link RichTextChange} to the given area when the {@link UndoManager}'s change stream emits an event
* by {@code area.replace(change.getPosition(), change.getRemovalEnd(), change.getInserted()}.
*/
public static Consumer> applyRichTextChange(
GenericStyledArea area) {
return change -> area.replace(change.getPosition(), change.getRemovalEnd(), change.getInserted());
}
/**
* Applies a list of {@link PlainTextChange}s to the given area when the {@link UndoManager}'s change stream emits
* an event by {@code area.replaceAbsolutely(change.getPosition(), change.getRemovalEnd(), change.getInserted()}.
*/
public static Consumer> applyMultiPlainTextChange(
GenericStyledArea area) {
return changeList -> {
MultiChangeBuilder builder = area.createMultiChange(changeList.size());
for (PlainTextChange c : changeList) {
builder.replaceTextAbsolutely(c.getPosition(), c.getRemovalEnd(), c.getInserted());
}
builder.commit();
};
}
/**
* Applies a list of {@link RichTextChange} to the given area when the {@link UndoManager}'s change stream emits
* an event by {@code area.replaceAbsolutely(change.getPosition(), change.getRemovalEnd(), change.getInserted()}.
*/
public static Consumer>> applyMultiRichTextChange(
GenericStyledArea area) {
return changeList -> {
MultiChangeBuilder builder = area.createMultiChange(changeList.size());
for (RichTextChange c : changeList) {
builder.replaceAbsolutely(c.getPosition(), c.getRemovalEnd(), c.getInserted());
}
builder.commit();
};
}
}