Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cc77460f3 | ||
|
|
ec78ffb864 | ||
|
|
9ce676c51c | ||
|
|
1ad62f4bf8 |
@@ -256,13 +256,14 @@
|
||||
TargetAttributes = {
|
||||
15B4E86F207994AF0024FDE4 = {
|
||||
CreatedOnToolsVersion = 9.3;
|
||||
LastSwiftMigration = 1000;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = B3B4C2BC1E25894B009F8E4E;
|
||||
};
|
||||
B3B4C2BC1E25894B009F8E4E = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
DevelopmentTeam = UNR5C68RPX;
|
||||
LastSwiftMigration = 0920;
|
||||
LastSwiftMigration = 1000;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
@@ -389,7 +390,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.acheronfail.PixelPickerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PixelPicker.app/Contents/MacOS/PixelPicker";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -417,7 +418,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.acheronfail.PixelPickerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PixelPicker.app/Contents/MacOS/PixelPicker";
|
||||
};
|
||||
name = Release;
|
||||
@@ -559,8 +560,7 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "PixelPicker/Bridging-Header.h";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -585,8 +585,7 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "PixelPicker/Bridging-Header.h";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -236,10 +236,9 @@ extension AppDelegate: NSMenuDelegate {
|
||||
}
|
||||
|
||||
// Build a submenu with each case in the PPColor enum.
|
||||
// TODO: with Swift 4.2, we shouldn't need to resort to the hacky "iterateEnum" approach.
|
||||
private func buildColorFormatsMenu() {
|
||||
let submenu = NSMenu()
|
||||
for format in iterateEnum(PPColor.self) {
|
||||
for format in PPColor.allCases {
|
||||
let formatItem = submenu.addItem(withTitle: format.rawValue, action: #selector(selectFormat(_:)), keyEquivalent: "")
|
||||
formatItem.representedObject = format
|
||||
if PPState.shared.chosenFormat == format { formatItem.state = .on }
|
||||
@@ -282,6 +281,7 @@ extension AppDelegate: NSMenuDelegate {
|
||||
contextMenu.addItem(withTitle: "Picker Shortcut", action: nil, keyEquivalent: "")
|
||||
|
||||
let shortcutView = MASShortcutView()
|
||||
shortcutView.style = .flat
|
||||
shortcutView.shortcutValue = PPState.shared.activatingShortcut
|
||||
shortcutView.shortcutValueChange = { PPState.shared.activatingShortcut = $0?.shortcutValue }
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import MASShortcut
|
||||
import CleanroomLogger
|
||||
|
||||
// The app's menu bar item.
|
||||
let ICON = setupMenuBarIcon(NSImage(named: NSImage.Name(rawValue: "icon")))
|
||||
let ICON = setupMenuBarIcon(NSImage(named: NSImage.Name(stringLiteral: "icon")))
|
||||
|
||||
@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.2</string>
|
||||
<string>1.2.3</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>7</string>
|
||||
<string>8</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -11,10 +11,10 @@ extension NSBezierPath {
|
||||
var points = [CGPoint](repeating: .zero, count: 3)
|
||||
for i in 0 ..< self.elementCount {
|
||||
switch self.element(at: i, associatedPoints: &points) {
|
||||
case .moveToBezierPathElement: path.move(to: points[0])
|
||||
case .lineToBezierPathElement: path.addLine(to: points[0])
|
||||
case .curveToBezierPathElement: path.addCurve(to: points[2], control1: points[0], control2: points[1])
|
||||
case .closePathBezierPathElement: path.closeSubpath()
|
||||
case .moveTo: path.move(to: points[0])
|
||||
case .lineTo: path.addLine(to: points[0])
|
||||
case .curveTo: path.addCurve(to: points[2], control1: points[0], control2: points[1])
|
||||
case .closePath: path.closeSubpath()
|
||||
}
|
||||
}
|
||||
return path
|
||||
|
||||
@@ -20,8 +20,8 @@ class PPOverlayPreview: NSView, CALayerDelegate {
|
||||
override func awakeFromNib() {
|
||||
// Make layers contents resize to fill, and disable antialiasing.
|
||||
wantsLayer = true
|
||||
layer?.magnificationFilter = kCAFilterNearest
|
||||
layer?.contentsGravity = kCAGravityResizeAspectFill
|
||||
layer?.magnificationFilter = .nearest
|
||||
layer?.contentsGravity = .resizeAspectFill
|
||||
layer?.delegate = self
|
||||
|
||||
// Add the grid shape layers to the view.
|
||||
|
||||
@@ -39,7 +39,7 @@ struct PPPickedColor {
|
||||
|
||||
// This enum is responsible for each of the color formats PixelPicker supports,
|
||||
// as well as being responsible for formatting them as strings, etc.
|
||||
enum PPColor: String {
|
||||
enum PPColor: String, CaseIterable {
|
||||
case genericHex = "Generic Hex"
|
||||
case generic8Bit = "Generic 8-Bit"
|
||||
case genericDecimal = "Generic Decimal"
|
||||
@@ -161,16 +161,15 @@ enum PPColor: String {
|
||||
|
||||
// Returns the PPColor that sits after this one.
|
||||
func next() -> PPColor {
|
||||
return next(withArray: iterateEnum(PPColor.self).map({ $0 }))
|
||||
return next(withArray: PPColor.allCases)
|
||||
}
|
||||
|
||||
// Same as next() but backwards.
|
||||
func previous() -> PPColor {
|
||||
return next(withArray: iterateEnum(PPColor.self).reversed())
|
||||
return next(withArray: PPColor.allCases.reversed())
|
||||
}
|
||||
|
||||
// Finds the next element after this element in the given array.
|
||||
// This method should only be passed the result of iterateEnum(PPColor.self).
|
||||
// Finds the next PPColor after this one in the list of PPColors.
|
||||
private func next(withArray array: [PPColor]) -> PPColor {
|
||||
var found = false
|
||||
for x in array {
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#import "PPMenuShortcutView.h"
|
||||
#import "PixelPicker-Swift.h"
|
||||
|
||||
// The trailing end of the cancel button in the MASShortcutView (within the NSMenuItem).
|
||||
CGFloat cancelBoundary = 15;
|
||||
|
||||
// In order to have a MASShortcutView inside our menubar dropdown menu, we need to
|
||||
// perform some hacks. Basically, we catch all the key and mouse events, and then
|
||||
// use those to manually control the shortcut view (the MASShortcutView doesn't work
|
||||
@@ -44,6 +47,21 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)drawRect:(NSRect)dirtyRect
|
||||
{
|
||||
[super drawRect:dirtyRect];
|
||||
|
||||
// Draw a border around the view.
|
||||
// Currently we don't use any of MASShortcut's custom drawing styles since they don't draw
|
||||
// nicely with macOS 10.14's new dark interface style.
|
||||
CGFloat xInset = 20;
|
||||
CGFloat yInset = 1;
|
||||
NSRect borderRect = NSMakeRect(self.frame.origin.x + xInset, self.frame.origin.y + yInset, self.frame.size.width - xInset - cancelBoundary, self.frame.size.height - (yInset * 2));
|
||||
NSBezierPath *border = [NSBezierPath bezierPathWithRoundedRect:borderRect xRadius:3 yRadius:3];
|
||||
[[[NSColor scrollBarColor] colorWithAlphaComponent:0.5] set];
|
||||
[border stroke];
|
||||
}
|
||||
|
||||
// This is called when the NSMenu is opened, so it's a good time to register our
|
||||
// intercepting event handlers to catch all keyboard events inside the NSMenu.
|
||||
- (void)viewDidMoveToWindow
|
||||
@@ -95,7 +113,7 @@
|
||||
// End of the MASShortcutView.
|
||||
CGFloat end = start + shortcutView.frame.size.width;
|
||||
// Start of the cancel button in the MASShortcutView.
|
||||
CGFloat cancelStart = end - 20;
|
||||
CGFloat cancelStart = end - cancelBoundary;
|
||||
|
||||
if (shortcutView.shortcutValue != nil) {
|
||||
if (point.x >= start && point.x <= cancelStart) {
|
||||
|
||||
+1
-13
@@ -8,18 +8,6 @@ import CleanroomLogger
|
||||
let APP_NAME = Bundle.main.infoDictionary![kCFBundleNameKey as String] as! String
|
||||
let APPLE_INTERFACE_STYLE = "AppleInterfaceStyle"
|
||||
|
||||
// This allows us to iterate over the raw values of an enum.
|
||||
// TODO: use `CaseIterable` when Swift 4.2 comes out
|
||||
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
|
||||
var i = 0
|
||||
return AnyIterator {
|
||||
let next = withUnsafeBytes(of: &i) { $0.load(as: T.self) }
|
||||
if next.hashValue != i { return nil }
|
||||
i += 1
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
// Copies the given string to the clipboard.
|
||||
func copyToPasteboard(stringValue value: String) {
|
||||
NSPasteboard.general.declareTypes([.string], owner: nil)
|
||||
@@ -68,7 +56,7 @@ enum Coordinate {
|
||||
func runAnimation(_ f: (NSAnimationContext) -> Void, done: (() -> Void)?) {
|
||||
NSAnimationContext.runAnimationGroup({ context in
|
||||
context.duration = 0.5
|
||||
context.timingFunction = .init(name: kCAMediaTimingFunctionEaseInEaseOut)
|
||||
context.timingFunction = CAMediaTimingFunction.init(name: .easeInEaseOut)
|
||||
context.allowsImplicitAnimation = true
|
||||
f(context)
|
||||
}, completionHandler: done)
|
||||
|
||||
@@ -4,6 +4,5 @@
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import PixelPicker
|
||||
|
||||
class AppDelegateTests: XCTestCase {}
|
||||
|
||||
@@ -4,4 +4,3 @@
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import PixelPicker
|
||||
|
||||
@@ -4,6 +4,5 @@
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import PixelPicker
|
||||
|
||||
class PPStateTests: XCTestCase {}
|
||||
|
||||
Reference in New Issue
Block a user