Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ fun HudCanvasResetMenu(
undoEnabled: Boolean = false,
onRedo: () -> Unit = {},
redoEnabled: Boolean = false,
onUndoAll: () -> Unit = {},
preview: Boolean = false,
onMeasured: (IntSize) -> Unit = {},
) {
Expand Down Expand Up @@ -480,6 +481,10 @@ fun HudCanvasResetMenu(
onRedo()
onDismiss()
}
HudMenuRow(icon = "undo", text = "Undo all", enabled = undoEnabled) {
onUndoAll()
onDismiss()
}
HudMenuDivider()
if (actionTargets.any(::hudHasPositionDefaults)) {
HudMenuRow(
Expand Down Expand Up @@ -543,6 +548,7 @@ fun HudCanvasPasteMenu(
undoEnabled: Boolean = false,
onRedo: () -> Unit = {},
redoEnabled: Boolean = false,
onUndoAll: () -> Unit = {},
onTour: (() -> Unit)? = null,
) {
if (!expanded) return
Expand Down Expand Up @@ -574,6 +580,10 @@ fun HudCanvasPasteMenu(
onRedo()
onDismiss()
}
HudMenuRow(icon = "undo", text = "Undo all", enabled = undoEnabled) {
onUndoAll()
onDismiss()
}
HudMenuDivider()
HudMenuRow(
icon = "clipboard",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ internal sealed interface StudioCommand {

data object Redo : StudioCommand

data object UndoAll : StudioCommand

data object Search : StudioCommand
}

Expand Down Expand Up @@ -175,6 +177,14 @@ object HudDesignSession {
return true
}

@JvmStatic
fun handleUndoAll(pressed: Boolean): Boolean {
if (!pressed) return false
if (!HudManager.isEditorOpen) return false
post(StudioCommand.UndoAll)
return true
}

@JvmStatic
fun handleRedo(pressed: Boolean): Boolean {
if (!pressed) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1368,9 +1368,13 @@ fun HudDesignStudio(visible: Boolean = true) {
}
}

StudioCommand.Undo, StudioCommand.Redo -> {
StudioCommand.Undo, StudioCommand.Redo, StudioCommand.UndoAll -> {
if (!isDragging && !isResizing && pendingPress == null) {
val revived = if (command == StudioCommand.Undo) history.undo() else history.redo()
val revived = when (command) {
StudioCommand.Undo -> history.undo()
StudioCommand.UndoAll -> history.undoAll()
else -> history.redo()
}
if (revived != null) {
Snapshot.withMutableSnapshot {
val live = HudManager.activeInstances
Expand Down Expand Up @@ -2621,6 +2625,7 @@ fun HudDesignStudio(visible: Boolean = true) {
undoEnabled = canUndo,
onRedo = { HudDesignSession.handleRedo(true) },
redoEnabled = canRedo,
onUndoAll = { HudDesignSession.handleUndoAll(true) },
)

HudCanvasPasteMenu(
Expand All @@ -2647,6 +2652,7 @@ fun HudDesignStudio(visible: Boolean = true) {
undoEnabled = canUndo,
onRedo = { HudDesignSession.handleRedo(true) },
redoEnabled = canRedo,
onUndoAll = { HudDesignSession.handleUndoAll(true) },
onTour = { startTour() },
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,24 @@ internal class HudHistory {

fun redo(): List<Hud>? = step(redoStack, undoStack)

/** Goes back to how the layout was when this history started, one [redo] per step to bring it back */
fun undoAll(): List<Hud>? {
val now = capture()
val last = recorded
if (last == null || last.owner !== now.owner) {
reset(now)
return null
}
if (!sameLayout(last, now)) record(now)
if (undoStack.isEmpty()) return null
recorded?.let(redoStack::addLast)
while (undoStack.size > 1) redoStack.addLast(undoStack.removeLast())
val revived = restore(undoStack.removeLast())
recorded = capture()
settling = null
return revived
}

private fun step(from: ArrayDeque<Layout>, to: ArrayDeque<Layout>): List<Hud>? {
val now = capture()
val last = recorded
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,27 @@ void addedHudIsRemovedOnUndoAndComesBackOnRedo() {
assertNotNull(HudManager.INSTANCE.instanceById(id));
}

@Test
void undoAllCanBeRedoneOneStepAtATime() {
Hud hud = place();
history.poll(false);

hud.setAbsolutePosition(100f, 60f);
settle();
hud.setAbsolutePosition(200f, 120f);
settle();

assertNotNull(history.undoAll());
assertEquals(10f, hud.getX(), 0.01f);
assertNull(history.undo());

assertNotNull(history.redo());
assertEquals(100f, hud.getX(), 0.01f);
assertNotNull(history.redo());
assertEquals(200f, hud.getX(), 0.01f);
assertNull(history.redo());
}

private void settle() {
history.poll(false);
history.poll(false);
Expand Down