From 4d0d8ef0a124a027fd204d460c2492a794cfacbe Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Thu, 8 Aug 2024 23:43:38 +0100 Subject: [PATCH] done with functional-core logic for redo (now just need to send REDO_ACTION on key callback when shortcut is pressed) --- dotscape | Bin 908144 -> 908144 bytes functional-core/app-update.sml | 67 +++++++++++++- functional-core/app-with.sml | 161 +++++++++++++++++---------------- message-types/input-msg.sml | 2 + 4 files changed, 145 insertions(+), 85 deletions(-) diff --git a/dotscape b/dotscape index d86b965196a94685f2c97b48dc713bdb4d997f1b..6f58cd071c06aad3e9b3630491c835f09e07cf4a 100755 GIT binary patch delta 28763 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 V8u+w-Vd(4*FS_ow44RSue*k5xa3BBx delta 28931 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 Lx|bR}HUIws%?FkZ diff --git a/functional-core/app-update.sml b/functional-core/app-update.sml index d8cd667..0877e53 100644 --- a/functional-core/app-update.sml +++ b/functional-core/app-update.sml @@ -120,15 +120,18 @@ struct case #triangleStage model of FIRST {x1, y1} => (* Change FIRST to NO_TRIANGLE and clear buttons. *) - let val model = AppWith.undoTriangleStage (model, NO_TRIANGLE, (x1, y1)) - in (model, CLEAR_BUTTONS) + let + val model = + AppWith.undo (model, NO_TRIANGLE, #triangles model, (x1, y1)) + in + (model, CLEAR_BUTTONS) end | SECOND {x1, y1, x2, y2} => (* Change FIRST to SECOND and redraw buttons. *) let val newTriangleStage = FIRST {x1 = x1, y1 = y1} val model = - AppWith.undoTriangleStage (model, newTriangleStage, (x2, y2)) + AppWith.undo (model, newTriangleStage, #triangles model, (x2, y2)) val emptyVec: Real32.real vector = Vector.fromList [] val drawVec = TriangleStage.firstToVector (x1, y1, emptyVec, model) @@ -145,8 +148,7 @@ struct let val triangleStage = SECOND {x1 = x1, y1 = y1, x2 = x2, y2 = y2} val model = - AppWith.undoTriangle - (model, triangleStage, trianglesTl, (x3, y3)) + AppWith.undo (model, triangleStage, trianglesTl, (x3, y3)) val newTriangleVec = Triangles.toVector model val drawVec = TriangleStage.secondToVector @@ -161,6 +163,60 @@ struct (* Can't undo, because there are no actions to undo. *) (model, NO_DRAW)) + fun redoAction model = + case #redo model of + (redoHd as (x, y)) :: tl => + (* There is a click point to redo. *) + (case #triangleStage model of + NO_TRIANGLE => + (* add to triangle stage, and redraw buttons *) + let + val newTriangleStage = FIRST {x1 = x, y1 = y} + val model = + AppWith.redo + (model, newTriangleStage, #triangles model, redoHd) + + val emptyVec: Real32.real vector = Vector.fromList [] + val drawVec = + TriangleStage.firstToVector (x1, y1, emptyVec, model) + val drawMsg = DRAW_BUTTON drawVec + in + (model, drawMsg) + end + | FIRST {x1, y1} => + (* add to triangle stage, redraw buttons *) + let + val newTriangleStage = SECOND {x1 = x1, y1 = y1, x2 = x, y2 = y} + val model = + AppWith.redo + (model, newTriangleStage, #triangles model, redoHd) + + val emptyVec: Real32.real vector = Vector.fromList [] + val drawVec = TriangleStage.secondToVector + (x1, y1, x, y, emptyVec, model) + val drawMsg = DRAW_BUTTON drawVec + in + (model, drawMsg) + end + | SECOND {x1, y1, x2, y2} => + (* clear triangle stage, add to trinagle list and redraw triangles *) + let + val newTriangleStage = NO_TRIANGLE + val newTriangle = + {x1 = x1, y1 = y1, x2 = x2, y2 = y2, x3 = x, y3 = y} + val newTriangles = newUndoTuple :: (#triangles model) + val model = + AppWith.redo (model, newTriangleStage, newTriangles, redoHd) + + val drawVec = Triangles.toVector model + val drawMsg = DRAW_TRIANGLES_AND_RESET_BUTTONS drawVec + in + (model, drawMsg) + end) + | [] => + (* Nothing to redo. *) + (model, NO_DRAW) + fun update (model: app_type, inputMsg) = case inputMsg of MOUSE_MOVE {x = mouseX, y = mouseY} => @@ -171,4 +227,5 @@ struct | MOUSE_LEFT_CLICK => mouseLeftClick model | RESIZE_WINDOW {width, height} => resizeWindow (model, width, height) | UNDO_ACTION => undoAction model + | REDO_ACTION => redoAction model end diff --git a/functional-core/app-with.sml b/functional-core/app-with.sml index e9051ab..65c5c77 100644 --- a/functional-core/app-with.sml +++ b/functional-core/app-with.sml @@ -5,11 +5,14 @@ sig val mousePosition: AppType.app_type * Real32.real * Real32.real -> AppType.app_type - val undoTriangleStage: - AppType.app_type * AppType.triangle_stage * (Real32.real * Real32.real) + val undo: + AppType.app_type + * AppType.triangle_stage + * AppType.triangle list + * (Real32.real * Real32.real) -> AppType.app_type - val undoTriangle: + val redo: AppType.app_type * AppType.triangle_stage * AppType.triangle list @@ -109,83 +112,6 @@ struct } end - (* add to redo, pop one from undo *) - fun undoTriangleStage (app: app_type, newTriangleStage, newRedoHd) = - let - val - { triangleStage = _ - , triangles - , xClickPoints - , yClickPoints - , windowWidth - , windowHeight - , graphLines - , undo - , redo - , mouseX - , mouseY - } = app - - val newUndo = - case undo of - hd :: tl => tl - | empty => empty - - val newRedo = newRedoHd :: redo - in - { triangleStage = newTriangleStage - , triangles = triangles - , undo = newUndo - , redo = newRedo - , xClickPoints = xClickPoints - , yClickPoints = yClickPoints - , windowWidth = windowWidth - , windowHeight = windowHeight - , graphLines = graphLines - , mouseX = mouseX - , mouseY = mouseY - } - end - - fun undoTriangle - (app: app_type, newTriangleStage: triangle_stage, trianglesTl, newRedoHd) : - app_type = - let - val - { triangleStage = _ - , triangles = _ - , xClickPoints - , yClickPoints - , windowWidth - , windowHeight - , graphLines - , undo - , redo - , mouseX - , mouseY - } = app - - val newUndo = - case undo of - hd :: tl => tl - | empty => empty - - val newRedo = newRedoHd :: redo - in - { triangleStage = newTriangleStage - , triangles = trianglesTl - , undo = newUndo - , redo = newRedo - , xClickPoints = xClickPoints - , yClickPoints = yClickPoints - , windowWidth = windowWidth - , windowHeight = windowHeight - , graphLines = graphLines - , mouseX = mouseX - , mouseY = mouseY - } - end - fun helpWindowResize (app: app_type, windowWidth, windowHeight, wStart, wFinish, hStart, hFinish) : app_type = @@ -276,4 +202,79 @@ struct , redo = redo } end + + (* add to redo, pop one from undo *) + fun undo (app: app_type, newTriangleStage, newTriangles, newRedoHd) = + let + val + { triangleStage = _ + , triangles = _ + , xClickPoints + , yClickPoints + , windowWidth + , windowHeight + , graphLines + , undo + , redo + , mouseX + , mouseY + } = app + + val newUndo = + case undo of + hd :: tl => tl + | empty => empty + + val newRedo = newRedoHd :: redo + in + { triangleStage = newTriangleStage + , triangles = newTriangles + , undo = newUndo + , redo = newRedo + , xClickPoints = xClickPoints + , yClickPoints = yClickPoints + , windowWidth = windowWidth + , windowHeight = windowHeight + , graphLines = graphLines + , mouseX = mouseX + , mouseY = mouseY + } + end + + (* add to undo, pop one from redo *) + fun redo (app: app_type, newTriangleStage, newTriangles, newUndoHd) = + let + val + { triangleStage = _ + , triangles = _ + , xClickPoints + , yClickPoints + , windowWidth + , windowHeight + , graphLines + , undo + , redo + , mouseX + , mouseY + } = app + + val newUndo = newUndoHd :: undo + val newRedo = + case redo of + hd :: tl => tl + | empty => empty + in + { triangleStage = newTriangleStage + , triangles = newTriangles + , undo = newUndo + , redo = newRedo + , xClickPoints = xClickPoints + , yClickPoints = yClickPoints + , windowWidth = windowWidth + , windowHeight = windowHeight + , graphLines = graphLines + , mouseX = mouseX + , mouseY = mouseY + } + end end diff --git a/message-types/input-msg.sml b/message-types/input-msg.sml index 3f2ce1a..4f8b6f2 100644 --- a/message-types/input-msg.sml +++ b/message-types/input-msg.sml @@ -6,6 +6,7 @@ sig | MOUSE_LEFT_RELEASE | RESIZE_WINDOW of {width: int, height: int} | UNDO_ACTION + | REDO_ACTION end structure InputMessage :> INPUT_MESSAGE = @@ -16,4 +17,5 @@ struct | MOUSE_LEFT_RELEASE | RESIZE_WINDOW of {width: int, height: int} | UNDO_ACTION + | REDO_ACTION end