Browse Source

Initial Commit

Localization
Abhishek Banthia 9 years ago
commit
bd6228efcb
  1. 401
      Clocker.xcodeproj/project.pbxproj
  2. 7
      Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  3. BIN
      Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate
  4. 5
      Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  5. 91
      Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/Clocker.xcscheme
  6. 22
      Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist
  7. 39
      Clocker/ApplicationDelegate.h
  8. 97
      Clocker/ApplicationDelegate.m
  9. 40
      Clocker/BackgroundView.h
  10. 144
      Clocker/BackgroundView.m
  11. BIN
      Clocker/Clock.jpeg
  12. 38
      Clocker/Clocker-Info.plist
  13. 9
      Clocker/Clocker-Prefix.pch
  14. 36
      Clocker/ColoredButton.h
  15. 61
      Clocker/ColoredButton.m
  16. 44
      Clocker/MenubarController.h
  17. 52
      Clocker/MenubarController.m
  18. 30
      Clocker/Panel.h
  19. 54
      Clocker/Panel.m
  20. 211
      Clocker/Panel.xib
  21. 78
      Clocker/PanelController.h
  22. 433
      Clocker/PanelController.m
  23. BIN
      Clocker/PowerIcon.png
  24. 356
      Clocker/PreferencesWindow.xib
  25. 46
      Clocker/PreferencesWindowController.h
  26. 412
      Clocker/PreferencesWindowController.m
  27. BIN
      Clocker/Status.png
  28. BIN
      Clocker/Status@2x.png
  29. BIN
      Clocker/StatusHighlighted.png
  30. BIN
      Clocker/StatusHighlighted@2x.png
  31. 49
      Clocker/StatusItemView.h
  32. 135
      Clocker/StatusItemView.m
  33. 652
      Clocker/en.lproj/MainMenu.xib
  34. 14
      Clocker/main.m

401
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 = "<group>"; };
9A8605B21BEC14A600A810A4 /* ColoredButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ColoredButton.m; path = Clocker/ColoredButton.m; sourceTree = "<group>"; };
9A8605B41BEC14BE00A810A4 /* MenubarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MenubarController.m; path = Clocker/MenubarController.m; sourceTree = "<group>"; };
9A8605B51BEC14BE00A810A4 /* ApplicationDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ApplicationDelegate.m; path = Clocker/ApplicationDelegate.m; sourceTree = "<group>"; };
9A8605B81BEC14DC00A810A4 /* StatusItemView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = StatusItemView.m; path = Clocker/StatusItemView.m; sourceTree = "<group>"; };
9A8605B91BEC14DC00A810A4 /* PanelController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PanelController.m; path = Clocker/PanelController.m; sourceTree = "<group>"; };
9A8605BC1BEC14F600A810A4 /* BackgroundView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BackgroundView.m; path = Clocker/BackgroundView.m; sourceTree = "<group>"; };
9A8605BD1BEC14F600A810A4 /* Panel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Panel.m; path = Clocker/Panel.m; sourceTree = "<group>"; };
9A8605BE1BEC14F600A810A4 /* PreferencesWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PreferencesWindowController.m; path = Clocker/PreferencesWindowController.m; sourceTree = "<group>"; };
9A8605C21BEC155B00A810A4 /* Clock.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = Clock.jpeg; path = Clocker/Clock.jpeg; sourceTree = "<group>"; };
9A8605C31BEC155B00A810A4 /* Clocker-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Clocker-Info.plist"; path = "Clocker/Clocker-Info.plist"; sourceTree = "<group>"; };
9A8605C41BEC155B00A810A4 /* BackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BackgroundView.h; path = Clocker/BackgroundView.h; sourceTree = "<group>"; };
9A8605C51BEC155B00A810A4 /* StatusItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatusItemView.h; path = Clocker/StatusItemView.h; sourceTree = "<group>"; };
9A8605C61BEC155B00A810A4 /* Panel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Panel.h; path = Clocker/Panel.h; sourceTree = "<group>"; };
9A8605C71BEC155B00A810A4 /* PreferencesWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreferencesWindowController.h; path = Clocker/PreferencesWindowController.h; sourceTree = "<group>"; };
9A8605C81BEC155B00A810A4 /* PanelController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PanelController.h; path = Clocker/PanelController.h; sourceTree = "<group>"; };
9A8605C91BEC155B00A810A4 /* MenubarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenubarController.h; path = Clocker/MenubarController.h; sourceTree = "<group>"; };
9A8605CA1BEC155B00A810A4 /* ApplicationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ApplicationDelegate.h; path = Clocker/ApplicationDelegate.h; sourceTree = "<group>"; };
9A8605CB1BEC155B00A810A4 /* ColoredButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColoredButton.h; path = Clocker/ColoredButton.h; sourceTree = "<group>"; };
9A8605CC1BEC155B00A810A4 /* Clocker-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Clocker-Prefix.pch"; path = "Clocker/Clocker-Prefix.pch"; sourceTree = "<group>"; };
9A8605CD1BEC155B00A810A4 /* Panel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = Panel.xib; path = Clocker/Panel.xib; sourceTree = "<group>"; };
9A8605CE1BEC155B00A810A4 /* PreferencesWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = PreferencesWindow.xib; path = Clocker/PreferencesWindow.xib; sourceTree = "<group>"; };
9A8605CF1BEC155B00A810A4 /* PowerIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = PowerIcon.png; path = Clocker/PowerIcon.png; sourceTree = "<group>"; };
9A8605D01BEC155B00A810A4 /* Status.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Status.png; path = Clocker/Status.png; sourceTree = "<group>"; };
9A8605D11BEC155B00A810A4 /* Status@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Status@2x.png"; path = "Clocker/Status@2x.png"; sourceTree = "<group>"; };
9A8605D21BEC155B00A810A4 /* StatusHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StatusHighlighted.png; path = Clocker/StatusHighlighted.png; sourceTree = "<group>"; };
9A8605D31BEC155B00A810A4 /* StatusHighlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "StatusHighlighted@2x.png"; path = "Clocker/StatusHighlighted@2x.png"; sourceTree = "<group>"; };
9A8605DE1BEC15C400A810A4 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = Clocker/en.lproj/MainMenu.xib; sourceTree = "<group>"; };
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 = "<group>";
};
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 = "<group>";
};
9A8605E21BEC161300A810A4 /* Superclass */ = {
isa = PBXGroup;
children = (
9A8605C61BEC155B00A810A4 /* Panel.h */,
9A8605BD1BEC14F600A810A4 /* Panel.m */,
9A8605CB1BEC155B00A810A4 /* ColoredButton.h */,
9A8605B21BEC14A600A810A4 /* ColoredButton.m */,
);
name = Superclass;
sourceTree = "<group>";
};
9A8605E31BEC163100A810A4 /* Views */ = {
isa = PBXGroup;
children = (
9A8605C41BEC155B00A810A4 /* BackgroundView.h */,
9A8605C51BEC155B00A810A4 /* StatusItemView.h */,
9A8605BC1BEC14F600A810A4 /* BackgroundView.m */,
9A8605B81BEC14DC00A810A4 /* StatusItemView.m */,
);
name = Views;
sourceTree = "<group>";
};
9A8605E41BEC164C00A810A4 /* Main */ = {
isa = PBXGroup;
children = (
9A8605C31BEC155B00A810A4 /* Clocker-Info.plist */,
9A8605CC1BEC155B00A810A4 /* Clocker-Prefix.pch */,
9A8605AD1BEC148400A810A4 /* main.m */,
);
name = Main;
sourceTree = "<group>";
};
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 = "<group>";
};
DD4F7BF913C30F9F00825C6E = {
isa = PBXGroup;
children = (
9A8605E01BEC15F400A810A4 /* XIB */,
9A8605E11BEC160700A810A4 /* Images */,
9A8605E41BEC164C00A810A4 /* Main */,
9A8605E31BEC163100A810A4 /* Views */,
9A8605E51BEC165400A810A4 /* Controllers */,
9A8605E21BEC161300A810A4 /* Superclass */,
DD4F7C0713C30F9F00825C6E /* Frameworks */,
DD4F7C0513C30F9F00825C6E /* Products */,
);
sourceTree = "<group>";
};
DD4F7C0513C30F9F00825C6E /* Products */ = {
isa = PBXGroup;
children = (
DD4F7C0413C30F9F00825C6E /* Clocker.app */,
);
name = Products;
sourceTree = "<group>";
};
DD4F7C0713C30F9F00825C6E /* Frameworks */ = {
isa = PBXGroup;
children = (
DD4F7C0B13C30F9F00825C6E /* AppKit.framework */,
DD4F7C0C13C30F9F00825C6E /* CoreData.framework */,
DD4F7C0D13C30F9F00825C6E /* Foundation.framework */,
DD4F7C0813C30F9F00825C6E /* Cocoa.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* 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 = "<group>";
};
/* 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 */;
}

7
Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata generated

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/abhishekbanthia/Downloads/Popup-master/Clocker.xcodeproj">
</FileRef>
</Workspace>

BIN
Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate generated

Binary file not shown.

5
Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "1"
version = "2.0">
</Bucket>

91
Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/Clocker.xcscheme

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DD4F7C0313C30F9F00825C6E"
BuildableName = "Clocker.app"
BlueprintName = "Clocker"
ReferencedContainer = "container:Clocker.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DD4F7C0313C30F9F00825C6E"
BuildableName = "Clocker.app"
BlueprintName = "Clocker"
ReferencedContainer = "container:Clocker.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DD4F7C0313C30F9F00825C6E"
BuildableName = "Clocker.app"
BlueprintName = "Clocker"
ReferencedContainer = "container:Clocker.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DD4F7C0313C30F9F00825C6E"
BuildableName = "Clocker.app"
BlueprintName = "Clocker"
ReferencedContainer = "container:Clocker.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

22
Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Clocker.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>DD4F7C0313C30F9F00825C6E</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

39
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 <NSApplicationDelegate, PanelControllerDelegate>
@property (nonatomic, strong) MenubarController *menubarController;
@property (nonatomic, strong, readonly) PanelController *panelController;
- (IBAction)togglePanel:(id)sender;
@end

97
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

40
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

144
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

BIN
Clocker/Clock.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

38
Clocker/Clocker-Info.plist

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>8</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2011, 2012 Shpakovski</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

9
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 <Cocoa/Cocoa.h>
#endif

36
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 <Cocoa/Cocoa.h>
@interface ColoredButton : NSButton
@end

61
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

44
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

52
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

30
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

54
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

211
Clocker/Panel.xib

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8191" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8191"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PanelController">
<connections>
<outlet property="backgroundView" destination="6" id="20"/>
<outlet property="logoLabel" destination="HR1-ZK-Ey0" id="5Mh-OP-GqP"/>
<outlet property="mainTableview" destination="dFw-ts-8OZ" id="wwJ-jA-lCy"/>
<outlet property="preferencesButton" destination="OFy-u1-TnH" id="SId-Ih-ssT"/>
<outlet property="scrollView" destination="4Gd-Nv-fXr" id="mw5-Tt-83x"/>
<outlet property="scrollViewHeight" destination="QcT-N0-G4s" id="EHr-Co-L0Z"/>
<outlet property="shutdownButton" destination="nTt-pf-Hw2" id="gCK-0D-gnK"/>
<outlet property="window" destination="5" id="7"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="none" id="5" customClass="Panel">
<windowStyleMask key="styleMask" utility="YES" nonactivatingPanel="YES" texturedBackground="YES"/>
<windowCollectionBehavior key="collectionBehavior" moveToActiveSpace="YES" ignoresCycle="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="162" y="101" width="280" height="273"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<view key="contentView" id="6" customClass="BackgroundView">
<rect key="frame" x="0.0" y="0.0" width="280" height="273"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="56" horizontalPageScroll="10" verticalLineScroll="56" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Gd-Nv-fXr">
<rect key="frame" x="-1" y="0.0" width="282" height="265"/>
<clipView key="contentView" id="4MZ-Di-yNR">
<rect key="frame" x="0.0" y="0.0" width="282" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="dFw-ts-8OZ">
<rect key="frame" x="0.0" y="0.0" width="282" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<size key="intercellSpacing" width="3" height="1"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<tableViewGridLines key="gridStyleMask" dashed="YES"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="279" minWidth="40" maxWidth="1000" id="LTt-db-Dwv">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="7LK-2q-H3f">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="timeZoneCell" id="qbN-ba-fho">
<rect key="frame" x="1" y="0.0" width="279" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" translatesAutoresizingMaskIntoConstraints="NO" id="etF-33-bCB">
<rect key="frame" x="8" y="29" width="144" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="140" id="32b-h6-joo"/>
<constraint firstAttribute="height" constant="26" id="vod-YN-iNX"/>
</constraints>
<animations/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" placeholderString="Timezone Name" id="rnh-AP-ooc">
<font key="font" size="15" name="Helvetica-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" tag="102" translatesAutoresizingMaskIntoConstraints="NO" id="QUd-7D-q14">
<rect key="frame" x="8" y="12" width="104" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="42Y-hy-Uo7"/>
<constraint firstAttribute="width" constant="100" id="fkH-oq-qvM"/>
</constraints>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" placeholderString="Date" id="74U-rv-5xj">
<font key="font" size="13" name="Helvetica-Bold"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="vnv-J2-7r1">
<rect key="frame" x="132" y="17" width="146" height="33"/>
<constraints>
<constraint firstAttribute="height" constant="33" id="3WU-de-OQL"/>
<constraint firstAttribute="width" constant="142" id="cQV-gJ-zMz"/>
</constraints>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" placeholderString="23:46" id="g8s-EU-UHx">
<font key="font" size="31" name="Helvetica-Light"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="QUd-7D-q14" firstAttribute="leading" secondItem="qbN-ba-fho" secondAttribute="leading" constant="10" id="0Qz-Ev-efP"/>
<constraint firstItem="etF-33-bCB" firstAttribute="top" secondItem="qbN-ba-fho" secondAttribute="top" constant="5" id="Lct-kG-usb"/>
<constraint firstItem="vnv-J2-7r1" firstAttribute="centerY" secondItem="qbN-ba-fho" secondAttribute="centerY" constant="-3.5" id="TuQ-gE-ZUh"/>
<constraint firstItem="QUd-7D-q14" firstAttribute="top" secondItem="etF-33-bCB" secondAttribute="bottom" constant="-5" id="VO6-Zn-eA3"/>
<constraint firstItem="etF-33-bCB" firstAttribute="leading" secondItem="qbN-ba-fho" secondAttribute="leading" constant="10" id="ueW-ow-ZRq"/>
<constraint firstAttribute="trailing" secondItem="vnv-J2-7r1" secondAttribute="trailing" constant="3" id="zXo-eA-0bQ"/>
</constraints>
<animations/>
<connections>
<outlet property="textField" destination="etF-33-bCB" id="6fd-cc-Qq2"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="-2" id="Q9t-Yx-hmz"/>
<outlet property="delegate" destination="-2" id="AqY-uU-Noo"/>
</connections>
</tableView>
</subviews>
<animations/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<constraints>
<constraint firstAttribute="height" constant="265" id="QcT-N0-G4s"/>
</constraints>
<animations/>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="DJr-1R-9LK">
<rect key="frame" x="-100" y="-100" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="cfu-8V-LKK">
<rect key="frame" x="-100" y="-100" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</scroller>
</scrollView>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="HR1-ZK-Ey0">
<rect key="frame" x="0.0" y="2" width="279" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="IxM-FF-J1F"/>
</constraints>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" alignment="center" placeholderString="Clocker" drawsBackground="YES" id="KVB-OA-XfT">
<font key="font" size="17" name="Palatino-Bold"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OFy-u1-TnH">
<rect key="frame" x="246" y="1" width="29" height="19"/>
<constraints>
<constraint firstAttribute="width" constant="29" id="MIQ-4K-E5A"/>
<constraint firstAttribute="height" constant="18" id="X7D-ep-wB4"/>
</constraints>
<animations/>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="NSActionTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="vYm-fs-Zjd">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<connections>
<action selector="openPreferences:" target="-2" id="0Yc-Eq-obQ"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nTt-pf-Hw2">
<rect key="frame" x="0.0" y="1" width="29" height="19"/>
<constraints>
<constraint firstAttribute="width" constant="29" id="8kZ-Pj-VK6"/>
<constraint firstAttribute="height" constant="18" id="sVG-VE-3q4"/>
</constraints>
<animations/>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="PowerIcon" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sUh-16-Fhk">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<connections>
<action selector="terminate:" target="-1" id="fpZ-pt-UiU"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="4Gd-Nv-fXr" firstAttribute="top" secondItem="6" secondAttribute="top" constant="8" id="1g0-Hm-7Gh"/>
<constraint firstAttribute="trailing" secondItem="HR1-ZK-Ey0" secondAttribute="trailing" constant="1" id="1ol-mo-aQU"/>
<constraint firstAttribute="bottom" secondItem="HR1-ZK-Ey0" secondAttribute="bottom" constant="2" id="Jtb-Nx-FYR"/>
<constraint firstAttribute="bottom" secondItem="nTt-pf-Hw2" secondAttribute="bottom" constant="2" id="QoV-TI-KVJ"/>
<constraint firstAttribute="bottom" secondItem="OFy-u1-TnH" secondAttribute="bottom" constant="2" id="Ubf-Mv-WMp"/>
<constraint firstAttribute="trailing" secondItem="4Gd-Nv-fXr" secondAttribute="trailing" constant="-1" id="XP6-W0-2XT"/>
<constraint firstItem="HR1-ZK-Ey0" firstAttribute="leading" secondItem="6" secondAttribute="leading" id="XQ8-hU-ayC"/>
<constraint firstItem="4Gd-Nv-fXr" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="-1" id="fHc-VQ-mJ3"/>
<constraint firstAttribute="trailing" secondItem="OFy-u1-TnH" secondAttribute="trailing" constant="5" id="p2a-qj-LHE"/>
<constraint firstItem="nTt-pf-Hw2" firstAttribute="leading" secondItem="6" secondAttribute="leading" id="pKl-Ay-0cB"/>
</constraints>
<animations/>
</view>
<connections>
<outlet property="delegate" destination="-2" id="8"/>
</connections>
<point key="canvasLocation" x="230" y="392.5"/>
</window>
<userDefaultsController representsSharedInstance="YES" id="O3B-kK-4vm"/>
</objects>
<resources>
<image name="NSActionTemplate" width="14" height="14"/>
<image name="PowerIcon" width="270" height="270"/>
</resources>
</document>

78
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 <NSObject>
@optional
- (StatusItemView *)statusItemViewForPanelController:(PanelController *)controller;
@end
#pragma mark -
@interface PanelController : NSWindowController <NSWindowDelegate, NSTableViewDataSource, NSTableViewDelegate>
{
BOOL _hasActivePanel;
__unsafe_unretained BackgroundView *_backgroundView;
__unsafe_unretained id<PanelControllerDelegate> _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<PanelControllerDelegate> 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<PanelControllerDelegate>)delegate;
- (void)openPanel;
- (void)closePanel;
- (void) updateDefaultPreferences;
- (void)showOptions:(BOOL)value;
@end

433
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<PanelControllerDelegate>)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<NSDraggingInfo>)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<NSDraggingInfo>)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

BIN
Clocker/PowerIcon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

356
Clocker/PreferencesWindow.xib

@ -0,0 +1,356 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8191" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8191"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PreferencesWindowController">
<connections>
<outlet property="availableTimezoneTableView" destination="6Hm-XH-CMI" id="GA1-tc-E9E"/>
<outlet property="is24HourFormatSelected" destination="N47-gw-Pay" id="2MV-F1-uYf"/>
<outlet property="messageLabel" destination="Rty-6T-aPw" id="Qg4-mk-P90"/>
<outlet property="searchField" destination="5jL-eb-qdB" id="K6C-JS-ko0"/>
<outlet property="timezonePanel" destination="Z6I-Ny-aGx" id="tXP-KH-Xfi"/>
<outlet property="timezoneTableView" destination="oKD-AN-gPT" id="oD2-n0-4jf"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window identifier="Selected Timezones" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="documentWindow" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="407" y="179" width="439" height="392"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<value key="minSize" type="size" width="439" height="351"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="439" height="392"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="DCz-qN-ydK">
<rect key="frame" x="11" y="107" width="21" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="aUK-f8-pvY"/>
<constraint firstAttribute="width" constant="21" id="hAr-3f-KNJ"/>
</constraints>
<animations/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="rjd-Yu-81P">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="addTimeZone:" target="-2" id="dXi-qw-Vu2"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ixe-Sn-8qT">
<rect key="frame" x="32" y="107" width="21" height="22"/>
<animations/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="SVO-Wt-Mfb">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="removeFromFavourites:" target="-2" id="65F-Jn-DMw"/>
</connections>
</button>
<scrollView focusRingType="none" autohidesScrollers="YES" horizontalLineScroll="22" horizontalPageScroll="10" verticalLineScroll="22" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cI0-M7-C9h">
<rect key="frame" x="10" y="134" width="419" height="250"/>
<clipView key="contentView" id="WWk-6i-nI7">
<rect key="frame" x="1" y="0.0" width="417" height="249"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnSelection="YES" autosaveColumns="NO" rowHeight="20" headerView="dKI-Ue-9QX" id="oKD-AN-gPT">
<rect key="frame" x="0.0" y="0.0" width="417" height="226"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="timezoneName" editable="NO" width="413.75" minWidth="40" maxWidth="1000" id="CJN-Eu-3s5">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Selected Timezone(s)">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="Vu3-3D-aDG">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="-2" id="do8-kY-7j3"/>
<outlet property="delegate" destination="-2" id="whN-25-mkj"/>
</connections>
</tableView>
</subviews>
<animations/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<animations/>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="Hxj-Tc-UWs">
<rect key="frame" x="1" y="214" width="337" height="15"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="s9V-58-jwp">
<rect key="frame" x="-14" y="-7" width="15" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</scroller>
<tableHeaderView key="headerView" id="dKI-Ue-9QX">
<rect key="frame" x="0.0" y="0.0" width="417" height="23"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</tableHeaderView>
</scrollView>
<button translatesAutoresizingMaskIntoConstraints="NO" id="P0l-kc-VxU" customClass="ColoredButton">
<rect key="frame" x="9" y="58" width="219" height="18"/>
<animations/>
<buttonCell key="cell" type="check" title="Show only city/region name" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="jaB-eA-S6N">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Helvetica-Light"/>
</buttonCell>
<connections>
<action selector="showOnlyCityName:" target="-2" id="1lf-cZ-gyt"/>
<binding destination="sEG-Zb-KUM" name="value" keyPath="values.showOnlyCity" id="xqX-Jx-epo"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="GDz-2Z-uX5" customClass="ColoredButton">
<rect key="frame" x="9" y="39" width="219" height="18"/>
<animations/>
<buttonCell key="cell" type="check" title="Start Clocker on system startup" bezelStyle="regularSquare" imagePosition="left" inset="2" id="h45-jZ-cPY">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Helvetica-Light"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.launchOnLogin" id="Vqw-iQ-qOe"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="N47-gw-Pay" customClass="ColoredButton">
<rect key="frame" x="9" y="77" width="343" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="339" id="0eX-T7-EbU"/>
<constraint firstAttribute="height" constant="18" id="qwS-Bk-vmy"/>
</constraints>
<animations/>
<buttonCell key="cell" type="check" title="Use a 24-hour clock" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="Fro-eC-cMC">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Helvetica-Light"/>
</buttonCell>
<connections>
<action selector="timeFormatSelectionChanged:" target="-2" id="6vB-XV-sSq"/>
<binding destination="sEG-Zb-KUM" name="value" keyPath="values.is24HourFormatSelected" id="wod-mK-9M5"/>
</connections>
</button>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="cso-OX-qzB">
<rect key="frame" x="8" y="13" width="413" height="20"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" title="Clocker v1.0 is open source. Find the source code here." placeholderString="" id="l7j-wK-zcu">
<font key="font" size="13" name="HelveticaNeue-Thin"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="DCz-qN-ydK" firstAttribute="top" secondItem="cI0-M7-C9h" secondAttribute="bottom" constant="6" id="6Ye-VD-kSE"/>
<constraint firstItem="cso-OX-qzB" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="10" id="Bux-4T-BB9"/>
<constraint firstItem="P0l-kc-VxU" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="11" id="DUR-uK-Ncx"/>
<constraint firstAttribute="bottom" secondItem="cso-OX-qzB" secondAttribute="bottom" constant="13" id="EdL-0P-Jrg"/>
<constraint firstItem="GDz-2Z-uX5" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="11" id="FLl-Pc-Gzn"/>
<constraint firstItem="cI0-M7-C9h" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="10" id="Fy5-6V-gu1"/>
<constraint firstItem="GDz-2Z-uX5" firstAttribute="top" secondItem="P0l-kc-VxU" secondAttribute="bottom" constant="5" id="NW3-cd-t0e"/>
<constraint firstAttribute="trailing" secondItem="cso-OX-qzB" secondAttribute="trailing" constant="20" id="Q4B-CE-JrO"/>
<constraint firstItem="ixe-Sn-8qT" firstAttribute="leading" secondItem="DCz-qN-ydK" secondAttribute="trailing" id="TLA-Fw-F7P"/>
<constraint firstItem="P0l-kc-VxU" firstAttribute="top" secondItem="N47-gw-Pay" secondAttribute="bottom" constant="5" id="Tfe-Y8-KcS"/>
<constraint firstItem="GDz-2Z-uX5" firstAttribute="width" secondItem="P0l-kc-VxU" secondAttribute="width" id="VUD-7V-5SX"/>
<constraint firstItem="DCz-qN-ydK" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="11" id="Waz-CP-UWF"/>
<constraint firstItem="GDz-2Z-uX5" firstAttribute="height" secondItem="P0l-kc-VxU" secondAttribute="height" id="c2z-Ik-d6W"/>
<constraint firstItem="N47-gw-Pay" firstAttribute="top" secondItem="ixe-Sn-8qT" secondAttribute="bottom" constant="11" id="gbd-HA-u9p"/>
<constraint firstItem="N47-gw-Pay" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="11" id="hXb-69-tI0"/>
<constraint firstItem="ixe-Sn-8qT" firstAttribute="width" secondItem="DCz-qN-ydK" secondAttribute="width" id="o7k-jf-cL0"/>
<constraint firstItem="cso-OX-qzB" firstAttribute="top" secondItem="GDz-2Z-uX5" secondAttribute="bottom" constant="8" id="qZY-wv-3kN"/>
<constraint firstItem="ixe-Sn-8qT" firstAttribute="height" secondItem="DCz-qN-ydK" secondAttribute="height" id="rsK-UP-Umg"/>
<constraint firstItem="cI0-M7-C9h" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="8" id="u5H-Ff-ivt"/>
<constraint firstAttribute="trailing" secondItem="cI0-M7-C9h" secondAttribute="trailing" constant="10" id="ut9-6b-cdu"/>
<constraint firstItem="N47-gw-Pay" firstAttribute="top" secondItem="DCz-qN-ydK" secondAttribute="bottom" constant="11" id="x0C-Ev-Imb"/>
</constraints>
<animations/>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="304.5" y="240"/>
</window>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hasShadow="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="alertPanel" appearanceType="aqua" frameAutosaveName="" id="Z6I-Ny-aGx" customClass="Panel">
<windowStyleMask key="styleMask" closable="YES" miniaturizable="YES" resizable="YES" documentModal="YES" nonactivatingPanel="YES" texturedBackground="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="120" y="64" width="345" height="320"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<value key="minSize" type="size" width="345" height="320"/>
<value key="maxSize" type="size" width="345" height="320"/>
<view key="contentView" id="byp-2M-iAO">
<rect key="frame" x="0.0" y="0.0" width="345" height="320"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView focusRingType="none" autohidesScrollers="YES" horizontalLineScroll="22" horizontalPageScroll="10" verticalLineScroll="22" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3B2-hV-f8v">
<rect key="frame" x="8" y="27" width="329" height="257"/>
<clipView key="contentView" id="xtL-kR-J62">
<rect key="frame" x="1" y="0.0" width="327" height="256"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="20" headerView="hHn-48-RCd" id="6Hm-XH-CMI">
<rect key="frame" x="0.0" y="0.0" width="327" height="233"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<tableViewGridLines key="gridStyleMask" vertical="YES"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="availableTimezones" editable="NO" width="205.5" minWidth="40" maxWidth="1000" id="TEh-P6-jcT">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Timezone Name">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="iJJ-UY-Q3g">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn identifier="abbreviation" width="115.71875" minWidth="10" maxWidth="3.4028234663852886e+38" id="Iuq-hc-Ma0">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Abbreviation">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="pwL-7P-icB">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
</tableColumns>
<connections>
<binding destination="-2" name="doubleClickTarget" keyPath="self" id="88W-iC-qMj">
<dictionary key="options">
<string key="NSSelectorName">addToFavorites:</string>
</dictionary>
</binding>
<outlet property="dataSource" destination="-2" id="OMp-pn-8oq"/>
<outlet property="delegate" destination="-2" id="mJw-oC-0dA"/>
</connections>
</tableView>
</subviews>
<animations/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<constraints>
<constraint firstAttribute="height" constant="257" id="Yru-1j-SeJ"/>
</constraints>
<animations/>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="nBP-zr-k3M">
<rect key="frame" x="1" y="241" width="327" height="15"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="x3e-JD-qwd">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</scroller>
<tableHeaderView key="headerView" id="hHn-48-RCd">
<rect key="frame" x="0.0" y="0.0" width="327" height="23"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</tableHeaderView>
</scrollView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KlN-dU-s3o">
<rect key="frame" x="2" y="-2" width="52" height="32"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="2QY-oM-3sO"/>
<constraint firstAttribute="width" constant="40" id="6JQ-5n-kb7"/>
</constraints>
<animations/>
<buttonCell key="cell" type="push" title="Add" bezelStyle="rounded" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="kZe-ua-0p9">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="HelveticaNeue-Light"/>
</buttonCell>
<connections>
<action selector="addToFavorites:" target="-2" id="y27-tR-f1g"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ueh-Ln-TC8">
<rect key="frame" x="44" y="-2" width="65" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="53" id="Bql-d6-oci"/>
</constraints>
<animations/>
<buttonCell key="cell" type="push" title="Close" bezelStyle="rounded" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ODT-4D-sWu">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="HelveticaNeue-Light"/>
</buttonCell>
<connections>
<action selector="closePanel:" target="-2" id="6v9-wN-07n"/>
</connections>
</button>
<searchField wantsLayer="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5jL-eb-qdB">
<rect key="frame" x="8" y="287" width="329" height="25"/>
<animations/>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Enter Timezone Name" drawsBackground="YES" usesSingleLineMode="YES" id="2DC-BS-vbb">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</searchFieldCell>
<connections>
<action selector="filterArray:" target="-2" id="tX8-FN-IPy"/>
</connections>
</searchField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Rty-6T-aPw">
<rect key="frame" x="104" y="8" width="232" height="20"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="y9Z-oT-NCB"/>
</constraints>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="ysU-zz-gJh">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="Rty-6T-aPw" secondAttribute="trailing" constant="11" id="1Gg-n3-Hv8"/>
<constraint firstItem="3B2-hV-f8v" firstAttribute="leading" secondItem="byp-2M-iAO" secondAttribute="leading" constant="8" id="Ahs-HL-zfw"/>
<constraint firstAttribute="bottom" secondItem="KlN-dU-s3o" secondAttribute="bottom" constant="5" id="Hfs-he-pyg"/>
<constraint firstItem="3B2-hV-f8v" firstAttribute="top" secondItem="5jL-eb-qdB" secondAttribute="bottom" constant="3" id="Kkl-0p-AQX"/>
<constraint firstItem="5jL-eb-qdB" firstAttribute="top" secondItem="byp-2M-iAO" secondAttribute="top" constant="8" id="Lsa-mI-nMD"/>
<constraint firstItem="Rty-6T-aPw" firstAttribute="leading" secondItem="Ueh-Ln-TC8" secondAttribute="trailing" constant="3" id="NEj-GQ-4oy"/>
<constraint firstItem="5jL-eb-qdB" firstAttribute="leading" secondItem="byp-2M-iAO" secondAttribute="leading" constant="8" id="YFf-7y-AA0"/>
<constraint firstAttribute="bottom" secondItem="Ueh-Ln-TC8" secondAttribute="bottom" constant="5" id="kS2-Vc-NT7"/>
<constraint firstAttribute="bottom" secondItem="Rty-6T-aPw" secondAttribute="bottom" constant="8" id="pyy-35-q2k"/>
<constraint firstItem="Ueh-Ln-TC8" firstAttribute="leading" secondItem="KlN-dU-s3o" secondAttribute="trailing" constant="2" id="qYv-aW-l68"/>
<constraint firstAttribute="trailing" secondItem="3B2-hV-f8v" secondAttribute="trailing" constant="8" id="rae-0k-Dgj"/>
<constraint firstAttribute="trailing" secondItem="5jL-eb-qdB" secondAttribute="trailing" constant="8" id="uy8-q5-8Vi"/>
<constraint firstItem="KlN-dU-s3o" firstAttribute="leading" secondItem="byp-2M-iAO" secondAttribute="leading" constant="8" id="y6V-Aa-AZU"/>
<constraint firstItem="Ueh-Ln-TC8" firstAttribute="height" secondItem="KlN-dU-s3o" secondAttribute="height" id="zET-ty-u3G"/>
</constraints>
<animations/>
</view>
<point key="canvasLocation" x="582.5" y="681"/>
</window>
<userDefaultsController representsSharedInstance="YES" id="sEG-Zb-KUM"/>
</objects>
<resources>
<image name="NSAddTemplate" width="11" height="11"/>
<image name="NSRemoveTemplate" width="11" height="11"/>
</resources>
</document>

46
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 <Cocoa/Cocoa.h>
@class AvailableTimezonesPanel;
@interface PreferencesWindowController : NSWindowController <NSCopying, NSTableViewDelegate, NSTableViewDataSource>
@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

412
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<NSDraggingInfo>)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<NSDraggingInfo>)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

BIN
Clocker/Status.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Clocker/Status@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
Clocker/StatusHighlighted.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

BIN
Clocker/StatusHighlighted@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

49
Clocker/StatusItemView.h

@ -0,0 +1,49 @@
// 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 StatusItemView : NSView {
@private
NSImage *_image;
NSImage *_alternateImage;
NSStatusItem *_statusItem;
BOOL _isHighlighted;
SEL _action;
__unsafe_unretained id _target;
}
- (id)initWithStatusItem:(NSStatusItem *)statusItem;
@property (nonatomic, strong, readonly) NSStatusItem *statusItem;
@property (nonatomic, strong) NSImage *image;
@property (nonatomic, strong) NSImage *alternateImage;
@property (nonatomic, setter = setHighlighted:) BOOL isHighlighted;
@property (nonatomic, readonly) NSRect globalRect;
@property (nonatomic) SEL action;
@property (nonatomic, unsafe_unretained) id target;
@end

135
Clocker/StatusItemView.m

@ -0,0 +1,135 @@
// 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 "StatusItemView.h"
@implementation StatusItemView
@synthesize statusItem = _statusItem;
@synthesize image = _image;
@synthesize alternateImage = _alternateImage;
@synthesize isHighlighted = _isHighlighted;
@synthesize action = _action;
@synthesize target = _target;
#pragma mark -
- (id)initWithStatusItem:(NSStatusItem *)statusItem
{
CGFloat itemWidth = [statusItem length];
CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
self = [super initWithFrame:itemRect];
if (self != nil) {
_statusItem = statusItem;
_statusItem.view = self;
}
return self;
}
#pragma mark -
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Set up dark mode for icon
if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"] isEqual: @"Dark"])
{
self.image = [NSImage imageNamed:@"StatusHighlighted"];
}
else
{
if (self.isHighlighted)
self.image = [NSImage imageNamed:@"StatusHighlighted"];
else
self.image = [NSImage imageNamed:@"Status"];
}
[self.statusItem drawStatusBarBackgroundInRect:dirtyRect withHighlight:self.isHighlighted];
NSImage *icon = self.image;
NSSize iconSize = [icon size];
NSRect bounds = self.bounds;
CGFloat iconX = roundf((NSWidth(bounds) - iconSize.width) / 2);
CGFloat iconY = roundf((NSHeight(bounds) - iconSize.height) / 2);
NSPoint iconPoint = NSMakePoint(iconX, iconY);
[icon drawAtPoint:iconPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}
#pragma mark -
#pragma mark Mouse tracking
- (void)mouseDown:(NSEvent *)theEvent
{
[NSApp sendAction:self.action to:self.target from:self];
}
#pragma mark -
#pragma mark Accessors
- (void)setHighlighted:(BOOL)newFlag
{
if (_isHighlighted == newFlag) return;
_isHighlighted = newFlag;
[self setNeedsDisplay:YES];
}
#pragma mark -
- (void)setImage:(NSImage *)newImage
{
if (_image != newImage) {
_image = newImage;
[self setNeedsDisplay:YES];
}
}
- (void)setAlternateImage:(NSImage *)newImage
{
if (_alternateImage != newImage) {
_alternateImage = newImage;
if (self.isHighlighted) {
[self setNeedsDisplay:YES];
}
}
}
#pragma mark -
- (NSRect)globalRect
{
NSRect frame = [self frame];
return [self.window convertRectToScreen:frame];
}
@end

652
Clocker/en.lproj/MainMenu.xib

@ -0,0 +1,652 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8191" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8191"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="Clocker" id="56">
<menu key="submenu" title="Clocker" systemMenu="apple" id="57">
<items>
<menuItem title="About Clocker" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
<menuItem isSeparatorItem="YES" id="143">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Services" id="131">
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide Clocker" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="Show All" id="150">
<connections>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit Clocker" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="83">
<menu key="submenu" title="File" id="81">
<items>
<menuItem title="New" keyEquivalent="n" id="82">
<connections>
<action selector="newDocument:" target="-1" id="373"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="72">
<connections>
<action selector="openDocument:" target="-1" id="374"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="124">
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
<items>
<menuItem title="Clear Menu" id="126">
<connections>
<action selector="clearRecentDocuments:" target="-1" id="127"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="79">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Close" keyEquivalent="w" id="73">
<connections>
<action selector="performClose:" target="-1" id="193"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="75">
<connections>
<action selector="saveDocument:" target="-1" id="362"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="112">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="74">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Page Setup..." keyEquivalent="P" id="77">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="87"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="78">
<connections>
<action selector="print:" target="-1" id="86"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207">
<connections>
<action selector="undo:" target="-1" id="223"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="215">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="redo:" target="-1" id="231"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="206">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Cut" keyEquivalent="x" id="199">
<connections>
<action selector="cut:" target="-1" id="228"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="197">
<connections>
<action selector="copy:" target="-1" id="224"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="203">
<connections>
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="486"/>
</connections>
</menuItem>
<menuItem title="Delete" id="202">
<connections>
<action selector="delete:" target="-1" id="235"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="198">
<connections>
<action selector="selectAll:" target="-1" id="232"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="214">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Find" id="218">
<menu key="submenu" title="Find" id="220">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
<connections>
<action selector="performFindPanelAction:" target="-1" id="241"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="535"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
<connections>
<action selector="performFindPanelAction:" target="-1" id="487"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="488"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
<connections>
<action selector="performFindPanelAction:" target="-1" id="489"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="216">
<menu key="submenu" title="Spelling and Grammar" id="200">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
<connections>
<action selector="showGuessPanel:" target="-1" id="230"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="201">
<connections>
<action selector="checkSpelling:" target="-1" id="225"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="453"/>
<menuItem title="Check Spelling While Typing" id="219">
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="346">
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="454">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="348">
<menu key="submenu" title="Substitutions" id="349">
<items>
<menuItem title="Show Substitutions" id="457">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="459"/>
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="460">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
</connections>
</menuItem>
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="462">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="450">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="451">
<items>
<menuItem title="Make Upper Case" id="452">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="464"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="465">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="468"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="466">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="467"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196">
<connections>
<action selector="startSpeaking:" target="-1" id="233"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="195">
<connections>
<action selector="stopSpeaking:" target="-1" id="227"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="375">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="376">
<items>
<menuItem title="Font" id="377">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389">
<connections>
<action selector="orderFrontFontPanel:" target="420" id="424"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390">
<connections>
<action selector="addFontTrait:" target="420" id="421"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391">
<connections>
<action selector="addFontTrait:" target="420" id="422"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="392">
<connections>
<action selector="underline:" target="-1" id="432"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="393"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394">
<connections>
<action selector="modifyFont:" target="420" id="425"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395">
<connections>
<action selector="modifyFont:" target="420" id="423"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="396"/>
<menuItem title="Kern" id="397">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="415">
<items>
<menuItem title="Use Default" id="416">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="438"/>
</connections>
</menuItem>
<menuItem title="Use None" id="417">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="441"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="418">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="431"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="419">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="435"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligature" id="398">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligature" id="411">
<items>
<menuItem title="Use Default" id="412">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="439"/>
</connections>
</menuItem>
<menuItem title="Use None" id="413">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="440"/>
</connections>
</menuItem>
<menuItem title="Use All" id="414">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="434"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="399">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="405">
<items>
<menuItem title="Use Default" id="406">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="437"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="407">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="430"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="408">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="429"/>
</connections>
</menuItem>
<menuItem title="Raise" id="409">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="426"/>
</connections>
</menuItem>
<menuItem title="Lower" id="410">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="427"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="400"/>
<menuItem title="Show Colors" keyEquivalent="C" id="401">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="433"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="402"/>
<menuItem title="Copy Style" keyEquivalent="c" id="403">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="428"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="404">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="436"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="496">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498">
<connections>
<action selector="alignLeft:" target="-1" id="524"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="499">
<connections>
<action selector="alignCenter:" target="-1" id="518"/>
</connections>
</menuItem>
<menuItem title="Justify" id="500">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="523"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="501">
<connections>
<action selector="alignRight:" target="-1" id="521"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="508">
<items>
<menuItem title="Paragraph" enabled="NO" id="509">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="510">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="525"/>
</connections>
</menuItem>
<menuItem id="511">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="526"/>
</connections>
</menuItem>
<menuItem id="512">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="527"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="513"/>
<menuItem title="Selection" enabled="NO" id="514">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="515">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="528"/>
</connections>
</menuItem>
<menuItem id="516">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="529"/>
</connections>
</menuItem>
<menuItem id="517">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="530"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="504"/>
<menuItem title="Show Ruler" id="505">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="520"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="506">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="522"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="507">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="519"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="295">
<menu key="submenu" title="View" id="296">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="366"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="298">
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="19">
<menu key="submenu" title="Window" systemMenu="window" id="24">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="23">
<connections>
<action selector="performMiniaturize:" target="-1" id="37"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="239">
<connections>
<action selector="performZoom:" target="-1" id="240"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="490">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="Clocker Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<customObject id="494" customClass="ApplicationDelegate"/>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>

14
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 <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **)argv);
}
Loading…
Cancel
Save