Skip to content

Commit

Permalink
Add undo/redo
Browse files Browse the repository at this point in the history
This should be replaced at somepoint with an event system in bean
that enables collaboration/version control etc. Moreover this is
probably very inefficient since we replace the entire sheet on
every recalc. The undo library warns against this.
  • Loading branch information
prabhanshuguptagit committed Jun 20, 2024
1 parent a0166e4 commit c72c0b3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
1 change: 1 addition & 0 deletions shadow-cljs.edn
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[metosin/malli "0.13.0"]
[org.clj-commons/hickory "0.7.4"]
[com.github.pkpkpk/cljs-node-io "2.0.332"]
[day8.re-frame/undo "0.3.3"]
^:dev [day8.re-frame/re-frame-10x "1.9.3"]]

:dev-http {8090 "public"}
Expand Down
56 changes: 42 additions & 14 deletions src/bean/ui/events.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns bean.ui.events
(:require [bean.code :as code]
[bean.code-errors :as code-errors]
[day8.re-frame.undo :as undo :refer [undoable]]
[bean.frames :as frames]
[bean.grid :as grid]
[bean.ui.db :as db]
Expand Down Expand Up @@ -39,35 +40,51 @@

(rf/reg-event-db
::update-cell
(undoable)
(fn update-cell [db [_ address content]]
(update-in db [:sheet] #(grid/update-cell-content address % content))))

(rf/reg-event-db
::clear-area
(undoable)
(fn clear-area [db [_ area]]
(update-in db [:sheet] #(grid/clear-area % area))))

(rf/reg-event-fx
::handle-global-kbd
(fn handle-global-kbd [{:keys [db]} [_ e]]
(let [selection (get-in db [:ui :grid :selection])]
(when-let [[r c] (:start selection)]
(let [[mr mc] (get-in db [:sheet :grid r c :style :merged-until])]
(if (or (= (.-key e) "Backspace")
(= (.-key e) "Delete"))
{:fx [[:dispatch [::clear-area selection]]]}
(if-let [move-to (cond
(= (.-key e) "ArrowUp") [(dec r) c]
(= (.-key e) "ArrowLeft") [r (dec c)]
(= (.-key e) "ArrowDown") [(if mr (inc mr) (inc r)) c]
(= (.-key e) "ArrowRight") [r (if mc (inc mc) (inc c))])]
{:fx [[:dispatch [::set-selection {:start move-to :end move-to}]]]}
(if (= (count (.-key e)) 1)
{:fx [[:dispatch [::edit-cell [r c] (.-key e)]]]}
{:fx [[:dispatch [::edit-cell [r c]]]]}))))))))
(cond
(and (= (.-key e) "z") (or (.-ctrlKey e) (.-metaKey e))
(.-shiftKey e))
(rf/dispatch [:redo])

(and (= (.-key e) "z") (or (.-ctrlKey e) (.-metaKey e)))
(rf/dispatch [:undo])

(or (.-ctrlKey e) (.-metaKey e)
(= (.-key e) "Shift")
(= (.-key e) "Escape")) nil

:else
(when-let [[r c] (:start selection)]
(let [[mr mc] (get-in db [:sheet :grid r c :style :merged-until])]
(if (or (= (.-key e) "Backspace")
(= (.-key e) "Delete"))
{:fx [[:dispatch [::clear-area selection]]]}
(if-let [move-to (cond
(= (.-key e) "ArrowUp") [(dec r) c]
(= (.-key e) "ArrowLeft") [r (dec c)]
(= (.-key e) "ArrowDown") [(if mr (inc mr) (inc r)) c]
(= (.-key e) "ArrowRight") [r (if mc (inc mc) (inc c))])]
{:fx [[:dispatch [::set-selection {:start move-to :end move-to}]]]}
(if (= (count (.-key e)) 1)
{:fx [[:dispatch [::edit-cell [r c] (.-key e)]]]}
{:fx [[:dispatch [::edit-cell [r c]]]]})))))))))

(rf/reg-event-fx
::paste-addressed-cells
(undoable)
(fn paste-addressed-cells [{:keys [db]} [_ addressed-cells]]
(let [selection (get-in db [:ui :grid :selection])]
{:db (update-in db [:sheet] #(grid/update-cells-bulk %
Expand Down Expand Up @@ -95,29 +112,34 @@

(rf/reg-event-fx
::cut-selection
(undoable)
(fn cut-selection [{:keys [db]}]
{:fx [[:dispatch [::copy-selection]]
[:dispatch [::clear-area (get-in db [:ui :grid :selection])]]]}))

(rf/reg-event-fx
::merge-cells
(undoable)
(fn merge-cells [{:keys [db]} [_ area]]
{:db (update-in db [:sheet] #(grid/merge-cells % area))
:fx [[:dispatch [::edit-cell (:start area)]]]}))

(rf/reg-event-fx
::unmerge-cells
(undoable)
(fn unmerge-cells [{:keys [db]} [_ addresses]]
{:db (update-in db [:sheet] #(grid/unmerge-cells % addresses))
:fx [[:dispatch [::edit-cell (first addresses)]]]}))

(rf/reg-event-db
::set-cell-backgrounds
(undoable)
(fn set-cell-backgrounds [db [_ addresses background]]
(update-in db [:sheet] #(grid/set-cell-backgrounds % addresses background))))

(rf/reg-event-db
::toggle-cell-bold
(undoable)
(fn toggle-cell-bold [db [_ addresses]]
(update-in db [:sheet] #(grid/toggle-cell-bolds % addresses))))

Expand All @@ -130,11 +152,13 @@

(rf/reg-event-db
::resize-row
(undoable)
(fn resize-row [db [_ row height]]
(assoc-in db [:sheet :grid-dimensions :row-heights row] height)))

(rf/reg-event-db
::resize-col
(undoable)
(fn resize-col [db [_ col width]]
(assoc-in db [:sheet :grid-dimensions :col-widths col] width)))

Expand Down Expand Up @@ -176,6 +200,7 @@

(rf/reg-event-fx
::make-frame
(undoable)
(fn make-frame [{:keys [db]} [_ area]]
(let [frame-number (inc (get-in db [:sheet :last-frame-number]))
frame-name (str "Frame " frame-number)]
Expand All @@ -186,19 +211,22 @@

(rf/reg-event-db
::add-labels
(undoable)
(fn add-labels [db [_ frame-name addresses dirn]]
(update-in db [:sheet]
#(grid/add-frame-labels % frame-name addresses dirn))))

(rf/reg-event-db
::remove-labels
(undoable)
(fn remove-labels [db [_ frame-name addresses]]
(-> db
(update-in [:sheet] #(frames/unmark-skipped % frame-name addresses))
(update-in [:sheet] #(grid/remove-frame-labels % frame-name addresses)))))

(rf/reg-event-db
::mark-skip-cells
(undoable)
(fn mark-skip-cells [db [_ frame-name addresses]]
(update-in db [:sheet]
#(frames/mark-skipped % frame-name addresses))))
Expand Down
8 changes: 2 additions & 6 deletions src/bean/ui/views/sheet.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -853,15 +853,11 @@
tag-name (and focused-element (.-tagName focused-element))]
(or (= (.toLowerCase tag-name) "span")
(= (.toLowerCase tag-name) "input")
(= (.toLowerCase tag-name) "div")
(= (.toLowerCase tag-name) "textarea"))))

(defn ctrl-or-meta? [e]
(or (.-ctrlKey e) (.-metaKey e)))

(defn handle-global-kbd [e]
(when (and (not (editing-text?)) (not (or (ctrl-or-meta? e)
(= (.-key e) "Shift")
(= (.-key e) "Escape"))))
(when (not (editing-text?))
(rf/dispatch [::events/handle-global-kbd e])))

(defn handle-paste [e]
Expand Down

0 comments on commit c72c0b3

Please sign in to comment.