LoginSignup
8
3

More than 5 years have passed since last update.

TouchBarを使ったペイントのサンプル

Posted at

20170206.gif

環境

  • MacOSX 10.12.3

TouchBarを使ったアプリを今更ながら試してみました。
Appleの提供しているサンプルであるToolbarSampleとNSTouchBar Catalogを読めば結構基本的な動きは使えるようになります。
問題はTouchBarをいかにうまく利用出来るかというところなんですが、そこは今後の課題です・・・。

サンプルはgithubに上げておきました。
TouchBarPaintSample

TouchBarの設定はWindowController上で実装します。


import Cocoa

fileprivate extension NSTouchBarCustomizationIdentifier {

    static let touchBar = NSTouchBarCustomizationIdentifier("com.ToolbarSample.touchBar")
}

fileprivate extension NSTouchBarItemIdentifier {

    static let colorStyle = NSTouchBarItemIdentifier("com.ToolbarSample.colorStyle")
    static let colorStyleText = NSTouchBarItemIdentifier("com.ToolbarSample.colorStyleText")
    static let colorStyleStroke = NSTouchBarItemIdentifier("com.ToolbarSample.colorStyleStroke")

    static let popover = NSTouchBarItemIdentifier("com.ToolbarSample.TouchBarItem.popover")
    static let popoverSlider = NSTouchBarItemIdentifier("com.ToolbarSample.popoverBar.slider")

}


class CustomeWindowController : NSWindowController {

    let DefaultPenWidth : Int   = 4
    var currentPenWidth: Int = 0


    override func windowDidLoad() {

        super.windowDidLoad()

        self.currentPenWidth = DefaultPenWidth


        if #available(OSX 10.12.2, *) {
            if ((NSClassFromString("NSTouchBar")) != nil) {
                let penWidthTouchBarItem = self.touchBar!.item(forIdentifier: .popover) as! NSPopoverTouchBarItem
                let sliderTouchBar = penWidthTouchBarItem.popoverTouchBar
                let sliderTouchBarItem = sliderTouchBar.item(forIdentifier: .popoverSlider) as! NSSliderTouchBarItem
                let slider = sliderTouchBarItem.slider

                // Make the font size slider a bit narrowed, about 250 pixels.
                let views = ["slider" : slider]
                let theConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[slider(250)]", options: NSLayoutFormatOptions(), metrics: nil, views:views)
                NSLayoutConstraint.activate(theConstraints)

                // Set the font size for the slider item to the same value as the stepper.
                slider.integerValue = Int(DefaultPenWidth)
            }
        }
    }

    // MARK: - NSTouchBar

    @available(OSX 10.12.2, *)
    override func makeTouchBar() -> NSTouchBar? {

        let touchBar = NSTouchBar()
        touchBar.delegate = self
        touchBar.customizationIdentifier = .touchBar
        touchBar.defaultItemIdentifiers = [.colorStyle, .colorStyleText, .colorStyleStroke, .popover, .otherItemsProxy]
        touchBar.customizationAllowedItemIdentifiers = [.colorStyle, .colorStyleText, .colorStyleStroke, .popover]

        return touchBar
    }


    @available(OSX 10.12.2, *)
    func changeColorWell(sender : NSColorPickerTouchBarItem) -> Void {
        let color = NSColor(calibratedHue: sender.color.hueComponent
            , saturation: sender.color.saturationComponent
            , brightness: sender.color.brightnessComponent
            , alpha: sender.color.alphaComponent)

        let appDelegate: AppDelegate = NSApplication.shared().delegate as! AppDelegate

        appDelegate.penColor = color
    }


    @available(OSX 10.12.2, *)
    func changePenWidthBySlider(_ sender: NSSlider) -> Void {
        let width = CGFloat(sender.floatValue)

        let appDelegate: AppDelegate = NSApplication.shared().delegate as! AppDelegate

        appDelegate.penWidth = Int(width)
    }

}


extension CustomeWindowController: NSTouchBarDelegate {

    @available(OSX 10.12.2, *)
    func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem? {

        switch identifier {

        case NSTouchBarItemIdentifier.colorStyle:

            let colorStylePicker = NSColorPickerTouchBarItem.colorPicker(withIdentifier: identifier)
            colorStylePicker.customizationLabel = "colorStylePicker"
            colorStylePicker.action = #selector(changeColorWell)

            return colorStylePicker

        case NSTouchBarItemIdentifier.colorStyleText:

            let colorStylePicker = NSColorPickerTouchBarItem.textColorPicker(withIdentifier: identifier)
            colorStylePicker.customizationLabel = "colorStyleText"
            colorStylePicker.action = #selector(changeColorWell)

            return colorStylePicker

        case NSTouchBarItemIdentifier.colorStyleStroke:

            let colorStylePicker = NSColorPickerTouchBarItem.strokeColorPicker(withIdentifier: identifier)
            colorStylePicker.customizationLabel = "colorStyleStroke"
            colorStylePicker.action = #selector(changeColorWell)

            return colorStylePicker

        case NSTouchBarItemIdentifier.popover:

            let popoverItem = NSPopoverTouchBarItem(identifier: identifier)
            popoverItem.customizationLabel = "Pen Width"
            popoverItem.collapsedRepresentationLabel = "Pen Width"

            let secondaryTouchBar = NSTouchBar()
            secondaryTouchBar.delegate = self
            secondaryTouchBar.defaultItemIdentifiers = [.popoverSlider];

            // We can setup a different NSTouchBar instance for popoverTouchBar and pressAndHoldTouchBar property
            // Here we just use the same instance.
            //
            popoverItem.pressAndHoldTouchBar = secondaryTouchBar
            popoverItem.popoverTouchBar = secondaryTouchBar

            return popoverItem


        case NSTouchBarItemIdentifier.popoverSlider:

            let sliderItem = NSSliderTouchBarItem(identifier: identifier)
            sliderItem.label = "Width"
            sliderItem.customizationLabel = "pen Width"

            let slider = sliderItem.slider
            slider.minValue = 2.0
            slider.maxValue = 20.0
            slider.target = self
            slider.action = #selector(changePenWidthBySlider)

            // Set the font size for the slider item to the same value as the stepper.
            slider.integerValue = Int(DefaultPenWidth)

            slider.bind(NSValueBinding, to: self, withKeyPath: "currentPenWidth", options: nil)

            return sliderItem

        default: return nil
        }
    }
}


TouchBarよりむしろ、ペイントの仕組みをiOSじゃなくてMacOSXで作る方に時間がかかったので、そのサンプル。


import Cocoa

class CustomeLine : NSObject {

    var path : NSBezierPath!

    override init() {

    }


    func move(point: NSPoint) {
        path = NSBezierPath()

        path.move(to: point)
    }

    func add(point: NSPoint) {
        if(path == nil){
            path = NSBezierPath()

            path.move(to: point)

            return
        }

        path.line(to: point)
    }


    func draw() {
        if(path == nil){
            return
        }

        let appDelegate: AppDelegate = NSApplication.shared().delegate as! AppDelegate

        let color = appDelegate.penColor
        let width = CGFloat(appDelegate.penWidth)

        color.set()
        path.lineWidth = width
        path.stroke()

    }
}


CustomeView.swift

import Cocoa

class CustomeView : NSView {

    var line : CustomeLine!
    var lastImage : NSImage!

    @IBOutlet weak var imageView: NSImageView!


    override func awakeFromNib() {
        super.awakeFromNib()
        line = CustomeLine()

        configure()
    }

    func configure() {
        let options:NSTrackingAreaOptions = [
            .mouseEnteredAndExited,
            .mouseMoved,
            .cursorUpdate,
            .activeAlways,
            .enabledDuringMouseDrag
        ]
        let trackingArea = NSTrackingArea(rect: bounds, options: options, owner: self, userInfo: nil)
        addTrackingArea(trackingArea)

    }


    override func mouseDown(with event: NSEvent) {
        let locationInView = self.convert(event.locationInWindow, from: nil)

        line.move(point: locationInView)

        drawImage()
    }

    override func mouseUp(with event: NSEvent) {
        let locationInView = self.convert(event.locationInWindow, from: nil)

        line.add(point: locationInView)

        drawImage()

        self.lastImage = imageView.image
    }

    override func mouseDragged(with event: NSEvent) {
        let locationInView = self.convert(event.locationInWindow, from: nil)

        line.add(point: locationInView)

        drawImage()

    }

    override func mouseMoved(with event: NSEvent) {
        //        NSLog("aaa")
    }


    func drawImage() {
        let size = self.frame.size

        let image = NSImage(size: size)

        let blub = NSBitmapImageRep(bitmapDataPlanes: nil,
                                    pixelsWide: Int(size.width),
                                    pixelsHigh: Int(size.height),
                                    bitsPerSample: 8,
                                    samplesPerPixel: 3,
                                    hasAlpha: false,
                                    isPlanar: false,
                                    colorSpaceName: NSCalibratedRGBColorSpace,
                                    bytesPerRow: 0, bitsPerPixel: 0)!

        let ctx = NSGraphicsContext(bitmapImageRep: blub)
        image.lockFocus()

        NSGraphicsContext.saveGraphicsState()

        lastImage?.draw(in: self.frame)

        line.draw()

        NSGraphicsContext.setCurrent(ctx)

        NSGraphicsContext.restoreGraphicsState()

        image.addRepresentation(blub)

        image.unlockFocus()

        imageView.image = image

    }

}


参考

[iOSアプリ開発] タッチでお絵かきしてみる
ここの描画部分をMacOSXに書き換えたのが、今回のサンプル。Undoとかは未実装。

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3