Skip to content

Commit

Permalink
Added drag and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
Gofake1 committed Jul 9, 2017
1 parent 1f623de commit 36b24f3
Show file tree
Hide file tree
Showing 14 changed files with 248 additions and 42 deletions.
4 changes: 4 additions & 0 deletions Color Picker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
4A66F1971EBC274100D81A4A /* ColorWheelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A66F1961EBC274100D81A4A /* ColorWheelView.swift */; };
4A66F19B1EBC6F0900D81A4A /* GradientSliderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A66F19A1EBC6F0900D81A4A /* GradientSliderCell.swift */; };
4A6A7EF01F09D3E60048A92E /* ColorPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A6A7EEF1F09D3E60048A92E /* ColorPickerView.swift */; };
4A6E05461F0F77D300A3C3AA /* ColorDragView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A6E05451F0F77D300A3C3AA /* ColorDragView.swift */; };
4A720F7C1EBD7E0000205678 /* NSColor+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A720F7B1EBD7E0000205678 /* NSColor+.swift */; };
4A720F811EBE8B8000205678 /* Preferences.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A720F831EBE8B8000205678 /* Preferences.storyboard */; };
4A720F841EBE8B8800205678 /* Palettes.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A720F861EBE8B8800205678 /* Palettes.storyboard */; };
Expand Down Expand Up @@ -48,6 +49,7 @@
4A66F1961EBC274100D81A4A /* ColorWheelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorWheelView.swift; sourceTree = "<group>"; };
4A66F19A1EBC6F0900D81A4A /* GradientSliderCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientSliderCell.swift; sourceTree = "<group>"; };
4A6A7EEF1F09D3E60048A92E /* ColorPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerView.swift; sourceTree = "<group>"; };
4A6E05451F0F77D300A3C3AA /* ColorDragView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorDragView.swift; sourceTree = "<group>"; };
4A720F7B1EBD7E0000205678 /* NSColor+.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSColor+.swift"; sourceTree = "<group>"; };
4A720F821EBE8B8000205678 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Preferences.storyboard; sourceTree = "<group>"; };
4A720F851EBE8B8800205678 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Palettes.storyboard; sourceTree = "<group>"; };
Expand Down Expand Up @@ -97,6 +99,7 @@
4A62A81B1EBED0FB003A02D2 /* PaletteCollectionViewItem.xib */,
4A66F1861EBC24E200D81A4A /* AppDelegate.swift */,
4AC3DDCA1ECA418200E08B8D /* ColorController.swift */,
4A6E05451F0F77D300A3C3AA /* ColorDragView.swift */,
4A6A7EEF1F09D3E60048A92E /* ColorPickerView.swift */,
4A66F1881EBC24E200D81A4A /* ColorPickerViewController.swift */,
4A66F1961EBC274100D81A4A /* ColorWheelView.swift */,
Expand Down Expand Up @@ -199,6 +202,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4A6E05461F0F77D300A3C3AA /* ColorDragView.swift in Sources */,
4A66F19B1EBC6F0900D81A4A /* GradientSliderCell.swift in Sources */,
4AC3DDCB1ECA418200E08B8D /* ColorController.swift in Sources */,
4A62A81D1EBED596003A02D2 /* PaletteCollectionViewItem.swift in Sources */,
Expand Down
6 changes: 6 additions & 0 deletions Color Picker/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
18 changes: 18 additions & 0 deletions Color Picker/Assets.xcassets/Pasteboard.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"images" : [
{
"idiom" : "mac",
"filename" : "Pasteboard.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"filename" : "[email protected]",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions Color Picker/Base.lproj/ColorPicker.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,16 @@
<outlet property="delegate" destination="3Pz-yC-UHG" id="C1F-Ht-MgT"/>
</connections>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BvD-L3-jqC" customClass="ColorDragView" customModule="Color_Picker" customModuleProvider="target">
<rect key="frame" x="160" y="8" width="20" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" image="Pasteboard" id="yQx-Ne-LuX"/>
</imageView>
</subviews>
</view>
<connections>
<outlet property="brightnessSlider" destination="kEI-3s-8V1" id="sIm-Vq-9Xz"/>
<outlet property="colorDragView" destination="BvD-L3-jqC" id="zxV-aV-XLO"/>
<outlet property="colorLabel" destination="dR5-XT-mBw" id="2YO-as-1NR"/>
<outlet property="colorWheelView" destination="RoW-gq-wFb" id="0WL-3s-3Mf"/>
</connections>
Expand All @@ -73,4 +79,7 @@
<point key="canvasLocation" x="-92" y="426.5"/>
</scene>
</scenes>
<resources>
<image name="Pasteboard" width="20" height="17"/>
</resources>
</document>
4 changes: 3 additions & 1 deletion Color Picker/ColorController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class ColorController {
saturation: color.saturationComponent,
brightness: 1.0,
alpha: 1.0)
colorPicker.updateSelectedColor()
colorPicker.updateColorWheel()
colorPicker.updateSlider()
colorPicker.updateLabel()
}
}
42 changes: 42 additions & 0 deletions Color Picker/ColorDragView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// ColorDragView.swift
// Color Picker
//
// Created by David Wu on 7/7/17.
// Copyright © 2017 Gofake1. All rights reserved.
//

import Cocoa

/// Allows colors to be dragged out
class ColorDragView: NSImageView {

override func mouseDown(with event: NSEvent) {
let pasteboardItem = NSPasteboardItem()
pasteboardItem.setDataProvider(self, forTypes: [.color])
let draggingImage = NSImage(size: bounds.size)
draggingImage.lockFocus()
ColorController.shared.selectedColor.drawSwatch(in: bounds)
draggingImage.unlockFocus()
let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardItem)
draggingItem.setDraggingFrame(bounds, contents: draggingImage)
beginDraggingSession(with: [draggingItem], event: event, source: self)
}
}

extension ColorDragView: NSDraggingSource {
func draggingSession(_ session: NSDraggingSession,
sourceOperationMaskFor context: NSDraggingContext)
-> NSDragOperation {
return .generic
}
}

extension ColorDragView: NSPasteboardItemDataProvider {
func pasteboard(_ pasteboard: NSPasteboard?,
item: NSPasteboardItem,
provideDataForType type: NSPasteboard.PasteboardType) {
guard let pasteboard = pasteboard, type == .color else { return }
ColorController.shared.selectedColor.write(to: pasteboard)
}
}
32 changes: 32 additions & 0 deletions Color Picker/ColorPickerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,40 @@

import Cocoa

/// `ColorPickerViewController` content view. Allows colors to be dragged in.
class ColorPickerView: NSView {

override func awakeFromNib() {
registerForDraggedTypes([.color])
}

// MARK: - NSDraggingDestination

override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
return .copy
}

override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool {
let pasteboard = sender.draggingPasteboard()
guard let colors = pasteboard.readObjects(forClasses: [NSColor.self], options: nil) as? [NSColor],
colors.count > 0
else { return false }
// Cancel if dragged color is the same as the current color
return ColorController.shared.selectedColor != colors[0]
}

override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
let pasteboard = sender.draggingPasteboard()
guard let colors = pasteboard.readObjects(forClasses: [NSColor.self], options: nil) as? [NSColor],
colors.count > 0
else { return false }
ColorController.shared.setColor(colors[0])
return true
}

// MARK: -

// Allows mouse click to lose `ColorPickerViewController`'s text field's focus
override func mouseDown(with event: NSEvent) {
window?.makeFirstResponder(self)
}
Expand Down
45 changes: 19 additions & 26 deletions Color Picker/ColorPickerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,34 @@ import Cocoa
class ColorPickerViewController: NSViewController {

@IBOutlet weak var brightnessSlider: NSSlider!
@IBOutlet weak var colorLabel: NSTextField!
@IBOutlet weak var colorWheelView: ColorWheelView!
@IBOutlet weak var colorLabel: NSTextField!
@IBOutlet weak var colorWheelView: ColorWheelView!
@IBOutlet weak var colorDragView: ColorDragView!

override func viewDidLoad() {
override func awakeFromNib() {
ColorController.shared.colorPicker = self
colorWheelView.delegate = self
}

/// - postcondition: Mutates `colorController.selectedColor`
override func controlTextDidEndEditing(_ obj: Notification) {
let string = (obj.userInfo?["NSFieldEditor"] as! NSTextView).textStorage!.string
let color = NSColor(hexString: string)
ColorController.shared.setColor(color)
view.window?.makeFirstResponder(view)
}

/// Should only be called by `colorController`
func updateSelectedColor() {
updateColorWheel()
updateLabel()
updateSlider()
}

/// - postcondition: Mutates `ColorController.brightness`
/// - postcondition: Mutates `ColorController.brightness`, redraws views
@IBAction func setBrightness(_ sender: NSSlider) {
ColorController.shared.brightness = CGFloat((sender.maxValue-sender.doubleValue) / sender.maxValue)
updateColorWheel(redrawCrosshair: false)
updateLabel()
}

private func updateColorWheel(redrawCrosshair: Bool = true) {
/// - postcondition: Mutates `colorController.selectedColor`, redraws views
@IBAction func setColor(_ sender: NSTextField) {
let color = NSColor(hexString: sender.stringValue)
ColorController.shared.setColor(color)
view.window?.makeFirstResponder(view)
}

func updateColorWheel(redrawCrosshair: Bool = true) {
colorWheelView.setColor(ColorController.shared.selectedColor, redrawCrosshair)
}

private func updateLabel() {
func updateLabel() {
colorLabel.backgroundColor = ColorController.shared.selectedColor
colorLabel.stringValue = "#"+ColorController.shared.selectedColor.rgbHexString
if ColorController.shared.selectedColor.scaledBrightness < 0.5 {
Expand All @@ -55,7 +48,7 @@ class ColorPickerViewController: NSViewController {
}
}

private func updateSlider() {
func updateSlider() {
guard let sliderCell = brightnessSlider.cell as? GradientSliderCell else { fatalError() }
sliderCell.colorA = ColorController.shared.masterColor
brightnessSlider.drawCell(sliderCell)
Expand All @@ -80,12 +73,12 @@ extension ColorPickerViewController: NSControlTextEditingDelegate {
// or 7 characters if the first character is '#'
switch string.characters.count {
case 6:
guard string.containsOnlyHexCharacters() else { return false }
guard string.containsOnlyHexCharacters else { return false }
return true
case 7:
guard string.hasPrefix("#") else { return false }
var trimmed = string; trimmed.remove(at: trimmed.startIndex)
guard trimmed.containsOnlyHexCharacters() else { return false }
guard trimmed.containsOnlyHexCharacters else { return false }
return true
default:
return false
Expand All @@ -94,15 +87,15 @@ extension ColorPickerViewController: NSControlTextEditingDelegate {

func control(_ control: NSControl, isValidObject obj: Any?) -> Bool {
if control == colorLabel {
guard let _obj = obj, let string = _obj as? String else { return false }
guard let string = obj as? String else { return false }
return validateControlString(string)
}
return false
}
}

extension String {
func containsOnlyHexCharacters() -> Bool {
var containsOnlyHexCharacters: Bool {
return !characters.contains {
switch $0 {
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "a", "b",
Expand Down
4 changes: 2 additions & 2 deletions Color Picker/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.1</string>
<string>1.1</string>
<key>CFBundleVersion</key>
<string>1.0.1</string>
<string>1.1</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.graphics-design</string>
<key>LSMinimumSystemVersion</key>
Expand Down
10 changes: 8 additions & 2 deletions Color Picker/PaletteCollectionViewItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class PaletteCollectionViewItem: NSCollectionViewItem {

@IBAction func edit(_ sender: NSMenuItem) {
isEditing = true
paletteColorsView.isEditing = true
paletteColorsView.state = .isEditing
}

@IBAction func delete(_ sender: NSMenuItem) {
Expand All @@ -63,7 +63,7 @@ class PaletteCollectionViewItem: NSCollectionViewItem {

@IBAction func finishEditing(_ sender: NSButton) {
isEditing = false
paletteColorsView.isEditing = false
paletteColorsView.state = .normal
}
}

Expand All @@ -73,6 +73,12 @@ extension PaletteCollectionViewItem: PaletteColorsViewDelegate {
ColorController.shared.setColor(color)
}

func addColor(_ color: NSColor) {
if let palette = representedObject as? Palette {
palette.addColor(color)
}
}

func removeColor(_ color: NSColor) {
if let palette = representedObject as? Palette {
palette.removeColor(color)
Expand Down
Loading

0 comments on commit 36b24f3

Please sign in to comment.