@@ -5,6 +5,9 @@ import reactify.Var
55class Transaction {
66 private var map = Map .empty[Var [_], TransactionChange ]
77
8+ /**
9+ * Called when the value of a Var changes
10+ */
811 def change [T ](owner : Var [T ], oldFunction : () => T , newFunction : () => T ): Unit = {
912 val change = map.get(owner) match {
1013 case Some (c) => c.copy(apply = () => owner := newFunction())
@@ -13,50 +16,83 @@ class Transaction {
1316 map += owner -> change
1417 }
1518
19+ /**
20+ * Gets the `TransactionChange` for the supplied `Var` if one is defined
21+ */
1622 def get [T ](v : Var [T ]): Option [TransactionChange ] = map.get(v)
1723
24+ /**
25+ * Returns the `TransactionChange` for the supplied `Var` or throws an exception if none exists
26+ */
1827 def apply [T ](v : Var [T ]): TransactionChange = get(v).getOrElse(throw new RuntimeException (s " No reference in transaction for $v" ))
1928
29+ /**
30+ * Commits all changes in this Transaction and then clears the transaction
31+ */
2032 def commit (): Unit = {
2133 map.keys.foreach { v =>
2234 commit(v.asInstanceOf [Var [Any ]])
2335 }
2436 map = Map .empty
2537 }
2638
39+ /**
40+ * Reverts all changes in this Transaction and then clears the transaction
41+ */
2742 def revert (): Unit = {
2843 map.keys.foreach { v =>
2944 revert(v.asInstanceOf [Var [Any ]])
3045 }
3146 map = Map .empty
3247 }
3348
49+ /**
50+ * Undoes all changes that occurred within this Transaction. Unlike `revert`, this doesn't clear the transaction.
51+ * This allows `redo` to run to re-apply the transaction in the future.
52+ */
3453 def undo (): Unit = {
3554 map.keys.foreach { v =>
3655 undo(v.asInstanceOf [Var [Any ]])
3756 }
3857 }
3958
59+ /**
60+ * Redoes all changes that occurred within this Transaction. Unlike `commit`, this doesn't clear the transaction.
61+ * This allows `undo` to un-apply the transaction in the future.
62+ */
4063 def redo (): Unit = {
4164 map.keys.foreach { v =>
4265 redo(v.asInstanceOf [Var [Any ]])
4366 }
4467 }
4568
69+ /**
70+ * Redoes the transaction for this `Var` and then clears it from the transaction.
71+ *
72+ * @return true if a change was applied
73+ */
4674 def commit [T ](v : Var [T ]): Boolean = if (redo(v)) {
4775 map -= v
4876 true
4977 } else {
5078 false
5179 }
5280
81+ /**
82+ * Undoes the transaction for this `Var` and then clears it from the transaction.
83+ *
84+ * @return true if a change was applied
85+ */
5386 def revert [T ](v : Var [T ]): Boolean = if (undo(v)) {
5487 map -= v
5588 true
5689 } else {
5790 false
5891 }
5992
93+ /**
94+ * Undoes the transaction for this `Var`.
95+ */
6096 def undo [T ](v : Var [T ]): Boolean = get(v) match {
6197 case Some (change) => {
6298 change.unapply()
@@ -65,6 +101,9 @@ class Transaction {
65101 case None => false
66102 }
67103
104+ /**
105+ * Redoes the transaction for this `Var`.
106+ */
68107 def redo [T ](v : Var [T ]): Boolean = get(v) match {
69108 case Some (change) => {
70109 change.apply()
@@ -74,13 +113,26 @@ class Transaction {
74113 }
75114}
76115
116+ /**
117+ * Transaction allows access to undo, redo, revert, and commit changes to `Var`s
118+ */
77119object Transaction {
78120 private val threadLocal = new ThreadLocal [Option [Transaction ]] {
79121 override def initialValue (): Option [Transaction ] = None
80122 }
81123
124+ /**
125+ * True if a Transaction is currently active on the current thread
126+ */
82127 def active : Boolean = threadLocal.get().nonEmpty
83128
129+ /**
130+ * Creates a new Transaction if one isn't already active or re-uses an existing one if a Transaction is already
131+ * in-progress for this thread.
132+ *
133+ * @param f the function to run within a Transaction
134+ * @return Transaction
135+ */
84136 def apply (f : => Unit ): Transaction = {
85137 val created = ! active
86138 val transaction = threadLocal.get().getOrElse {
@@ -95,6 +147,9 @@ object Transaction {
95147 transaction
96148 }
97149
150+ /**
151+ * Called when the value of a Var changes
152+ */
98153 def change [T ](owner : Var [T ], oldFunction : () => T , newFunction : () => T ): Unit = {
99154 threadLocal.get().foreach(_.change(owner, oldFunction, newFunction))
100155 }
0 commit comments