• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-cqtcocoa誰得pythonphprubygameguibathyscaphec翻訳計画中(planning stage)omegatframeworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

macOSのスクリーンショットの保存場所を変更するメニュバーエクストラ


Commit MetaInfo

Revisionbb8adaf3739e5f08a6b5162c883ae57a968a1b04 (tree)
Time2018-04-16 23:20:55
Authormasakih <masakih@user...>
Commitermasakih

Log Message

コーディング規約を変更

Change Summary

Incremental Difference

--- a/GoInto/AppDelegate.swift
+++ b/GoInto/AppDelegate.swift
@@ -14,9 +14,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
1414 let statusBar = StatusBar()
1515
1616 class var appName: String {
17+
1718 guard let dict = Bundle.main.localizedInfoDictionary,
18- let name = dict["CFBundleDisplayName"] as? String
19- else { return "GO into" }
19+ let name = dict["CFBundleDisplayName"] as? String else {
20+
21+ return "GO into"
22+ }
2023 return name
2124 }
2225 }
--- a/GoInto/ChooseFolderItem.swift
+++ b/GoInto/ChooseFolderItem.swift
@@ -9,10 +9,12 @@
99 import Cocoa
1010
1111 class ChooseFolderItem: StatusItem {
12+
1213 let menuItem = NSMenuItem()
1314 let urlSelector: (URL) -> Void
1415
1516 init(_ handler: @escaping ((URL) -> Void)) {
17+
1618 urlSelector = handler
1719 menuItem.title = NSLocalizedString("Choose Folder", comment: "Choose Folder MenuItem")
1820 menuItem.action = #selector(selectFolder(_:))
@@ -20,6 +22,7 @@ class ChooseFolderItem: StatusItem {
2022 }
2123
2224 @IBAction func selectFolder(_ sender: Any?) {
25+
2326 let panel = NSOpenPanel()
2427 panel.canChooseDirectories = true
2528 panel.allowsMultipleSelection = false
@@ -31,7 +34,10 @@ class ChooseFolderItem: StatusItem {
3134
3235 NSApplication.shared.activate(ignoringOtherApps: true)
3336 guard panel.runModal() == NSApplication.ModalResponse(NSFileHandlingPanelOKButton),
34- let url = panel.directoryURL else { return }
37+ let url = panel.directoryURL else {
38+
39+ return
40+ }
3541 urlSelector(url)
3642 }
3743 }
--- a/GoInto/FolderItem.swift
+++ b/GoInto/FolderItem.swift
@@ -9,16 +9,21 @@
99 import Cocoa
1010
1111 final class FolderItem: StatusItem {
12+
1213 let url: URL
1314 let menuItem = NSMenuItem()
1415
1516 init(_ url: URL) {
17+
1618 self.url = url
1719
1820 if let either = try? url.resourceValues(forKeys: [.localizedNameKey]),
1921 let name = either.localizedName {
22+
2023 menuItem.title = name
24+
2125 } else {
26+
2227 menuItem.title = FileManager.default.displayName(atPath: url.path)
2328 }
2429
@@ -27,44 +32,59 @@ final class FolderItem: StatusItem {
2732 menuItem.action = #selector(changeFolder(_:))
2833 menuItem.target = self
2934 }
35+
3036 deinit {
37+
3138 remove()
3239 }
3340
3441 func set() {
42+
3543 let newUrl = url
44+
3645 DispatchQueue(label: "Launch defaults").async {
46+
3747 Screenshot.shared.location = newUrl
3848 if #available(macOS 10.12, *) {
49+
3950 return
51+
4052 } else {
53+
4154 Screenshot.shared.apply()
4255 }
4356 }
4457 }
4558
4659 func update(_ url: URL) {
60+
4761 menuItem.state = (self.url == url ? .on : .off)
4862 }
4963
5064 @IBAction func changeFolder(_ sender: Any?) {
65+
5166 set()
5267 }
5368 }
5469
5570 func fitSize(_ image: NSImage) -> NSImage {
71+
5672 let fitSize: CGFloat = 19
5773 let size = image.size
5874 guard size.width > fitSize else { return image }
75+
5976 let ratio = fitSize / size.width
6077 let newSize = NSSize(width: size.width * ratio, height: size.height * ratio)
6178 image.resizingMode = .stretch
6279 image.size = newSize
80+
6381 return image
6482 }
6583
6684 extension FolderItem: Equatable {
85+
6786 static func ==(lhs: FolderItem, rhs: FolderItem) -> Bool {
87+
6888 return lhs.url == rhs.url
6989 }
7090 }
--- a/GoInto/ImageTypeItem.swift
+++ b/GoInto/ImageTypeItem.swift
@@ -9,17 +9,23 @@
99 import Cocoa
1010
1111 private func loadImageTypes() -> [String] {
12+
1213 guard let url = Bundle.main.url(forResource: "ImageType", withExtension: "plist"),
13- let array = NSArray(contentsOf: url)
14- else { return [] }
14+ let array = NSArray(contentsOf: url) else {
15+
16+ return []
17+ }
18+
1519 return array as? [String] ?? []
1620 }
1721
1822 class ImageTypeItem: StatusItem {
23+
1924 let menuItem = NSMenuItem()
2025 private let supportTypes = loadImageTypes()
2126
22- init() {
27+ init() {
28+
2329 menuItem.title = NSLocalizedString("Image Type", comment: "Image Type MenuItem")
2430
2531 let ws = NSWorkspace.shared
@@ -28,38 +34,51 @@ class ImageTypeItem: StatusItem {
2834 supportTypes
2935 .filter { ws.localizedDescription(forType: $0) != nil }
3036 .map {
37+
3138 let item = NSMenuItem()
3239 item.title = ws.localizedDescription(forType: $0) ?? "Never Use Default Value"
3340 item.action = #selector(selectType(_:))
3441 item.target = self
3542 item.representedObject = ws.preferredFilenameExtension(forType: $0)
43+
3644 return item
3745 }
3846 .forEach { menuItem.submenu?.addItem($0) }
3947 }
4048
4149 func update() {
50+
4251 let current = Screenshot.shared.type
4352 menuItem.submenu?.items.forEach {
53+
4454 if let type = $0.representedObject as? String,
4555 type == current {
56+
4657 $0.state = .on
58+
4759 } else {
60+
4861 $0.state = .off
4962 }
5063 }
5164 }
5265
5366 fileprivate func set(_ typeName: String) {
67+
5468 DispatchQueue(label: "Launch defaults").async {
69+
5570 Screenshot.shared.type = typeName
5671 }
5772 }
5873
5974 @IBAction func selectType(_ sender: Any?) {
75+
6076 guard let item = sender as? NSMenuItem,
61- let typeName = item.representedObject as? String
62- else { return }
77+ let typeName = item.representedObject as? String else {
78+
79+ return
80+ }
81+
6382 set(typeName)
6483 }
6584 }
--- a/GoInto/LimitedArray.swift
+++ b/GoInto/LimitedArray.swift
@@ -14,33 +14,43 @@ struct LimitedArray<Element: Equatable>: Collection {
1414 let size: Int
1515
1616 init(_ size: Int) {
17+
1718 self.size = size
1819 }
20+
1921 mutating func append(_ newObject: Element) {
22+
2023 if let index = array.index(of: newObject) {
24+
2125 array.remove(at: index)
2226 }
2327 array.insert(newObject, at: 0)
2428 if array.count > size {
29+
2530 array.remove(at: size)
2631 }
2732 }
2833
2934 // Collection
3035 var startIndex: Int {
36+
3137 return array.startIndex
3238 }
3339 var endIndex: Int {
40+
3441 return array.endIndex
3542 }
3643 func index(after i: Int) -> Int {
44+
3745 return array.index(after: i)
3846 }
3947 subscript(position: Int) -> Element {
48+
4049 return array[position]
4150 }
4251 }
4352 extension LimitedArray: CustomDebugStringConvertible {
53+
4454 var description: String { return array.description }
4555 var debugDescription: String { return array.debugDescription }
4656 }
--- a/GoInto/QuitItem.swift
+++ b/GoInto/QuitItem.swift
@@ -9,9 +9,11 @@
99 import Cocoa
1010
1111 class QuitItem: StatusItem {
12+
1213 let menuItem = NSMenuItem()
1314
1415 init() {
16+
1517 let format = NSLocalizedString("Quit %@", comment: "Quit Menu Item")
1618 menuItem.title = String(format: format, AppDelegate.appName)
1719 menuItem.action = #selector(quit(_:))
@@ -19,6 +21,7 @@ class QuitItem: StatusItem {
1921 }
2022
2123 @IBAction func quit(_ sender: Any?) {
24+
2225 NSApplication.shared.terminate(nil)
2326 }
2427 }
--- a/GoInto/Screenshot.swift
+++ b/GoInto/Screenshot.swift
@@ -11,7 +11,9 @@ import Foundation
1111 class Screenshot {
1212
1313 private enum Attrubute: String {
14+
1415 case location = "location"
16+
1517 case type = "type"
1618 }
1719
@@ -20,16 +22,19 @@ class Screenshot {
2022 private init() {}
2123
2224 var location: URL {
25+
2326 get { return screencaptureAttribute(.location).map { URL(fileURLWithPath: $0) } ?? desktopURL() }
2427 set { setScreencaptureAttribute(newValue.path, for: .location) }
2528 }
2629 var type: String {
30+
2731 get { return screencaptureAttribute(.type) ?? "jpeg" }
2832 set { setScreencaptureAttribute(newValue, for: .type) }
2933 }
3034
3135 @available(macOS, deprecated: 10.12)
3236 func apply() {
37+
3338 let process = Process()
3439 process.launchPath = "/usr/bin/killall"
3540 process.arguments = ["SystemUIServer"]
@@ -37,6 +42,7 @@ class Screenshot {
3742 }
3843
3944 private func screencaptureAttribute(_ attr: Attrubute) -> String? {
45+
4046 let process = Process()
4147 process.launchPath = "/usr/bin/defaults"
4248 process.arguments = ["read", "com.apple.screencapture", attr.rawValue]
@@ -48,20 +54,26 @@ class Screenshot {
4854 let data = pipe.fileHandleForReading.readDataToEndOfFile()
4955 guard let output = String(data: data, encoding: .utf8),
5056 let type = output.components(separatedBy: "\n").first,
51- process.terminationStatus == 0
52- else { return nil }
57+ process.terminationStatus == 0 else {
58+
59+ return nil
60+ }
61+
5362 return type
5463 }
64+
5565 private func setScreencaptureAttribute(_ value: String, for attr: Attrubute) {
66+
5667 let process = Process()
5768 process.launchPath = "/usr/bin/defaults"
5869 process.arguments = ["write", "com.apple.screencapture", attr.rawValue, value]
5970 process.launch()
6071 process.waitUntilExit()
6172
62- guard process.terminationStatus == 0
63- else {
73+ guard process.terminationStatus == 0 else {
74+
6475 print("Can not set location")
76+
6577 return
6678 }
6779 }
--- a/GoInto/StatusBar.swift
+++ b/GoInto/StatusBar.swift
@@ -9,15 +9,20 @@
99 import Cocoa
1010
1111 final class StatusBar: NSObject {
12+
1213 let myStatusBar = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
1314 let menu = NSMenu()
15+
1416 private(set) var items: [StatusItem] = []
1517 private(set) var recentItems = LimitedArray<FolderItem>(5) {
18+
1619 didSet { UserDefaults.standard.recentURLs = recentItems.map { $0.url } }
1720 }
1821
1922 override init() {
23+
2024 super.init()
25+
2126 menu.delegate = self
2227
2328 myStatusBar.menu = menu
@@ -27,6 +32,7 @@ final class StatusBar: NSObject {
2732 }
2833
2934 private func build() {
35+
3036 items = [
3137 FolderItem(desktopURL()),
3238 FolderItem(picturesURL()),
@@ -53,26 +59,35 @@ final class StatusBar: NSObject {
5359 let newItem = FolderItem(url)
5460 recentItems.append(newItem)
5561 newItem.enter(menu)
62+
5663 return newItem
5764 }
5865
5966 private func appendFolder(_ url: URL) {
67+
6068 _ = newFolderItem(url)
6169 }
6270
6371 private func appendAndChooseFolder(_ url: URL) {
72+
6473 newFolderItem(url)?.set()
6574 }
6675 }
6776
6877 extension StatusBar: NSMenuDelegate {
78+
6979 func menuWillOpen(_ menu: NSMenu) {
80+
7081 let url = Screenshot.shared.location
7182 recentItems.forEach { $0.update(url) }
7283 items.forEach { item in
84+
7385 switch item {
86+
7487 case let f as FolderItem: f.update(url)
88+
7589 case let i as ImageTypeItem: i.update()
90+
7691 default: ()
7792 }
7893 }
@@ -81,15 +96,17 @@ extension StatusBar: NSMenuDelegate {
8196
8297
8398 fileprivate func picturesURL() -> URL {
99+
84100 return FileManager
85101 .default
86102 .urls(for: .picturesDirectory,
87- in: .userDomainMask).last ?? URL(fileURLWithPath: NSHomeDirectory())
103+ in: .userDomainMask).last ?? FileManager.default.homeDirectoryForCurrentUser
88104 }
89105
90106 func desktopURL() -> URL {
107+
91108 return FileManager
92109 .default
93110 .urls(for: .desktopDirectory,
94- in: .userDomainMask).last ?? URL(fileURLWithPath: NSHomeDirectory())
111+ in: .userDomainMask).last ?? FileManager.default.homeDirectoryForCurrentUser
95112 }
--- a/GoInto/StatusItem.swift
+++ b/GoInto/StatusItem.swift
@@ -9,6 +9,7 @@
99 import Cocoa
1010
1111 protocol StatusItem {
12+
1213 var menuItem: NSMenuItem { get }
1314
1415 func enter(_ menu: NSMenu)
@@ -16,18 +17,25 @@ protocol StatusItem {
1617 }
1718
1819 extension StatusItem {
20+
1921 func enter(_ menu: NSMenu) {
22+
2023 if let currentMenu = menuItem.menu,
2124 currentMenu == menu {
25+
2226 return
2327 }
28+
2429 menu.insertItem(menuItem, at: 0)
2530 }
31+
2632 func remove() {
33+
2734 menuItem.menu?.removeItem(menuItem)
2835 }
2936 }
3037
3138 struct SeparatorItem: StatusItem {
39+
3240 let menuItem = NSMenuItem.separator()
3341 }
--- a/GoInto/UserDefaultsExtension.swift
+++ b/GoInto/UserDefaultsExtension.swift
@@ -9,22 +9,32 @@
99 import Foundation
1010
1111 extension UserDefaults {
12+
1213 func set(archived: Any?, forKey: String) {
14+
1315 if let object = archived {
16+
1417 let data = NSKeyedArchiver.archivedData(withRootObject: object)
1518 set(data, forKey: forKey)
19+
1620 } else {
21+
1722 set(nil, forKey: forKey)
1823 }
1924 }
25+
2026 func unarchiveObject(forKey: String) -> Any? {
27+
2128 if let data = object(forKey: forKey) as? Data {
29+
2230 return NSKeyedUnarchiver.unarchiveObject(with: data)
2331 }
32+
2433 return nil
2534 }
2635
2736 var recentURLs: [URL]? {
37+
2838 get { return unarchiveObject(forKey: "recentURLs") as? [URL] }
2939 set { set(archived: newValue, forKey: "recentURLs") }
3040 }
--- a/GoIntoTests/LimitedArrayTest.swift
+++ b/GoIntoTests/LimitedArrayTest.swift
@@ -13,6 +13,7 @@ import XCTest
1313 class LimitedArrayTest: XCTestCase {
1414
1515 func testExample() {
16+
1617 var limited = LimitedArray<Int>(3)
1718 XCTAssertEqual(limited.array, [])
1819
--- a/GoIntoTests/UserDefaultsTest.swift
+++ b/GoIntoTests/UserDefaultsTest.swift
@@ -11,19 +11,23 @@ import XCTest
1111 @testable import GoInto
1212
1313 class UserDefaultsTest: XCTestCase {
14+
1415 var originalURLs: [URL]? = []
1516
1617 override func setUp() {
18+
1719 super.setUp()
1820 originalURLs = UserDefaults.standard.recentURLs
1921 }
2022
2123 override func tearDown() {
24+
2225 UserDefaults.standard.recentURLs = originalURLs
2326 super.tearDown()
2427 }
2528
2629 func testRecentFolders() {
30+
2731 let urls = [URL(fileURLWithPath: "/System/"),
2832 URL(fileURLWithPath: "/Users/"),
2933 URL(fileURLWithPath: "/var/")]