diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6675e6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +._* + +.DS_Store +.Trashes +.aux_LaTeX \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..a419028 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +# The MIT License (MIT) + +Copyright © 2022 Hans Schülein, Theme Creators + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/Padbury Clock Revived.xcodeproj/project.pbxproj b/Padbury Clock Revived.xcodeproj/project.pbxproj new file mode 100644 index 0000000..97a48fd --- /dev/null +++ b/Padbury Clock Revived.xcodeproj/project.pbxproj @@ -0,0 +1,340 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 3A93869525C9C7920031FA1E /* ConfigureSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3AA5BF7725C9B470005B39FE /* ConfigureSheet.xib */; }; + 3A9386A225CAE6D30031FA1E /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A9386A125CAE6D30031FA1E /* Preferences.swift */; }; + 3A93924925C9BE4700FC3E93 /* ConfigureSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A93924825C9BE4700FC3E93 /* ConfigureSheetController.swift */; }; + 3AA5BF6B25C98A84005B39FE /* ClockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA5BF6A25C98A84005B39FE /* ClockView.swift */; }; + 3AA5BF7425C9B160005B39FE /* thumbnail@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AA5BF7225C9B160005B39FE /* thumbnail@2x.png */; }; + 3AA5BF7525C9B160005B39FE /* thumbnail.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AA5BF7325C9B160005B39FE /* thumbnail.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3A9386A125CAE6D30031FA1E /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; + 3A93924825C9BE4700FC3E93 /* ConfigureSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigureSheetController.swift; sourceTree = ""; }; + 3AA5BF5A25C98A31005B39FE /* Padbury Clock Revived.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Padbury Clock Revived.saver"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3AA5BF6125C98A31005B39FE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3AA5BF6A25C98A84005B39FE /* ClockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClockView.swift; sourceTree = ""; }; + 3AA5BF7225C9B160005B39FE /* thumbnail@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumbnail@2x.png"; sourceTree = ""; }; + 3AA5BF7325C9B160005B39FE /* thumbnail.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumbnail.png; sourceTree = ""; }; + 3AA5BF7725C9B470005B39FE /* ConfigureSheet.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ConfigureSheet.xib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3AA5BF5725C98A31005B39FE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3AA5BF5025C98A31005B39FE = { + isa = PBXGroup; + children = ( + 3AA5BF5C25C98A31005B39FE /* Padbury Clock Revived */, + 3AA5BF5B25C98A31005B39FE /* Products */, + ); + sourceTree = ""; + }; + 3AA5BF5B25C98A31005B39FE /* Products */ = { + isa = PBXGroup; + children = ( + 3AA5BF5A25C98A31005B39FE /* Padbury Clock Revived.saver */, + ); + name = Products; + sourceTree = ""; + }; + 3AA5BF5C25C98A31005B39FE /* Padbury Clock Revived */ = { + isa = PBXGroup; + children = ( + 3AA5BF7725C9B470005B39FE /* ConfigureSheet.xib */, + 3AA5BF6125C98A31005B39FE /* Info.plist */, + 3AA5BF6A25C98A84005B39FE /* ClockView.swift */, + 3A93924825C9BE4700FC3E93 /* ConfigureSheetController.swift */, + 3A9386A125CAE6D30031FA1E /* Preferences.swift */, + 3AA5BF7325C9B160005B39FE /* thumbnail.png */, + 3AA5BF7225C9B160005B39FE /* thumbnail@2x.png */, + ); + path = "Padbury Clock Revived"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3AA5BF5525C98A31005B39FE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3AA5BF5925C98A31005B39FE /* Padbury Clock Revived */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3AA5BF6425C98A31005B39FE /* Build configuration list for PBXNativeTarget "Padbury Clock Revived" */; + buildPhases = ( + 3AA5BF5525C98A31005B39FE /* Headers */, + 3AA5BF5625C98A31005B39FE /* Sources */, + 3AA5BF5725C98A31005B39FE /* Frameworks */, + 3AA5BF5825C98A31005B39FE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Padbury Clock Revived"; + productName = "Padbury Clock Revived"; + productReference = 3AA5BF5A25C98A31005B39FE /* Padbury Clock Revived.saver */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3AA5BF5125C98A31005B39FE /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1240; + TargetAttributes = { + 3AA5BF5925C98A31005B39FE = { + CreatedOnToolsVersion = 12.4; + LastSwiftMigration = 1240; + }; + }; + }; + buildConfigurationList = 3AA5BF5425C98A31005B39FE /* Build configuration list for PBXProject "Padbury Clock Revived" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3AA5BF5025C98A31005B39FE; + productRefGroup = 3AA5BF5B25C98A31005B39FE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3AA5BF5925C98A31005B39FE /* Padbury Clock Revived */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3AA5BF5825C98A31005B39FE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3AA5BF7525C9B160005B39FE /* thumbnail.png in Resources */, + 3AA5BF7425C9B160005B39FE /* thumbnail@2x.png in Resources */, + 3A93869525C9C7920031FA1E /* ConfigureSheet.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3AA5BF5625C98A31005B39FE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3AA5BF6B25C98A84005B39FE /* ClockView.swift in Sources */, + 3A93924925C9BE4700FC3E93 /* ConfigureSheetController.swift in Sources */, + 3A9386A225CAE6D30031FA1E /* Preferences.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 3AA5BF6225C98A31005B39FE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 3AA5BF6325C98A31005B39FE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; + 3AA5BF6525C98A31005B39FE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = VW549R3EEQ; + INFOPLIST_FILE = "Padbury Clock Revived/Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Screen Savers"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.hans.Padbury-Clock-Revived"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + WRAPPER_EXTENSION = saver; + }; + name = Debug; + }; + 3AA5BF6625C98A31005B39FE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = VW549R3EEQ; + INFOPLIST_FILE = "Padbury Clock Revived/Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Screen Savers"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.hans.Padbury-Clock-Revived"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + WRAPPER_EXTENSION = saver; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3AA5BF5425C98A31005B39FE /* Build configuration list for PBXProject "Padbury Clock Revived" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3AA5BF6225C98A31005B39FE /* Debug */, + 3AA5BF6325C98A31005B39FE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3AA5BF6425C98A31005B39FE /* Build configuration list for PBXNativeTarget "Padbury Clock Revived" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3AA5BF6525C98A31005B39FE /* Debug */, + 3AA5BF6625C98A31005B39FE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3AA5BF5125C98A31005B39FE /* Project object */; +} diff --git a/Padbury Clock Revived.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Padbury Clock Revived.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Padbury Clock Revived.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Padbury Clock Revived.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Padbury Clock Revived.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Padbury Clock Revived.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Padbury Clock Revived.xcodeproj/project.xcworkspace/xcuserdata/hans.xcuserdatad/UserInterfaceState.xcuserstate b/Padbury Clock Revived.xcodeproj/project.xcworkspace/xcuserdata/hans.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..b647ddb Binary files /dev/null and b/Padbury Clock Revived.xcodeproj/project.xcworkspace/xcuserdata/hans.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Padbury Clock Revived.xcodeproj/xcuserdata/hans.xcuserdatad/xcschemes/xcschememanagement.plist b/Padbury Clock Revived.xcodeproj/xcuserdata/hans.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..2f01122 --- /dev/null +++ b/Padbury Clock Revived.xcodeproj/xcuserdata/hans.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Padbury Clock Revived.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Padbury Clock Revived/ClockView.swift b/Padbury Clock Revived/ClockView.swift new file mode 100644 index 0000000..95a1914 --- /dev/null +++ b/Padbury Clock Revived/ClockView.swift @@ -0,0 +1,131 @@ +// +// ClockView.swift +// Padbury Clock Revived +// +// Created by Hans Schülein on 2.2.2021. +// + +import Cocoa +import ScreenSaver + +final class ClockView: ScreenSaverView { + lazy var sheetController: ConfigureSheetController = ConfigureSheetController() + var preferences: Preferences = Preferences() + + static var shared: ClockView? = nil + + override init?(frame: NSRect, isPreview: Bool) { + super.init(frame: frame, isPreview: isPreview) + ClockView.shared = self + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + ClockView.shared = self + } + + // MARK: - Configuration + + var hasSetup = false + + var fontSize: CGFloat = 0 + var vOffset: CGFloat = 0 + + var backgroundColor: NSColor = .red + var foregroundColor: NSColor = .red + + var dateFormatter: DateFormatter = DateFormatter() + var attributes: [NSAttributedString.Key: Any] = [:] + + func setup(force: Bool = false) { + if force || !hasSetup { + hasSetup = true + + if preferences.darkTheme { + backgroundColor = .black + foregroundColor = .white + } else { + backgroundColor = .white + foregroundColor = .black + } + + let separator = preferences.showTimeSeparators ? ":" : " " + + let hour = preferences.useAmPm ? "h" : "HH" + let minute = "\(separator)mm" + let second = preferences.showSeconds ? "\(separator)ss" : "" + let suffix = preferences.useAmPm ? " a" : "" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + dateFormatter.dateFormat = "\(hour)\(minute)\(second)\(suffix)" + dateFormatter.amSymbol = "AM" + dateFormatter.pmSymbol = "PM" + + fontSize = 0.2 * bounds.width + + // TODO: dynamically determine value. I don't know how though + // 0.5: align center of target rect with center of screen + // 0.15: offset so font is visually centered + vOffset = fontSize * 0.5 - 0.15 * fontSize + + let font: NSFont + if preferences.useSystemFont { + font = NSFont.monospacedDigitSystemFont(ofSize: fontSize, weight: preferences.fontWeight) + } else { + let fontName: String + switch preferences.fontWeight { + case .ultraLight: fontName = "Helvetica Neue UltraLight" + case .thin: fontName = "Helvetica Neue Thin" + case .light: fontName = "Helvetica Neue Light" + case .regular: fontName = "Helvetica Neue" + case .medium: fontName = "Helvetica Neue Medium" + case .bold: fontName = "Helvetica Neue Bold" + default: fontName = "Helvetica Neue" + } + // not supported: + // semibold, heavy, black + font = NSFont(name: fontName, size: fontSize)! + } + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.alignment = .center + attributes = [ + .font : font, + .foregroundColor: foregroundColor, + .paragraphStyle: paragraphStyle, + ] + } + } + + // MARK: - Drawing + + override func animateOneFrame() { + super.animateOneFrame() + setNeedsDisplay(bounds) + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + setup() + + backgroundColor.setFill() + bounds.fill() + + let targetRect = NSRect(x: 0, y: bounds.height * 0.5 - vOffset, width: bounds.width, height: fontSize) + +// NSColor.red.setFill() +// targetRect.fill() + + let time = NSString(string: dateFormatter.string(from: Date())) + time.draw(in: targetRect, withAttributes: attributes) + } + + // MARK: - Preferences + + override var hasConfigureSheet: Bool { + return true + } + + override var configureSheet: NSWindow? { + return sheetController.window + } +} diff --git a/Padbury Clock Revived/ConfigureSheet.xib b/Padbury Clock Revived/ConfigureSheet.xib new file mode 100644 index 0000000..305f4fb --- /dev/null +++ b/Padbury Clock Revived/ConfigureSheet.xib @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Padbury Clock Revived/ConfigureSheetController.swift b/Padbury Clock Revived/ConfigureSheetController.swift new file mode 100644 index 0000000..4266702 --- /dev/null +++ b/Padbury Clock Revived/ConfigureSheetController.swift @@ -0,0 +1,70 @@ +// +// ConfigureSheetController.swift +// Padbury Clock Revived +// +// Created by Hans Schülein on 2.2.2021. +// +// + +import Cocoa + +class ConfigureSheetController: NSObject { + + @IBOutlet var window: NSWindow? + + @IBOutlet var darkThemeCheckbox: NSButton! + @IBOutlet var twentyfourHoursCheckbox: NSButton! + @IBOutlet var showSecondsCheckbox: NSButton! + @IBOutlet var showTimeSeparatorsCheckbox: NSButton! + @IBOutlet var useSystemFontCheckbox: NSButton! + @IBOutlet var fontWeightSelector: NSPopUpButton! + + override init() { + super.init() + let myBundle = Bundle(for: ConfigureSheetController.self) + myBundle.loadNibNamed("ConfigureSheet", owner: self, topLevelObjects: nil) + } + + override func awakeFromNib() { + super.awakeFromNib() + setup() + } + + func setup() { + if let preferences = Preferences.shared { + darkThemeCheckbox.state = preferences.darkTheme ? .on : .off + twentyfourHoursCheckbox.state = preferences.useAmPm ? .off : .on + showSecondsCheckbox.state = preferences.showSeconds ? .on : .off + showTimeSeparatorsCheckbox.state = preferences.showTimeSeparators ? .on : .off + useSystemFontCheckbox.state = preferences.useSystemFont ? .on : .off + + fontWeightSelector.removeAllItems() + let availableFontWeights: [NSFont.Weight] = preferences.useSystemFont ? + [.ultraLight, .thin, .light, .regular, .medium, .semibold, .bold, .heavy, .black] : + [.ultraLight, .thin, .light, .regular, .medium, .bold] + for fontWeight in availableFontWeights { + fontWeightSelector.addItem(withTitle: fontWeight.name) + } + fontWeightSelector.selectItem(at: availableFontWeights.firstIndex(of: preferences.fontWeight) ?? 0) + preferences.fontWeight = NSFont.Weight.from(name: fontWeightSelector.selectedItem?.title ?? "") + ClockView.shared?.setup(force: true) + } + } + + @IBAction func toggledCheckbox(_ sender: NSObject) { + if let preferences = Preferences.shared { + preferences.darkTheme = darkThemeCheckbox.state == .on + preferences.useAmPm = twentyfourHoursCheckbox.state == .off + preferences.showSeconds = showSecondsCheckbox.state == .on + preferences.showTimeSeparators = showTimeSeparatorsCheckbox.state == .on + preferences.useSystemFont = useSystemFontCheckbox.state == .on + preferences.fontWeight = NSFont.Weight.from(name: fontWeightSelector.selectedItem?.title ?? "") + + self.setup() + } + } + + @IBAction func closeConfigureSheet(_ sender: AnyObject) { + window?.sheetParent?.endSheet(window!) + } +} diff --git a/Padbury Clock Revived/Info.plist b/Padbury Clock Revived/Info.plist new file mode 100644 index 0000000..9ea7548 --- /dev/null +++ b/Padbury Clock Revived/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSPrincipalClass + ClockView + + diff --git a/Padbury Clock Revived/Preferences.swift b/Padbury Clock Revived/Preferences.swift new file mode 100644 index 0000000..e4561bc --- /dev/null +++ b/Padbury Clock Revived/Preferences.swift @@ -0,0 +1,88 @@ +// +// Preferences.swift +// Padbury Clock Revived +// +// Created by Hans Schülein on 3.2.2021. +// + +import Foundation +import ScreenSaver + +class Preferences: NSObject { + + static var shared: Preferences? = nil + + private let defaults: UserDefaults + + override init() { + defaults = ScreenSaverDefaults(forModuleWithName: Bundle(for: Preferences.self).bundleIdentifier!)! + super.init() + Preferences.shared = self + } + + var useSystemFont: Bool { + get { return (defaults.value(forKey: "UseSystemFont") as? Bool) ?? true } + set { defaults.setValue(newValue, forKey: "UseSystemFont") } + } + + var darkTheme: Bool { + get { return (defaults.value(forKey: "DarkTheme") as? Bool) ?? true } + set { defaults.setValue(newValue, forKey: "DarkTheme") } + } + + var useAmPm: Bool { + get { return !((defaults.value(forKey: "24h") as? Bool) ?? true) } + set { defaults.setValue(!newValue, forKey: "24h") } + } + + var showTimeSeparators: Bool { + get { return (defaults.value(forKey: "showTimeSeparators") as? Bool) ?? false } + set { defaults.setValue(newValue, forKey: "showTimeSeparators") } + } + + var fontWeight: NSFont.Weight { + get { return NSFont.Weight.from(name: (defaults.value(forKey: "fontWeight") as? String) ?? "Ultra Light") } + set { defaults.setValue(newValue.name, forKey: "fontWeight") } + } + + var showSeconds: Bool { + get { return (defaults.value(forKey: "ShowSeconds") as? Bool) ?? true } + set { defaults.setValue(newValue, forKey: "ShowSeconds") } + } +} + +// MARK: - NSFont.Weight Names + +extension NSFont.Weight { + var name: String { + get { + switch self { + case .ultraLight: return "Ultra Light" + case .thin: return "Thin" + case .light: return "Light" + case .regular: return "Regular" + case .medium: return "Medium" + case .semibold: return "Semibold" + case .bold: return "Bold" + case .heavy: return "Heavy" + case .black: return "Black" + default: return "Regular" + } + } + } + + static func from(name: String) -> NSFont.Weight { + switch name { + case "Ultra Light": return .ultraLight + case "Thin": return .thin + case "Light": return .light + case "Regular": return .regular + case "Medium": return .medium + case "Semibold": return .semibold + case "Bold": return .bold + case "Heavy": return .heavy + case "Black": return .black + default: return .regular + } + } +} diff --git a/Padbury Clock Revived/thumbnail.png b/Padbury Clock Revived/thumbnail.png new file mode 100644 index 0000000..d80d12e Binary files /dev/null and b/Padbury Clock Revived/thumbnail.png differ diff --git a/Padbury Clock Revived/thumbnail@2x.png b/Padbury Clock Revived/thumbnail@2x.png new file mode 100644 index 0000000..8b00e2a Binary files /dev/null and b/Padbury Clock Revived/thumbnail@2x.png differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..b56e36f --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Padbury Clock Revived + +![screenshot](screenshots/screenshot-0.png) + +The [Padbury Clock](https://padbury.app) is a minimalist screensaver created by [Robert Padbury](https://twitter.com/Padbury). +It has not been updated in ages and actually broke for me during the Big Sur beta cycle (although that issue resolved itself). +At that point I decided to recreate it. +This new version retains most of the settings from the original (if you require the red mode feel free to add a pull request) and ads a new font family and font weight selection system. +The original screensaver used Helvetia Neue Ultra Light. +With the new version you will also be able to select San Francisco, Apple's new system font as the font used. + +![screenshot](screenshots/screenshot-1.png)![screenshot](screenshots/screenshot-2.png) + +![settings](screenshots/settings.png) + +## License + +This project is licensed under the [MIT license](LICENSE.md). + +I could not get in touch with Robert Padbury about the intellectual property rights for his original screensaver. \ No newline at end of file diff --git a/screenshots/screenshot-0.png b/screenshots/screenshot-0.png new file mode 100644 index 0000000..3beaa21 Binary files /dev/null and b/screenshots/screenshot-0.png differ diff --git a/screenshots/screenshot-1.png b/screenshots/screenshot-1.png new file mode 100644 index 0000000..0a198d9 Binary files /dev/null and b/screenshots/screenshot-1.png differ diff --git a/screenshots/screenshot-2.png b/screenshots/screenshot-2.png new file mode 100644 index 0000000..fcc5748 Binary files /dev/null and b/screenshots/screenshot-2.png differ diff --git a/screenshots/settings.png b/screenshots/settings.png new file mode 100644 index 0000000..7773193 Binary files /dev/null and b/screenshots/settings.png differ