From bd6228efcb7c4bfdc65c816cfb1177e9f2de2208 Mon Sep 17 00:00:00 2001 From: Abhishek Banthia Date: Thu, 5 Nov 2015 18:44:44 -0500 Subject: [PATCH] Initial Commit --- Clocker.xcodeproj/project.pbxproj | 401 +++++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 67903 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 + .../xcschemes/Clocker.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + Clocker/ApplicationDelegate.h | 39 ++ Clocker/ApplicationDelegate.m | 97 +++ Clocker/BackgroundView.h | 40 ++ Clocker/BackgroundView.m | 144 ++++ Clocker/Clock.jpeg | Bin 0 -> 1149 bytes Clocker/Clocker-Info.plist | 38 + Clocker/Clocker-Prefix.pch | 9 + Clocker/ColoredButton.h | 36 + Clocker/ColoredButton.m | 61 ++ Clocker/MenubarController.h | 44 ++ Clocker/MenubarController.m | 52 ++ Clocker/Panel.h | 30 + Clocker/Panel.m | 54 ++ Clocker/Panel.xib | 211 ++++++ Clocker/PanelController.h | 78 +++ Clocker/PanelController.m | 433 ++++++++++++ Clocker/PowerIcon.png | Bin 0 -> 17462 bytes Clocker/PreferencesWindow.xib | 356 ++++++++++ Clocker/PreferencesWindowController.h | 46 ++ Clocker/PreferencesWindowController.m | 412 +++++++++++ Clocker/Status.png | Bin 0 -> 3487 bytes Clocker/Status@2x.png | Bin 0 -> 1502 bytes Clocker/StatusHighlighted.png | Bin 0 -> 389 bytes Clocker/StatusHighlighted@2x.png | Bin 0 -> 1387 bytes Clocker/StatusItemView.h | 49 ++ Clocker/StatusItemView.m | 135 ++++ Clocker/en.lproj/MainMenu.xib | 652 ++++++++++++++++++ Clocker/main.m | 14 + 34 files changed, 3556 insertions(+) create mode 100755 Clocker.xcodeproj/project.pbxproj create mode 100644 Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/Clocker.xcscheme create mode 100644 Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100755 Clocker/ApplicationDelegate.h create mode 100755 Clocker/ApplicationDelegate.m create mode 100755 Clocker/BackgroundView.h create mode 100755 Clocker/BackgroundView.m create mode 100644 Clocker/Clock.jpeg create mode 100755 Clocker/Clocker-Info.plist create mode 100755 Clocker/Clocker-Prefix.pch create mode 100644 Clocker/ColoredButton.h create mode 100644 Clocker/ColoredButton.m create mode 100755 Clocker/MenubarController.h create mode 100755 Clocker/MenubarController.m create mode 100755 Clocker/Panel.h create mode 100755 Clocker/Panel.m create mode 100755 Clocker/Panel.xib create mode 100755 Clocker/PanelController.h create mode 100755 Clocker/PanelController.m create mode 100644 Clocker/PowerIcon.png create mode 100644 Clocker/PreferencesWindow.xib create mode 100644 Clocker/PreferencesWindowController.h create mode 100644 Clocker/PreferencesWindowController.m create mode 100755 Clocker/Status.png create mode 100755 Clocker/Status@2x.png create mode 100755 Clocker/StatusHighlighted.png create mode 100755 Clocker/StatusHighlighted@2x.png create mode 100755 Clocker/StatusItemView.h create mode 100755 Clocker/StatusItemView.m create mode 100755 Clocker/en.lproj/MainMenu.xib create mode 100755 Clocker/main.m diff --git a/Clocker.xcodeproj/project.pbxproj b/Clocker.xcodeproj/project.pbxproj new file mode 100755 index 0000000..e081e8b --- /dev/null +++ b/Clocker.xcodeproj/project.pbxproj @@ -0,0 +1,401 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9A8605AE1BEC148400A810A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605AD1BEC148400A810A4 /* main.m */; }; + 9A8605B31BEC14A600A810A4 /* ColoredButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605B21BEC14A600A810A4 /* ColoredButton.m */; }; + 9A8605B61BEC14BE00A810A4 /* MenubarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605B41BEC14BE00A810A4 /* MenubarController.m */; }; + 9A8605B71BEC14BE00A810A4 /* ApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605B51BEC14BE00A810A4 /* ApplicationDelegate.m */; }; + 9A8605BA1BEC14DC00A810A4 /* StatusItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605B81BEC14DC00A810A4 /* StatusItemView.m */; }; + 9A8605BB1BEC14DC00A810A4 /* PanelController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605B91BEC14DC00A810A4 /* PanelController.m */; }; + 9A8605BF1BEC14F600A810A4 /* BackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605BC1BEC14F600A810A4 /* BackgroundView.m */; }; + 9A8605C01BEC14F600A810A4 /* Panel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605BD1BEC14F600A810A4 /* Panel.m */; }; + 9A8605C11BEC14F600A810A4 /* PreferencesWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605BE1BEC14F600A810A4 /* PreferencesWindowController.m */; }; + 9A8605D41BEC155B00A810A4 /* Clock.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605C21BEC155B00A810A4 /* Clock.jpeg */; settings = {ASSET_TAGS = (); }; }; + 9A8605D51BEC155B00A810A4 /* Clocker-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605C31BEC155B00A810A4 /* Clocker-Info.plist */; settings = {ASSET_TAGS = (); }; }; + 9A8605D61BEC155B00A810A4 /* Panel.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605CD1BEC155B00A810A4 /* Panel.xib */; settings = {ASSET_TAGS = (); }; }; + 9A8605D71BEC155B00A810A4 /* PreferencesWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605CE1BEC155B00A810A4 /* PreferencesWindow.xib */; settings = {ASSET_TAGS = (); }; }; + 9A8605D81BEC155B00A810A4 /* PowerIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605CF1BEC155B00A810A4 /* PowerIcon.png */; settings = {ASSET_TAGS = (); }; }; + 9A8605D91BEC155B00A810A4 /* Status.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605D01BEC155B00A810A4 /* Status.png */; settings = {ASSET_TAGS = (); }; }; + 9A8605DA1BEC155B00A810A4 /* Status@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605D11BEC155B00A810A4 /* Status@2x.png */; settings = {ASSET_TAGS = (); }; }; + 9A8605DB1BEC155B00A810A4 /* StatusHighlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605D21BEC155B00A810A4 /* StatusHighlighted.png */; settings = {ASSET_TAGS = (); }; }; + 9A8605DC1BEC155B00A810A4 /* StatusHighlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605D31BEC155B00A810A4 /* StatusHighlighted@2x.png */; settings = {ASSET_TAGS = (); }; }; + 9A8605DF1BEC15C400A810A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A8605DD1BEC15C400A810A4 /* MainMenu.xib */; settings = {ASSET_TAGS = (); }; }; + DD4F7C0913C30F9F00825C6E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD4F7C0813C30F9F00825C6E /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9A8605AD1BEC148400A810A4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Clocker/main.m; sourceTree = ""; }; + 9A8605B21BEC14A600A810A4 /* ColoredButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ColoredButton.m; path = Clocker/ColoredButton.m; sourceTree = ""; }; + 9A8605B41BEC14BE00A810A4 /* MenubarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MenubarController.m; path = Clocker/MenubarController.m; sourceTree = ""; }; + 9A8605B51BEC14BE00A810A4 /* ApplicationDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ApplicationDelegate.m; path = Clocker/ApplicationDelegate.m; sourceTree = ""; }; + 9A8605B81BEC14DC00A810A4 /* StatusItemView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = StatusItemView.m; path = Clocker/StatusItemView.m; sourceTree = ""; }; + 9A8605B91BEC14DC00A810A4 /* PanelController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PanelController.m; path = Clocker/PanelController.m; sourceTree = ""; }; + 9A8605BC1BEC14F600A810A4 /* BackgroundView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BackgroundView.m; path = Clocker/BackgroundView.m; sourceTree = ""; }; + 9A8605BD1BEC14F600A810A4 /* Panel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Panel.m; path = Clocker/Panel.m; sourceTree = ""; }; + 9A8605BE1BEC14F600A810A4 /* PreferencesWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PreferencesWindowController.m; path = Clocker/PreferencesWindowController.m; sourceTree = ""; }; + 9A8605C21BEC155B00A810A4 /* Clock.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = Clock.jpeg; path = Clocker/Clock.jpeg; sourceTree = ""; }; + 9A8605C31BEC155B00A810A4 /* Clocker-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Clocker-Info.plist"; path = "Clocker/Clocker-Info.plist"; sourceTree = ""; }; + 9A8605C41BEC155B00A810A4 /* BackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BackgroundView.h; path = Clocker/BackgroundView.h; sourceTree = ""; }; + 9A8605C51BEC155B00A810A4 /* StatusItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatusItemView.h; path = Clocker/StatusItemView.h; sourceTree = ""; }; + 9A8605C61BEC155B00A810A4 /* Panel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Panel.h; path = Clocker/Panel.h; sourceTree = ""; }; + 9A8605C71BEC155B00A810A4 /* PreferencesWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreferencesWindowController.h; path = Clocker/PreferencesWindowController.h; sourceTree = ""; }; + 9A8605C81BEC155B00A810A4 /* PanelController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PanelController.h; path = Clocker/PanelController.h; sourceTree = ""; }; + 9A8605C91BEC155B00A810A4 /* MenubarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenubarController.h; path = Clocker/MenubarController.h; sourceTree = ""; }; + 9A8605CA1BEC155B00A810A4 /* ApplicationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ApplicationDelegate.h; path = Clocker/ApplicationDelegate.h; sourceTree = ""; }; + 9A8605CB1BEC155B00A810A4 /* ColoredButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColoredButton.h; path = Clocker/ColoredButton.h; sourceTree = ""; }; + 9A8605CC1BEC155B00A810A4 /* Clocker-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Clocker-Prefix.pch"; path = "Clocker/Clocker-Prefix.pch"; sourceTree = ""; }; + 9A8605CD1BEC155B00A810A4 /* Panel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = Panel.xib; path = Clocker/Panel.xib; sourceTree = ""; }; + 9A8605CE1BEC155B00A810A4 /* PreferencesWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = PreferencesWindow.xib; path = Clocker/PreferencesWindow.xib; sourceTree = ""; }; + 9A8605CF1BEC155B00A810A4 /* PowerIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = PowerIcon.png; path = Clocker/PowerIcon.png; sourceTree = ""; }; + 9A8605D01BEC155B00A810A4 /* Status.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Status.png; path = Clocker/Status.png; sourceTree = ""; }; + 9A8605D11BEC155B00A810A4 /* Status@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Status@2x.png"; path = "Clocker/Status@2x.png"; sourceTree = ""; }; + 9A8605D21BEC155B00A810A4 /* StatusHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StatusHighlighted.png; path = Clocker/StatusHighlighted.png; sourceTree = ""; }; + 9A8605D31BEC155B00A810A4 /* StatusHighlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "StatusHighlighted@2x.png"; path = "Clocker/StatusHighlighted@2x.png"; sourceTree = ""; }; + 9A8605DE1BEC15C400A810A4 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = Clocker/en.lproj/MainMenu.xib; sourceTree = ""; }; + DD4F7C0413C30F9F00825C6E /* Clocker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Clocker.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DD4F7C0813C30F9F00825C6E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + DD4F7C0B13C30F9F00825C6E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + DD4F7C0C13C30F9F00825C6E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + DD4F7C0D13C30F9F00825C6E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DD4F7C0113C30F9F00825C6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DD4F7C0913C30F9F00825C6E /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9A8605E01BEC15F400A810A4 /* XIB */ = { + isa = PBXGroup; + children = ( + 9A8605DD1BEC15C400A810A4 /* MainMenu.xib */, + 9A8605CD1BEC155B00A810A4 /* Panel.xib */, + 9A8605CE1BEC155B00A810A4 /* PreferencesWindow.xib */, + ); + name = XIB; + sourceTree = ""; + }; + 9A8605E11BEC160700A810A4 /* Images */ = { + isa = PBXGroup; + children = ( + 9A8605C21BEC155B00A810A4 /* Clock.jpeg */, + 9A8605CF1BEC155B00A810A4 /* PowerIcon.png */, + 9A8605D01BEC155B00A810A4 /* Status.png */, + 9A8605D11BEC155B00A810A4 /* Status@2x.png */, + 9A8605D21BEC155B00A810A4 /* StatusHighlighted.png */, + 9A8605D31BEC155B00A810A4 /* StatusHighlighted@2x.png */, + ); + name = Images; + sourceTree = ""; + }; + 9A8605E21BEC161300A810A4 /* Superclass */ = { + isa = PBXGroup; + children = ( + 9A8605C61BEC155B00A810A4 /* Panel.h */, + 9A8605BD1BEC14F600A810A4 /* Panel.m */, + 9A8605CB1BEC155B00A810A4 /* ColoredButton.h */, + 9A8605B21BEC14A600A810A4 /* ColoredButton.m */, + ); + name = Superclass; + sourceTree = ""; + }; + 9A8605E31BEC163100A810A4 /* Views */ = { + isa = PBXGroup; + children = ( + 9A8605C41BEC155B00A810A4 /* BackgroundView.h */, + 9A8605C51BEC155B00A810A4 /* StatusItemView.h */, + 9A8605BC1BEC14F600A810A4 /* BackgroundView.m */, + 9A8605B81BEC14DC00A810A4 /* StatusItemView.m */, + ); + name = Views; + sourceTree = ""; + }; + 9A8605E41BEC164C00A810A4 /* Main */ = { + isa = PBXGroup; + children = ( + 9A8605C31BEC155B00A810A4 /* Clocker-Info.plist */, + 9A8605CC1BEC155B00A810A4 /* Clocker-Prefix.pch */, + 9A8605AD1BEC148400A810A4 /* main.m */, + ); + name = Main; + sourceTree = ""; + }; + 9A8605E51BEC165400A810A4 /* Controllers */ = { + isa = PBXGroup; + children = ( + 9A8605CA1BEC155B00A810A4 /* ApplicationDelegate.h */, + 9A8605B51BEC14BE00A810A4 /* ApplicationDelegate.m */, + 9A8605C91BEC155B00A810A4 /* MenubarController.h */, + 9A8605B41BEC14BE00A810A4 /* MenubarController.m */, + 9A8605C81BEC155B00A810A4 /* PanelController.h */, + 9A8605B91BEC14DC00A810A4 /* PanelController.m */, + 9A8605C71BEC155B00A810A4 /* PreferencesWindowController.h */, + 9A8605BE1BEC14F600A810A4 /* PreferencesWindowController.m */, + ); + name = Controllers; + sourceTree = ""; + }; + DD4F7BF913C30F9F00825C6E = { + isa = PBXGroup; + children = ( + 9A8605E01BEC15F400A810A4 /* XIB */, + 9A8605E11BEC160700A810A4 /* Images */, + 9A8605E41BEC164C00A810A4 /* Main */, + 9A8605E31BEC163100A810A4 /* Views */, + 9A8605E51BEC165400A810A4 /* Controllers */, + 9A8605E21BEC161300A810A4 /* Superclass */, + DD4F7C0713C30F9F00825C6E /* Frameworks */, + DD4F7C0513C30F9F00825C6E /* Products */, + ); + sourceTree = ""; + }; + DD4F7C0513C30F9F00825C6E /* Products */ = { + isa = PBXGroup; + children = ( + DD4F7C0413C30F9F00825C6E /* Clocker.app */, + ); + name = Products; + sourceTree = ""; + }; + DD4F7C0713C30F9F00825C6E /* Frameworks */ = { + isa = PBXGroup; + children = ( + DD4F7C0B13C30F9F00825C6E /* AppKit.framework */, + DD4F7C0C13C30F9F00825C6E /* CoreData.framework */, + DD4F7C0D13C30F9F00825C6E /* Foundation.framework */, + DD4F7C0813C30F9F00825C6E /* Cocoa.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DD4F7C0313C30F9F00825C6E /* Clocker */ = { + isa = PBXNativeTarget; + buildConfigurationList = DD4F7C2213C30F9F00825C6E /* Build configuration list for PBXNativeTarget "Clocker" */; + buildPhases = ( + DD4F7C0013C30F9F00825C6E /* Sources */, + DD4F7C0113C30F9F00825C6E /* Frameworks */, + DD4F7C0213C30F9F00825C6E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Clocker; + productName = Popup; + productReference = DD4F7C0413C30F9F00825C6E /* Clocker.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DD4F7BFB13C30F9F00825C6E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0700; + }; + buildConfigurationList = DD4F7BFE13C30F9F00825C6E /* Build configuration list for PBXProject "Clocker" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DD4F7BF913C30F9F00825C6E; + productRefGroup = DD4F7C0513C30F9F00825C6E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DD4F7C0313C30F9F00825C6E /* Clocker */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DD4F7C0213C30F9F00825C6E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9A8605D51BEC155B00A810A4 /* Clocker-Info.plist in Resources */, + 9A8605D71BEC155B00A810A4 /* PreferencesWindow.xib in Resources */, + 9A8605DF1BEC15C400A810A4 /* MainMenu.xib in Resources */, + 9A8605D91BEC155B00A810A4 /* Status.png in Resources */, + 9A8605D61BEC155B00A810A4 /* Panel.xib in Resources */, + 9A8605D41BEC155B00A810A4 /* Clock.jpeg in Resources */, + 9A8605DC1BEC155B00A810A4 /* StatusHighlighted@2x.png in Resources */, + 9A8605DA1BEC155B00A810A4 /* Status@2x.png in Resources */, + 9A8605DB1BEC155B00A810A4 /* StatusHighlighted.png in Resources */, + 9A8605D81BEC155B00A810A4 /* PowerIcon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DD4F7C0013C30F9F00825C6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9A8605BF1BEC14F600A810A4 /* BackgroundView.m in Sources */, + 9A8605C01BEC14F600A810A4 /* Panel.m in Sources */, + 9A8605C11BEC14F600A810A4 /* PreferencesWindowController.m in Sources */, + 9A8605BA1BEC14DC00A810A4 /* StatusItemView.m in Sources */, + 9A8605BB1BEC14DC00A810A4 /* PanelController.m in Sources */, + 9A8605B61BEC14BE00A810A4 /* MenubarController.m in Sources */, + 9A8605B71BEC14BE00A810A4 /* ApplicationDelegate.m in Sources */, + 9A8605B31BEC14A600A810A4 /* ColoredButton.m in Sources */, + 9A8605AE1BEC148400A810A4 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9A8605DD1BEC15C400A810A4 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 9A8605DE1BEC15C400A810A4 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DD4F7C2013C30F9F00825C6E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + DD4F7C2113C30F9F00825C6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; + DD4F7C2313C30F9F00825C6E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Clocker/Clocker-Prefix.pch"; + INFOPLIST_FILE = "Clocker/Clocker-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_BUNDLE_IDENTIFIER = com.abhishek.Clocker; + PRODUCT_NAME = Clocker; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + DD4F7C2413C30F9F00825C6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Clocker/Clocker-Prefix.pch"; + INFOPLIST_FILE = "Clocker/Clocker-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_BUNDLE_IDENTIFIER = com.abhishek.Clocker; + PRODUCT_NAME = Clocker; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DD4F7BFE13C30F9F00825C6E /* Build configuration list for PBXProject "Clocker" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DD4F7C2013C30F9F00825C6E /* Debug */, + DD4F7C2113C30F9F00825C6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DD4F7C2213C30F9F00825C6E /* Build configuration list for PBXNativeTarget "Clocker" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DD4F7C2313C30F9F00825C6E /* Debug */, + DD4F7C2413C30F9F00825C6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DD4F7BFB13C30F9F00825C6E /* Project object */; +} diff --git a/Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..5d3fc1b --- /dev/null +++ b/Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate b/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..26be72316b866d79e682be3bf8f4ed017bbf5918 GIT binary patch literal 67903 zcmdRX1$Y}r^Y`uU>F%TxhuL8?bKA6$WjS_Zie)EpNL6elabv1%2b!e4ZBu6EHq@rf z%*@QplqO~7Z}v!%EeG5G_x63Bw@FU3znz^O+S$F^MeWT^9i15&FLQ{)9N~D*!U^8D zyl>ALvpf>*XliSnGp23P!I6f}j`}g-Xv5Mbcw9TCv#s6Bp`+Jd=dtX^iJZjs;rep@ zxbfTsZX!2{o6Jq&Qn@rPoy*{IxP7>Nxgb}|)p4`9+1wnio}0_f$#rqdxfR@@+!5T7+|k@|+y&f)+(q2Q+$G$4ZUeWGyP3O%yOq0*yPdm(yOX<% zyO+C#&s$s_q>Dk&nRq>LO$s>w`JLuQfLWDcn(bIC!Zfh-|Q zNt7%n$CBg7S>$YT4mp>cM=l~4lgr5!aBl%H$ z7N5=M@VR^*pU)TY2lADC6(8hl`8j+&zkpxJFX9{cCHzvpnQ!4&@rUxO`8E7np7KZV zC-NupC-bN9XYl9n=klBROZm(AE&S#D75p{)4g5X)1N?*h)BN-N%l!NN2mGh}XZ+{< zcK#Rs5B^V!Xpt>0%Mi;@%Sg*8%V^7ZOSUD)l55Gc}M&lOt+L;$}AO@nU)2X zg_e-zAWPV?$gmE};&VU}Yp$61cIoM1V{a)#v+%X-TO%SOv4%Vx{v zma8qdTkf_zYI)M~tmRG1TbB1MA6dS(d~f+vK!Qc^2wtJTFjyEPOb{jtsY05NC1eXz zh5dyCglU3L2neM@jSv)Sg*suDFjrV0ED@Fp%|e^7LRc-V5fp(6rwFGCrwOMEX9#Bs zX9*Vw7YZAMD}*bBtAwkCYlK^bTZKo3$Arg)Cxj=3r-Y}4=Y=Vd8LcgqR|Z6i11p#WCVoak4l?%oGd7eZ+mm z{lsE1AeM<0;!JUtI9r?}E)pBWMlm8biL1mz#ns{(ajkfmc({0^c(inebhdP!bfI*K zv{AZLx?H+Sx>mYDx>>qSx>LGGx?g%odQ^HsdRlr;dQo~sdR=-;dRO{D`dIo*`a=3r z`bPR*`bqj#`a}BLimeu_WRtH;{cI>0*EI?S449c>+FooJn6O}A!QbFBr|eXaXj zeb!>@bnAiE3Tw4BXq{!Px6ZeQtc$D>>r(47YpeATYo~RE^-$|tt71LUdbIU8>xtG= ztfyPgvYum%03txs8>wZ33|+4`FG zP3t?>_pKjUKecYPZnu7I{m%NM^%v{!*1v4X#@j@j&E~MVZGCM0ZG&t>Z6j=>Y-4Q` zY?EziwoF@&E#J0}ZK`dW&2KBQmD$Q|Rkj*ioo$Y7o^7EmY-_YFu^nt{v9;SeY|Cw{ zY-?O^(W4@=AHNe3(q-b@DOt@$yOXsqz`}+46bvh4LlxM)^|ta``IxTKNX~7JIrq z+n!@Duov2=+V{5?+5PtE_ELMfy}~}zUSpqSpKYIKpKm|N9=1p9i|q&7m)YCw?e`&OAv_ETq&i<19W&7*)H|+1&-?e{e|H%HC{d4&pm9OF2{ai-%e$JvgJj!lluj!PYvIkq@1ciil_#c`|SHpfGbhaHbN9(BCvc**gy z;}ypTjt?ClIX-rLP&O)3>s;(y;#}(NbapwHJ6AZ5bgpwAaw}|y9T%hx(2z%y2iQ2yC%4DT)D11SH8>dDs}~2C9WD*&{gX?$Q5=iay7WxTvh)~u1{Q_x;}G#?)t&?qw6Qv&u-%8-4?gt_PYDH`?~wNN4iJ3N4v+kGu)Z(EcgEI z1KiWxK6jDZ?=E%++%w%Z?x4HYeULlsUgU0Yx4GNhhq$Be!`z3v6*qOCo7rQTUU**2qeU1BC_nq#$+;_Y0aX;aH(*2bCY4@A%cir!~KXQNU{@lIQ{iXXW z_jm5^-M_kjbN}TLJhI2->FXKn8R8k?8S9zgN%LfR3OxIGrg@4z2YM7+Ox)^c&O(n&(WUaJtufh@to>8({q;R0?&n>^`6T-TRfM0uJPRDxy^I8 z=N`|!o`*e;c%JY)>v_)eyysQVo1XVP?|VM*eCFBa`Ns3D=R40Yo zZy#@8?_lo`?@(`sH`ANt&GzPabG>=qd~bob(7TU!U+;e2sosFM%zL1>(p%-7?VaPT z_s;ds^EP-Jy{+ChZ@c#p?<((+-gVxiyhnSF@gD0v&U=RUOz&CVv%TxR8@wC6o4nU} zul3&Oz191u_c8C|-Y2|IdY|>a;C<2ilJ{lr>vdyVyPBI{;;fvFlQ}!*;=HpfgK5hm zt2*YwpL*6hYfM9PxT9ku=ir(%q&3P1_qC#a{$UP=Ar`Vqv$jwMCE-uJP&B-gy zN-fIF$w|%5Dap<)%+1R72Ld5?-?HMs?6&B#j`navq`0l2t0mIfY4qHm8_tc}!VTaC za)Y?R+z@UkH%zf8f+8xCVpVL4yoDRVrEnvGg<;$nZmeQg913GbR@{n5nG|vlWcW?3 zjcqGx!;6Z-(Xx(NO&v{(nj;I%A4;O(mPp7w5*}1V8za$3qsb7o@wc^hM%$X3A!QG_ zr^Ius!Nz{CYi&BDD^k`7187>@6p4o1BY@o3&S5(kjX`DTU+y@IQ~NJ{o^}J z;3QO1Qj(wJFV0T&W#;=+a{`6gsYQhuS*aO;lFXdKjKa)}jAAL|?zeh%#*~ztwNp}7 zXJ!?^U-R>`*RFk0oz+Y(djm*QR$MP~xm+HX&lSwoCbSjAF-QArqyy&N7mbEjZ3KeC zIhDaGb;V*eW@tZdIydf0ZYsAwcK|ny^KnI-pDX49T#4dU`Y3&seoB93fHF`SqzqPu zT*;NfEFH+r;L5oQt`h!U&COJX!dwkghAWemlazDe?-wW+vYG4e>*#<5RJgS>(Ad=3 z7VRhxuWIY+47uGPm*CR26_w%TO-sV?%RG1h@+l85iZqAZslAG=uCuARsdJSt8VLts zan?DjDY8O?GojdT-KIG~^2L#krX{Tj2=f_Cab!`~k|k`;4eqqgnj#%c(Ey{QsX0;| z?p(S6{;3U!p}0AiC0{#m(-7{2C1G)-IRayfq%Achd=R&Y8@GWAD}rfukDhkedXD{1Q<0V2s`-_{;wI4Ow$^YIbYdk}XmqohJFHtb z3Uo6;88>=bYdpw0?x=;8!HTZVFc_h#TAR3aOu4i^j^U0Cx%-#|vCcMe$HaGcJa;;C z4JU9Xawl;obEj~pa;GU%lvE{6NmnwIOeJdzcLsMRcNTXxcMf+hcb<~1?5_lsS|y@% zDr=Y+hs|kdYmB79e9UO-Ofyv=Ex4*>Q5z^yN-w_`g*zLTmVi%znFzvsHFQQA&DOoc zmUVP=MZkv)?FCjFF)5tIzab(<0;q~?P}=kibjm-*u-7Mecso|XSOsn$8YQ7%UNYR&3Qn}DwHe5mvrR_E0!l=u85~E`!fdBA z5^aTnHnlEE4xrD4h6|D&9S5Mh3dXJJiy14L<=o93yk41Dt^MPEE_=P=G6eY$_Y61g z3hrU<5$;j$G465h3GPYmDeh_I0A-ruQ;HP7Qmh1&5@q@o+_T`{O1T%nT-cu@xL1`@ z@NPqu1C?_1PrFjh1j}S(Dv>EjKLnX@dq<>kdbF*pU1z^1S+Idcqw2PfCT4};CgZ^> zm}&+)S2aUC8z29J*^8mDHEk=(U}9G?jbu@+XGb-W_GXC5zD|(%qAt*JL-Z_Uo8-(6 zYFD*Gf5YM*oBgrhE5OXUF;N)BGJBW*#aFhzA>P2|=1NS5MQ$3_g9jdx2m7rQI$o|6p z8gjc#?zBdm;PG#2aMk{;k^aH`3F(1J+I<=}aer}tvjO!^5^{SXcz2sVU9Ay9g!67d zSedy2@k$NL*jz9Vv%<~bqj#978Rpu%4l?7LDBhVl;7!83xhoRx{-xTmc3zd)(hCdf64e;Ma z)-g-t0?}w&6v8OD0dN6Jw_f_+-43>vw=NC>%$;&C!(=e2Z z($*^nsZ)+JP$uZK9vYd_!jmknunx2<(y96;l%tbFUXJorr=>mLC+_)F_3y@HOhb^N zU50$92>DSlOi78dSXrVhRhnQj4!#VPqB7>IP&qe3S*A3DpRy|*@PA$CV08`4{B14m z(FmktZLO+;gxmvQm}sncJ=DYHfu{ zENX6RSO$%l?=XHUgC@{fC;Y58cVlBPv(Q{_+$J;|%|Z1_i_)sJZ9?<7F=&C(4lygr zm}V2Ha%N6AOOQhDOn6=zULGlf+@>kq+`P*8-Ctd&WpAv*rA^I^(FjBt@HLtX4Xlhb zbTL;OXkFeEZEI!g6JH|`b$~}=im19IHXjWrZ3Ajl4p9!Ot8Q!WYG0VKGJkPHK{zMB zF+VRS1J*j-)gZrM?OJ1K2ctG_+-9^4HKP{Ps&pyKl@-d$%@9RKpeSN9VpmovtJx5l z{skMBMp`00^=~-*RuTraZ)6EWM^6G~<%Xg&EAM7N20MqMHKu=9s~oC~Gk#DIHN3$N z$8!`qk?Gyh=ooY?Iu0F=PEgh=hbf0Eib9nmE<-1wlhG+Kw$niGj#Q3Sj)U=?py?e8 zFvjetiANGXHFp(15G^Or?9y0B_8dNob*6eIbW#*q3?a#E!TN+`jY-R2!Stc4hcFG1 zT!1cOvbs=Nw*g(O9JM1~x)E)LY#wb=j^2PSRgO_6&Gs`Bh(xP*q8?YFYs@~bRgRC% z#|`L4Z9WWcZb7%1l(#D<#whPXcPCQbhaNDN7U)6cWMz`(OCI44-h>`SkD(f3Egd+6uUF9P360-CZz^XfXTmy! zO}Dzl)7q_5o0;w2Lmwuz`v`rkoUNQ=bZV}%w8rhz)Ye9)ThVrI+(z^T+NPYRoWBv0 z-7(-O)bw_Q>i?NDit{*Z{i7{$!DS3FDf9@F@M|!=t^@Mf^zfpkO&v=k%ND^(b!k&L zy|`^fYjaz;u_Ime0;w(G4sdAc`aGvsM9Ws|a5xm3CAO3Yz|F$@mUPAp&%OJG!6 zl*^TyVW=ztyP$SfKkd-8}JzAYGqPw1*~0+Unk%xoOctRh$rF6$~DTh%5|G?D#$%uxgI2a zBh$-?3Eio|BnZWd)+Op+%{46)2OwT0(&{Nl_vh0iZ7q?`sJ2|exlp^odCCpuDg_tf zeKaAcCXA;tg8h}76jy>a?U#Y=(WVwC0`&Mvxm)3sTa^1=#RuXU&_Ow_z?INR0MEoVILIxS z16$o{l%3Tc21Dqa*PvwyS|XOxs22f!>XtZ5@)8wvUR#vq8>+HGPj@T#x{-40E4U8N zg5GB1Ik=v?0ndXT7l76nk-%6+ER0n=ST#naXo1;{J!bKht&FM`8*O91DYwJo_%7)6 zwmygdt^MyMd=PXS#*1(RE}3UAUsqFJ-`UgxAvoO9uH2#AsX(EpW--L&ebUqS%yA^G z5~+zJUV>pDeV}|}aBPfrBW_}Agk(QyEtg>^bW8x-)O?0$jo^Q0@U4-mAbu84@Sl$+UGk=!{m1#4GVCE%!24>IpTtL>=9T4`n>D)$Xp4 zYr|fH*J|Z~oi*8r4`b-8lCU#U!#^naC`jZm#Yf;H@jB%JAfvXnYJR#m6a+ zC{IG7{h~5yPI+XpUV~IuA4W;i^pA73kuoP-U(>W?sY+~gb1FWIb#od%9iM^ER323x zQyy2IVEJOHTF$Y9Gtvt=LuQ4eP0Wy>_8nQF2DO^-3T>$uat}`Y)hMDgw6R5fO2Ut7 z^R{RwR6!e}P3^2G3(+EhL`7$oZ1A}rZ#0q&yh(XVPcrajP^-jS@a4+W%5!Fdfv>{X z#>aYm9ll<9MtN2lXUb~yv_q8m2#;^Uw?J`Rqa)?S^^_EWqS zavuB{{#{4Cj2*7N|5rIGL$0e{~%Hlkvn(; zk(AHP*&s6M1BFpyCl2ByF5)I0;#IaPUntv@?aG(RSIXC0NMF*A^d|$zKr)C7R=!cb zReq(2Py~Bh7K#LA(tKDZM2f?mVW#Qxv^i8`J5(xqbDp4M2~M_B-E|sdxa=gq4KaQT ztb{y`86}0Tt4_2|HExIaA8#+v+udB1I1yYy>J$)cSmOfCZ$Ele@`5t8o>Utx+$0(p| zKdq^yy&38SdfJrIjV9UHL+)`2I}w_a8#<8|RJF^`{3MwNM^xtH60(p4**5VasOrvx zKckUm7~%4W!cio`(A3aN!ekK?v_NY&k}%u!fdqgwGAoTxWK||6&Q{$Xo?&ZIVl=P zQ4U3uD9WWMPhCzlw6&y#Vb>0JkGf5IcACGfp)H&?r>w}(p5w_W%=AtmCz6xM$rQOL za#Q4?2p*nFP9rCiGbrjqQ9pP>(NJcBgA5y~h_ozpqlY$lhI%P1N|(O`;(FtH3ME2`@1Y=&)~?i}?kD+0|~ z*8TCIa#$PBXoUrHT)Wv#jh)8sC%Kwjld!lW*OMEx2cxGgQ=^^{n#e8WPDqHzt>iXx zJGq0RVH6FgXaq$mo5@||ZgLN~m!gprjiP8YMPtE+=eD)Alz`uY9b`Y41{7i1np&ZR zJb>vs6wun*%OlGp&H5Y^gY3s>wSltY+BTDQO{_*#tq8Y|KHwXTv-zvDGBaWSJ+mM! zSKD+sWr_^QcdO1X81KOdoy{Ryg}Y1Z&5UnqA3)mQ2U{rLX;0Dd5x znnFdC|DE!GQHz~g22#sD)Uq!#-o8apQ(4x|ETBU@vjQ;-cDM)YMVq)Br=z4T3jVue zzIL=lt3(5U_D`tn!}0*C_v!*2O8W@_>RFp$)1eU^BjnCthQu})nj_F*tTdy+7C|g& zRDt2(2Gjvy@d1@zBMNB+G_cEoTG=;I=!{3*#Q4$tB&bI7WB9TBIDR}ofd>=tQ&db* zfFg*y(@YBoB2+@i;wavC|W>K2%b>1nE99g+q{oIjK!V9DOw15UrENHsRzzU^)ENl68=d3 z7|8qhb^K9080tY3g(+IJi9ePNX5k*TVT1rt9MF&IP$FJu%fcIv3AEYtO6t(<&c^{;E*%@iD zT+PnS*3v!x%9wx+cCY2HOB~sa{B106O}0GXZ|CnIC-Zkv)JD-E>hhpdFQD=FGU)p# zYFAvroWd*v{vrOcB*{AeIR6Ao)1iflG_q(yw>9SO!=IT3}@aYDXzLf}*2Tx#Z+cNy*B}(3Hb64CG=N zZW%$*krb^1uIJ{JrB<#=4NqU$(;6*fEMpTHm|#f-1}qaTlPr@hkj@`N(XkXAN73<{ zEoqi?ONJ$rq7x`Oi6U5Zp7DS0UMvMLBbGvnPK2?|T<%Y;C`?_Izr>K}R14$}n}E#& zERZ(FX@>LyE(#n0T!X%wCQuele?ftDGG!mPAZB|fOJ%x2OJT52tImRS^?Nzqvp zolVg>;8iU3mbn&i#{%WpI*Hd(Z>Q`^p{i@{-27Q5A95UwV9?JvCoauv>hnO?Hk)oRtoatj0*g=Wgp|?C` zc{=gIbC#DGYsrI*OdH2)FAFSD3v`N8r_GFAQ6@*7iCh}d_ls%l8= zFAE&#h!cT;1(Ntc5aiyqOK=EI!KI4eUWy><->*zsxZ2QyY_q;3^y$H=FhCfX*wYYU z1h6g)6^04JDSD8ihbek=laL~e6h=|>I7QD<1lwG339~R>PnaJHxvTan)z?%0)Uwva zZE3LK+0hx_%@nlbo_0w&#DAy3Gs z=n0CRr0A(l+zrA$!oJE>ik_zE8Rl)-LA_9Qd0DVF6eupMt*QwH1LXmKZCO=iXhxtO zwqAP>%qk0(6_p2SfJ!6ji4mAn?Su2o21eWoJ@xEIUV-uck5B}s6$L*<&$82}P=pss z)Z?VO!U|lF+AV`eo~b3+>ZMRQ>@Z4eQ<6{{TP#M+ z%Q!Owd?X_`_^u5{mqhfMozC{4xPIZJHaoej_iR|x*}}Q7fhe3q(PtY3$QM6n(&^e+Efj61=*wMrnG24`#w2MT zw_~S$Vm1HK(<0O2*Ve+d!VQUCa@PwtDNttqn!VSxHsRcXaGP*1)L4bvg*${hg}a2i zg?lLamZI+{`kta6DEg72pDq*b6Ydut5FQjB5+LmSOwq3t!J_SVivFNT-J8{Cw#O_M zH+3{Lw?R3WZJc+&sq3sXI8!~axHzXI-=C40neETcC@Cz-$SBCl_2&g*KV|p+Q&#Uk zW%T@M+_Jcdj#n__ogAp08>hjAXPDb~mZD#jgWxcqzpZ^$N>Nv9V{;^>CZbJ*QJfZD z6kbY<(60)wB|dmlcq{S2yTW_ggIVkiPkluxd<4;7_?V)<71ztcXE@A`rU{=5TZJ!# zZS@`M$sX8yrWg(RQ^9-H;TKJy1-fx6&h3_aP z6!R2YHVHonKMFrlEKn>`EGd&_X*N1bvn%5bx9lF%A7`EedYJ~}EVUNT{$j%Tn_{b( zw24^MlP+}=OB6)WcwNt^rFVA*n?y;pvVAP=Wx?Lak{_{yoy1-^)nz2w#lBEO7agKg zbct@!BYMR?6gwz(QtYDGO|ge!FU5Vfi2cO=;s9}=I7l2U4xzX&#r-HAM)7cpM^KzX z$<%+@LJ9dx3jgsoLgR0&~0r)SCH9(r=^41+OkI*8U&yd#IoYurpFvS!TH zIB^2_aB)1v{WpjcDITx`A1x$a#VZixu*4aKck!~?|{+5^?R#7ZzPv5Ml6alS^Z5rbl_u#Ms| z6pyBOlgnzi3cf%Pz)0_ z0p73B6)NN&)$0t$xt8A5KpXX9HtHo5PmDR0gT+H2?1{_7X0b(V72CviiYHM#nc^uF zr&63oar$NC3$X(ZW|oS}*@iwm%79~sLn+SEP9Mhe1`M}HqMfT)n1h%HFJZ1ykKxBQ z2OyBZ0izV1P(4MiTaWrfqWUI4jE<9m(T{o#G?B`Dfi1D8RVn&GCbdi5BPQvRv8#zo zfrC9Fr8rZWsJ|8|9;H-5g2fIqM^ehmXH}%+r)8w1!mfJjlCJQQ$eK0N{r*sOO`xP~ zPN+2CgE#FosAIT;uk#?Ac&vDwc)WOmc%pccc(Qnkc&d1sc)ECoc&2!kc(!P! zc)oanc%gWac(HhixL({KZWK3(o5f4T%fv0><>D3MmEu+6)#5ecwc>T+_2LcUjp9w> z&EhTMt>SIs?cyEco#I{M-Qqpsz2bf1{o(`SgW^Nt!{Q_2qvB)Y*5>Yo8nvI+u}RoyW)G|`{D=UhvG-#$KogAr{ZVg z=i*lJ3vrvcUHnq~O8i>|mGY!~sX!`}_L26L_LHVc z`%4E%(AOcDIk?d)1^|WOgd1SA(cxNQl(TSRZBCa8Yw8%N_EmKX|^;+s+Z(juurYLp_KZ>VPyg$VUP&|!dAH_u!`zbD_I6!d;#nUM+rMQgZ z11X+CaXG~m6jxFVzO9<#nH1Mh9Hh9G;yQ|FQ9PUCITY7ZJeT5m6ocU!eF!ieIAmWr|;+_*IHuqxf}--=O$Sir=F6ZHnKa_+5(MqxgM_ zKcM(Sia(LGhmy|3&fNlyHV8@}ml5~tL0sc6 zHAyaDBm=sW07y+$Rjq+@F(Vq?gQ%{$x~ir&Pz)t7Uu{WMO@)cNfi)P?y}>MBd0BDD z7vKG6MmQe9XJR6qY#hO0pf*(P^UnxX_$tdv0#I3FhoiMvVz9G?HJV~J3RDyU53#1f zP+29ks4A|58e36aWpR1HXnCbR5WTxVr4MRxA*i$!2cW;=P)#6MRafH=m;H2^?u6?6!JCC4e^q5|pt4r| z(+A=V1!tF)m`eCaQjYW~EGnz@R~4J{{5Yc>-@T*hfyzLQuNF$SHB}{L^s{t9#p^-&Yx88m8%J2!;>BDEX zVf6MIqaKUcIq;Mqd>IK!Uu)Jd!GwZk(Rpz6&Und5nf zkx%KB+_1V(O&uFiwXe3+;O%|Za!j|DRkfvo8g=S44ok}8OztDrVsy6_FhQ*FURBBF zT$_DUS3YG82B2d2R7%?_cDx>}thT1CIstVnBO01OP~ zlvT4q0}aZr8Rd{(Fe~B|^E*a3p%=pHKutwikc|y=foX&R|08QPGNBb%c~My^ zXk1x^Z+eXU7e=0vKwccEF0ZO*6CWzC(v;Q!|D92f>y5g)Dp(6r20t1Efg5f9Vr>Q| zv@v{UyacVNce;4_S$Re`JSiTNUWiSg-nUg`w0#q3i(!^yG0tjZ6oV2d4DR9-(&}Jj zV-v_KeEzE790(z%v}%1d(*uTmS=~LG=nezgl&IkY;)=SBWU$+ZHAzkA#W0c}1Q>=6 z{t~{LQs#$o`YOsy-(l_Fa~#1LWz|M_GI|)q$i^h}plZEAr-lVJgc>b|vK9lAv9+ZbuduvQ{ArGfdMy)5spHokubd50HMWSRb6lT)|$G?P#wg7kdHw>R%19h zy-ur6xnTg-2^uRi;ElFOa|$eIyP9EX3aSBKCRFLGFg$>DG9w&{k`qEuuQ8`GZAXy7 z+A6~fSTh;n@LnJjqoOs3(GEc6O|8pR*Q=#0U~<~RS#>Mcd`2`jMpRs1URDG?umY5` ztO$ZxZGE?BYu$%6fseu%xO$Vini^)&-I$olh=;`y!?Im>vCJ7($L!cTjggLzkwPGy z0sgqSEC_jEeUN2t)5}4Bn262E@Uuo!VvQiI1_L#-0-(f3N6Zp}A(n=LV>NS0Ye~0Z zKmwwT#4ykJsVrl}BV*n4qzo1Lg67PZcf*FQS1qH3JgcaxT=S@g239fRJ~3=yq_Qeh zU1p-yFoOOu0ydx!#D-e%xduobqZt>YVZsZ|E~_mKfudCw`)Z0qFtIg|VZ~%OhqdV! zYXc4k(#241eYFWYkCF6^k*LX}8V`()7cz>WaTID0g}!R5s>K0k5VywJ@6D zvF>LC0@V=M%Vx27%o3}bN|Uyo(dNf!VcureRRNu@xZqCf)a*vhrI<+pGoa6aW(I3( z2Ll-s1E~p^x>8aDiaxulW=5jMFJ~=AC2gV2aD5{Es-4rbKx7VU4Wo}!br=@7O-2Hz z5ZEG1O{7fn!x?#;#A04qRdw|MgE0d~Fxof`FlHcOX4N8KT>n9BISBCy54`fsw`ep+v9*Jvo_?#xYP=X--Kp^F6H_1G9ZKYC70W zvCm{=adHB&#_4Qz0te?X+Oen_KCcyCqWW%@-`DGTEUZG+pcbE%SFSH6Y$s7s*7E7 z)nQO?V${QWp@x}Pa5M|J+)G-E{KXj0c*kOnd@Nd6|CXN_=cuTt7lAS zAPI84x(7=!8|xOgu4AMLGKsMi?^JGNbO~~g(P<72hN|bRu%b%P^jlcl(ed2JwXLhI zt^@xC)eoPUCfvS*&Jwzb<$tD~-nE0ywAnCA>Y8EQ%Nis|K+}c_U!t-;z~~aRA~uQ` zQ^r(3%&5o3kD2MRwtUhecQ9010xMo$tV-l#; zV_=Na5Jdc*I`IZ;ks#3Ox+16rm^p7rPuaZ9+DwS=g{9D7SE{ub{RApuu^yM7y~kQ5 z81(EK@Jk@~9=87>BOQ-|kuZFyCxv}XhZW(-HqOen#nr&iZvL~twBv-Zc_Ab8S#GIhy!!f@(!y3`s<)- z1*vIVN18$#XX-5NK%jrJ zMtueE9@6fiyS5{sJIlR%H zu=Zn+{tYp$gru)Dz}VCrFVS<`1lD4BLJOTjjfL?6!DeN&V|%C70za%J{N)BicGe`N z_a>SzHK<)Xp$^uS#NwdM+biqLK?ds~v#l_Y`!U*)z4M`#R83!H8_3AhC$Mk#PlPSi z_^MP{b!k;)pbC6$FO>${5Y{*?Y2(>Gs4?%T?QquifF66gYE=-vfB_$eW;I|~r z4p=Cvo373ii+e0vDG$sFn8F{qTVQhv@?bg2(m_B34+phLR?adcIEI1kx2v4#1!1** z>8}Eff+ClJG@c>l?i`7gu9>HWg$Zm~_~MFKwn+?P+O9#EIgTnVNOPEOsOw6Dp;U%e zw3}$E{TV}3&BPQ{2E)tQHN4__2xt(0)HST%;3#`H##dIU`-B=+QjcGI8EARCF+OeT z)oLSnjOnnbf-J0RHrp>U$5+Vkc0ozm1nP1&-Yi{k?0t~~qa}3Q~ ztEy|uD$3?+mI~5U)0DWZ%2vwY(svHW##90;cPR3hMS9x|*0^BT8rPOWU?~pzN|;oD zpV-`1GL&5~bJaNY@=S8Ao5_%}c8#C9%9<+JQYo*hsy4N(mbKpn8`osZCODaVjoF^f z(303>R|kAPD207B0lq^OO(|&(FM;Gs-`j{^f7s^sBAFc`RF~I5J+3a8fV6-iCDFX( zNX81;pMY^t^6``>9RBgc&SI!62t{1Bhs5^w;DI5L28NK?V}245bo2EEE7*GyP+loE znlEO}drog+bAO1%sXB1}W?{`}-^AMQ?DUc!91nCItgo!~8S7tLGi#Z;6UNIb)#M)* z0&xX8TN`V-&rX`Mf|OPaG@P@R^TskxTa@ASG}Oew>#~Cg25z+4EE(ClSmU1ICTU~v zySkG!hLC}iW%Eh*t;pOi{ zNHG|O7=Oe}T@Tw1V<0=5-lQ$*u5_=v~M>-|5X#llRoaOmW1zP&_?}ZRI~--FNm8oY;KP=1 z;8>eYmR0~rDQsJ^^;LOD&ofL_yED1ic7RqLD24+`Wv1ZoVF*3f3CR&^)l!GS1gmfa zYHF%#Om^;PU^9BiP6z7%gM<%drZnsMPy8VLr2#m}2B(FX5+S+-}8#yFF}zRqCxNKx~0LbX+)>@3)DQjgztV9RgJ!?I^d$KsqhLl1(#93!nr2p8<@v93$P&RF4 z51Rt!`2S|eyAvAB@#}U6rTk+z*@Qh zsl0yn3O4)$m zP+-zG9nKW#HY4|CfF-*jfH<3hnqUBqSgB4s?tr*FU@w?dGiPJ+3?>INz&)~;x=Ixg z0*krnA`fF|yAx95WT>LCW11BZGmJu=oU*t4!IASi)1F7~t@zaU4&a3iLww^HV9%9u zoYKTqDOBZ#)guIXw%h~z(RP|*iM~8>r^8k8OtG=0{j9Q@+B&G=#NZ6>rtBJbCK?>d zhGX+4prI?KMyE5p9cpwUcUssktJL1QsVXUfLpfC?P`LNk7+V=~7Q^gW=h=Y-q1cl# zCw7p)K&MNq zirJQh-*~Y=-j@OIFyHD8SYy=i$G+MswuuJ0035KWjTLI;{r9c|BaP94>(xp$BuZtb z#C^Lb8dJ}-vXmCTphm5}4O3g?uQE1o<>Ec&JZ?d1N=aSvYGKN-jOna{9Y&A@*_)i} z^$qPCOHiFin9u_m=nnJS0=m>NkTA{oF2pA`&phe0U;GA@Fsqi1gygy5l>AIa4W zaL$f`QXF6k+}M@^#U!Jgs2Yn345uBm)r$H$M6eW2_s6B>a**{>x7WRxc@t#*@HQ5c zj+q0@`e(X;QWHD-Sj_55A@EJJ13sfnDA%(tcGWb*wli z&u1OXG(Y;Ty(SMEaqyY<*sfe^iuvvvT)qJ7HvMogOI|`yc+fVz{dI8mAGWLE{Wa4( zLkxbO-GhgHwpw^6EL0gg=`1f|IEA~1qirI_@7l=`29vXUFbQQac_~B4-8}?YkHQ-& zrc9PGh`il{U}_IL6DCG0!^o@(`t+SsD8Ch{pHeU3e2T(xEmdxu4H39Rx5F~SG0 z=hnk2-Ec1}7*f?PASFd%n+l9G16I{W^HodvPzFAAufPpH*D|Q$o>1zkAP|CfN08yB zj8Q^Hz$Ayqw*}o9;KNBl6L` zaHNe5rq^`Lsis3VN2)qyUoGqv8wF_jIEEMK$3hR3BoO+i4^2}&oq?9_4XD1%0WWKosieDBOwB!*t*cfVvv?Mwhw?&(5Z(z%kcxF@rAKfn;|M z4TmaVi3@Q(_Kt?Ufx*t%D_A(i#h4GU7lB}FoNa&vinZFIA(zdpm*79v3%mXf>^!G&{#L${q3_+a#tW$i_Tml6T*IJuWa2xY)_7>hm;KeoPK$g! z1F!tYq%sR$d6=Pp$4S0XzA52DQ}V4ceEkWF938C<###rlf(A2qjA>X`*BqB`uV+QE~_+ z9h7uYvVxLTl&q#?EhUFjLMb_tlA|a&hLYnbIf0UsC^?0a(#`kyUXsjd+c6&AA4VWKYM@s0Q*4uAp2nZ z5c^R3F#B-(2z!csqD0zgECn$NI zl9wrYoszdHd7qMxDfyg|?UZ~?$@i4}Ov&$*{6%?0c?;#Ol($pfP5C~QA3*sblpjI) z(Uc!Y`AL*dqkI2KNBIEd%P3z#`I(fjrTiSq&!c>Z@(q+ZJi*;f9YHYY*aR;7cgR&zTu% znVD%Fjmy%5tKib@mh|$bMNzmtIbFRFX+>LfSx0(F8+;#9?K^F86h8jNo~G-E;ycp) z>H6!->6JnF$Ryl~q~4DliNdYnv8!|J`TD4eAW1StwOjX;$6X?rh`gVUTpV)WXdwT8 zl^1l*uHM>-tg6+^WfElM(??PQJ0r$O_CQAJg=;PG!Y|Q*;Wlmm9s%p0)lBaRJwt~+ zFyy|+fc_6iU%SB=?5CqM3Rfa^CaP4mJ}9`s^oIY?p!|{M=EQ;2=>vf%S!)br4>ZcR zJlxdGE^0RJUFy)ZH$lnf>U~v*+-p~+u4EsBPHk-JfDb6cU6IYJ;C}IrPI##_q}s&+ z&Ec-rhNVGvUZ}0LCbD>H{^G{m%&d&X;jF@paVn+if=a_3OQ#m(7UmRW=4TZa6lP{+ z=4BM*X2y{ituq!c%4&!dWW;NJNN1{M@4np5GK{Vc_EBPXRb*PixEu8@YD4Z@4H^G` zwSZms*S=^pyed&+n)K1k`X~H!f}C1)0v$L%=v4@p<5A*jY?WtaC^)41dqPrJ^ zV3)ov3P*br)e(9x@J;A{wwDAII7aVf(Vl(`-c$iKcqU+F4a3}4Y_aopHR77lU!^_i3)e6KAiTw^UyJP z)k7yp>^i**xXt>m|B%G0;eOl5qPB3fk>xdsQoC6n5?pHgzme1IniABq9JS{J-Jy?W z`JP@nYS>L;CXf(*?$!HP8FJtKA5sD}1MDp+ct{`9p&|E!{}W^KLmsx{u zj?4Fp;i{Y^Jr)VS={=qL-ztCxmP6?}(H#HQM{@d}u0oAKt(K>HnSKYa_j2ZcZ&78e z6cfbeu<8Rk`@a>M^u zwV}DIF#@IJD7=K(k!S~_biUUAQ@4R8_3RG)(owSUAB=(VaonL_H%d1D_Z(DNYhz?3 zT=bJTG5Y1EtUC_ip?EO0F3MmP?l< zQ{ZBr+m%UhP35-i_Oyv-&0C$Fm7P5$r64zV?cCLw*#%isQsA!!=3>XPq?pZ)7Qlp~ zJ$F)a7sI?;#oX?2JU%m0&o1N4%qh%STfaIpCr`bZ(*W#p914Jr<&G7Ol@2%ybT1|M zQF1>e4{Ual7|@R!|ZOsfz{Eb7C0kf+)2rlrlT|50wvZl-F}+Y)X@Yb zIsejdG~57rL=AjUAhMvesWAed7tqcO!Z#4RH8L*1O>6}M+IoG(x)DcfgUK(*gu&$G zfpoI7Oz9l!I4P-gPIjCE1A$Xak5cj&8_46DbmTj%m%KEGNhd2eXYK6OnFUi)@=dgJ z92YXtoa;ExalQl2JUvOtQ$+1~HN`Oi{w zB*x@k;kY)bJg#$G5AwK?k{2j>k;&sFRUTj5d)i5_OqsvBAR{Lq6ed3-15~geKQ|NP zQ(%hacE>$QLGN|k2cQp7@(LxdGSJsF(9b$=sxF_mI*;jHW?o)_s@8eA@Q>KUJ?40t zi8`qkKI3>6aN!Ww8{q|Mac)0e8})V zQt`HXj-9zCb^hwi{A^$?Gbg7IbT%s|6UH91=pP)vCdK^C@jGDtNy#Uae9ACCQ!%#% zuC<+c)%?}$6a-95PDVD!GcPwETt<$mx=!Mhl7Tv{P8&DE31C|(`GSFN(-?L1`_B2B zZdow!9&WZQ(K{E;U!4W22VOTLH*@X0)j5UvIiT8^ znI`f|=h~!WJ+qD{MFgnxyX?-QIGJ#pI)G*sX0v=L zrZ`_Y;kNHyOy&pYkJ_}1q5N0?HvQJXy2m+f_*wZe#s0&E7*sNoabXwXM!4Yk@Oa8k zU_4G#dEENIKA#?cBn&*i5R@e=uOORgP9gZ}Tyxwm+2!sP*W>a6F3k62%1>dqsT%GJ z>+0;48jBgK3o9r9gUL2^$TiqCBAGBpZRU%&thRlse<-#xMMwFRp)vvOIAoSB!C2QDZxJ0}wcAIIl(S9z}z zt#DOplfEzI_XB8s(zjk;eC6Uh)oda=GdAKn*W9EG&U4KN1{YF(f65=g7@Ve!*#78R z+xdp-Fon!!P7P9S!?<0IuBN1j2fLO5VhiPqDDP*8#kvf~UHkIODkAvCB*Dtn;ab`2 zU{|>g1<*B=FQNQ&23o3uZoQ@<_0l?Zu$g(8kmh9Of)kJNc!cYiq&yz$Iu77Yp!|W9 zpTXeD^-+KOSLX}bs56rVRM%;)vy%dz<2n}r;S78w<*OKAwFW3}x#{I)8h<(2ke3(4 zFIimcU6-;EC(A`#m$|lR(_2INARrnxJ@mD$D<9Uxm|tk-vaV}g@RCQ*C7SDI*Db)< zZIrL0{4B=UY?ZMu4zIdB@5u$={0p;K*vrdOola&>R(vdQ-Q#+&R|X$)J*+WUPx-lV z4E8@LLT-=AP>%(!r(Dk`W$*>pi@@N^l%G%e1&qOkDudf5F6jC_3Jxc?ka^ldSn`3V z&CO=an(@H(rt7_=pzpgr0ML&pe-P!v40MqO`o=d$A92KfAq+06!EKR0y8hvLtFsE&N~JKL z`Pl624DhjeW;Ae*bx#7!q{{7{?4F|OPABEN0M}6N{xe%{?_-*at~%~)cL5-|bKJS^ zJU2Mf6_j5|`TtkkcYrmOZTkmJEYu|Q&rF zLu}Y6353ugl+e4vI69V5N5}5?KLMHR%=O*-zIWgI{(K)_l9O|Od+n9Ie|zn{*Ip|N zfM%bA6W|u0gjN7_I{@7wkZ|Y!-)^c0950y1nl8^d!BGQTR{3*0hkL_+$nEezILPgAklXhF z&^!U?-epis_U*csAaKoL2^1s%@aHo(GY1DWlRx_aJPQ6pdWXlsL3)RS^u7;(?iYX- zEH{bE+rJWYmMV@jU20*3??(i%)NbYcu+(AM6fAlN(Zuk%R9ljq9@;e-aD+HiN1&GI%g?ud592Wty9u_Y!fK9+UgQzBW z(B=Z0@yf^sKL-CH$-|j&kmTVY$)5nACk3cQ%c%1&ginAxVzRUpfCtAmP*U^d0{+A- zhYP6wpO(Ir7BvD{>YpqQ_%-;g9|GQn-vI&d z0njr5v_t@Sb{SA~fuk$D0w}QFjLifb_zw-M5`L!4$KewIv=)Hg z0-*H(lm$RJe>p}5pIu(ugo2w$CM(A=;*+AmV;IJEPWDFjjz;#TQgg4eVbF_2R$K#D0_08?@ zrg%FCV}gT&@%KoNz9E4dCx1h7Fm*C>bTT*ACzzY!^v!HR5IoittM6oMhO;-fb+W?~ z9KJ_-_6-T#4*44r&dlD{$j;tK-_*h04y>K2u>i?d-_+QMU~59KvnSyGBGapHNZ=O4 z-;m6)j^Iq!94Os5nmHKb2*yT^D_r{q{uZKD0skFK13KI0{;Xtt$=?9px1LHMj;}r!r@<6g&`map;b;01NbZg z77B;cwAsZ5+M#De1Bp2E;s@K zrZ5CEQMo5Y|Gh$02qZ!hLijJg2lMne_;~&Osc*_dNF%_tr3!=$0KHv-0H>mN{u|0e zD1ypEC;`yBKT_TT0-Vw<>*qWGz4s6OXd#5*5@5wwipC&x|53Ca0By+CS^8}dh5~pa z0NVH?_(uqEI9-On2tb?ugogwp1X^7Iw?u%mo0WQj69x7PxUB#jwDX&P1pW*Go+n)f zzYIWI{sc$3fwHgu4t^7YB7g@+zt#!_c>0w4-%*>lplBZe+V-QOUm=25ioOCs+y5*Y zY*^pdD;xoiaTgE~h)6^ff{xgXh(>_T5v00q0NM*cc>r_(fDQrB;R}d3#1=$6A_0+z zNJ4Raf%Sk#^ZyN4($>WIr0}RT!zH&1{RDw;GXp-Up!bOO^e< z=%WHvNQBGCD6epGGlC-!vju=IR3KUbD7aDc?|;Y+K@~uL`{}P$=tcA`SK(&>`f#ZV z|66^3Y4=2QSMG{^ffz!7M&U~P184n@SF}4W5Dl~hfBCCuGl-`^WCaqm%RW~iLA&fru2!%h6Db%2V%hJ-_uHto@_-Uj3xd3eR7R>GRgr2)btD?8 zfz$+`UjY~dfC&MxRRC-?0D}TB7yw&y5vdK)fT$pKkh(}cq&`FgfUV7igHt8gIsmpF zfC&RI5%9B?e|mUoG(8=RS`iSN<_M0#0+#}iKbJ3qp)X=1=^MeLz^R~jbXppiGW`25 zR!r_tICA;&Qh17VdSrS=DhTrJ;xdR+ctUJ^7MPa&djK#23O!zsG4P*C1pSL6Q|amS zz=ZI~q_k~Ip)|mZpi!CWQA;xEgEmQcynZB@4GVM?O0`(}7?YHi?z0U{4v00Qgn%JB z>;&YWnglM38?R`QgtUcdRU)mCHULZvfJsy$?U42W3<1Ev{hsga8>GwfXa^Jjzw^ua z-lZMs@vS`g|6O@2zB5P)(i4KLL{gD70EPr$l9fm=q&EPQ0$|d)THae@qtau1V(0>U z3~f^YS^7iU6wuraE)2+ z9-j2*1VMNf&}HVI9{Cp8Z`lm^E1FkqdOUrJosg-JxN2k?G98(L%tUSlU`hZC>?Ioj zm>vK#%EhdRo{h{Ah`t@U1Gy7`DFZMS0H#`n+=a|V0su@6fT;s8v_N#Nf0E-bl7fyn zNrK>AU_$JFeWT!rh$lT6^y*1Z0*^gn{`K9c08iItW!|R1bM8(AYHi5y#1TN1$8j$g%XrKEGAxv)xEx!g6m>vKhXHhBupl!13H z9c>&@QdSXGRZ~ZU*F9si>0qgwmvZ=lp9QRsw$WNv8$t}8yEbhb@lkv&?G2cKWl1SI#(EkGcjEeveHBc{A`W|Z*+(SyJ1oy*x@S81sCz435)zrGvC}ZD=omL z|AXtHaEZUgEE*z`yi${r(sP9%>mUdS3WA2{Lrfqzh$F-eLW2ZCA|OeS6i6B*1F{Q} z4>4FSFCLj+WKS6$mJQflXS|fxILJ6q}X$a{H znF(15Z4`1B+9X5~@)imf3KOCWr3z&TWeXJw9T&PFR4>#d#97wzDxu|9i1oMEZ!bbz z0A{#k+av3cw}Ll$dSs*vPQHSUw&7LarP~k!sAs{am2Pnt$%bg12MMAc*?`=MY(lb@ zXu=qPnSe|Iz)S&{*?Huy)lZNdWb5iDtDgv1L&yMtnFBDK;EfR2;=!@)U-xsbtYmPM z{5LlVyn(@7&;J@paFb_xmSC9wH+Kr050~!bBYVM)*oWi^nteKWRbbAj1VrBS1z^}^ zWep$)m-RxgL=Fh1J8-Y0sPHV+@N`wIg{iqJ#RL9ig^-r{cN7v=0TBcH7iRhMBqXjp z7xRO5gPcXqc?+i3^rfaF4^fBcf@^CQ5NqK^VUBRW@R;xe;m5+yg6)nYKQwPNeVM8w3zB*YM6 zl42Xgbj0+;48)AYOvKE@uwr;I3o$D(66l{A2YNG{7poV0EcUzjI&oQXO>u2;YjJmR zvN%=TOWa4?Pdr{cLp)o2hj@;7uJ~c`&=mqIu|{H@1OoIyz(^QL5G2SFJ`#}XZx9LyYeWzt7jYhO4RIZD6H$j~La-3c;M{B;@c^-ic!+p}_yzG4 z@f`62@k(H9BiA8?k)lX(BpiuEN+D&Ca-gk6N9KT*>p1dPNpVSSNk7SO$wbLy$t=mk zk|!lEO4dm>NwOt7CHa!$k_(bgCErNCm3%KHBqbsxCM7NqAq(pRM0q$i}`$gG!9mBGm9$mq$K%h<_mlp)Lb z$@t3z%0$V~Wuj%0Wm06)WOm5xl-VV7NTyikjLcb?GMNgQDw%4Tn=-d#?#SGeX^?4> zVav40Ow0T(DniIm>n|H78zCDdyID3tHc2)`Hcd7|_OL8R_NnX}*>|!ZWIxFX z$-(8c<;>)Wa@KOTa`tkLa+~BRax^(FIUhMcxpcWAxeIc4Kxf!`x zxjDJ}a_{7!@(6iJd1-lBd3kvSc_n!rc|Capc_Vofc{6#eJYJqGA0nSDe^Q<+zaalY z{x|tI^6%t7$bUkKp-?C#lnP26rGe5y8K4YNPAE^556TY}hzdr9qT*2rs6fFZ3#iMeE2wLz8>l)|6N-y!M|GmQQN5@M)GTTq^#JuV>M`mG z>KW>*!a4VvJ&(;x0u%agX9&#eIqe ziU$=BD;6pqQ#_$qq?ytOesMrQ7K6&MJY!KP}-xEue4w3 zfYME+W~El8Hl6OxJrQem_DSc4ZR3<8WD~BkDD@Q8R zl~a||l+%?nm3JxcR?bt-S3awJRhg?itNdR1qw;6vKU5$p@+#^o7!`9BKb0tz%_=b} zaVqgDi7I8gpUd8!4fWvUld zhgB!kR;wwhDXW1tf|`b!zM7GmiJF-jQ7u|6UX7tvrq-_3qxMqmi~1V%b?UbeFfcu=Aj4CeDo-K96gDCj(&^&g#Lp5sv)Eyt|6%*ts$$S zsG+Q(s-do-r(v#Pr{S!zQNvAxqCwN}((uuU(MZwA(b%K0S7V>XA&ny%M>URXlxuWp z@HD10<~1H@ENVQ~c%t!KjZU;;4Vm`DsA6OBp4q+rr8 znV4-D0F#H=hbh1?Fx8j~m`j)%OfBXb<_4w?(~4=wbYXfi{g@%l2xc5JsUxH#t|P01 z(oxb;)j{j%=@{ym=$Px^bu4szbhhan(y7+Ds&hlkzk8>}0u8>5?{o1+Wp=IQR!J)nC+m!Vs%TcTU0 zTcLYJ_nt0a_k-RlJqbNIJq0~wJykt*JwrVsJ!3snJr_MUy-j))Jx@Jvy?uH|^@{aM z^vd)q^{VwQ=-tw5)@#@6((BRV>5c2%*ZZmu)ko`tyNUW(eS$to-%Wp$K2_gKKTReX6B!dZ69p4xlN6I2 zlU$QMCiy0#CJQD%nLILiVrpt?V`^vWXzF5GXj)=gYFc4>&h&%X8Z!wqq?xptoSA}| zhMBgRjv2VeYGz`#$t>9{&+M$(d9zDqSIn-O)thyg@yrIzhRw#zX3g%KEt>so_Sk%t zxjg7YWM^(~?qKd@?rH92?rrXC9%i0ko@t(CzQcT%`EK)r=10trnV&Rgnird&Grw-$ zWB$tg5A0g3FjfpJfmOsRVU@9}SbZ!OOTb!Tt+94kH|!=X73+od#rk6-uykw;HV&JJ z-HzRj-HY9iJ%~MyEyA9{p242QUdGm7uVAlY8?jAT7PcANhaJUEV5hNj*az4r*yq@n z*w@&%*!Q^AI8ht|Cxw&6$>S7psyKa|0nQL-j3eQkajrNI90liz3&MrsB5-tE3@#3r zhReid;kM)QaVK!6ac6PmxGLObTrKW8t`2t_*NWrf+Hf7XVcZCA6gQ6h3HKcL689SS z7WV@o>BXUIUN8>){RY#&|2dGu{jDjrYO(;pzB9dA&3#=2$}>vf+4|#U{0_iSQG3Bjs#~yIAI&%B%y*( zNvI-J6K)df2)77#2wXxRVSvCVj1ndY4+uXI9ub}po)caWK3c4?P_=Nj@UjTD2(yT^ zpj)I`q*>&#W{-$7MCq*Ev{MgT0FNDvP4;;EwwB$mb#XB zOKVFzOGir=OR^=+(%aI{GQcw3@}T7f%UhPWE$>*~vuwBQuwa==+ieXh|RcTdibXy}As|G8URf|=tRj*aQ)sWS&)qSf+R!^*+TfMY;XZ6wQ3lTzGMU)`Ii3p-3QI)7h zR3~Z>jfoaSBGHCuPjn)Zi8P`&(T^BN3?{}A(}`yCSD}g z5U&#N5*vstVhfQ=Y$x^;hlnG@G2$Ze3Gq4cCGj=!Bk>CfLRw9Nk&q-wk`zgXgeGZ_ zG)dYdGZK+xL$W71kv5WOByW-*DUcLG3L_w3YHg{~eHa#{xn?ajln<<+an|YfBo1bi9 zwi|3W+J@Q2+Q!=^*{0ZL+ithrX?wu-nC(ehrtN9l3fn5%^R}04YiwI>du{t|hir#! zXKZI}=WUSG)&b?9R{zy>)_zv z?6A?n$05)m#39^avqP*yyhEbH4u?XAI)^5QZijw{A%_u%Nr!2NIfwfWzc{>gTUQQA@6QPXjQqpqWYqp_ozBi1p>ahKz1$J>sBjvt&>Il-LPISD(dI~h6| zIT<^dI@vgZ&LvI`PE;qFlc$rnQ-o8bQ8moeP`~I-hbbc0TP~;#}?A z?%e16%w?5}q6@|a?_%jfabaG|@zxNLDrbV+eZbE$IaclokW zf1}sNJsYoV?AkcGabn~2#<`6THZE>_=L&I!xvp~+aTRk#xvIFTyK1`Xxazwaxth4z zxO%#7bhpM>V9HP|c}$swI^~wWT^xovE%=4=RP~ zN%f)nQ-i3X)Cek_8bjSeO{At!)2Umj+0>oXT=NYCW}y+DvVwwo|*Pz0`i{5Ost)PMxC8Qtwk2sXtSHp+2L&p#Dbv zo%){oiTVdkhz6ytr3ur-XmFY&O@<~3ZT)M=Wu4K!Vv0nM0ZM#Ir8XhfO~&7S5& z+emW2x!k$K+1W!v(f6oZdD9VXaeSY?N>AIYs1s-!XddVp7!(*1xF_&X;E}-Ff$YGRz`4LjfxiT;3qk}*1{nug1X%?I z2W<|D3ECZWFz9g5?I3ngOVC2l)1c?UV!<-Oa=~`NZowYGJA(HH?+d;Zd^7k~@I>%~ z;KdMFh5F@kp7V8A#X$8hay82LX|=- zLc!$pp$Vaxq1!@_g`N&A31x+Lgm#6k3KIzv3o{ENhFOP2g(ZX~g`EsL8&(#^4eJZ* z4|@^zKI~(-RJc;OO1OQvd-$gCxbU>_jPRoH((v-|ws2nfK={+}H{ow1WFu4~)FWIY zJR`g#@*@f(jzwIJxEoO)F%$7H;!)(pe5Y-mNiyDafE$UO$7rGYRkZw#51Q*3O(+|>5 z(iwC%y_4Qee@cHtf4dp68MRq)v;AiG&6_rF-JH95_vYHocQ)VKJhAz~=EZ2SXqjla zXq)Jb(QeVn(OJ>kqbs5>M_-BVj~oc9;+LxAL|tx92**&8(R>2Ft#qXDV81kAofY@vp9)3xj0muWt>BtQ(RnJT3kll zg}Cc+H{%xLp2hvT#b^s*i{+M`Tk^N;-_p5da0@?PI9@VdI^HinJU%l1V*HKxy7(vY zuj7ADz$e%y*eC2yIF@iCVKiYb;eMi6qD-P(;-*C3ME}I&iDweeCO$}flK3o1IY~PS zlN6Pdkd%~kHR*0rebTQf1fuI;$7@{GCsR+ho#dSyC{iubFES`HEHW-472PdrC}I`06mg3>in@#XiUx}KMWaO% zMbkxdMGuO8Dtc7(r099k%c9psZ;L(@eJ=XSSjB)b)-gmF;tT{siXqEDF_ajp3^YTF zfnn$|3>hX2a|WJa$sjRo84e6*hAYE^L1B0@d>HIw9lbOrh!^~$EFb^>cna7zY znH9_`=6U9&Q*o!Zp2|A4<)X@RA25zm~i#d0q1M ztixIASqI{}+w)}oYc|~o-wThb+w<}XB zb1HKy_f+OrPFDV0`MC0F<*!v&s~W3VRV`KAbCTy& l&Jh$Q8!nqgcUY&b$?p?KG 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 literal 0 HcmV?d00001 diff --git a/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/Clocker.xcscheme b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/Clocker.xcscheme new file mode 100644 index 0000000..912ba2b --- /dev/null +++ b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/Clocker.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..5ec2516 --- /dev/null +++ b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + Clocker.xcscheme + + orderHint + 1 + + + SuppressBuildableAutocreation + + DD4F7C0313C30F9F00825C6E + + primary + + + + + diff --git a/Clocker/ApplicationDelegate.h b/Clocker/ApplicationDelegate.h new file mode 100755 index 0000000..4588e0e --- /dev/null +++ b/Clocker/ApplicationDelegate.h @@ -0,0 +1,39 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "MenubarController.h" +#import "PanelController.h" + +@interface ApplicationDelegate : NSObject + +@property (nonatomic, strong) MenubarController *menubarController; +@property (nonatomic, strong, readonly) PanelController *panelController; + +- (IBAction)togglePanel:(id)sender; + +@end diff --git a/Clocker/ApplicationDelegate.m b/Clocker/ApplicationDelegate.m new file mode 100755 index 0000000..cd12f81 --- /dev/null +++ b/Clocker/ApplicationDelegate.m @@ -0,0 +1,97 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "ApplicationDelegate.h" + +@implementation ApplicationDelegate + +@synthesize panelController = _panelController; +@synthesize menubarController = _menubarController; + +#pragma mark - + +- (void)dealloc +{ + [self.panelController removeObserver:self forKeyPath:@"hasActivePanel"]; +} + +#pragma mark - + +void *kContextActivePanel = &kContextActivePanel; + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (context == kContextActivePanel) { + self.menubarController.hasActiveIcon = self.panelController.hasActivePanel; + } + else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +#pragma mark - NSApplicationDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + // Install icon into the menu bar + self.menubarController = [[MenubarController alloc] init]; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + // Explicitly remove the icon from the menu bar + self.menubarController = nil; + return NSTerminateNow; +} + +#pragma mark - Actions + +- (IBAction)togglePanel:(id)sender +{ + self.menubarController.hasActiveIcon = !self.menubarController.hasActiveIcon; + self.panelController.hasActivePanel = self.menubarController.hasActiveIcon; +} + +#pragma mark - Public accessors + +- (PanelController *)panelController +{ + if (_panelController == nil) { + _panelController = [[PanelController alloc] initWithDelegate:self]; + [_panelController addObserver:self forKeyPath:@"hasActivePanel" options:0 context:kContextActivePanel]; + } + return _panelController; +} + +#pragma mark - PanelControllerDelegate + +- (StatusItemView *)statusItemViewForPanelController:(PanelController *)controller +{ + return self.menubarController.statusItemView; +} + +@end diff --git a/Clocker/BackgroundView.h b/Clocker/BackgroundView.h new file mode 100755 index 0000000..00fef8b --- /dev/null +++ b/Clocker/BackgroundView.h @@ -0,0 +1,40 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#define ARROW_WIDTH 12 +#define ARROW_HEIGHT 12 + +@interface BackgroundView : NSView +{ + NSInteger _arrowX; +} + +@property (nonatomic, assign) NSInteger arrowX; +@property (nonatomic, strong) NSTrackingArea *trackingArea; + +@end diff --git a/Clocker/BackgroundView.m b/Clocker/BackgroundView.m new file mode 100755 index 0000000..c048454 --- /dev/null +++ b/Clocker/BackgroundView.m @@ -0,0 +1,144 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "BackgroundView.h" + +#define FILL_OPACITY 0.9f +#define STROKE_OPACITY 1.0f + +#define LINE_THICKNESS 1.0f +#define CORNER_RADIUS 6.0f + +#define SEARCH_INSET 10.0f +#import "ApplicationDelegate.h" +#import "PanelController.h" + +#pragma mark - + +@implementation BackgroundView + + +@synthesize arrowX = _arrowX; + +#pragma mark - + +- (void)drawRect:(NSRect)dirtyRect +{ + NSRect contentRect = NSInsetRect([self bounds], LINE_THICKNESS, LINE_THICKNESS); + NSBezierPath *path = [NSBezierPath bezierPath]; + + [path moveToPoint:NSMakePoint(_arrowX, NSMaxY(contentRect))]; + [path lineToPoint:NSMakePoint(_arrowX + ARROW_WIDTH / 2, NSMaxY(contentRect) - ARROW_HEIGHT)]; + [path lineToPoint:NSMakePoint(NSMaxX(contentRect) - CORNER_RADIUS, NSMaxY(contentRect) - ARROW_HEIGHT)]; + + NSPoint topRightCorner = NSMakePoint(NSMaxX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT); + [path curveToPoint:NSMakePoint(NSMaxX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT - CORNER_RADIUS) + controlPoint1:topRightCorner controlPoint2:topRightCorner]; + + [path lineToPoint:NSMakePoint(NSMaxX(contentRect), NSMinY(contentRect) + CORNER_RADIUS)]; + + NSPoint bottomRightCorner = NSMakePoint(NSMaxX(contentRect), NSMinY(contentRect)); + [path curveToPoint:NSMakePoint(NSMaxX(contentRect) - CORNER_RADIUS, NSMinY(contentRect)) + controlPoint1:bottomRightCorner controlPoint2:bottomRightCorner]; + + [path lineToPoint:NSMakePoint(NSMinX(contentRect) + CORNER_RADIUS, NSMinY(contentRect))]; + + [path curveToPoint:NSMakePoint(NSMinX(contentRect), NSMinY(contentRect) + CORNER_RADIUS) + controlPoint1:contentRect.origin controlPoint2:contentRect.origin]; + + [path lineToPoint:NSMakePoint(NSMinX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT - CORNER_RADIUS)]; + + NSPoint topLeftCorner = NSMakePoint(NSMinX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT); + [path curveToPoint:NSMakePoint(NSMinX(contentRect) + CORNER_RADIUS, NSMaxY(contentRect) - ARROW_HEIGHT) + controlPoint1:topLeftCorner controlPoint2:topLeftCorner]; + + [path lineToPoint:NSMakePoint(_arrowX - ARROW_WIDTH / 2, NSMaxY(contentRect) - ARROW_HEIGHT)]; + [path closePath]; + + [[NSColor colorWithDeviceWhite:1 alpha:FILL_OPACITY] setFill]; + [path fill]; + + [NSGraphicsContext saveGraphicsState]; + + NSBezierPath *clip = [NSBezierPath bezierPathWithRect:[self bounds]]; + [clip appendBezierPath:path]; + [clip addClip]; + + [path setLineWidth:LINE_THICKNESS * 2]; + [[NSColor whiteColor] setStroke]; + [path stroke]; + + [NSGraphicsContext restoreGraphicsState]; +} + +-(void)mouseEntered:(NSEvent *)theEvent +{ + [super mouseEntered:theEvent]; + + ApplicationDelegate *delegate = (ApplicationDelegate*)[NSApplication sharedApplication].delegate; + PanelController *controller = delegate.panelController; + + [controller showOptions:YES]; +} + +-(void)mouseExited:(NSEvent *)theEvent +{ + [super mouseExited:theEvent]; + + ApplicationDelegate *delegate = (ApplicationDelegate*) [NSApplication sharedApplication].delegate; + PanelController *controller = delegate.panelController; + + [controller showOptions:NO]; +} + +-(void)updateTrackingAreas +{ + if(self.trackingArea != nil) { + [self removeTrackingArea:self.trackingArea]; + } + + int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways); + self.trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds] + options:opts + owner:self + userInfo:nil]; + [self addTrackingArea:self.trackingArea]; +} + + + +#pragma mark - +#pragma mark Public accessors + +- (void)setArrowX:(NSInteger)value +{ + _arrowX = value; + [self setNeedsDisplay:YES]; +} + +@end diff --git a/Clocker/Clock.jpeg b/Clocker/Clock.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..7c90aeea56e3631232118dfdd19db4721aec51b9 GIT binary patch literal 1149 zcmex=kR1VRQz zDF#+Bn}NZLQ5wz;V$^`DVPart&tzbMs)+*9AdmpWK;2N9Wl|dhJCIib#1j@UB1~Vv z1lK9HfEmsf0;*$h40iVP1k#?liRq~dIho0+dBv$I3MKgpQHfPmIjIVsdC7VTjyX9B zrFn^^B^mienN>jf(&AKw%wmOtqWp}^q|B1k6g`C$)1*`bvt$!pW3!Z0T@$kuQ{5y} zlO$b(WMea9qZD(KG_xd-jlj@&%U}_ZkzbNuoRMFkV611rVBzHH%L4Kp5P;dLV5Yzo z*`AyI44YV9HgL{(^TVm`{{aR;4hA6xF=j?V1|~s9WuA0}~@NGZPClD=Wwv##*2}1B)Q5kfNa@n{Z$vyHcTuQRBpg9Li1` z4~hm|{Gei-RMf=DB_=K*DW$5WuA!-AVrph?VQJ;;;_Bw^;pr6|5*ijB5gC=7lA4yD zk(pIoQd(ACQCZd8(%RPE(b+X=@|3C5rq7r;YtiB*OP4KQv2xX>&0Dr^+rDGxu0w~9 z96fgY#K}{aE?>EN?fQ+Iw;n!v{N(Ag=PzEq`uOSdm#^Qx|M>X}K zQ!#m{`Vr(cu+NC|SQA-3gL@3&uiFgH3@psdAOv(c(A}(TTz{|AtERwF2u(#DkCZ`DJd;2Eg&K*FDoT4Atf#KA7}_83o9!dD;p0xJCBqgzn~P! z;Qw7r-}4kD`-FKbXH|jdWLjW0uw7ksCbm$#Nt)=oE&ECs$Fx;d(H&2 zr|y1>KP=$B6*}AW>D@OUj!S!$wL8^UEPgkM--+S42;={Yzdv3vP;5x-YYAZ0&{c@+ T))CZ}TcU7s0r#T@`~Noq9qMCk literal 0 HcmV?d00001 diff --git a/Clocker/Clocker-Info.plist b/Clocker/Clocker-Info.plist new file mode 100755 index 0000000..6ecfb64 --- /dev/null +++ b/Clocker/Clocker-Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 8 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + LSUIElement + + NSHumanReadableCopyright + Copyright © 2011, 2012 Shpakovski + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Clocker/Clocker-Prefix.pch b/Clocker/Clocker-Prefix.pch new file mode 100755 index 0000000..096da72 --- /dev/null +++ b/Clocker/Clocker-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header for all source files of the 'Clocker' target in the 'Clocker' project +// + +#ifdef __OBJC__ + +#import + +#endif diff --git a/Clocker/ColoredButton.h b/Clocker/ColoredButton.h new file mode 100644 index 0000000..a251010 --- /dev/null +++ b/Clocker/ColoredButton.h @@ -0,0 +1,36 @@ +// +// ColoredButton.h +// Clocker +// +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@interface ColoredButton : NSButton + +@end diff --git a/Clocker/ColoredButton.m b/Clocker/ColoredButton.m new file mode 100644 index 0000000..b34f95e --- /dev/null +++ b/Clocker/ColoredButton.m @@ -0,0 +1,61 @@ +// +// ColoredButton.m +// Clocker +// +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "ColoredButton.h" + +@implementation ColoredButton + +- (void)setButtonTitleFor:(NSButton*)button toString:(NSString*)title withColor:(NSColor*)color +{ + NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; + [style setAlignment:NSLeftTextAlignment]; + NSFont *font = [NSFont fontWithName:@"HelveticaNeue-Light" size:13.0]; + NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:color, NSForegroundColorAttributeName, style, NSParagraphStyleAttributeName, font,NSFontAttributeName, nil]; + + + NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc]initWithString:title attributes:attrsDictionary]; + [attrString setAlignment:NSTextAlignmentLeft range:NSMakeRange(0, self.title.length)]; + + + [button setAttributedTitle:attrString]; +} + +-(void)awakeFromNib +{ + NSString *title = self.title; + NSColor *color = [NSColor blackColor]; + [self setButtonTitleFor:self toString:title withColor:color]; +} + + + +@end diff --git a/Clocker/MenubarController.h b/Clocker/MenubarController.h new file mode 100755 index 0000000..aec5db5 --- /dev/null +++ b/Clocker/MenubarController.h @@ -0,0 +1,44 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#define STATUS_ITEM_VIEW_WIDTH 24.0 + +#pragma mark - + +@class StatusItemView; + +@interface MenubarController : NSObject { +@private + StatusItemView *_statusItemView; +} + +@property (nonatomic) BOOL hasActiveIcon; +@property (nonatomic, strong, readonly) NSStatusItem *statusItem; +@property (nonatomic, strong, readonly) StatusItemView *statusItemView; + +@end diff --git a/Clocker/MenubarController.m b/Clocker/MenubarController.m new file mode 100755 index 0000000..003ddf8 --- /dev/null +++ b/Clocker/MenubarController.m @@ -0,0 +1,52 @@ + + +#import "MenubarController.h" +#import "StatusItemView.h" + +@implementation MenubarController + +@synthesize statusItemView = _statusItemView; + +#pragma mark - + +- (id)init +{ + self = [super init]; + if (self != nil) + { + // Install status item into the menu bar + NSStatusItem *statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:STATUS_ITEM_VIEW_WIDTH]; + _statusItemView = [[StatusItemView alloc] initWithStatusItem:statusItem]; + _statusItemView.image = [NSImage imageNamed:@"Status"]; + _statusItemView.alternateImage = [NSImage imageNamed:@"StatusHighlighted"]; + _statusItemView.action = @selector(togglePanel:); + } + return self; +} + +- (void)dealloc +{ + [[NSStatusBar systemStatusBar] removeStatusItem:self.statusItem]; +} + +#pragma mark - +#pragma mark Public accessors + +- (NSStatusItem *)statusItem +{ + return self.statusItemView.statusItem; +} + +#pragma mark - + +- (BOOL)hasActiveIcon +{ + return self.statusItemView.isHighlighted; +} + +- (void)setHasActiveIcon:(BOOL)flag +{ + self.statusItemView.isHighlighted = flag; +} + +@end diff --git a/Clocker/Panel.h b/Clocker/Panel.h new file mode 100755 index 0000000..949513e --- /dev/null +++ b/Clocker/Panel.h @@ -0,0 +1,30 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +@interface Panel : NSPanel +@end diff --git a/Clocker/Panel.m b/Clocker/Panel.m new file mode 100755 index 0000000..5a2c893 --- /dev/null +++ b/Clocker/Panel.m @@ -0,0 +1,54 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "Panel.h" + +@implementation Panel + +- (BOOL)canBecomeKeyWindow; +{ + return YES; // Allow Search field to become the first responder +} + + +- (BOOL)canBecomeMainWindow +{ + return YES; +} + +-(void)keyDown:(NSEvent *)theEvent +{ + [super keyDown:theEvent]; + + if (theEvent.keyCode == 53) { + [self close]; + } +} + + +@end diff --git a/Clocker/Panel.xib b/Clocker/Panel.xib new file mode 100755 index 0000000..f5cbb3c --- /dev/null +++ b/Clocker/Panel.xib @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Clocker/PanelController.h b/Clocker/PanelController.h new file mode 100755 index 0000000..dc1cef7 --- /dev/null +++ b/Clocker/PanelController.h @@ -0,0 +1,78 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "BackgroundView.h" +#import "StatusItemView.h" +#import "PreferencesWindowController.h" + +@class PanelController; + +@protocol PanelControllerDelegate + +@optional + +- (StatusItemView *)statusItemViewForPanelController:(PanelController *)controller; + +@end + +#pragma mark - + +@interface PanelController : NSWindowController +{ + BOOL _hasActivePanel; + __unsafe_unretained BackgroundView *_backgroundView; + __unsafe_unretained id _delegate; + __unsafe_unretained NSSearchField *_searchField; + __unsafe_unretained NSTextField *_textField; +} + +@property (nonatomic, unsafe_unretained) IBOutlet BackgroundView *backgroundView; +@property (nonatomic, strong) PreferencesWindowController *preferencesWindow; +@property (nonatomic, strong) NSMutableArray *defaultPreferences; + +@property (nonatomic) BOOL hasActivePanel; +@property (nonatomic, unsafe_unretained, readonly) id delegate; +@property (weak) IBOutlet NSTableView *mainTableview; +@property (weak) IBOutlet NSScrollView *scrollView; + +@property (weak) IBOutlet NSLayoutConstraint *scrollViewHeight; + +@property (weak) IBOutlet NSButton *shutdownButton; +@property (weak) IBOutlet NSButton *preferencesButton; +@property (weak) IBOutlet NSTextField *logoLabel; + + + +- (id)initWithDelegate:(id)delegate; + +- (void)openPanel; +- (void)closePanel; +- (void) updateDefaultPreferences; +- (void)showOptions:(BOOL)value; + +@end diff --git a/Clocker/PanelController.m b/Clocker/PanelController.m new file mode 100755 index 0000000..6838328 --- /dev/null +++ b/Clocker/PanelController.m @@ -0,0 +1,433 @@ +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "PanelController.h" +#import "BackgroundView.h" +#import "StatusItemView.h" +#import "MenubarController.h" + +#define OPEN_DURATION .15 +#define CLOSE_DURATION .1 + +#define SEARCH_INSET 17 + +#define POPUP_HEIGHT 300 +#define PANEL_WIDTH 280 +#define MENU_ANIMATION_DURATION .1 + +#define BUFFER 2 +#define MAX_TALL 15 + +#pragma mark - + +#import "PreferencesWindowController.h" + +@implementation PanelController + + + +#pragma mark - + +- (id)initWithDelegate:(id)delegate +{ + self = [super initWithWindowNibName:@"Panel"]; + if (self != nil) + { + _delegate = delegate; + self.window.backgroundColor = [NSColor whiteColor]; + } + return self; +} + +#pragma mark - + +- (void)awakeFromNib +{ + [super awakeFromNib]; + + [self updateDefaultPreferences]; + + // Make a fully skinned panel + NSPanel *panel = (id)[self window]; + [panel setAcceptsMouseMovedEvents:YES]; + [panel setLevel:NSPopUpMenuWindowLevel]; + [panel setOpaque:NO]; + [panel setBackgroundColor:[NSColor clearColor]]; + + //Register for drag and drop + [self.mainTableview registerForDraggedTypes: [NSArray arrayWithObject: @"public.text"]]; + +} + +- (void) updateDefaultPreferences +{ + NSArray *defaultZones = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultPreferences"]; + + if (self.defaultPreferences == nil) + { + self.defaultPreferences = [[NSMutableArray alloc] initWithArray:defaultZones]; + } + else + { + self.defaultPreferences = [NSMutableArray arrayWithArray:defaultZones]; + } + + + if (self.defaultPreferences.count <= 10) { + self.scrollViewHeight.constant = self.window.contentView.frame.size.height; + } + else + { + self.scrollViewHeight.constant = 550; + } +} + +#pragma mark - Public accessors + +- (BOOL)hasActivePanel +{ + return _hasActivePanel; +} + +- (void)setHasActivePanel:(BOOL)flag +{ + if (_hasActivePanel != flag) + { + _hasActivePanel = flag; + + if (_hasActivePanel) + { + [self openPanel]; + } + else + { + [self closePanel]; + } + } +} + +#pragma mark - NSWindowDelegate + +- (void)windowWillClose:(NSNotification *)notification +{ + self.hasActivePanel = NO; +} + +- (void)windowDidResignKey:(NSNotification *)notification; +{ + if ([[self window] isVisible]) + { + self.hasActivePanel = NO; + } +} + +- (void)windowDidResize:(NSNotification *)notification +{ + NSWindow *panel = [self window]; + NSRect statusRect = [self statusRectForWindow:panel]; + NSRect panelRect = [panel frame]; + + CGFloat statusX = roundf(NSMidX(statusRect)); + CGFloat panelX = statusX - NSMinX(panelRect); + + self.backgroundView.arrowX = panelX; + +} + +#pragma mark - Keyboard + +- (void)cancelOperation:(id)sender +{ + self.hasActivePanel = NO; +} + +#pragma mark - Public methods + +- (NSRect)statusRectForWindow:(NSWindow *)window +{ + NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; + NSRect statusRect = NSZeroRect; + + StatusItemView *statusItemView = nil; + if ([self.delegate respondsToSelector:@selector(statusItemViewForPanelController:)]) + { + statusItemView = [self.delegate statusItemViewForPanelController:self]; + } + + if (statusItemView) + { + statusRect = statusItemView.globalRect; + statusRect.origin.y = NSMinY(statusRect) - NSHeight(statusRect); + } + else + { + statusRect.size = NSMakeSize(STATUS_ITEM_VIEW_WIDTH, [[NSStatusBar systemStatusBar] thickness]); + statusRect.origin.x = roundf((NSWidth(screenRect) - NSWidth(statusRect)) / 2); + statusRect.origin.y = NSHeight(screenRect) - NSHeight(statusRect) * 2; + } + return statusRect; +} + +- (void)openPanel +{ + NSWindow *panel = [self window]; + + NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; + NSRect statusRect = [self statusRectForWindow:panel]; + + + NSRect panelRect = [panel frame]; + panelRect.size.width = PANEL_WIDTH; + + if (self.defaultPreferences.count <= 10) + { + panelRect.size.height = self.defaultPreferences.count*55 + 30; + } + else + { + panelRect.size.height = 500; + } + + panelRect.origin.x = roundf(NSMidX(statusRect) - NSWidth(panelRect) / 2); + panelRect.origin.y = NSMaxY(statusRect) - NSHeight(panelRect); + + if (NSMaxX(panelRect) > (NSMaxX(screenRect) - ARROW_HEIGHT)) + panelRect.origin.x -= NSMaxX(panelRect) - (NSMaxX(screenRect) - ARROW_HEIGHT); + + [NSApp activateIgnoringOtherApps:NO]; + [panel setAlphaValue:0]; + [panel setFrame:statusRect display:YES]; + [panel makeKeyAndOrderFront:nil]; + + NSTimeInterval openDuration = OPEN_DURATION; + + NSEvent *currentEvent = [NSApp currentEvent]; + if ([currentEvent type] == NSLeftMouseDown) + { + NSUInteger clearFlags = ([currentEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask); + BOOL shiftPressed = (clearFlags == NSShiftKeyMask); + BOOL shiftOptionPressed = (clearFlags == (NSShiftKeyMask | NSAlternateKeyMask)); + if (shiftPressed || shiftOptionPressed) + { + openDuration *= 5; + + if (shiftOptionPressed) + NSLog(@"Icon is at %@\n\tMenu is on screen %@\n\tWill be animated to %@", + NSStringFromRect(statusRect), NSStringFromRect(screenRect), NSStringFromRect(panelRect)); + } + } + + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:openDuration]; + [[panel animator] setFrame:panelRect display:YES]; + [[panel animator] setAlphaValue:1]; + [NSAnimationContext endGrouping]; + +} + +- (void)closePanel +{ + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:CLOSE_DURATION]; + [[[self window] animator] setAlphaValue:0]; + [NSAnimationContext endGrouping]; + + dispatch_after(dispatch_walltime(NULL, NSEC_PER_SEC * CLOSE_DURATION * 2), dispatch_get_main_queue(), ^{ + + [self.window orderOut:nil]; + }); +} + +-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return self.defaultPreferences.count; +} + +-(NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + NSTableCellView *cell = [tableView makeViewWithIdentifier:@"timeZoneCell" owner:self]; + + NSTextField *cellText = [cell viewWithTag:100]; + + NSTextField *timeCell = [cell viewWithTag:101]; + + NSTextField *dateCell = [cell viewWithTag:102]; + + dateCell.stringValue = [self getDateForTimeZone:self.defaultPreferences[row]]; + + timeCell.stringValue = [self getTimeForTimeZone:self.defaultPreferences[row]]; + + NSNumber *shouldShowOnlyCity = [[NSUserDefaults standardUserDefaults] objectForKey:@"showOnlyCity"]; + + cellText.stringValue = [self formatStringShouldContainCity:shouldShowOnlyCity.boolValue withTimezoneName:self.defaultPreferences[row]]; + + return cell; +} + +- (NSString *)formatStringShouldContainCity:(BOOL)value withTimezoneName:(NSString *)name +{ + if (value) { + NSRange range = [name rangeOfString:@"/"]; + + if (range.location != NSNotFound) { + return [name substringFromIndex:range.location+1]; + } + } + + return name; +} + +- (NSString *)getTimeForTimeZone:(NSString *)timezoneName +{ + NSDate *currentDate = [NSDate date]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.dateStyle = kCFDateFormatterNoStyle; + + NSNumber *is24HourFormatSelected = [[NSUserDefaults standardUserDefaults] objectForKey:@"is24HourFormatSelected"]; + + is24HourFormatSelected.boolValue ? [dateFormatter setDateFormat:@"HH:mm"] : [dateFormatter setTimeStyle:NSDateFormatterShortStyle]; + + dateFormatter.timeZone = [NSTimeZone timeZoneWithName:timezoneName]; + //In the format 22:10 + + return [dateFormatter stringFromDate:currentDate]; +} + +- (NSString *)getLocalCurrentDate +{ + NSDate *currentDate = [NSDate date]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.dateStyle = kCFDateFormatterShortStyle; + dateFormatter.timeStyle = kCFDateFormatterNoStyle; + + + + dateFormatter.timeZone = [NSTimeZone systemTimeZone]; + + return [dateFormatter stringFromDate:currentDate]; + +} + +- (NSString *)compareSystemDate:(NSString *)systemDate toTimezoneDate:(NSString *)date +{ + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"MM/dd/yy"; + + NSDate *localDate = [formatter dateFromString:systemDate]; + NSDate *timezoneDate = [formatter dateFromString:date]; + + // Specify which units we would like to use + unsigned units = NSCalendarUnitDay; + NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + NSInteger systemDay = [calendar component:units fromDate:localDate]; + NSInteger timezoneDay = [calendar component:units fromDate:timezoneDate]; + + if (systemDay == timezoneDay) { + return @"Today"; + } + else if (systemDay > timezoneDay) + { + return @"Yesterday"; + } + else + { + return @"Tomorrow"; + } + + + +} + +- (NSString *)getDateForTimeZone:(NSString *)timezoneName +{ + NSDate *currentDate = [NSDate date]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.dateStyle = kCFDateFormatterShortStyle; + dateFormatter.timeStyle = kCFDateFormatterNoStyle; + + dateFormatter.timeZone = [NSTimeZone timeZoneWithName:timezoneName]; + //In the format 22:10 + + return [self compareSystemDate:[self getLocalCurrentDate] toTimezoneDate:[dateFormatter stringFromDate:currentDate]];; +} + +- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard +{ + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes]; + + [pboard declareTypes:[NSArray arrayWithObject:@"public.text"] owner:self]; + + [pboard setData:data forType:@"public.text"]; + + return YES; +} + + +-(BOOL)tableView:(NSTableView *)tableView acceptDrop:(id)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation +{ + NSPasteboard *pBoard = [info draggingPasteboard]; + + NSData *data = [pBoard dataForType:@"public.text"]; + + NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + + [self.defaultPreferences exchangeObjectAtIndex:rowIndexes.firstIndex withObjectAtIndex:row]; + + [[NSUserDefaults standardUserDefaults] setObject:self.defaultPreferences forKey:@"defaultPreferences"]; + + [self.mainTableview reloadData]; + + return YES; +} + +-(NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation +{ + return NSDragOperationEvery; +} + + + +- (IBAction)openPreferences:(id)sender +{ + self.preferencesWindow = [PreferencesWindowController sharedPreferences]; + [self.preferencesWindow showWindow:nil]; + + [NSApp activateIgnoringOtherApps:YES]; + +} + +- (void)showOptions:(BOOL)value +{ + if (self.defaultPreferences.count > 0) { + self.shutdownButton.hidden = !value; + self.preferencesButton.hidden = !value; + } +} + +@end diff --git a/Clocker/PowerIcon.png b/Clocker/PowerIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..50e5ca059ce781043ca010e8c2264350b1f8c063 GIT binary patch literal 17462 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addToFavorites: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Clocker/PreferencesWindowController.h b/Clocker/PreferencesWindowController.h new file mode 100644 index 0000000..3e0268b --- /dev/null +++ b/Clocker/PreferencesWindowController.h @@ -0,0 +1,46 @@ +// +// PreferencesWindowController.h +// Clocker +// +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import + +@class AvailableTimezonesPanel; + +@interface PreferencesWindowController : NSWindowController + +@property (strong, nonatomic) NSMutableArray *timeZoneArray; +@property (strong, nonatomic) NSMutableArray *selectedTimeZones; +@property (strong, nonatomic) NSArray *filteredArray; +@property (strong, nonatomic) NSArray *fontFamilies; +@property (atomic, assign) BOOL launchOnLogin; + ++ (instancetype)sharedPreferences; + +@end diff --git a/Clocker/PreferencesWindowController.m b/Clocker/PreferencesWindowController.m new file mode 100644 index 0000000..dc3e510 --- /dev/null +++ b/Clocker/PreferencesWindowController.m @@ -0,0 +1,412 @@ +// +// PreferencesWindowController.m +// Clocker +// +// Created by Abhishek Banthia on 11/4/15. +// Copyright (c) 2015 Abhishek Banthia All rights reserved. +// + +// Copyright (c) 2015, Abhishek Banthia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "PreferencesWindowController.h" +#import "Panel.h" +#import "PanelController.h" +#import "ApplicationDelegate.h" + +@interface PreferencesWindowController () + +@property (weak) IBOutlet NSTableView *timezoneTableView; +@property (strong) IBOutlet Panel *timezonePanel; + +@property (weak) IBOutlet NSTableView *availableTimezoneTableView; +@property (weak) IBOutlet NSSearchField *searchField; + +@property (weak) IBOutlet NSButton *is24HourFormatSelected; +@property (weak) IBOutlet NSTextField *messageLabel; + +@end + +static PreferencesWindowController *sharedPreferences = nil; + +@implementation PreferencesWindowController + +- (void)windowDidLoad { + [super windowDidLoad]; + + NSMutableArray *defaultTimeZones = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultPreferences"]; + + if (!self.timeZoneArray || !self.selectedTimeZones) + { + self.timeZoneArray = [[NSMutableArray alloc] initWithArray:[NSTimeZone knownTimeZoneNames]]; + self.selectedTimeZones = [[NSMutableArray alloc] initWithArray:defaultTimeZones]; + self.filteredArray = [[NSArray alloc] init]; + } + + self.fontFamilies = [[NSArray alloc] initWithArray:[[NSFontManager sharedFontManager] availableFonts]]; + + self.messageLabel.stringValue = @""; + + [self.timezoneTableView reloadData]; + [self.availableTimezoneTableView reloadData]; + + //Register for drag and drop + [self.timezoneTableView registerForDraggedTypes: [NSArray arrayWithObject: @"public.text"]]; + + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. +} + +-(id)copyWithZone:(NSZone *)zone +{ + id copy = [[[self class] alloc] initWithWindowNibName:@"PreferencesWindow"]; + + if (copy) + { + self.timeZoneArray = [[NSMutableArray alloc] initWithArray:[NSTimeZone knownTimeZoneNames]]; + } + + return copy; +} + +-(BOOL)acceptsFirstResponder +{ + return YES; +} + ++ (instancetype)sharedPreferences +{ + if (sharedPreferences == nil) + { + /*Using a thread safe pattern*/ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedPreferences = [[self alloc] initWithWindowNibName:@"PreferencesWindow"]; + + }); + + } + + return sharedPreferences; +} + +-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + if (tableView == self.timezoneTableView) { + return self.selectedTimeZones.count; + } + else + { + if (self.searchField.stringValue.length > 0) { + return self.filteredArray.count; + } + return self.timeZoneArray.count; + } + + return 0; +} + +- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row +{ + if ([[tableColumn identifier] isEqualToString:@"timezoneName"]) + { + return self.selectedTimeZones[row]; + } + else if([[tableColumn identifier] isEqualToString:@"availableTimezones"]) + { + if (self.searchField.stringValue.length > 0) + { + return self.filteredArray[row]; + } + + return self.timeZoneArray[row];; + } + if ([tableColumn.identifier isEqualToString:@"abbreviation"]) + { + return [NSTimeZone timeZoneWithName:self.timeZoneArray[row]].abbreviation; + } + + return nil; + +} + +- (IBAction)addTimeZone:(id)sender +{ + + [self.window beginSheet:self.timezonePanel completionHandler:^(NSModalResponse returnCode) { + + }]; +} + +- (IBAction)addToFavorites:(id)sender +{ + NSString *selectedTimezone; + + if (self.selectedTimeZones.count > 9) + { + self.messageLabel.stringValue = @"Maximum 10 timezones allowed!"; + [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO]; + return; + } + + for (NSString *name in self.selectedTimeZones) + { + if (self.searchField.stringValue.length > 0) { + if ([name isEqualToString:self.filteredArray[self.availableTimezoneTableView.selectedRow]]) + { + self.messageLabel.stringValue = @"Timezone has already been selected!"; + [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO]; + return; + } + } + else if ([name isEqualToString:self.timeZoneArray[self.availableTimezoneTableView.selectedRow]]) + { + self.messageLabel.stringValue = @"Timezone has already been selected!"; + [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO]; + return; + } + } + + + selectedTimezone = self.searchField.stringValue.length > 0 ? self.filteredArray[self.availableTimezoneTableView.selectedRow] : self.timeZoneArray[self.availableTimezoneTableView.selectedRow]; + + [self.selectedTimeZones addObject:selectedTimezone]; + + NSArray *defaultTimeZones = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultPreferences"]; + NSMutableArray *newDefaults; + + if (defaultTimeZones == nil) + { + defaultTimeZones = [[NSMutableArray alloc] init]; + } + + newDefaults = [[NSMutableArray alloc] initWithArray:defaultTimeZones]; + + [newDefaults addObject:selectedTimezone]; + + [[NSUserDefaults standardUserDefaults] setObject:newDefaults forKey:@"defaultPreferences"]; + + [self.timezoneTableView reloadData]; + + [self refreshMainTableview]; + + [self.timezonePanel close]; +} + +- (void)clearLabel +{ + self.messageLabel.stringValue = @""; +} + +- (IBAction)closePanel:(id)sender +{ + [self.timezonePanel close]; +} + +- (IBAction)removeFromFavourites:(id)sender +{ + + NSMutableArray *itemsToRemove = [NSMutableArray array]; + + if (self.timezoneTableView.selectedRow == -1) + { + return; + } + + [self.timezoneTableView.selectedRowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { + + [itemsToRemove addObject:self.selectedTimeZones[idx]]; + + }]; + + [self.selectedTimeZones removeObjectsInArray:itemsToRemove]; + + + NSArray *defaultTimeZones = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultPreferences"]; + NSMutableArray *newDefaults; + + if (defaultTimeZones == nil) + { + defaultTimeZones = [[NSMutableArray alloc] init]; + } + + newDefaults = [[NSMutableArray alloc] initWithArray:self.selectedTimeZones]; + + + [[NSUserDefaults standardUserDefaults] setObject:newDefaults forKey:@"defaultPreferences"]; + + [self.timezoneTableView reloadData]; + + [self refreshMainTableview]; +} + +-(void)keyDown:(NSEvent *)theEvent +{ + [super keyDown:theEvent]; + + if (theEvent.keyCode == 53) { + [self.timezonePanel close]; + } + +} + +-(void)keyUp:(NSEvent *)theEvent +{ + if (theEvent.keyCode == 53) { + [self.timezonePanel close]; + } +} + +- (IBAction)filterArray:(id)sender +{ + + if (self.searchField.stringValue.length > 0) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", self.searchField.stringValue]; + + self.filteredArray = [self.timeZoneArray filteredArrayUsingPredicate:predicate]; + } + + [self.availableTimezoneTableView reloadData]; +} +- (IBAction)timeFormatSelectionChanged:(id)sender { + + [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:self.is24HourFormatSelected.state] forKey:@"is24HourFormatSelected"]; + + [self refreshMainTableview]; +} + +- (void)refreshMainTableview +{ + ApplicationDelegate *appDelegate = [[NSApplication sharedApplication] delegate]; + + PanelController *panelController = appDelegate.panelController; + + [panelController updateDefaultPreferences]; + + [panelController.mainTableview reloadData]; + +} + +- (IBAction)showOnlyCityName:(id)sender { + + NSButton *checkbox = (NSButton *)sender; + + [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:checkbox.state] forKey:@"showOnlyCity"]; + + [self refreshMainTableview]; +} + +- (IBAction)startAppAtLogin:(id)sender +{ +} + +#pragma mark Reordering + +- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard +{ + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes]; + + [pboard declareTypes:[NSArray arrayWithObject:@"public.text"] owner:self]; + + [pboard setData:data forType:@"public.text"]; + + return YES; +} + + +-(BOOL)tableView:(NSTableView *)tableView acceptDrop:(id)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation +{ + NSPasteboard *pBoard = [info draggingPasteboard]; + + NSData *data = [pBoard dataForType:@"public.text"]; + + NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + + [self.selectedTimeZones exchangeObjectAtIndex:rowIndexes.firstIndex withObjectAtIndex:row]; + + [[NSUserDefaults standardUserDefaults] setObject:self.selectedTimeZones forKey:@"defaultPreferences"]; + + [self.timezoneTableView reloadData]; + + [self refreshMainTableview]; + + return YES; +} + +-(NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation +{ + return NSDragOperationEvery; +} + + +- (BOOL)launchOnLogin +{ + LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL); + NSArray* loginItems = CFBridgingRelease(snapshotRef); + NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; + for (id item in loginItems) { + LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item; + CFURLRef itemURLRef; + if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) { + NSURL *itemURL = (NSURL *)CFBridgingRelease(itemURLRef); + if ([itemURL isEqual:bundleURL]) { + return YES; + } + } + } + return NO; +} + +-(void)setLaunchOnLogin:(BOOL)launchOnLogin +{ + NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; + LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + + if (launchOnLogin) { + NSDictionary *properties; + properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"com.apple.loginitem.HideOnLaunch"]; + LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsListRef, kLSSharedFileListItemLast, NULL, NULL, (__bridge CFURLRef)bundleURL, (__bridge CFDictionaryRef)properties,NULL); + if (itemRef) { + CFRelease(itemRef); + } + } else { + LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL); + NSArray* loginItems = CFBridgingRelease(snapshotRef); + + for (id item in loginItems) { + LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item; + CFURLRef itemURLRef; + if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) { + NSURL *itemURL = (NSURL *)CFBridgingRelease(itemURLRef); + if ([itemURL isEqual:bundleURL]) { + LSSharedFileListItemRemove(loginItemsListRef, itemRef); + } + } + } + } +} + +@end diff --git a/Clocker/Status.png b/Clocker/Status.png new file mode 100755 index 0000000000000000000000000000000000000000..abccff70090b7368d6e26b856b846da4b76e9217 GIT binary patch literal 3487 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 Cac^P( literal 0 HcmV?d00001 diff --git a/Clocker/Status@2x.png b/Clocker/Status@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..0f94c71496ef9e26127ba82cecf6c5fc2f4e9c75 GIT binary patch literal 1502 zcmV<41tI#0P)?}s6AKlv?3RUHSoTt3kN%X1LPb7tn8?|kR`&-V|6QYt)42MHE% zR8&+@@7ruPzn&L`XYAN0z`G${|3?BQgz%7m!xEFw(9jYL{O!H}`;ec1Du4wB0J|c> zz`#J5hti`M9UUE8;Lf7~!_a{M4m#;#Vq(0V!C&&O+9EG_~)sbF!W)bluLeo_%2*gqEf4j$NHf}y#&wx4~`iO!>Dm| zhImM*9VN$0%ErdV-W3?tzMUXh3bj5oGbSl-mS3Rq!>k=IcBjAEdHwq5O;GjSgWI#{ zB@k%{xhtNYLL2R$9tINK8`LmNQ*8?p_%GaMVP?XDn;ivN2b8Ku9%1oiwaFmoD zzgm6vY(HGiL(D*!AsndbV5}KOcn)GKL?W_1I5_xX)tNID^Jeo4>h{mT`ly#suUDW+ zP_A1z;$q|Ood4wfh3xF?pE#=uvkwH}@qXe@ErIfgfY^a-JDtvLr#?FM!LV_7Kf^** z4KQkD)yQWCo~PfN85v(+y43WAR;x8Z)6Wnnh2_V|AeiFk4-(mzoBQ#+$@G%ovr%{# zhN=}EjuRUfJKcY)zuF%O1nYDjKEN*!lSZR)X~AMikw8i!O3>4f@eYaBv=h0*4Nj+0`J~WPfvHh zmY(i+{S!0d_c=4otWm)fVI`)H>!$8u`P5B5dEiHX(Vq)T( zw6wIFwY9Z3^m@IC8^9cQEH?)nrqm)3I~Nuf^za#VWPE%)@8#6geLqZ2-Wnbr-f+Mq zKR^F;PEO92%F0S~Dl2CdL9b+HX0G{K$B@y8tEhw629bak-_X#I*w@#$*52O!>0ep# zlK>pT?HTKeU%81eRzcpT8tnVzKllIP{{jEo0RJYy02OyFw;ga@*#H0l07*qoM6N<$ Ef;zv%3IG5A literal 0 HcmV?d00001 diff --git a/Clocker/StatusHighlighted.png b/Clocker/StatusHighlighted.png new file mode 100755 index 0000000000000000000000000000000000000000..8cff2c382911768f29accd8890d82139cac37659 GIT binary patch literal 389 zcmV;00eb$4P)m zbmD$3Od1BXaR^%U!GX&?-}(66%K`pcB=aQmasAtIjgI5gNNNBNiO5!IHk-Xor_(*@|Ow9Oq_v_B`)8Dcu>#A<2(W=@7Aw^adnPeez91r_j z*s{FucDt%jDAYw{5Endc7)H&u?UvR$OuInVTHChWG7RGuKzh?(5ddYS)G!*Xlo|pk zM_v+NB#%}RlRR8EyLKyl-@g(Ona}5eWmyf&vKm1U1R^57?_VaO1pwD|Uq++Rd!ho=%k3nh{$Kh8;+FBE!WIfw00000NkvXXu0mjfxn-;w literal 0 HcmV?d00001 diff --git a/Clocker/StatusHighlighted@2x.png b/Clocker/StatusHighlighted@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..b147bd83fe520662dfd25a1c600c7976a7e10890 GIT binary patch literal 1387 zcmV-x1(f=UP)SL&Q zBqBzINCgTZ2G{Yf?Ok)(ndzCG+4Y(LzCfKIbVAwH9Rn@mOO?y`=HB5&=iP9T|ut@-vh0eg|a5L~y1t@gJ>J*X=OfH+_)ui^Eum%O zJ1}570Jdoh3k#n?pJGht($eA=Oow*@#RX%^0(@W&^NEZO`_~x?g)UJZZxjrME-)Rk zFUm>8|0t?HC3K7t7IO9K_o1!r?F{HB)-eTYsMmhD)}ZSc8G?5R=&DW$0A&c<)0LH# zuc1#3!MXu@b#?VyW;6XjZ;cV-o)aY?H>Ww#bI6UCvgRn}_4*-WhsjaQOvfErxNXEeDE@XuajAu(~gy2nPgK-Kdh}-Sn z-rU?whr{92exU@4jW=ZxQ98wFG$V>fL@K(dm9HHup#vp}F-G6A(bO?Q!GluSB( zCEOJL71`KQ?p;D^XlVTX`j6LpRW&})1Q>etrReuH%Oj+tK} zH}GU4<#VoyNmJE_O-)UoLRV%KP_rub*ZQmS#lg6yeK$Pp^7(vk<-=tzU=N{LTqpwH zQzIiI>_xR~Hj8NmweCQb?%dh4AH(Lk%<^nftnhYL5K<@Hkw3DBx|)EUfx5cS^Od0x z9LjI3l^mGe@Avnyu?4njd?NMt_j{paf5;c5cFvK7#l@fDflr)hy$qaoQd>szdc8dZ z0|R~lFIV)zSK;+inw_0JlTIsCQ52e1_!AD`Vl)~(5B67?+!!7G5_EqlhCNNw>9pY& zn~j}gb3ngp_hHxa^53J10IDc5ei)1W)Y;j23T%xaJ|PVq9UZUF%*>2|A2xhtg|0k) z9A$G<6R; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Clocker/main.m b/Clocker/main.m new file mode 100755 index 0000000..9a29e3e --- /dev/null +++ b/Clocker/main.m @@ -0,0 +1,14 @@ +// +// main.m +// Clocker +// +// Created by Vadim Shpakovski on 7/5/11. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +}