Skip to content

Commit

Permalink
Add save & load
Browse files Browse the repository at this point in the history
New app icon
  • Loading branch information
LEOYoon-Tsaw committed Oct 16, 2021
1 parent 8fd2a11 commit d2aa714
Show file tree
Hide file tree
Showing 17 changed files with 300 additions and 212 deletions.
8 changes: 4 additions & 4 deletions ChineseTime.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 20;
CURRENT_PROJECT_VERSION = 22;
DEVELOPMENT_TEAM = 28HU5A7B46;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = ChineseTime/Info.plist;
Expand All @@ -311,7 +311,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.8;
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = "Yuncao-Liu.ChineseTime";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand All @@ -327,7 +327,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 20;
CURRENT_PROJECT_VERSION = 22;
DEVELOPMENT_TEAM = 28HU5A7B46;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = ChineseTime/Info.plist;
Expand All @@ -336,7 +336,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.8;
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = "Yuncao-Liu.ChineseTime";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand Down
72 changes: 70 additions & 2 deletions ChineseTime/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

func loadSave() {
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let managedContext = self.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Layout")
if let fetchedEntities = try? managedContext.fetch(fetchRequest),
let savedLayout = fetchedEntities.last?.value(forKey: "code") as? String {
Expand All @@ -32,6 +31,75 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

func saveLayout() -> String? {
let managedContext = self.persistentContainer.viewContext
managedContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
let layoutEntity = NSEntityDescription.entity(forEntityName: "Layout", in: managedContext)!
let savedLayout = NSManagedObject(entity: layoutEntity, insertInto: managedContext)
let encoded = WatchFace.currentInstance?._view.watchLayout.encode()
savedLayout.setValue(encoded, forKey: "code")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
return encoded
}

@IBAction func saveFile(_ sender: Any) {
let panel = NSSavePanel()
if let watchFace = WatchFace.currentInstance {
panel.level = watchFace.level
}
panel.title = NSLocalizedString("Select File", comment: "Save File")
panel.nameFieldStringValue = "new layout.txt"
panel.begin() {
result in
if result == .OK, let file = panel.url {
do {
let codeString = self.saveLayout()
try codeString?.data(using: .utf8)?.write(to: file, options: .atomicWrite)
} catch let error {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Save Failed", comment: "Save Failed")
alert.informativeText = error.localizedDescription
alert.runModal()
}
}
}
}

@IBAction func openFile(_ sender: Any) {
let panel = NSOpenPanel()
if let watchFace = WatchFace.currentInstance {
panel.level = watchFace.level
}
panel.allowsMultipleSelection = false
panel.canChooseDirectories = false
panel.allowedFileTypes = ["txt", "yaml"]
panel.title = NSLocalizedString("Select Layout File", comment: "Open File")
panel.message = NSLocalizedString("Warning: The current layout will be discarded!", comment: "Warning")
panel.begin {
result in
if result == .OK, let file = panel.url {
do {
let content = try String(contentsOf: file)
if let watchFace = WatchFace.currentInstance {
watchFace._view.watchLayout.update(from: content)
watchFace.updateSize(with: watchFace.frame)
watchFace._view.drawView()
ConfigurationViewController.currentInstance?.updateUI()
}
} catch let error {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Load Failed", comment: "Load Failed")
alert.informativeText = error.localizedDescription
alert.runModal()
}
}
}
}

func applicationDidFinishLaunching(_ aNotification: Notification) {
loadSave()
let preview = WatchFace(position: NSZeroRect)
Expand Down
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-1024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-257.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-33.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-513.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ChineseTime/Assets.xcassets/AppIcon.appiconset/icon-64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions ChineseTime/ChineseTime.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
58 changes: 37 additions & 21 deletions ChineseTime/Layout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ extension String {
guard !string.isEmpty else {
return nil
}
return Double(string) != nil ? CGFloat(Double(string)!) : nil
return Double(string).map {CGFloat($0)}
}
var boolValue: Bool? {
guard !self.isEmpty else {
Expand Down Expand Up @@ -200,6 +200,8 @@ class WatchLayout {
var innerColor: NSColor
var majorTickColor: NSColor
var minorTickColor: NSColor
var majorTickAlpha: CGFloat
var minorTickAlpha: CGFloat
var fontColor: NSColor
var centerFontColor: Gradient
var evenSolarTermTickColor: NSColor
Expand Down Expand Up @@ -245,8 +247,10 @@ class WatchLayout {
innerColorDark = NSColor(displayP3Red: 143/255, green: 115/255, blue: 140/255, alpha: 0.5)
majorTickColor = NSColor.black
majorTickColorDark = NSColor.black
majorTickAlpha = 1
minorTickColor = NSColor(displayP3Red: 22/255, green: 22/255, blue: 22/255, alpha: 1.0)
minorTickColorDark = NSColor(displayP3Red: 22/255, green: 22/255, blue: 22/255, alpha: 1.0)
minorTickAlpha = 1
fontColor = NSColor.white
fontColorDark = NSColor.white
evenSolarTermTickColor = NSColor.black
Expand Down Expand Up @@ -282,7 +286,9 @@ class WatchLayout {
encoded += "thirdRing: \(thirdRing.encode().replacingOccurrences(of: "\n", with: "{}"))\n"
encoded += "innerColor: \(innerColor.hexCode)\n"
encoded += "majorTickColor: \(majorTickColor.hexCode)\n"
encoded += "majorTickAlpha: \(majorTickAlpha)\n"
encoded += "minorTickColor: \(minorTickColor.hexCode)\n"
encoded += "minorTickAlpha: \(minorTickAlpha)\n"
encoded += "fontColor: \(fontColor.hexCode)\n"
encoded += "centerFontColor: \(centerFontColor.encode().replacingOccurrences(of: "\n", with: "{}"))\n"
encoded += "evenSolarTermTickColor: \(evenSolarTermTickColor.hexCode)\n"
Expand Down Expand Up @@ -329,7 +335,9 @@ class WatchLayout {
thirdRing = Gradient(from: values["thirdRing"]?.replacingOccurrences(of: "{}", with: "\n")) ?? thirdRing
innerColor = values["innerColor"]?.colorValue ?? innerColor
majorTickColor = values["majorTickColor"]?.colorValue ?? majorTickColor
majorTickAlpha = values["majorTickAlpha"]?.floatValue ?? majorTickAlpha
minorTickColor = values["minorTickColor"]?.colorValue ?? minorTickColor
minorTickAlpha = values["minorTickAlpha"]?.floatValue ?? minorTickAlpha
fontColor = values["fontColor"]?.colorValue ?? fontColor
centerFontColor = Gradient(from: values["centerFontColor"]?.replacingOccurrences(of: "{}", with: "\n")) ?? centerFontColor
evenSolarTermTickColor = values["evenSolarTermTickColor"]?.colorValue ?? evenSolarTermTickColor
Expand Down Expand Up @@ -388,6 +396,7 @@ class ColorWell: NSColorWell {
}

class ConfigurationViewController: NSViewController, NSWindowDelegate {
static var currentInstance: ConfigurationViewController? = nil
@IBOutlet weak var globalMonthToggle: NSSwitch!
@IBOutlet weak var datetimePicker: NSDatePicker!
@IBOutlet weak var currentTimeToggle: NSButton!
Expand All @@ -403,6 +412,10 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
@IBOutlet weak var innerTextGradientPicker: GradientSlider!
@IBOutlet weak var backAlphaValuePicker: NSSlider!
@IBOutlet weak var backAlphaValueLabel: NSTextField!
@IBOutlet weak var minorTickAlphaValuePicker: NSSlider!
@IBOutlet weak var minorTickAlphaValueLabel: NSTextField!
@IBOutlet weak var majorTickAlphaValuePicker: NSSlider!
@IBOutlet weak var majorTickAlphaValueLabel: NSTextField!
@IBOutlet weak var innerColorPicker: NSColorWell!
@IBOutlet weak var majorTickColorPicker: NSColorWell!
@IBOutlet weak var minorTickColorPicker: NSColorWell!
Expand Down Expand Up @@ -497,20 +510,6 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
return nil
}

func saveLayout() {
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
managedContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
let layoutEntity = NSEntityDescription.entity(forEntityName: "Layout", in: managedContext)!
let savedLayout = NSManagedObject(entity: layoutEntity, insertInto: managedContext)
savedLayout.setValue(WatchFace.currentInstance?._view.watchLayout.encode(), forKey: "code")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}

@IBAction func currentTimeToggled(_ sender: Any) {
view.window?.makeFirstResponder(datetimePicker)
datetimePicker.isEnabled = !readToggle(button: currentTimeToggle)
Expand Down Expand Up @@ -549,6 +548,14 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
view.window?.makeFirstResponder(backAlphaValuePicker)
backAlphaValueLabel.stringValue = String(format: "%1.2f", backAlphaValuePicker.doubleValue)
}
@IBAction func minorTickAlphaPickerChanged(_ sender: Any) {
view.window?.makeFirstResponder(minorTickAlphaValuePicker)
minorTickAlphaValueLabel.stringValue = String(format: "%1.2f", minorTickAlphaValuePicker.doubleValue)
}
@IBAction func majorTickAlphaPickerChanged(_ sender: Any) {
view.window?.makeFirstResponder(majorTickAlphaValuePicker)
majorTickAlphaValueLabel.stringValue = String(format: "%1.2f", majorTickAlphaValuePicker.doubleValue)
}
@IBAction func textFontFamilyChange(_ sender: Any) {
view.window?.makeFirstResponder(textFontFamilyPicker)
populateFontMember(textFontTraitPicker, inFamily: textFontFamilyPicker)
Expand Down Expand Up @@ -580,7 +587,8 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
}
@IBAction func ok(_ sender: Any) {
apply(sender)
saveLayout()
guard let delegate = NSApplication.shared.delegate as? AppDelegate else { return }
WatchFaceView.layoutTemplate = delegate.saveLayout()
self.view.window?.close()
}

Expand Down Expand Up @@ -614,12 +622,14 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
watchLayout.firstRing = firstRingGradientPicker.gradient
watchLayout.secondRing = secondRingGradientPicker.gradient
watchLayout.thirdRing = thirdRingGradientPicker.gradient
watchLayout.shadeAlpha = CGFloat(shadeAlphaValuePicker.doubleValue)
watchLayout.shadeAlpha = shadeAlphaValuePicker.doubleValue
watchLayout.centerFontColor = innerTextGradientPicker.gradient
watchLayout.backAlpha = CGFloat(backAlphaValuePicker.doubleValue)
watchLayout.backAlpha = backAlphaValuePicker.doubleValue
watchLayout.innerColor = innerColorPicker.color
watchLayout.majorTickColor = majorTickColorPicker.color
watchLayout.minorTickColor = minorTickColorPicker.color
watchLayout.minorTickAlpha = minorTickAlphaValueLabel.doubleValue
watchLayout.majorTickAlpha = majorTickAlphaValueLabel.doubleValue
watchLayout.fontColor = textColorPicker.color
watchLayout.oddSolarTermTickColor = oddStermTickColorPicker.color
watchLayout.evenSolarTermTickColor = evenStermTickColorPicker.color
Expand All @@ -640,9 +650,9 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
watchLayout.centerFont = readFont(family: centerTextFontFamilyPicker, style: centerTextFontTraitPicker) ?? watchLayout.centerFont
watchLayout.watchSize = NSMakeSize(max(0, widthPicker.doubleValue), max(0, heightPicker.doubleValue))
watchLayout.cornerRadiusRatio = max(0, min(1, cornerRadiusRatioPicker.doubleValue))
watchLayout.centerTextOffset = CGFloat(centerTextOffsetPicker.doubleValue)
watchLayout.horizontalTextOffset = CGFloat(textHorizontalOffsetPicker.doubleValue)
watchLayout.verticalTextOffset = CGFloat(textVerticalOffsetPicker.doubleValue)
watchLayout.centerTextOffset = centerTextOffsetPicker.doubleValue
watchLayout.horizontalTextOffset = textHorizontalOffsetPicker.doubleValue
watchLayout.verticalTextOffset = textVerticalOffsetPicker.doubleValue
}

func updateUI() {
Expand Down Expand Up @@ -673,6 +683,10 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {
innerColorPicker.color = watchLayout.innerColor
majorTickColorPicker.color = watchLayout.majorTickColor
minorTickColorPicker.color = watchLayout.minorTickColor
minorTickAlphaValuePicker.doubleValue = Double(watchLayout.minorTickAlpha)
minorTickAlphaValueLabel.stringValue = String(format: "%1.2f", watchLayout.minorTickAlpha)
majorTickAlphaValuePicker.doubleValue = Double(watchLayout.majorTickAlpha)
majorTickAlphaValueLabel.stringValue = String(format: "%1.2f", watchLayout.majorTickAlpha)
textColorPicker.color = watchLayout.fontColor
oddStermTickColorPicker.color = watchLayout.oddSolarTermTickColor
evenStermTickColorPicker.color = watchLayout.evenSolarTermTickColor
Expand Down Expand Up @@ -732,12 +746,14 @@ class ConfigurationViewController: NSViewController, NSWindowDelegate {


override func viewDidLoad() {
Self.currentInstance = self
super.viewDidLoad()
updateUI()
scrollToTop()
}

override func viewDidDisappear() {
Self.currentInstance = nil
NSColorPanel.shared.showsAlpha = false
NSColorPanel.shared.setTarget(nil)
NSColorPanel.shared.setAction(nil)
Expand Down
20 changes: 10 additions & 10 deletions ChineseTime/Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,8 @@ class ChineseCalendar {
leapLabel = ""
}
var month_name = leapLabel + Self.month_chinese[(i - leap) % 12]
if Self.alternativeMonthName[month_name] != nil {
month_name = Self.alternativeMonthName[month_name]!
if let alter = Self.alternativeMonthName[month_name] {
month_name = alter
}
months.append(month_name)
}
Expand Down Expand Up @@ -401,7 +401,7 @@ class ChineseCalendar {
}
}
var timeString: String {
let time_in_seconds = CGFloat(_calendar.startOfDay(for: _time).distance(to: _time))
let time_in_seconds = _calendar.startOfDay(for: _time).distance(to: _time)
let time_in_chinese_minutes = Int(time_in_seconds / 144)
let chinese_hour_index = time_in_chinese_minutes / 25
var residual = time_in_chinese_minutes - chinese_hour_index * 25
Expand All @@ -422,27 +422,27 @@ class ChineseCalendar {
return "\(chinese_hour)\(percent_day_chinese)\(residual_minutes_chinese)"
}
var evenSolarTerms: [CGFloat] {
var evenSolarTermsPositions = _evenSolarTerms.map { CGFloat(_year_start.distance(to: $0) / _year_length) }
var evenSolarTermsPositions = _evenSolarTerms.map { _year_start.distance(to: $0) / _year_length as CGFloat }
evenSolarTermsPositions = evenSolarTermsPositions.filter { ($0 < 1) && ($0 > 0) }
return [0] + evenSolarTermsPositions
}
var oddSolarTerms: [CGFloat] {
var oddSolarTermsPositions = _oddSolarTerms.map { CGFloat(_year_start.distance(to: $0) / _year_length) }
var oddSolarTermsPositions = _oddSolarTerms.map { _year_start.distance(to: $0) / _year_length as CGFloat }
oddSolarTermsPositions = oddSolarTermsPositions.filter { ($0 < 1) && ($0 > 0) }
return oddSolarTermsPositions
}
var monthDivides: [CGFloat] {
var monthSplitPositions: [CGFloat]
if Self.globalMonth {
monthSplitPositions = _moonEclipses.map { CGFloat(_year_start.distance(to: $0) / _year_length) }
monthSplitPositions = _moonEclipses.map { _year_start.distance(to: $0) / _year_length }
} else {
monthSplitPositions = _moonEclipses.map { CGFloat(_year_start.distance(to: _calendar.startOfDay(for: $0)) / _year_length) }
monthSplitPositions = _moonEclipses.map { _year_start.distance(to: _calendar.startOfDay(for: $0)) / _year_length }
}
monthSplitPositions = monthSplitPositions.filter { ($0 < 1) && ($0 > 0) }
return monthSplitPositions
}
var fullmoon: [CGFloat] {
_fullMoons.map { CGFloat(_year_start.distance(to: $0) / _year_length) }.filter { ($0 < 1) && ($0 > 0) }
_fullMoons.map { _year_start.distance(to: $0) / _year_length }.filter { ($0 < 1) && ($0 > 0) }
}
var monthNames: [String] {
return _monthNames
Expand All @@ -456,7 +456,7 @@ class ChineseCalendar {
}
}
var currentDayInYear: CGFloat {
CGFloat(_year_start.distance(to: _time) / _year_length)
_year_start.distance(to: _time) / _year_length
}
var currentDayInMonth: CGFloat {
if Self.globalMonth {
Expand All @@ -467,7 +467,7 @@ class ChineseCalendar {
}
}
var currentHour: CGFloat {
CGFloat(_calendar.startOfDay(for: _time).distance(to: _time)) / 3600
_calendar.startOfDay(for: _time).distance(to: _time) / 3600
}
var currentDay: Int {
_day + 1
Expand Down
Loading

0 comments on commit d2aa714

Please sign in to comment.