DotViewUndo/ViewController.swift
/* |
Copyright (C) 2017 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
A NSViewController subclass showing how to use IBActions to manipulate a view, and how to use UndoManager. |
*/ |
import Cocoa |
class ViewController: NSViewController { |
@IBOutlet weak var dotView: DotView! |
// radiusChanged(_:) is an action method which lets you change the radius of the dot. |
// A possible optimization is to check to see if the old and new value is the same, |
// and not do anything if so. |
@IBAction func radiusChanged(_ sender: NSSlider) { |
updateRadius(CGFloat(sender.doubleValue)) |
} |
// Having a method which takes the updated radius value as a parameter means that undo can just call this same method |
// with the previous value. This also makes redo work without any extra code. |
private func updateRadius(_ radius: CGFloat) { |
if let undoManager = undoManager { |
undoManager.registerUndo(withTarget: self, handler: { [previousRadius = dotView.radius] (_) -> Void in |
self.updateRadius(previousRadius) |
}) |
undoManager.setActionName("Change Radius") |
} |
dotView.radius = radius |
} |
// colorChanged(_:) is an action method which lets you change the color of the dot. |
// A possible optimization is to check to see if the old and new value is the same, |
// and not do anything if so. |
@IBAction func colorChanged(_ sender: NSColorWell) { |
updateColor(sender.color) |
} |
private func updateColor(_ color: NSColor) { |
if let undoManager = undoManager { |
undoManager.registerUndo(withTarget: self, handler: { [previousColor = dotView.color] (_) -> Void in |
self.updateColor(previousColor) |
}) |
undoManager.setActionName("Change Color") |
} |
dotView.color = color |
} |
// The recommended way to handle events is to override NSResponder (superclass |
// of NSView) methods in the NSView subclass. One such method is mouseUp(with:). |
// These methods get the event as the argument. The event has the mouse |
// location in window coordinates; use convert(_:from:) (with "nil" |
// as the view argument) to convert this point to view coordinates local |
// to dotView. |
// |
// Note that once we set the new center, needsDisplay is set to true in the center |
// property's didSet observer to mark that the view needs to be redisplayed (which |
// is done automatically by AppKit). |
override func mouseUp(with event: NSEvent) { |
let convertedCenter = dotView.convert(event.locationInWindow, from: nil) |
updateCenter(convertedCenter) |
} |
private func updateCenter(_ center: NSPoint) { |
// Since the previous center was already converted from the window coordinates |
// before setting it as the dotView's center, there is no need to convert |
// previousCenter from window coordinates. |
if let undoManager = undoManager { |
undoManager.registerUndo(withTarget: self, handler: { [previousCenter = dotView.center, unowned self] (_) -> Void in |
self.updateCenter(previousCenter) |
}) |
undoManager.setActionName("Change Center") |
} |
dotView.center = center |
} |
} |
Copyright © 2017 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2017-08-17