Suppress undo during strokes.

pull/1/head
Matthew Chen 6 years ago
parent 9378ab2192
commit 3d67c6574d

@ -320,6 +320,13 @@ public class ImageEditorModel: NSObject {
private var undoStack = [ImageEditorOperation]()
private var redoStack = [ImageEditorOperation]()
// In some cases, we want to suppress changes to undo state.
// e.g. drawing a stroke will modify the model many times (once
// for each touch event/stroke sample), but we only want that
// to add a single undo operation.
private var isUndoSuppressed = false
private var suppressedUndoContents: ImageEditorContents?
// We don't want to allow editing of images if:
//
// * They are invalid.
@ -365,6 +372,28 @@ public class ImageEditorModel: NSObject {
return !undoStack.isEmpty
}
@objc
public func setIsUndoSuppressed(isUndoSuppressed: Bool) {
if isUndoSuppressed {
if self.isUndoSuppressed {
owsFailDebug("Undo already suppressed.")
}
if suppressedUndoContents != nil {
owsFailDebug("Unexpected suppressed undo contents.")
}
suppressedUndoContents = contents.clone()
} else {
if self.isUndoSuppressed {
if suppressedUndoContents == nil {
owsFailDebug("Missing suppressed undo contents.")
}
}
suppressedUndoContents = nil
}
self.isUndoSuppressed = isUndoSuppressed
}
@objc
public func canRedo() -> Bool {
return !redoStack.isEmpty
@ -402,29 +431,47 @@ public class ImageEditorModel: NSObject {
@objc
public func append(item: ImageEditorItem) {
performAction { (newContents) in
performAction({ (newContents) in
newContents.append(item: item)
}
})
}
@objc
public func replace(item: ImageEditorItem) {
performAction { (newContents) in
public func replace(item: ImageEditorItem,
shouldRemoveUndoSuppression: Bool = false) {
performAction({ (newContents) in
newContents.replace(item: item)
}
}, shouldRemoveUndoSuppression: shouldRemoveUndoSuppression)
}
@objc
public func remove(item: ImageEditorItem) {
performAction { (newContents) in
performAction({ (newContents) in
newContents.remove(item: item)
}
})
}
private func performAction(action: (ImageEditorContents) -> Void) {
let undoOperation = ImageEditorOperation(contents: contents)
undoStack.append(undoOperation)
redoStack.removeAll()
private func performAction(_ action: (ImageEditorContents) -> Void,
shouldRemoveUndoSuppression: Bool = false) {
if shouldRemoveUndoSuppression {
if !isUndoSuppressed {
owsFailDebug("Can't remove undo suppression, not suppressed.")
}
if let suppressedUndoContents = self.suppressedUndoContents {
let undoOperation = ImageEditorOperation(contents: suppressedUndoContents)
undoStack.append(undoOperation)
redoStack.removeAll()
} else {
owsFailDebug("Missing suppressed undo contents.")
}
self.isUndoSuppressed = false
setIsUndoSuppressed(isUndoSuppressed: false)
} else if !isUndoSuppressed {
let undoOperation = ImageEditorOperation(contents: contents)
undoStack.append(undoOperation)
redoStack.removeAll()
}
let newContents = contents.clone()
action(newContents)

@ -107,6 +107,7 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
if let stroke = self.currentStroke {
self.model.remove(item: stroke)
}
self.model.setIsUndoSuppressed(isUndoSuppressed: false)
self.currentStroke = nil
self.currentStrokeSamples.removeAll()
}
@ -131,9 +132,11 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
currentStrokeSamples.append(unitSampleForGestureLocation())
let stroke = ImageEditorStrokeItem(color: strokeColor, unitSamples: self.currentStrokeSamples, unitStrokeWidth: unitStrokeWidth)
self.model.append(item: stroke)
self.currentStroke = stroke
model.setIsUndoSuppressed(isUndoSuppressed: true)
let stroke = ImageEditorStrokeItem(color: strokeColor, unitSamples: currentStrokeSamples, unitStrokeWidth: unitStrokeWidth)
model.append(item: stroke)
currentStroke = stroke
case .changed, .ended:
currentStrokeSamples.append(unitSampleForGestureLocation())
@ -146,13 +149,15 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
// Model items are immutable; we _replace_ the
// stroke item rather than modify it.
let stroke = ImageEditorStrokeItem(itemId: lastStroke.itemId, color: strokeColor, unitSamples: self.currentStrokeSamples, unitStrokeWidth: unitStrokeWidth)
self.model.replace(item: stroke)
self.currentStroke = stroke
let stroke = ImageEditorStrokeItem(itemId: lastStroke.itemId, color: strokeColor, unitSamples: currentStrokeSamples, unitStrokeWidth: unitStrokeWidth)
if gestureRecognizer.state == .ended {
self.currentStroke = nil
self.currentStrokeSamples.removeAll()
model.replace(item: stroke, shouldRemoveUndoSuppression: true)
currentStroke = nil
currentStrokeSamples.removeAll()
} else {
model.replace(item: stroke)
currentStroke = stroke
}
default:
removeCurrentStroke()

Loading…
Cancel
Save