diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ff851d3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,10 @@ +[submodule "MonashTimetable/SSKeychain"] + path = MonashTimetable/SSKeychain + url = https://github.com/soffes/sskeychain.git + ignore = dirty +[submodule "CCNStatusItem"] + path = MonashTimetable/CCNStatusItem/ + url = https://github.com/phranck/CCNStatusItem.git +[submodule "MonashTimetable/MXLCalendarManager"] + path = MonashTimetable/MXLCalendarManager + url = https://github.com/josh-/MXLCalendarManager.git diff --git a/MonashTimetable.xcodeproj/project.pbxproj b/MonashTimetable.xcodeproj/project.pbxproj index ba17242..56b3d82 100644 --- a/MonashTimetable.xcodeproj/project.pbxproj +++ b/MonashTimetable.xcodeproj/project.pbxproj @@ -9,10 +9,42 @@ /* Begin PBXBuildFile section */ 0302353F1AFB543400F91D59 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0302353E1AFB543400F91D59 /* AppDelegate.m */; }; 030235411AFB543400F91D59 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 030235401AFB543400F91D59 /* main.m */; }; - 030235441AFB543400F91D59 /* MonashTimetable.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 030235421AFB543400F91D59 /* MonashTimetable.xcdatamodeld */; }; 030235461AFB543400F91D59 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 030235451AFB543400F91D59 /* Images.xcassets */; }; 030235491AFB543400F91D59 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030235471AFB543400F91D59 /* MainMenu.xib */; }; 030235551AFB543400F91D59 /* MonashTimetableTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 030235541AFB543400F91D59 /* MonashTimetableTests.m */; }; + 030235611AFC346000F91D59 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0302355F1AFC346000F91D59 /* LoginViewController.m */; }; + 030235621AFC346000F91D59 /* LoginViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030235601AFC346000F91D59 /* LoginViewController.xib */; }; + 0302356B1AFC3F0100F91D59 /* TimetableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 030235691AFC3F0100F91D59 /* TimetableViewController.m */; }; + 0302356C1AFC3F0100F91D59 /* TimetableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0302356A1AFC3F0100F91D59 /* TimetableViewController.xib */; }; + 0302356F1AFC7B1B00F91D59 /* CredentialsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0302356E1AFC7B1B00F91D59 /* CredentialsManager.m */; }; + 030235721AFCB79C00F91D59 /* TimetableManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 030235711AFCB79C00F91D59 /* TimetableManager.m */; }; + 0321A9771B67B1290005D7D0 /* ScheduleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0321A9761B67B1290005D7D0 /* ScheduleKit.framework */; }; + 0321A9781B67B1350005D7D0 /* ScheduleKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0321A9761B67B1290005D7D0 /* ScheduleKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 0321A9861B68BEE10005D7D0 /* CCNStatusItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A97B1B68BEE10005D7D0 /* CCNStatusItem.m */; }; + 0321A9871B68BEE10005D7D0 /* CCNStatusItemDropView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A97D1B68BEE10005D7D0 /* CCNStatusItemDropView.m */; }; + 0321A9881B68BEE10005D7D0 /* CCNStatusItemWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A97F1B68BEE10005D7D0 /* CCNStatusItemWindow.m */; }; + 0321A9891B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9811B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.m */; }; + 0321A98A1B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9831B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.m */; }; + 0321A98B1B68BEE10005D7D0 /* CCNStatusItemWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9851B68BEE10005D7D0 /* CCNStatusItemWindowController.m */; }; + 0321A9991B69B7A80005D7D0 /* MXLCalendar.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9901B69B7A80005D7D0 /* MXLCalendar.m */; }; + 0321A99A1B69B7A80005D7D0 /* MXLCalendarAttendee.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9921B69B7A80005D7D0 /* MXLCalendarAttendee.m */; }; + 0321A99B1B69B7A80005D7D0 /* MXLCalendarEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9941B69B7A80005D7D0 /* MXLCalendarEvent.m */; }; + 0321A99C1B69B7A80005D7D0 /* MXLCalendarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9961B69B7A80005D7D0 /* MXLCalendarManager.m */; }; + 0321A99D1B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0321A9981B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.m */; }; + 0321A99F1B69BA350005D7D0 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 0321A99E1B69BA350005D7D0 /* Credits.rtf */; }; + 032D41E01B61E65A0081C55E /* NSDate+DateBetween.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D41DF1B61E65A0081C55E /* NSDate+DateBetween.m */; }; + 032D41E31B6498EF0081C55E /* NSFileManager+ApplicationSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D41E21B6498EF0081C55E /* NSFileManager+ApplicationSupport.m */; }; + 032D41E71B64CB380081C55E /* ClassViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D41E51B64CB380081C55E /* ClassViewController.m */; }; + 032D41E81B64CB380081C55E /* ClassViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032D41E61B64CB380081C55E /* ClassViewController.xib */; }; + 032D421B1B670D520081C55E /* UnitColorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D421A1B670D520081C55E /* UnitColorManager.m */; }; + 032D421E1B670E5D0081C55E /* NSColor+DefaultColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D421D1B670E5D0081C55E /* NSColor+DefaultColor.m */; }; + 032D42261B673EF40081C55E /* LaunchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D42251B673EF40081C55E /* LaunchManager.m */; }; + 032D422E1B67507B0081C55E /* JPLaunchAtLoginManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 032D422D1B67507B0081C55E /* JPLaunchAtLoginManager.m */; }; + 033015B41B677549002EB39C /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033015B31B677549002EB39C /* Sparkle.framework */; }; + 033015B61B67758F002EB39C /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 033015B31B677549002EB39C /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 037D242F1AFDE2EA00123964 /* SSKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 037D242C1AFDE2EA00123964 /* SSKeychain.m */; }; + 037D24301AFDE2EA00123964 /* SSKeychainQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 037D242E1AFDE2EA00123964 /* SSKeychainQuery.m */; }; + 038596531B400A5700927C82 /* UniversityClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 038596521B400A5700927C82 /* UniversityClass.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -25,18 +57,89 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 033015B51B677582002EB39C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 033015B61B67758F002EB39C /* Sparkle.framework in CopyFiles */, + 0321A9781B67B1350005D7D0 /* ScheduleKit.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 030235381AFB543400F91D59 /* MonashTimetable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MonashTimetable.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0302353C1AFB543400F91D59 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0302353D1AFB543400F91D59 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 0302353E1AFB543400F91D59 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 030235401AFB543400F91D59 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 030235431AFB543400F91D59 /* MonashTimetable.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MonashTimetable.xcdatamodel; sourceTree = ""; }; 030235451AFB543400F91D59 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 030235481AFB543400F91D59 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 0302354E1AFB543400F91D59 /* MonashTimetableTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MonashTimetableTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 030235531AFB543400F91D59 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 030235541AFB543400F91D59 /* MonashTimetableTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MonashTimetableTests.m; sourceTree = ""; }; + 0302355E1AFC346000F91D59 /* LoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = ""; }; + 0302355F1AFC346000F91D59 /* LoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = ""; }; + 030235601AFC346000F91D59 /* LoginViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LoginViewController.xib; sourceTree = ""; }; + 030235681AFC3F0100F91D59 /* TimetableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimetableViewController.h; sourceTree = ""; }; + 030235691AFC3F0100F91D59 /* TimetableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TimetableViewController.m; sourceTree = ""; }; + 0302356A1AFC3F0100F91D59 /* TimetableViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TimetableViewController.xib; sourceTree = ""; }; + 0302356D1AFC7B1B00F91D59 /* CredentialsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialsManager.h; sourceTree = ""; }; + 0302356E1AFC7B1B00F91D59 /* CredentialsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CredentialsManager.m; sourceTree = ""; }; + 030235701AFCB79B00F91D59 /* TimetableManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimetableManager.h; sourceTree = ""; }; + 030235711AFCB79C00F91D59 /* TimetableManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TimetableManager.m; sourceTree = ""; }; + 0321A9761B67B1290005D7D0 /* ScheduleKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ScheduleKit.framework; sourceTree = ""; }; + 0321A97A1B68BEE10005D7D0 /* CCNStatusItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNStatusItem.h; path = CCNStatusItem/CCNStatusItem/CCNStatusItem.h; sourceTree = ""; }; + 0321A97B1B68BEE10005D7D0 /* CCNStatusItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCNStatusItem.m; path = CCNStatusItem/CCNStatusItem/CCNStatusItem.m; sourceTree = ""; }; + 0321A97C1B68BEE10005D7D0 /* CCNStatusItemDropView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNStatusItemDropView.h; path = CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.h; sourceTree = ""; }; + 0321A97D1B68BEE10005D7D0 /* CCNStatusItemDropView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCNStatusItemDropView.m; path = CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.m; sourceTree = ""; }; + 0321A97E1B68BEE10005D7D0 /* CCNStatusItemWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNStatusItemWindow.h; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.h; sourceTree = ""; }; + 0321A97F1B68BEE10005D7D0 /* CCNStatusItemWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCNStatusItemWindow.m; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.m; sourceTree = ""; }; + 0321A9801B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNStatusItemWindowBackgroundView.h; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.h; sourceTree = ""; }; + 0321A9811B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCNStatusItemWindowBackgroundView.m; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.m; sourceTree = ""; }; + 0321A9821B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNStatusItemWindowConfiguration.h; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.h; sourceTree = ""; }; + 0321A9831B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCNStatusItemWindowConfiguration.m; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.m; sourceTree = ""; }; + 0321A9841B68BEE10005D7D0 /* CCNStatusItemWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNStatusItemWindowController.h; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.h; sourceTree = ""; }; + 0321A9851B68BEE10005D7D0 /* CCNStatusItemWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCNStatusItemWindowController.m; path = CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.m; sourceTree = ""; }; + 0321A98F1B69B7A80005D7D0 /* MXLCalendar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MXLCalendar.h; path = MXLCalendarManager/MXLCalendarManager/MXLCalendar.h; sourceTree = ""; }; + 0321A9901B69B7A80005D7D0 /* MXLCalendar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MXLCalendar.m; path = MXLCalendarManager/MXLCalendarManager/MXLCalendar.m; sourceTree = ""; }; + 0321A9911B69B7A80005D7D0 /* MXLCalendarAttendee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MXLCalendarAttendee.h; path = MXLCalendarManager/MXLCalendarManager/MXLCalendarAttendee.h; sourceTree = ""; }; + 0321A9921B69B7A80005D7D0 /* MXLCalendarAttendee.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MXLCalendarAttendee.m; path = MXLCalendarManager/MXLCalendarManager/MXLCalendarAttendee.m; sourceTree = ""; }; + 0321A9931B69B7A80005D7D0 /* MXLCalendarEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MXLCalendarEvent.h; path = MXLCalendarManager/MXLCalendarManager/MXLCalendarEvent.h; sourceTree = ""; }; + 0321A9941B69B7A80005D7D0 /* MXLCalendarEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MXLCalendarEvent.m; path = MXLCalendarManager/MXLCalendarManager/MXLCalendarEvent.m; sourceTree = ""; }; + 0321A9951B69B7A80005D7D0 /* MXLCalendarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MXLCalendarManager.h; path = MXLCalendarManager/MXLCalendarManager/MXLCalendarManager.h; sourceTree = ""; }; + 0321A9961B69B7A80005D7D0 /* MXLCalendarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MXLCalendarManager.m; path = MXLCalendarManager/MXLCalendarManager/MXLCalendarManager.m; sourceTree = ""; }; + 0321A9971B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSTimeZone+ProperAbbreviation.h"; path = "MXLCalendarManager/MXLCalendarManager/NSTimeZone+ProperAbbreviation.h"; sourceTree = ""; }; + 0321A9981B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSTimeZone+ProperAbbreviation.m"; path = "MXLCalendarManager/MXLCalendarManager/NSTimeZone+ProperAbbreviation.m"; sourceTree = ""; }; + 0321A99E1B69BA350005D7D0 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; + 032D41DE1B61E65A0081C55E /* NSDate+DateBetween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+DateBetween.h"; sourceTree = ""; }; + 032D41DF1B61E65A0081C55E /* NSDate+DateBetween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+DateBetween.m"; sourceTree = ""; }; + 032D41E11B6498EF0081C55E /* NSFileManager+ApplicationSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+ApplicationSupport.h"; sourceTree = ""; }; + 032D41E21B6498EF0081C55E /* NSFileManager+ApplicationSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+ApplicationSupport.m"; sourceTree = ""; }; + 032D41E41B64CB380081C55E /* ClassViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassViewController.h; sourceTree = ""; }; + 032D41E51B64CB380081C55E /* ClassViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClassViewController.m; sourceTree = ""; }; + 032D41E61B64CB380081C55E /* ClassViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ClassViewController.xib; sourceTree = ""; }; + 032D41F11B65B8810081C55E /* NSGeometry+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSGeometry+Additions.h"; sourceTree = ""; }; + 032D42191B670D510081C55E /* UnitColorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitColorManager.h; sourceTree = ""; }; + 032D421A1B670D520081C55E /* UnitColorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UnitColorManager.m; sourceTree = ""; }; + 032D421C1B670E5D0081C55E /* NSColor+DefaultColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSColor+DefaultColor.h"; sourceTree = ""; }; + 032D421D1B670E5D0081C55E /* NSColor+DefaultColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSColor+DefaultColor.m"; sourceTree = ""; }; + 032D42241B673EF40081C55E /* LaunchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LaunchManager.h; sourceTree = ""; }; + 032D42251B673EF40081C55E /* LaunchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LaunchManager.m; sourceTree = ""; }; + 032D422C1B67507B0081C55E /* JPLaunchAtLoginManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLaunchAtLoginManager.h; sourceTree = ""; }; + 032D422D1B67507B0081C55E /* JPLaunchAtLoginManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLaunchAtLoginManager.m; sourceTree = ""; }; + 033015B31B677549002EB39C /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = ""; }; + 0368A22F1B69C90700A33924 /* NSEvent+KeyCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSEvent+KeyCodes.h"; sourceTree = ""; }; + 037D242B1AFDE2EA00123964 /* SSKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SSKeychain.h; path = SSKeychain/SSKeychain/SSKeychain.h; sourceTree = ""; }; + 037D242C1AFDE2EA00123964 /* SSKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SSKeychain.m; path = SSKeychain/SSKeychain/SSKeychain.m; sourceTree = ""; }; + 037D242D1AFDE2EA00123964 /* SSKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SSKeychainQuery.h; path = SSKeychain/SSKeychain/SSKeychainQuery.h; sourceTree = ""; }; + 037D242E1AFDE2EA00123964 /* SSKeychainQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SSKeychainQuery.m; path = SSKeychain/SSKeychain/SSKeychainQuery.m; sourceTree = ""; }; + 038596511B400A5700927C82 /* UniversityClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniversityClass.h; sourceTree = ""; }; + 038596521B400A5700927C82 /* UniversityClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UniversityClass.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -44,6 +147,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0321A9771B67B1290005D7D0 /* ScheduleKit.framework in Frameworks */, + 033015B41B677549002EB39C /* Sparkle.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -80,9 +185,24 @@ children = ( 0302353D1AFB543400F91D59 /* AppDelegate.h */, 0302353E1AFB543400F91D59 /* AppDelegate.m */, + 0321A98E1B68BF2C0005D7D0 /* View Controllers */, + 0302356D1AFC7B1B00F91D59 /* CredentialsManager.h */, + 0302356E1AFC7B1B00F91D59 /* CredentialsManager.m */, + 030235701AFCB79B00F91D59 /* TimetableManager.h */, + 030235711AFCB79C00F91D59 /* TimetableManager.m */, + 032D42191B670D510081C55E /* UnitColorManager.h */, + 032D421A1B670D520081C55E /* UnitColorManager.m */, + 038596511B400A5700927C82 /* UniversityClass.h */, + 038596521B400A5700927C82 /* UniversityClass.m */, + 032D42241B673EF40081C55E /* LaunchManager.h */, + 032D42251B673EF40081C55E /* LaunchManager.m */, + 032D422C1B67507B0081C55E /* JPLaunchAtLoginManager.h */, + 032D422D1B67507B0081C55E /* JPLaunchAtLoginManager.m */, + 0321A98D1B68BF160005D7D0 /* Vendor */, + 0321A98C1B68BEEF0005D7D0 /* Frameworks */, + 032D421F1B673B4B0081C55E /* Categories */, 030235451AFB543400F91D59 /* Images.xcassets */, 030235471AFB543400F91D59 /* MainMenu.xib */, - 030235421AFB543400F91D59 /* MonashTimetable.xcdatamodeld */, 0302353B1AFB543400F91D59 /* Supporting Files */, ); path = MonashTimetable; @@ -92,6 +212,7 @@ isa = PBXGroup; children = ( 0302353C1AFB543400F91D59 /* Info.plist */, + 0321A99E1B69BA350005D7D0 /* Credits.rtf */, 030235401AFB543400F91D59 /* main.m */, ); name = "Supporting Files"; @@ -114,6 +235,103 @@ name = "Supporting Files"; sourceTree = ""; }; + 0321A9791B68BED40005D7D0 /* CCNStatusItem */ = { + isa = PBXGroup; + children = ( + 0321A97A1B68BEE10005D7D0 /* CCNStatusItem.h */, + 0321A97B1B68BEE10005D7D0 /* CCNStatusItem.m */, + 0321A97C1B68BEE10005D7D0 /* CCNStatusItemDropView.h */, + 0321A97D1B68BEE10005D7D0 /* CCNStatusItemDropView.m */, + 0321A97E1B68BEE10005D7D0 /* CCNStatusItemWindow.h */, + 0321A97F1B68BEE10005D7D0 /* CCNStatusItemWindow.m */, + 0321A9801B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.h */, + 0321A9811B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.m */, + 0321A9821B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.h */, + 0321A9831B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.m */, + 0321A9841B68BEE10005D7D0 /* CCNStatusItemWindowController.h */, + 0321A9851B68BEE10005D7D0 /* CCNStatusItemWindowController.m */, + ); + name = CCNStatusItem; + sourceTree = ""; + }; + 0321A98C1B68BEEF0005D7D0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0321A9761B67B1290005D7D0 /* ScheduleKit.framework */, + 033015B31B677549002EB39C /* Sparkle.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 0321A98D1B68BF160005D7D0 /* Vendor */ = { + isa = PBXGroup; + children = ( + 0321A9791B68BED40005D7D0 /* CCNStatusItem */, + 038596541B40B9AF00927C82 /* MXLCalendarManager */, + 037D24311AFDE2EE00123964 /* SSKeychain */, + ); + name = Vendor; + sourceTree = ""; + }; + 0321A98E1B68BF2C0005D7D0 /* View Controllers */ = { + isa = PBXGroup; + children = ( + 0302355E1AFC346000F91D59 /* LoginViewController.h */, + 0302355F1AFC346000F91D59 /* LoginViewController.m */, + 030235601AFC346000F91D59 /* LoginViewController.xib */, + 030235681AFC3F0100F91D59 /* TimetableViewController.h */, + 030235691AFC3F0100F91D59 /* TimetableViewController.m */, + 0302356A1AFC3F0100F91D59 /* TimetableViewController.xib */, + 032D41E41B64CB380081C55E /* ClassViewController.h */, + 032D41E51B64CB380081C55E /* ClassViewController.m */, + 032D41E61B64CB380081C55E /* ClassViewController.xib */, + ); + name = "View Controllers"; + sourceTree = ""; + }; + 032D421F1B673B4B0081C55E /* Categories */ = { + isa = PBXGroup; + children = ( + 032D41DE1B61E65A0081C55E /* NSDate+DateBetween.h */, + 032D41DF1B61E65A0081C55E /* NSDate+DateBetween.m */, + 032D41E11B6498EF0081C55E /* NSFileManager+ApplicationSupport.h */, + 032D41E21B6498EF0081C55E /* NSFileManager+ApplicationSupport.m */, + 032D421C1B670E5D0081C55E /* NSColor+DefaultColor.h */, + 032D421D1B670E5D0081C55E /* NSColor+DefaultColor.m */, + 032D41F11B65B8810081C55E /* NSGeometry+Additions.h */, + 0368A22F1B69C90700A33924 /* NSEvent+KeyCodes.h */, + ); + name = Categories; + sourceTree = ""; + }; + 037D24311AFDE2EE00123964 /* SSKeychain */ = { + isa = PBXGroup; + children = ( + 037D242B1AFDE2EA00123964 /* SSKeychain.h */, + 037D242C1AFDE2EA00123964 /* SSKeychain.m */, + 037D242D1AFDE2EA00123964 /* SSKeychainQuery.h */, + 037D242E1AFDE2EA00123964 /* SSKeychainQuery.m */, + ); + name = SSKeychain; + sourceTree = ""; + }; + 038596541B40B9AF00927C82 /* MXLCalendarManager */ = { + isa = PBXGroup; + children = ( + 0321A98F1B69B7A80005D7D0 /* MXLCalendar.h */, + 0321A9901B69B7A80005D7D0 /* MXLCalendar.m */, + 0321A9911B69B7A80005D7D0 /* MXLCalendarAttendee.h */, + 0321A9921B69B7A80005D7D0 /* MXLCalendarAttendee.m */, + 0321A9931B69B7A80005D7D0 /* MXLCalendarEvent.h */, + 0321A9941B69B7A80005D7D0 /* MXLCalendarEvent.m */, + 0321A9951B69B7A80005D7D0 /* MXLCalendarManager.h */, + 0321A9961B69B7A80005D7D0 /* MXLCalendarManager.m */, + 0321A9971B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.h */, + 0321A9981B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.m */, + ); + name = MXLCalendarManager; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -122,8 +340,9 @@ buildConfigurationList = 030235581AFB543400F91D59 /* Build configuration list for PBXNativeTarget "MonashTimetable" */; buildPhases = ( 030235341AFB543400F91D59 /* Sources */, - 030235351AFB543400F91D59 /* Frameworks */, 030235361AFB543400F91D59 /* Resources */, + 033015B51B677582002EB39C /* CopyFiles */, + 030235351AFB543400F91D59 /* Frameworks */, ); buildRules = ( ); @@ -163,6 +382,12 @@ TargetAttributes = { 030235371AFB543400F91D59 = { CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = 3C7269R37R; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 0; + }; + }; }; 0302354D1AFB543400F91D59 = { CreatedOnToolsVersion = 6.3.1; @@ -195,7 +420,11 @@ buildActionMask = 2147483647; files = ( 030235461AFB543400F91D59 /* Images.xcassets in Resources */, + 0321A99F1B69BA350005D7D0 /* Credits.rtf in Resources */, 030235491AFB543400F91D59 /* MainMenu.xib in Resources */, + 0302356C1AFC3F0100F91D59 /* TimetableViewController.xib in Resources */, + 032D41E81B64CB380081C55E /* ClassViewController.xib in Resources */, + 030235621AFC346000F91D59 /* LoginViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -213,9 +442,33 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 038596531B400A5700927C82 /* UniversityClass.m in Sources */, + 0321A9991B69B7A80005D7D0 /* MXLCalendar.m in Sources */, + 032D421B1B670D520081C55E /* UnitColorManager.m in Sources */, + 0321A9861B68BEE10005D7D0 /* CCNStatusItem.m in Sources */, + 0321A99B1B69B7A80005D7D0 /* MXLCalendarEvent.m in Sources */, + 0302356F1AFC7B1B00F91D59 /* CredentialsManager.m in Sources */, + 0321A99A1B69B7A80005D7D0 /* MXLCalendarAttendee.m in Sources */, + 0321A9871B68BEE10005D7D0 /* CCNStatusItemDropView.m in Sources */, + 0321A99D1B69B7A80005D7D0 /* NSTimeZone+ProperAbbreviation.m in Sources */, + 032D421E1B670E5D0081C55E /* NSColor+DefaultColor.m in Sources */, + 032D42261B673EF40081C55E /* LaunchManager.m in Sources */, + 032D41E01B61E65A0081C55E /* NSDate+DateBetween.m in Sources */, + 030235611AFC346000F91D59 /* LoginViewController.m in Sources */, + 0321A9891B68BEE10005D7D0 /* CCNStatusItemWindowBackgroundView.m in Sources */, + 032D41E71B64CB380081C55E /* ClassViewController.m in Sources */, + 032D422E1B67507B0081C55E /* JPLaunchAtLoginManager.m in Sources */, + 032D41E31B6498EF0081C55E /* NSFileManager+ApplicationSupport.m in Sources */, 030235411AFB543400F91D59 /* main.m in Sources */, - 030235441AFB543400F91D59 /* MonashTimetable.xcdatamodeld in Sources */, + 0321A98A1B68BEE10005D7D0 /* CCNStatusItemWindowConfiguration.m in Sources */, + 0321A98B1B68BEE10005D7D0 /* CCNStatusItemWindowController.m in Sources */, + 0302356B1AFC3F0100F91D59 /* TimetableViewController.m in Sources */, + 037D242F1AFDE2EA00123964 /* SSKeychain.m in Sources */, + 037D24301AFDE2EA00123964 /* SSKeychainQuery.m in Sources */, 0302353F1AFB543400F91D59 /* AppDelegate.m in Sources */, + 0321A99C1B69B7A80005D7D0 /* MXLCalendarManager.m in Sources */, + 030235721AFCB79C00F91D59 /* TimetableManager.m in Sources */, + 0321A9881B68BEE10005D7D0 /* CCNStatusItemWindow.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -332,10 +585,16 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Developer ID Application"; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/MonashTimetable", + ); INFOPLIST_FILE = MonashTimetable/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; }; name = Debug; }; @@ -343,10 +602,16 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Developer ID Application"; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/MonashTimetable", + ); INFOPLIST_FILE = MonashTimetable/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; }; name = Release; }; @@ -405,6 +670,7 @@ 0302355A1AFB543400F91D59 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 0302355B1AFB543400F91D59 /* Build configuration list for PBXNativeTarget "MonashTimetableTests" */ = { isa = XCConfigurationList; @@ -413,21 +679,9 @@ 0302355D1AFB543400F91D59 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCVersionGroup section */ - 030235421AFB543400F91D59 /* MonashTimetable.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - 030235431AFB543400F91D59 /* MonashTimetable.xcdatamodel */, - ); - currentVersion = 030235431AFB543400F91D59 /* MonashTimetable.xcdatamodel */; - path = MonashTimetable.xcdatamodeld; - sourceTree = ""; - versionGroupType = wrapper.xcdatamodel; - }; -/* End XCVersionGroup section */ }; rootObject = 030235301AFB543400F91D59 /* Project object */; } diff --git a/MonashTimetable/AppDelegate.h b/MonashTimetable/AppDelegate.h index c153ed9..e96af46 100644 --- a/MonashTimetable/AppDelegate.h +++ b/MonashTimetable/AppDelegate.h @@ -6,14 +6,13 @@ // Copyright (c) 2015 Josh Parnham. All rights reserved. // -#import +@import Cocoa; -@interface AppDelegate : NSObject +#import "CCNStatusItem.h" -@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; -@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; -@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; +@interface AppDelegate : NSObject +@property (strong, nonatomic) CCNStatusItem *statusItem; @end diff --git a/MonashTimetable/AppDelegate.m b/MonashTimetable/AppDelegate.m index 59cdf61..0f91dfe 100644 --- a/MonashTimetable/AppDelegate.m +++ b/MonashTimetable/AppDelegate.m @@ -8,171 +8,81 @@ #import "AppDelegate.h" +#import "LoginViewController.h" +#import "TimetableViewController.h" + +#import "CredentialsManager.h" + @interface AppDelegate () @property (weak) IBOutlet NSWindow *window; -- (IBAction)saveAction:(id)sender; + +@property (strong, nonatomic) LoginViewController *loginViewController; +@property (strong, nonatomic) TimetableViewController *timetableViewController; @end @implementation AppDelegate -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // Insert code here to tear down your application +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + [self addObservations]; + + self.statusItem = [CCNStatusItem sharedInstance]; + [self presentViewController]; } -#pragma mark - Core Data stack +#pragma mark - Methods -@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; -@synthesize managedObjectModel = _managedObjectModel; -@synthesize managedObjectContext = _managedObjectContext; - -- (NSURL *)applicationDocumentsDirectory { - // The directory the application uses to store the Core Data store file. This code uses a directory named "com.joshparnham.MonashTimetable" in the user's Application Support directory. - NSURL *appSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject]; - return [appSupportURL URLByAppendingPathComponent:@"com.joshparnham.MonashTimetable"]; +- (void)addObservations +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(authorizationStatusChanged) name:@"AuthorizationStatusDidChange" object:nil]; } -- (NSManagedObjectModel *)managedObjectModel { - // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. - if (_managedObjectModel) { - return _managedObjectModel; - } - - NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MonashTimetable" withExtension:@"momd"]; - _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; - return _managedObjectModel; -} - -- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { - // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.) - if (_persistentStoreCoordinator) { - return _persistentStoreCoordinator; - } - - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSURL *applicationDocumentsDirectory = [self applicationDocumentsDirectory]; - BOOL shouldFail = NO; - NSError *error = nil; - NSString *failureReason = @"There was an error creating or loading the application's saved data."; +- (void)presentViewController +{ + NSImage *iconImage = [NSImage imageNamed:@"StatusIcon"]; + [iconImage setSize:NSMakeSize(16, 16)]; - // Make sure the application files directory is there - NSDictionary *properties = [applicationDocumentsDirectory resourceValuesForKeys:@[NSURLIsDirectoryKey] error:&error]; - if (properties) { - if (![properties[NSURLIsDirectoryKey] boolValue]) { - failureReason = [NSString stringWithFormat:@"Expected a folder to store application data, found a file (%@).", [applicationDocumentsDirectory path]]; - shouldFail = YES; - } - } else if ([error code] == NSFileReadNoSuchFileError) { - error = nil; - [fileManager createDirectoryAtPath:[applicationDocumentsDirectory path] withIntermediateDirectories:YES attributes:nil error:&error]; + if ([CredentialsManager userLoggedIn]) { + [self.statusItem presentStatusItemWithImage:iconImage contentViewController:self.timetableViewController]; } - - if (!shouldFail && !error) { - NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; - NSURL *url = [applicationDocumentsDirectory URLByAppendingPathComponent:@"OSXCoreDataObjC.storedata"]; - if (![coordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]) { - coordinator = nil; - } - _persistentStoreCoordinator = coordinator; - } - - if (shouldFail || error) { - // Report any error we got. - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; - dict[NSLocalizedFailureReasonErrorKey] = failureReason; - if (error) { - dict[NSUnderlyingErrorKey] = error; - } - error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; - [[NSApplication sharedApplication] presentError:error]; + else { + [self.statusItem presentStatusItemWithImage:iconImage contentViewController:self.loginViewController]; + [self.statusItem showStatusItemWindow]; } - return _persistentStoreCoordinator; } -- (NSManagedObjectContext *)managedObjectContext { - // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) - if (_managedObjectContext) { - return _managedObjectContext; +#pragma mark - Notification response + +- (void)authorizationStatusChanged +{ + if ([CredentialsManager userLoggedIn]) { + [self.statusItem updateContentViewController:self.timetableViewController]; } - - NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; - if (!coordinator) { - return nil; + else { + [self.statusItem updateContentViewController:self.loginViewController]; } - _managedObjectContext = [[NSManagedObjectContext alloc] init]; - [_managedObjectContext setPersistentStoreCoordinator:coordinator]; - - return _managedObjectContext; } -#pragma mark - Core Data Saving and Undo support +#pragma mark - Getters -- (IBAction)saveAction:(id)sender { - // Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user. - if (![[self managedObjectContext] commitEditing]) { - NSLog(@"%@:%@ unable to commit editing before saving", [self class], NSStringFromSelector(_cmd)); - } - - NSError *error = nil; - if ([[self managedObjectContext] hasChanges] && ![[self managedObjectContext] save:&error]) { - [[NSApplication sharedApplication] presentError:error]; +- (TimetableViewController *)timetableViewController +{ + if (!_timetableViewController) { + _timetableViewController = [[TimetableViewController alloc] init]; + _timetableViewController.preferredContentSize = NSMakeSize(500, 500); } + return _timetableViewController; } -- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window { - // Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application. - return [[self managedObjectContext] undoManager]; -} - -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - // Save changes in the application's managed object context before the application terminates. - - if (!_managedObjectContext) { - return NSTerminateNow; +- (LoginViewController *)loginViewController +{ + if (!_loginViewController) { + _loginViewController = [[LoginViewController alloc] init]; + _loginViewController.preferredContentSize = NSMakeSize(300, 250); } - - if (![[self managedObjectContext] commitEditing]) { - NSLog(@"%@:%@ unable to commit editing to terminate", [self class], NSStringFromSelector(_cmd)); - return NSTerminateCancel; - } - - if (![[self managedObjectContext] hasChanges]) { - return NSTerminateNow; - } - - NSError *error = nil; - if (![[self managedObjectContext] save:&error]) { - - // Customize this code block to include application-specific recovery steps. - BOOL result = [sender presentError:error]; - if (result) { - return NSTerminateCancel; - } - - NSString *question = NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", @"Quit without saves error question message"); - NSString *info = NSLocalizedString(@"Quitting now will lose any changes you have made since the last successful save", @"Quit without saves error question info"); - NSString *quitButton = NSLocalizedString(@"Quit anyway", @"Quit anyway button title"); - NSString *cancelButton = NSLocalizedString(@"Cancel", @"Cancel button title"); - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:question]; - [alert setInformativeText:info]; - [alert addButtonWithTitle:quitButton]; - [alert addButtonWithTitle:cancelButton]; - - NSInteger answer = [alert runModal]; - - if (answer == NSAlertFirstButtonReturn) { - return NSTerminateCancel; - } - } - - return NSTerminateNow; + return _loginViewController; } @end diff --git a/MonashTimetable/Base.lproj/MainMenu.xib b/MonashTimetable/Base.lproj/MainMenu.xib index 171ad8a..59f33aa 100644 --- a/MonashTimetable/Base.lproj/MainMenu.xib +++ b/MonashTimetable/Base.lproj/MainMenu.xib @@ -1,7 +1,8 @@ - + - + + @@ -11,12 +12,7 @@ - - - - - - + @@ -63,618 +59,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MonashTimetable/CCNStatusItem/.gitignore b/MonashTimetable/CCNStatusItem/.gitignore new file mode 100644 index 0000000..89c499e --- /dev/null +++ b/MonashTimetable/CCNStatusItem/.gitignore @@ -0,0 +1,18 @@ +# Xcode +.DS_Store +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside +DerivedData +.idea/ diff --git a/MonashTimetable/CCNStatusItem/.travis.yml b/MonashTimetable/CCNStatusItem/.travis.yml new file mode 100644 index 0000000..7cf471f --- /dev/null +++ b/MonashTimetable/CCNStatusItem/.travis.yml @@ -0,0 +1,3 @@ +language: objective-c +xcode_project: 'CCNStatusItem Example/CCNStatusItem Example.xcodeproj' +xcode_scheme: 'CCNStatusItem Example' diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example.xcodeproj/project.pbxproj b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example.xcodeproj/project.pbxproj new file mode 100644 index 0000000..85d0cf6 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example.xcodeproj/project.pbxproj @@ -0,0 +1,372 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1782392C1AFBCEEB00D41AB3 /* CCNStatusItemDropView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1782392B1AFBCEEB00D41AB3 /* CCNStatusItemDropView.m */; }; + 6800FB481AEB486700942B4E /* ContentView2Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 6800FB461AEB486700942B4E /* ContentView2Controller.m */; }; + 6800FB491AEB486700942B4E /* ContentView2Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6800FB471AEB486700942B4E /* ContentView2Controller.xib */; }; + FD2CF54C1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = FD2CF54B1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.m */; }; + FD9AC0331A4F728600129381 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FD9AC0321A4F728600129381 /* AppDelegate.m */; }; + FD9AC0351A4F728600129381 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FD9AC0341A4F728600129381 /* main.m */; }; + FD9AC0371A4F728600129381 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FD9AC0361A4F728600129381 /* Images.xcassets */; }; + FD9AC03A1A4F728600129381 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FD9AC0381A4F728600129381 /* MainMenu.xib */; }; + FD9AC0621A4F74BC00129381 /* ContentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FD9AC0601A4F74BC00129381 /* ContentViewController.m */; }; + FD9AC0631A4F74BC00129381 /* ContentViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = FD9AC0611A4F74BC00129381 /* ContentViewController.xib */; }; + FDA94B991A69F9D000EB4169 /* CCNStatusItem.m in Sources */ = {isa = PBXBuildFile; fileRef = FDA94B901A69F9D000EB4169 /* CCNStatusItem.m */; }; + FDA94B9A1A69F9D000EB4169 /* CCNStatusItemWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = FDA94B921A69F9D000EB4169 /* CCNStatusItemWindow.m */; }; + FDA94B9C1A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = FDA94B961A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.m */; }; + FDA94B9D1A69F9D000EB4169 /* CCNStatusItemWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = FDA94B981A69F9D000EB4169 /* CCNStatusItemWindowController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1782392A1AFBCEEB00D41AB3 /* CCNStatusItemDropView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNStatusItemDropView.h; sourceTree = ""; }; + 1782392B1AFBCEEB00D41AB3 /* CCNStatusItemDropView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNStatusItemDropView.m; sourceTree = ""; }; + 6800FB451AEB486700942B4E /* ContentView2Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentView2Controller.h; sourceTree = ""; }; + 6800FB461AEB486700942B4E /* ContentView2Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContentView2Controller.m; sourceTree = ""; }; + 6800FB471AEB486700942B4E /* ContentView2Controller.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentView2Controller.xib; sourceTree = ""; }; + FD2CF54A1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNStatusItemWindowConfiguration.h; sourceTree = ""; }; + FD2CF54B1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNStatusItemWindowConfiguration.m; sourceTree = ""; }; + FD9AC02C1A4F728600129381 /* CCNStatusItem Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CCNStatusItem Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + FD9AC0301A4F728600129381 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + FD9AC0311A4F728600129381 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + FD9AC0321A4F728600129381 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + FD9AC0341A4F728600129381 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + FD9AC0361A4F728600129381 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + FD9AC0391A4F728600129381 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + FD9AC05F1A4F74BC00129381 /* ContentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentViewController.h; sourceTree = ""; }; + FD9AC0601A4F74BC00129381 /* ContentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContentViewController.m; sourceTree = ""; }; + FD9AC0611A4F74BC00129381 /* ContentViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentViewController.xib; sourceTree = ""; }; + FDA94B8F1A69F9D000EB4169 /* CCNStatusItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNStatusItem.h; sourceTree = ""; }; + FDA94B901A69F9D000EB4169 /* CCNStatusItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNStatusItem.m; sourceTree = ""; }; + FDA94B911A69F9D000EB4169 /* CCNStatusItemWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNStatusItemWindow.h; sourceTree = ""; }; + FDA94B921A69F9D000EB4169 /* CCNStatusItemWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNStatusItemWindow.m; sourceTree = ""; }; + FDA94B951A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNStatusItemWindowBackgroundView.h; sourceTree = ""; }; + FDA94B961A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNStatusItemWindowBackgroundView.m; sourceTree = ""; }; + FDA94B971A69F9D000EB4169 /* CCNStatusItemWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNStatusItemWindowController.h; sourceTree = ""; }; + FDA94B981A69F9D000EB4169 /* CCNStatusItemWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNStatusItemWindowController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FD9AC0291A4F728600129381 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FD9AC0231A4F728600129381 = { + isa = PBXGroup; + children = ( + FD9AC02E1A4F728600129381 /* CCNStatusItem Example */, + FD9AC02D1A4F728600129381 /* Products */, + ); + sourceTree = ""; + }; + FD9AC02D1A4F728600129381 /* Products */ = { + isa = PBXGroup; + children = ( + FD9AC02C1A4F728600129381 /* CCNStatusItem Example.app */, + ); + name = Products; + sourceTree = ""; + }; + FD9AC02E1A4F728600129381 /* CCNStatusItem Example */ = { + isa = PBXGroup; + children = ( + FD9AC0311A4F728600129381 /* AppDelegate.h */, + FD9AC0321A4F728600129381 /* AppDelegate.m */, + FD9AC05F1A4F74BC00129381 /* ContentViewController.h */, + FD9AC0601A4F74BC00129381 /* ContentViewController.m */, + FD9AC0611A4F74BC00129381 /* ContentViewController.xib */, + 6800FB451AEB486700942B4E /* ContentView2Controller.h */, + 6800FB461AEB486700942B4E /* ContentView2Controller.m */, + 6800FB471AEB486700942B4E /* ContentView2Controller.xib */, + FD9AC0381A4F728600129381 /* MainMenu.xib */, + FD9AC0361A4F728600129381 /* Images.xcassets */, + FDA94B8E1A69F9D000EB4169 /* CCNStatusItem */, + FD9AC02F1A4F728600129381 /* Supporting Files */, + ); + path = "CCNStatusItem Example"; + sourceTree = ""; + }; + FD9AC02F1A4F728600129381 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + FD9AC0301A4F728600129381 /* Info.plist */, + FD9AC0341A4F728600129381 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + FDA94B8E1A69F9D000EB4169 /* CCNStatusItem */ = { + isa = PBXGroup; + children = ( + FDA94B8F1A69F9D000EB4169 /* CCNStatusItem.h */, + FDA94B901A69F9D000EB4169 /* CCNStatusItem.m */, + 1782392A1AFBCEEB00D41AB3 /* CCNStatusItemDropView.h */, + 1782392B1AFBCEEB00D41AB3 /* CCNStatusItemDropView.m */, + FDA94B911A69F9D000EB4169 /* CCNStatusItemWindow.h */, + FDA94B921A69F9D000EB4169 /* CCNStatusItemWindow.m */, + FDA94B951A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.h */, + FDA94B961A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.m */, + FD2CF54A1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.h */, + FD2CF54B1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.m */, + FDA94B971A69F9D000EB4169 /* CCNStatusItemWindowController.h */, + FDA94B981A69F9D000EB4169 /* CCNStatusItemWindowController.m */, + ); + name = CCNStatusItem; + path = ../../CCNStatusItem; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FD9AC02B1A4F728600129381 /* CCNStatusItem Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = FD9AC0491A4F728600129381 /* Build configuration list for PBXNativeTarget "CCNStatusItem Example" */; + buildPhases = ( + FDA94B8D1A69D90100EB4169 /* Update Build Number */, + FD9AC0281A4F728600129381 /* Sources */, + FD9AC0291A4F728600129381 /* Frameworks */, + FD9AC02A1A4F728600129381 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "CCNStatusItem Example"; + productName = "CCNStatusItemView Example"; + productReference = FD9AC02C1A4F728600129381 /* CCNStatusItem Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FD9AC0241A4F728600129381 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = "cocoa:naut"; + TargetAttributes = { + FD9AC02B1A4F728600129381 = { + CreatedOnToolsVersion = 6.1.1; + }; + }; + }; + buildConfigurationList = FD9AC0271A4F728600129381 /* Build configuration list for PBXProject "CCNStatusItem Example" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = FD9AC0231A4F728600129381; + productRefGroup = FD9AC02D1A4F728600129381 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FD9AC02B1A4F728600129381 /* CCNStatusItem Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FD9AC02A1A4F728600129381 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FD9AC0371A4F728600129381 /* Images.xcassets in Resources */, + FD9AC03A1A4F728600129381 /* MainMenu.xib in Resources */, + FD9AC0631A4F74BC00129381 /* ContentViewController.xib in Resources */, + 6800FB491AEB486700942B4E /* ContentView2Controller.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + FDA94B8D1A69D90100EB4169 /* Update Build Number */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Update Build Number"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd \"${EXECUTABLE_NAME}\"\nBASE_PATH=$(pwd)\nPLIST_PATH=\"${BASE_PATH}/Info.plist\"\nBUNDLE_VERSION=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"${PLIST_PATH}\")\nBUNDLE_VERSION=$[$BUNDLE_VERSION + 1]\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $BUNDLE_VERSION\" \"${PLIST_PATH}\""; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FD9AC0281A4F728600129381 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FD2CF54C1AE2E60A006F3D46 /* CCNStatusItemWindowConfiguration.m in Sources */, + FDA94B9C1A69F9D000EB4169 /* CCNStatusItemWindowBackgroundView.m in Sources */, + FD9AC0351A4F728600129381 /* main.m in Sources */, + FDA94B9A1A69F9D000EB4169 /* CCNStatusItemWindow.m in Sources */, + FDA94B991A69F9D000EB4169 /* CCNStatusItem.m in Sources */, + FD9AC0331A4F728600129381 /* AppDelegate.m in Sources */, + 6800FB481AEB486700942B4E /* ContentView2Controller.m in Sources */, + FDA94B9D1A69F9D000EB4169 /* CCNStatusItemWindowController.m in Sources */, + FD9AC0621A4F74BC00129381 /* ContentViewController.m in Sources */, + 1782392C1AFBCEEB00D41AB3 /* CCNStatusItemDropView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + FD9AC0381A4F728600129381 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + FD9AC0391A4F728600129381 /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FD9AC0471A4F728600129381 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + FD9AC0481A4F728600129381 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + FD9AC04A1A4F728600129381 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "CCNStatusItem Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "CCNStatusItem Example"; + SDKROOT = macosx; + }; + name = Debug; + }; + FD9AC04B1A4F728600129381 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "CCNStatusItem Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "CCNStatusItem Example"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FD9AC0271A4F728600129381 /* Build configuration list for PBXProject "CCNStatusItem Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FD9AC0471A4F728600129381 /* Debug */, + FD9AC0481A4F728600129381 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FD9AC0491A4F728600129381 /* Build configuration list for PBXNativeTarget "CCNStatusItem Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FD9AC04A1A4F728600129381 /* Debug */, + FD9AC04B1A4F728600129381 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FD9AC0241A4F728600129381 /* Project object */; +} diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example.xcodeproj/xcshareddata/xcschemes/CCNStatusItem Example.xcscheme b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example.xcodeproj/xcshareddata/xcschemes/CCNStatusItem Example.xcscheme new file mode 100644 index 0000000..d85cf32 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example.xcodeproj/xcshareddata/xcschemes/CCNStatusItem Example.xcscheme @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/AppDelegate.h b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/AppDelegate.h new file mode 100644 index 0000000..66e76e3 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/AppDelegate.h @@ -0,0 +1,12 @@ +// +// Created by Frank Gregor on 28.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/AppDelegate.m b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/AppDelegate.m new file mode 100644 index 0000000..3ee7919 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/AppDelegate.m @@ -0,0 +1,108 @@ +// +// Created by Frank Gregor on 28.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +#import "AppDelegate.h" +#import "CCNStatusItem.h" +#import "CCNStatusItemWindowConfiguration.h" +#import "ContentViewController.h" + + +@interface AppDelegate () +@property (weak) IBOutlet NSWindow *window; +@property (weak) IBOutlet NSButton *appearsDisabledCheckbox; +@property (weak) IBOutlet NSButton *disableCheckbox; +@property (weak) IBOutlet NSButton *proximityDetectionCheckbox; +@property (weak) IBOutlet NSButton *dragAndDropCheckbox; +@property (weak) IBOutlet NSButton *pinPopoverCheckbox; +@property (weak) IBOutlet NSSlider *proximityDragZoneDistanceSlider; +@property (weak) IBOutlet NSTextField *currentpProximityDragZoneDistanceTextField; +@property (weak) IBOutlet NSMatrix *presentationTransitionRadios; + +@property (assign) BOOL proximityDetectionEnabled; +@property (readwrite, assign) NSInteger proximitySliderValue; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // configure the status item + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.windowConfiguration.presentationTransition = CCNPresentationTransitionSlideAndFade; + sharedItem.proximityDragDetectionHandler = [self proximityDragDetectionHandler]; + [sharedItem presentStatusItemWithImage:[NSImage imageNamed:@"statusbar-icon"] + contentViewController:[ContentViewController viewController] + dropHandler:nil]; + + + // restore GUI elements + // (this is an excerpt from the example app) + self.proximitySliderValue = sharedItem.proximityDragZoneDistance; + self.appearsDisabledCheckbox.state = (sharedItem.appearsDisabled ? NSOnState : NSOffState); + self.disableCheckbox.state = (sharedItem.enabled ? NSOffState : NSOnState); + [self.presentationTransitionRadios selectCellAtRow:(NSInteger)sharedItem.windowConfiguration.presentationTransition column:0]; +} + +- (CCNStatusItemProximityDragDetectionHandler)proximityDragDetectionHandler { + return ^(CCNStatusItem *item, NSPoint eventLocation, CCNStatusItemProximityDragStatus dragStatus) { + switch (dragStatus) { + case CCNProximityDragStatusEntered: + [item showStatusItemWindow]; + break; + + case CCNProximityDragStatusExited: + [item dismissStatusItemWindow]; + break; + } + }; +} + +- (IBAction)appearsDisabledCheckboxAction:(id)sender { + [CCNStatusItem sharedInstance].appearsDisabled = (self.appearsDisabledCheckbox.state == NSOnState); +} + +- (IBAction)disableCheckboxAction:(id)sender { + [CCNStatusItem sharedInstance].enabled = (self.disableCheckbox.state == NSOffState); +} + +- (IBAction)proximityDetectionCheckboxAction:(NSButton *)proximityDetectionCheckbox { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.proximityDragDetectionEnabled = (proximityDetectionCheckbox.state == NSOnState); +} + +- (IBAction)dragAndDropCheckboxAction:(NSButton *)dragAndDropCheckbox { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + if (dragAndDropCheckbox.state == NSOnState) { + sharedItem.dropHandler = ^(CCNStatusItem *sharedItem, NSString *pasteboardType, NSArray *droppedObjects) { + NSAlert *alert = [[NSAlert alloc] init]; + alert.messageText = @"Dropped Objects"; + __block NSMutableString *objects = [NSMutableString new]; + [droppedObjects enumerateObjectsUsingBlock:^(NSString *path, NSUInteger idx, BOOL *stop) { + [objects appendFormat:@"%@. %@\n\n", @(idx+1), path]; + }]; + alert.informativeText = objects; + [alert runModal]; + }; + } + else { + sharedItem.dropHandler = nil; + } +} + +- (IBAction)pinPopoverCheckboxAction:(NSButton *)pinPopoverCheckbox { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.windowConfiguration.pinned = (pinPopoverCheckbox.state == NSOnState); +} + +- (IBAction)proximityDragZoneDistanceSliderAction:(NSSlider *)proximityDragZoneDistanceSlider { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.proximityDragZoneDistance = self.proximitySliderValue; +} + +- (IBAction)presentationTransitionRadiosAction:(NSMatrix *)presentationTransitionRadios { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.windowConfiguration.presentationTransition = (CCNPresentationTransition)presentationTransitionRadios.selectedRow; +} + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Base.lproj/MainMenu.xib b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..f0315b1 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Base.lproj/MainMenu.xib @@ -0,0 +1,890 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + When enabled it activates a circular proximity zone around the statusbar item. Entering/exiting this zone while dragging objects wil make the CCNStatusItem fire the proximityDragDetectionHandler property - if defined. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %{value1}@ + + + + + + + + + + When enabled the popover keeps visible even if it loses its key window status. Pinning the popover will ignore proximity detection. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.h b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.h new file mode 100644 index 0000000..8e75772 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.h @@ -0,0 +1,15 @@ +// +// ContentView2Controller.h +// CCNStatusItem Example +// +// Created by im61 on 4/25/15. +// Copyright (c) 2015 cocoa:naut. All rights reserved. +// + +#import + +@interface ContentView2Controller : NSViewController + ++ (instancetype)viewController; + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.m b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.m new file mode 100644 index 0000000..27c5e8e --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.m @@ -0,0 +1,29 @@ +// +// ContentView2Controller.m +// CCNStatusItem Example +// +// Created by im61 on 4/25/15. +// Copyright (c) 2015 cocoa:naut. All rights reserved. +// + +#import "ContentView2Controller.h" + +@interface ContentView2Controller () + +@end + +@implementation ContentView2Controller + ++ (instancetype)viewController { + return [[[self class] alloc] initWithNibName:NSStringFromClass([self class]) bundle:nil]; +} + +- (IBAction)quitButtonAction:(id)sender { + [[NSApplication sharedApplication] terminate:self]; +} + +- (CGSize)preferredContentSize { + return self.view.frame.size; +} + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.xib b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.xib new file mode 100644 index 0000000..01a4c3e --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentView2Controller.xib @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.h b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.h new file mode 100644 index 0000000..cfb82d7 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.h @@ -0,0 +1,20 @@ +// +// ContentViewController.h +// CCNStatusItemView Example +// +// Created by Frank Gregor on 28.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +#import + +@interface ContentViewController : NSViewController + ++ (instancetype)viewController; + +@property (weak) IBOutlet NSButton *quitButton; +@property (weak) IBOutlet NSTabView *tabview; + +- (IBAction)quitButtonAction:(id)sender; + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.m b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.m new file mode 100644 index 0000000..0e613d9 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.m @@ -0,0 +1,35 @@ +// +// ContentViewController.m +// CCNStatusItemView Example +// +// Created by Frank Gregor on 28.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +#import "ContentViewController.h" +#import "ContentView2Controller.h" +#import "CCNStatusItem.h" +#import "AppDelegate.h" + +@interface ContentViewController () +@end + +@implementation ContentViewController + ++ (instancetype)viewController { + return [[[self class] alloc] initWithNibName:NSStringFromClass([self class]) bundle:nil]; +} + +- (IBAction)quitButtonAction:(id)sender { + [[NSApplication sharedApplication] terminate:self]; +} + +- (IBAction)switchContentViewControllerAction:(id)sender { + [[CCNStatusItem sharedInstance] updateContentViewController:[ContentView2Controller viewController]]; +} + +- (CGSize)preferredContentSize { + return self.view.frame.size; +} + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.xib b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.xib new file mode 100644 index 0000000..f53416c --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/ContentViewController.xib @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/AppIcon.appiconset/Contents.json b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/Contents.json b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/Contents.json new file mode 100644 index 0000000..53e9819 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "statusbar-alternate-icon.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "statusbar-alternate-icon@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "statusbar-alternate-icon@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon.png b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon.png new file mode 100644 index 0000000..9914b1e Binary files /dev/null and b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon.png differ diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon@2x.png b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon@2x.png new file mode 100644 index 0000000..509cb01 Binary files /dev/null and b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon@2x.png differ diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon@3x.png b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon@3x.png new file mode 100644 index 0000000..b7af681 Binary files /dev/null and b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-alternate-icon.imageset/statusbar-alternate-icon@3x.png differ diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/Contents.json b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/Contents.json new file mode 100644 index 0000000..ff4c1ad --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "statusbar-icon.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "statusbar-icon@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "statusbar-icon@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon.png b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon.png new file mode 100644 index 0000000..895b36e Binary files /dev/null and b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon.png differ diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon@2x.png b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon@2x.png new file mode 100644 index 0000000..65627c0 Binary files /dev/null and b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon@2x.png differ diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon@3x.png b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon@3x.png new file mode 100644 index 0000000..c85c906 Binary files /dev/null and b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Images.xcassets/statusbar-icon.imageset/statusbar-icon@3x.png differ diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Info.plist b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Info.plist new file mode 100644 index 0000000..b0bf61a --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + com.cocoanaut.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.2.0 + CFBundleSignature + ???? + CFBundleVersion + 408 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2014 cocoa:naut. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/main.m b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/main.m new file mode 100644 index 0000000..ab98f0e --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem Example/CCNStatusItem Example/main.m @@ -0,0 +1,13 @@ +// +// main.m +// CCNStatusItemView Example +// +// Created by Frank Gregor on 28.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem.podspec b/MonashTimetable/CCNStatusItem/CCNStatusItem.podspec new file mode 100644 index 0000000..4de50de --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem.podspec @@ -0,0 +1,12 @@ +Pod::Spec.new do |s| + s.name = 'CCNStatusItem' + s.version = '0.4.0' + s.summary = 'CCNStatusItem is a subclass of NSObject for presenting a NSStatusItem with a custom Popover Window.' + s.homepage = 'https://github.com/phranck/CCNStatusItem' + s.author = { 'Frank Gregor' => 'phranck@cocoanaut.com' } + s.source = { :git => 'https://github.com/phranck/CCNStatusItem.git', :tag => s.version.to_s } + s.osx.deployment_target = '10.10' + s.requires_arc = true + s.source_files = 'CCNStatusItem/*.{h,m}' + s.license = { :type => 'MIT' } +end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItem.h b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItem.h new file mode 100644 index 0000000..c180bd5 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItem.h @@ -0,0 +1,215 @@ +// +// Created by Frank Gregor on 21/12/14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +#import +#import "CCNStatusItemWindowConfiguration.h" + + +@class CCNStatusItem; + +typedef NS_ENUM(NSUInteger, CCNStatusItemPresentationMode) { + CCNStatusItemPresentationModeUndefined = 0, + CCNStatusItemPresentationModeImage, + CCNStatusItemPresentationModeCustomView +}; +typedef NS_ENUM(NSInteger, CCNStatusItemProximityDragStatus) { + CCNProximityDragStatusEntered = 0, + CCNProximityDragStatusExited +}; + +typedef void (^CCNStatusItemDropHandler)(CCNStatusItem *sharedItem, NSString *pasteboardType, NSArray *droppedObjects); +typedef void (^CCNStatusItemProximityDragDetectionHandler)(CCNStatusItem *sharedItem, NSPoint eventLocation, CCNStatusItemProximityDragStatus proxymityDragStatus); + + +#pragma mark - CCNStatusItem + +@interface CCNStatusItem : NSObject + +#pragma mark - Initialization +/** @name Initialization */ + +/** + Returns a shared `CCNStatusItem` object. + + If the shared `CCNStatusItem` object doesn't exist yet, it is created. + + @return The shared `CCNStatusItem` object. + */ ++ (instancetype)sharedInstance; + +#pragma mark - Creating and Displaying a StatusBarItem +/** @name Creating and Displaying a StatusBarItem */ + +/** + Presents the shared `CCNStatusItem` object with the given image and contentViewController for the popover window. + + @param itemImage The image the is displayed in the status bar item. This image becomes a template image automatically. + @param contentViewController The contentViewController that is displayed in the popover window. + */ +- (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController; + +/** + Presents the shared `CCNStatusItem` object with the given image and contentViewController for the popover window. + + @param itemImage The image the is displayed in the status bar item. This image becomes a template image automatically. + @param contentViewController The contentViewController that is displayed in the popover window. + @param dropHandler A handler to be called when a drop occurs on the status bar item. + */ +- (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler; + +/** + Presents the shared `CCNStatusItem` object with the given custom view and contentViewController for the popover window. + + @param itemView A view to be presented as the status item view. + @param contentViewController The contentViewController that is displayed in the popover window. + */ +- (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController; + +/** + Presents the shared `CCNStatusItem` object with the given custom view and contentViewController for the popover window. + + @param itemView A view to be presented as the status item view. + @param contentViewController The contentViewController that is displayed in the popover window. + @param dropHandler A handler to be called when a drop occurs on the status bar item. + */ +- (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler; + +/** + Update the contentViewController for the popover window. + + @param contentViewController The contentViewController that is displayed in the popover window. + */ +- (void)updateContentViewController:(NSViewController *)contentViewController; + +/** + Property that represents the underlying `NSStatusItem` to be displayed in the statusbar. + */ +@property (strong, readonly) NSStatusItem *statusItem; + +/** + Property that represents the dropHandler to be executed if not nil. + */ + +@property (copy, nonatomic) CCNStatusItemDropHandler dropHandler; + + +#pragma mark - StatusBarItem and Popover presentation +/** @name StatusBarItem and Popover presentation */ + +/** + Boolean property that determines whether the system, thus the status item is in dark (dark menu bar) or light mode. + */ +@property (readonly, nonatomic) BOOL isDarkMode; + +/** + Boolean property that determines whether the status item appears disabled or normal. + + Appearing disabled doesn't mean the status item itself is disabled too. This behaviour is often used for indicating network reachability e.g. + */ +@property (assign, nonatomic) BOOL appearsDisabled; + +/** + Boolean property that determines whether the status item is enabled or not. + + @value YES The status item is enable. + @value NO The status item is disabled. + */ +@property (assign, nonatomic) BOOL enabled; + +/** + Boolean property that determines whether the status item popover is currently visible or not. + + @value YES The popover is visible. + @value NO The popover is not visible. + */ +@property (readonly, nonatomic) BOOL isStatusItemWindowVisible; + +/** + Presents the popover window. + + If the `contentViewController` isn't set nothing will happen. + */ +- (void)showStatusItemWindow; + +/** + Dismisses the popover window. + + Since this popover is a subclass of `NSPanel` it won't released when it's closed. + */ +- (void)dismissStatusItemWindow; + + +# pragma mark - Handling Drag Events and Proximity Drag Detection +/** @name Handling Drag Events and Proximity Drag Detection */ + +/** + Boolean property that determines whether the status item is sensitive for advances or not. + + + */ +@property (assign, nonatomic, getter=isProximityDragDetectionEnabled) BOOL proximityDragDetectionEnabled; +@property (assign, nonatomic) NSInteger proximityDragZoneDistance; +@property (copy, nonatomic) CCNStatusItemProximityDragDetectionHandler proximityDragDetectionHandler; +@property (copy, nonatomic) NSArray *dropTypes; + + +#pragma mark - Handling StatusItem Popover Layout +/** @name Handling StatusItem Popover Layout */ + +/** + Property that holds an window configuration object. + + @see `CCNStatusItemWindowConfiguration`. + */ +@property (strong, nonatomic) CCNStatusItemWindowConfiguration *windowConfiguration; + +@end + + +#pragma mark - Deprecated + +@interface CCNStatusItem (CCNStatusItemDeprecated) + ++ (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController __attribute__((deprecated("Please use the instance method instead!"))); ++ (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler __attribute__((deprecated("Please use the instance method instead!"))); ++ (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController __attribute__((deprecated("Please use the instance method instead!"))); ++ (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler __attribute__((deprecated("Please use the instance method instead!"))); ++ (void)setWindowConfiguration:(CCNStatusItemWindowConfiguration *)configuration __attribute__((deprecated("Please use the property instead!"))); + +@end + + + + +// Each notification has the statusItemWindow as notification object. The userInfo dictionary is nil. +FOUNDATION_EXPORT NSString *const CCNStatusItemWindowWillShowNotification; +FOUNDATION_EXPORT NSString *const CCNStatusItemWindowDidShowNotification; +FOUNDATION_EXPORT NSString *const CCNStatusItemWindowWillDismissNotification; +FOUNDATION_EXPORT NSString *const CCNStatusItemWindowDidDismissNotification; +FOUNDATION_EXPORT NSString *const CCNSystemInterfaceThemeChangedNotification; // sent every time when system theme toggles between dark menu mode and mormal menu mode diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItem.m b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItem.m new file mode 100644 index 0000000..4d9767d --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItem.m @@ -0,0 +1,399 @@ +// +// Created by Frank Gregor on 21/12/14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +#import +#import "CCNStatusItem.h" +#import "CCNStatusItemDropView.h" +#import "CCNStatusItemWindowController.h" + + +static NSString *const CCNStatusItemFrameKeyPath = @"statusItem.button.window.frame"; +static NSString *const CCNStatusItemWindowConfigurationPinnedPath = @"windowConfiguration.pinned"; + + +@interface NSStatusBarButton (Tools) +@end +@implementation NSStatusBarButton (Tools) +- (void)rightMouseDown:(NSEvent *)theEvent {} +@end + + + +#pragma mark - CCNStatusItemView +#pragma mark - + +@interface CCNStatusItem () { + id _globalDragEventMonitor; + BOOL _proximityDragCollisionHandled; + NSBezierPath *_proximityDragCollisionArea; + NSInteger _pbChangeCount; +} +@property (strong) NSStatusItem *statusItem; +@property (assign) CCNStatusItemPresentationMode presentationMode; +@property (assign, nonatomic) BOOL isStatusItemWindowVisible; +@property (strong) CCNStatusItemDropView *dropView; +@property (strong, nonatomic) CCNStatusItemWindowController *statusItemWindowController; +@end + +@implementation CCNStatusItem + +#pragma mark - Initialization + ++ (instancetype)sharedInstance { + static dispatch_once_t _onceToken; + __strong static CCNStatusItem *_sharedInstance; + dispatch_once(&_onceToken, ^{ + _sharedInstance = [[[self class] alloc] initSingleton]; + }); + return _sharedInstance; +} + +- (instancetype)init { + NSString *exceptionMessage = [NSString stringWithFormat:@"You must NOT init '%@' manually! Use class method 'sharedInstance' instead.", [self className]]; + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:exceptionMessage userInfo:nil]; +} + +- (instancetype)initSingleton { + self = [super init]; + if (self) { + _globalDragEventMonitor = nil; + _proximityDragCollisionHandled = NO; + + _pbChangeCount = [NSPasteboard pasteboardWithName:NSDragPboard].changeCount; + + self.statusItem = nil; + self.presentationMode = CCNStatusItemPresentationModeUndefined; + self.isStatusItemWindowVisible = NO; + self.statusItemWindowController = nil; + self.windowConfiguration = [CCNStatusItemWindowConfiguration defaultConfiguration]; + self.appearsDisabled = NO; + self.enabled = YES; + + self.dropTypes = @[NSFilenamesPboardType]; + self.dropHandler = nil; + self.proximityDragDetectionEnabled = NO; + self.proximityDragZoneDistance = 23.0; + self.proximityDragDetectionHandler = nil; + + // We need to observe that because when an status bar item has been removed from the status bar + // and OS X reorganize all items, we must recalculate our _proximityDragCollisionArea. + [self addObserver:self forKeyPath:CCNStatusItemFrameKeyPath options:NSKeyValueObservingOptionNew context:nil]; + [self addObserver:self forKeyPath:CCNStatusItemWindowConfigurationPinnedPath options:NSKeyValueObservingOptionPrior|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; + } + return self; +} + +- (void)dealloc { + [self removeObserver:self forKeyPath:CCNStatusItemFrameKeyPath]; + [self removeObserver:self forKeyPath:CCNStatusItemWindowConfigurationPinnedPath]; + + _statusItem = nil; + _statusItemWindowController = nil; + _windowConfiguration = nil; + _dropHandler = nil; + _proximityDragDetectionHandler = nil; + _proximityDragCollisionArea = nil; +} + +- (void)configureWithImage:(NSImage *)itemImage { + [itemImage setTemplate:YES]; + + self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; + + NSStatusBarButton *button = self.statusItem.button; + button.target = self; + button.action = @selector(handleStatusItemButtonAction:); + button.image = itemImage; +} + +- (void)configureWithView:(NSView *)itemView { + self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSWidth(itemView.frame)]; + + NSStatusBarButton *button = self.statusItem.button; + button.frame = itemView.frame; + [button addSubview:itemView]; + itemView.autoresizingMask = (NSViewWidthSizable | NSViewHeightSizable); +} + +- (void)configureProximityDragCollisionArea { + NSRect statusItemFrame = self.statusItem.button.window.frame; + NSRect collisionFrame = NSInsetRect(statusItemFrame, -_proximityDragZoneDistance, -_proximityDragZoneDistance); + _proximityDragCollisionArea = [NSBezierPath bezierPathWithRoundedRect:collisionFrame xRadius:NSWidth(collisionFrame)/2 yRadius:NSHeight(collisionFrame)/2]; +} + +- (void)configureDropView { + [self.dropView removeFromSuperview]; + self.dropView = nil; + + if (!self.dropHandler) { + return; + }; + + NSStatusBarButton *button = self.statusItem.button; + NSRect buttonWindowFrame = button.window.frame; + NSRect statusItemFrame = NSMakeRect(0.0, 0.0, NSWidth(buttonWindowFrame), NSHeight(buttonWindowFrame)); + self.dropView = [[CCNStatusItemDropView alloc] initWithFrame:statusItemFrame]; + self.dropView.statusItem = self; + self.dropView.dropTypes = self.dropTypes; + self.dropView.dropHandler = self.dropHandler; + [button addSubview:self.dropView]; + self.dropView.autoresizingMask = (NSViewWidthSizable | NSViewHeightSizable); +} + +#pragma mark - Creating and Displaying a StatusBarItem + +- (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController { + [self presentStatusItemWithImage:itemImage contentViewController:contentViewController dropHandler:nil]; +} + +- (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler { + if (self.presentationMode != CCNStatusItemPresentationModeUndefined) return; + + [self configureWithImage:itemImage]; + [self configureProximityDragCollisionArea]; + + self.dropHandler = dropHandler; + self.presentationMode = CCNStatusItemPresentationModeImage; + self.statusItemWindowController = [[CCNStatusItemWindowController alloc] initWithConnectedStatusItem:self + contentViewController:contentViewController + windowConfiguration:self.windowConfiguration]; +} + +- (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController { + [self presentStatusItemWithView:itemView contentViewController:contentViewController dropHandler:nil]; +} + +- (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler { + if (self.presentationMode != CCNStatusItemPresentationModeUndefined) return; + + [self configureWithView:itemView]; + [self configureProximityDragCollisionArea]; + + self.dropHandler = dropHandler; + self.presentationMode = CCNStatusItemPresentationModeCustomView; + self.statusItemWindowController = [[CCNStatusItemWindowController alloc] initWithConnectedStatusItem:self + contentViewController:contentViewController + windowConfiguration:self.windowConfiguration]; +} + +- (void)updateContentViewController:(NSViewController *)contentViewController { + [self.statusItemWindowController updateContenetViewController:contentViewController]; +} + +#pragma mark - Button Action Handling + +- (void)handleStatusItemButtonAction:(id)sender { + if (self.isStatusItemWindowVisible) { + [self dismissStatusItemWindow]; + } else { + [self showStatusItemWindow]; + } +} + +#pragma mark - Custom Accessors + +- (BOOL)isStatusItemWindowVisible { + return (self.statusItemWindowController ? self.statusItemWindowController.windowIsOpen : NO); +} + +- (void)setWindowConfiguration:(CCNStatusItemWindowConfiguration *)configuration { + _windowConfiguration = configuration; + self.statusItem.button.toolTip = configuration.toolTip; +} + +- (BOOL)isDarkMode { + NSDictionary *dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain]; + id style = [dict objectForKey:@"AppleInterfaceStyle"]; + return ( style && [style isKindOfClass:[NSString class]] && NSOrderedSame == [style caseInsensitiveCompare:@"dark"] ); +} + +- (void)setAppearsDisabled:(BOOL)appearsDisabled { + self.statusItem.button.appearsDisabled = appearsDisabled; +} + +- (BOOL)appearsDisabled { + return self.statusItem.button.appearsDisabled; +} + +- (void)setEnabled:(BOOL)enabled { + self.statusItem.button.enabled = enabled; +} + +- (BOOL)enabled { + return self.statusItem.button.enabled; +} + +- (void)setProximityDragDetectionEnabled:(BOOL)proximityDraggingDetectionEnabled { + if (_proximityDragDetectionEnabled != proximityDraggingDetectionEnabled) { + _proximityDragDetectionEnabled = proximityDraggingDetectionEnabled; + + if (_proximityDragDetectionEnabled && !self.windowConfiguration.isPinned) { + [self configureProximityDragCollisionArea]; + [self enableDragEventMonitor]; + } + else { + [self disableDragEventMonitor]; + } + } +} + +- (void)setProximityDragZoneDistance:(NSInteger)proximityDragZoneDistance { + if (_proximityDragZoneDistance != proximityDragZoneDistance) { + _proximityDragZoneDistance = proximityDragZoneDistance; + [self configureProximityDragCollisionArea]; + } +} + +- (void)setDropHandler:(CCNStatusItemDropHandler)dropHandler { + _dropHandler = [dropHandler copy]; + [self configureDropView]; +} + +#pragma mark - Helper + +- (void)enableDragEventMonitor { + if (_globalDragEventMonitor) return; + + __weak typeof(self) wSelf = self; + _globalDragEventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDraggedMask handler:^(NSEvent *event) { + NSPoint eventLocation = [event locationInWindow]; + if ([_proximityDragCollisionArea containsPoint:eventLocation]) { + // This is for detection if files has been dragged. If it happens the NSPasteboard's changeCount will be incremented. + // Dragging a window will keep that changeCount untouched. + // (Thank you Matthias aka @eternalstorms Gansrigler for that smart hint!). + NSInteger currentChangeCount = [NSPasteboard pasteboardWithName:NSDragPboard].changeCount; + if (_pbChangeCount == currentChangeCount) { + return; + } + + if (!_proximityDragCollisionHandled) { + if (wSelf.proximityDragDetectionHandler) { + wSelf.proximityDragDetectionHandler(wSelf, eventLocation, CCNProximityDragStatusEntered); + _proximityDragCollisionHandled = YES; + _pbChangeCount = currentChangeCount; + } + } + } + else { + if (_proximityDragCollisionHandled) { + if (wSelf.proximityDragDetectionHandler) { + wSelf.proximityDragDetectionHandler(wSelf, eventLocation, CCNProximityDragStatusExited); + _proximityDragCollisionHandled = NO; + _pbChangeCount--; + } + } + } + }]; +} + +- (void)disableDragEventMonitor { + [NSEvent removeMonitor:_globalDragEventMonitor]; + _globalDragEventMonitor = nil; +} + + +#pragma mark - Handling the Status Item Window + +- (void)showStatusItemWindow { + [self.statusItemWindowController showStatusItemWindow]; +} + +- (void)dismissStatusItemWindow { + [self.statusItemWindowController dismissStatusItemWindow]; +} + +#pragma mark - KVO + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqualToString:CCNStatusItemFrameKeyPath]) { + [self configureProximityDragCollisionArea]; + } + else if ([keyPath isEqualToString:CCNStatusItemWindowConfigurationPinnedPath]) { + if ([change[NSKeyValueChangeOldKey] integerValue] == NSOffState) { + [self disableDragEventMonitor]; + } + else { + [self dismissStatusItemWindow]; + if (self.proximityDragDetectionEnabled) { + [self enableDragEventMonitor]; + } + } + } +} + +@end + + + + +#pragma mark - Deprecated + +@implementation CCNStatusItem (CCNStatusItemDeprecated) + ++ (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController { + [[self class] presentStatusItemWithImage:itemImage contentViewController:contentViewController dropHandler:nil]; +} + ++ (void)presentStatusItemWithImage:(NSImage *)itemImage contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + if (sharedItem.presentationMode == CCNStatusItemPresentationModeUndefined) { + sharedItem.dropHandler = dropHandler; + [sharedItem configureWithImage:itemImage]; + [sharedItem configureProximityDragCollisionArea]; + sharedItem.presentationMode = CCNStatusItemPresentationModeImage; + sharedItem.statusItemWindowController = [[CCNStatusItemWindowController alloc] initWithConnectedStatusItem:sharedItem + contentViewController:contentViewController + windowConfiguration:sharedItem.windowConfiguration]; + } +} + ++ (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController { + [[self class] presentStatusItemWithView:itemView contentViewController:contentViewController dropHandler:nil]; +} + ++ (void)presentStatusItemWithView:(NSView *)itemView contentViewController:(NSViewController *)contentViewController dropHandler:(CCNStatusItemDropHandler)dropHandler { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + if (sharedItem.presentationMode == CCNStatusItemPresentationModeUndefined) { + sharedItem.dropHandler = dropHandler; + [sharedItem configureWithView:itemView]; + [sharedItem configureProximityDragCollisionArea]; + sharedItem.presentationMode = CCNStatusItemPresentationModeCustomView; + sharedItem.statusItemWindowController = [[CCNStatusItemWindowController alloc] initWithConnectedStatusItem:sharedItem + contentViewController:contentViewController + windowConfiguration:sharedItem.windowConfiguration]; + } +} + ++ (void)setWindowConfiguration:(CCNStatusItemWindowConfiguration *)configuration { + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.windowConfiguration = configuration; +} + +@end + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.h b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.h new file mode 100644 index 0000000..9248836 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.h @@ -0,0 +1,40 @@ +// +// Created by David Sinclair on 2015-05-06. +// Copyright (c) 2015 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2015 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +#import "CCNStatusItem.h" + + +@interface CCNStatusItemDropView : NSView + +@property (nonatomic, weak) CCNStatusItem *statusItem; +@property (nonatomic, copy) CCNStatusItemDropHandler dropHandler; +@property (nonatomic, copy) NSArray *dropTypes; + +@end + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.m b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.m new file mode 100644 index 0000000..9e9a211 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemDropView.m @@ -0,0 +1,86 @@ +// +// Created by David Sinclair on 2015-05-06. +// Copyright (c) 2015 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2015 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +#import "CCNStatusItemDropView.h" + + +@interface CCNStatusItemDropView () + +@property (nonatomic, copy) NSArray *privateDropTypes; + +@end + + +@implementation CCNStatusItemDropView + +- (NSArray *)dropTypes { + return self.privateDropTypes; +} + +- (void)setDropTypes:(NSArray *)dropTypes { + self.privateDropTypes = dropTypes; + [self registerForDraggedTypes:self.privateDropTypes]; +} + +- (NSString *)dropTypeInPasteboardTypes:(NSArray *)pasteboardTypes { + for (NSString *type in self.dropTypes) { + if ([pasteboardTypes containsObject:type]) { + return type; + } + } + return nil; +} + +- (NSDragOperation)draggingEntered:(id )sender { + NSPasteboard *pboard = [sender draggingPasteboard]; + + if ([self dropTypeInPasteboardTypes:pboard.types]) { + return NSDragOperationCopy; + } + else { + return NSDragOperationNone; + } +} + +- (BOOL)performDragOperation:(id )sender { + NSPasteboard *pboard = [sender draggingPasteboard]; + NSString *type = [self dropTypeInPasteboardTypes:pboard.types]; + + if (type) { + NSArray *items = [pboard propertyListForType:type]; + if (self.dropHandler) { + self.dropHandler(self.statusItem, type, items); + return YES; + } + } + return NO; +} + +@end + diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.h b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.h new file mode 100644 index 0000000..2fd0e7c --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.h @@ -0,0 +1,38 @@ +// +// Created by Frank Gregor on 26.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import +#import "CCNStatusItemWindowConfiguration.h" + +@interface CCNStatusItemWindow : NSPanel + ++ (instancetype)statusItemWindowWithConfiguration:(CCNStatusItemWindowConfiguration *)configuration; + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.m b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.m new file mode 100644 index 0000000..453f763 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindow.m @@ -0,0 +1,109 @@ +// +// Created by Frank Gregor on 26.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import "CCNStatusItemWindow.h" +#import "CCNStatusItemWindowBackgroundView.h" +#import "CCNStatusItem.h" +#import "CCNStatusItemWindowConfiguration.h" + + +@interface CCNStatusItemWindow () { + CCNStatusItemWindowConfiguration *_configuration; +} +@property (strong) NSView *userContentView; +@property (strong, nonatomic) CCNStatusItemWindowBackgroundView *backgroundView; +@end + +@implementation CCNStatusItemWindow + ++ (instancetype)statusItemWindowWithConfiguration:(CCNStatusItemWindowConfiguration *)configuration { + return [[[self class] alloc] initWithContentRect:NSZeroRect styleMask:NSNonactivatingPanelMask backing:NSBackingStoreBuffered defer:YES configuration:configuration]; +} + +- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag configuration:(CCNStatusItemWindowConfiguration *)configuration { + _configuration = configuration; + self = [super initWithContentRect:contentRect styleMask:styleMask backing:bufferingType defer:flag]; + if (self) { + self.opaque = NO; + self.hasShadow = YES; + self.level = NSStatusWindowLevel; + self.backgroundColor = [NSColor clearColor]; + self.collectionBehavior = (NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorIgnoresCycle); + [self setAppearance:[NSAppearance currentAppearance]]; + } + return self; +} + +- (BOOL)canBecomeKeyWindow { return YES; } +//- (BOOL)hidesOnDeactivate { return NO; } + +- (void)setContentView:(id)contentView { + if ([self.userContentView isEqual:contentView]) return; + + NSView *userContentView = (NSView *)contentView; + NSRect bounds = userContentView.bounds; + CAEdgeAntialiasingMask antialiasingMask = kCALayerLeftEdge | kCALayerRightEdge | kCALayerBottomEdge | kCALayerTopEdge; + + self.backgroundView = super.contentView; + if (!self.backgroundView) { + self.backgroundView = [[CCNStatusItemWindowBackgroundView alloc] initWithFrame:bounds windowConfiguration:_configuration]; + self.backgroundView.wantsLayer = YES; + self.backgroundView.layer.frame = bounds; + self.backgroundView.layer.cornerRadius = CCNDefaultCornerRadius; + self.backgroundView.layer.masksToBounds = YES; + self.backgroundView.layer.edgeAntialiasingMask = antialiasingMask; + super.contentView = self.backgroundView; + } + + if (self.userContentView) { + [self.userContentView removeFromSuperview]; + } + + self.userContentView = userContentView; + self.userContentView.frame = [self contentRectForFrameRect:bounds]; + self.userContentView.autoresizingMask = (NSViewWidthSizable | NSViewHeightSizable); + self.userContentView.wantsLayer = YES; + self.userContentView.layer.frame = bounds; + self.userContentView.layer.cornerRadius = CCNDefaultCornerRadius; + self.userContentView.layer.masksToBounds = YES; + self.userContentView.layer.edgeAntialiasingMask = antialiasingMask; + + [self.backgroundView addSubview:self.userContentView]; +} + +- (id)contentView { + return self.userContentView; +} + +- (NSRect)frameRectForContentRect:(NSRect)contentRect { + return NSMakeRect(NSMinX(contentRect), NSMinY(contentRect), NSWidth(contentRect), NSHeight(contentRect) + CCNDefaultArrowHeight); +} + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.h b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.h new file mode 100644 index 0000000..2bc314d --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.h @@ -0,0 +1,38 @@ +// +// Created by Frank Gregor on 21/12/14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import +#import "CCNStatusItemWindowConfiguration.h" + +@interface CCNStatusItemWindowBackgroundView : NSView + +- (instancetype)initWithFrame:(NSRect)frameRect windowConfiguration:(CCNStatusItemWindowConfiguration *)configuration; + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.m b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.m new file mode 100644 index 0000000..c54bdc1 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowBackgroundView.m @@ -0,0 +1,86 @@ +// +// Created by Frank Gregor on 21/12/14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import "CCNStatusItemWindowBackgroundView.h" + + +@interface CCNStatusItemWindowBackgroundView () +@property (strong) CCNStatusItemWindowConfiguration *windowConfiguration; +@end + +@implementation CCNStatusItemWindowBackgroundView + +- (instancetype)initWithFrame:(NSRect)frameRect windowConfiguration:(CCNStatusItemWindowConfiguration *)configuration { + self = [super initWithFrame:frameRect]; + if (self) { + self.windowConfiguration = configuration; + } + return self; +} + +- (void)drawRect:(NSRect)dirtyRect { + CGFloat arrowHeight = CCNDefaultArrowHeight; + CGFloat arrowWidth = CCNDefaultArrowWidth; + CGFloat cornerRadius = CCNDefaultCornerRadius; + NSRect backgroundRect = NSMakeRect(NSMinX(self.bounds), NSMinY(self.bounds), NSWidth(self.bounds), NSHeight(self.bounds) - arrowHeight); + + NSBezierPath *windowPath = [NSBezierPath bezierPath]; + NSBezierPath *arrowPath = [NSBezierPath bezierPath]; + NSBezierPath *backgroundPath = [NSBezierPath bezierPathWithRoundedRect:backgroundRect xRadius:cornerRadius yRadius:cornerRadius]; + + NSPoint leftPoint = {NSWidth(backgroundRect)/2 - arrowWidth/2, NSMaxY(backgroundRect)}; + NSPoint topPoint = {NSWidth(backgroundRect)/2, NSMaxY(backgroundRect) + arrowHeight}; + NSPoint rightPoint = {NSWidth(backgroundRect)/2 + arrowWidth/2, NSMaxY(backgroundRect)}; + + [arrowPath moveToPoint:leftPoint]; + [arrowPath curveToPoint:topPoint + controlPoint1: NSMakePoint(NSWidth(backgroundRect)/2 - arrowWidth/4, NSMaxY(backgroundRect)) + controlPoint2: NSMakePoint(NSWidth(backgroundRect)/2 - arrowWidth/7, NSMaxY(backgroundRect) + arrowHeight)]; + [arrowPath curveToPoint:rightPoint + controlPoint1: NSMakePoint(NSWidth(backgroundRect)/2 + arrowWidth/7, NSMaxY(backgroundRect) + arrowHeight) + controlPoint2: NSMakePoint(NSWidth(backgroundRect)/2 + arrowWidth/4, NSMaxY(backgroundRect))]; + [arrowPath lineToPoint:leftPoint]; + [arrowPath closePath]; + + [windowPath appendBezierPath:arrowPath]; + [windowPath appendBezierPath:backgroundPath]; + + [self.windowConfiguration.backgroundColor setFill]; + [windowPath fill]; +} + +#pragma mark - Custom Accessors + +- (void)setFrame:(NSRect)frame { + [super setFrame:frame]; + [self setNeedsDisplay:YES]; +} + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.h b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.h new file mode 100644 index 0000000..76ca10c --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.h @@ -0,0 +1,60 @@ +// +// Created by Frank Gregor on 27.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import +#import + + +typedef NS_ENUM(NSInteger, CCNPresentationTransition) { + CCNPresentationTransitionNone = 0, + CCNPresentationTransitionFade, + CCNPresentationTransitionSlideAndFade +}; + +static const CGFloat CCNDefaultArrowHeight = 11.0; +static const CGFloat CCNDefaultArrowWidth = 42.0; +static const CGFloat CCNDefaultCornerRadius = 5.0; + + +@interface CCNStatusItemWindowConfiguration : NSObject + ++ (instancetype)defaultConfiguration; + +// status item window +@property (assign, nonatomic) CGFloat windowToStatusItemMargin; // default: 2.0 +@property (assign, nonatomic) NSTimeInterval animationDuration; // default: 0.21 +@property (strong, nonatomic) NSColor *backgroundColor; // default: [NSColor windowBackgroundColor] +@property (assign, nonatomic) CCNPresentationTransition presentationTransition; // default: CCNPresentationTransitionFade + // On setting the 'presentationTranstion' to case 'CCNPresentationTransitionNone' property 'animationDuration' will be set to 0 + // status item +@property (strong, nonatomic) NSString *toolTip; +@property (assign, nonatomic, getter=isPinned) BOOL pinned; // default: NO; Normally if the window loses its key window status it will be dismissed automatically. Setting this property to YES keeps the window visible. + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.m b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.m new file mode 100644 index 0000000..cf48357 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowConfiguration.m @@ -0,0 +1,71 @@ +// +// Created by Frank Gregor on 27.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import "CCNStatusItemWindowConfiguration.h" + + +static const CGFloat CCNDefaultStatusItemMargin = 2.0; +static const NSTimeInterval CCNDefaultAnimationDuration = 0.21; + + +@implementation CCNStatusItemWindowConfiguration + ++ (instancetype)defaultConfiguration { + return [[[self class] alloc] init]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.windowToStatusItemMargin = CCNDefaultStatusItemMargin; + self.animationDuration = CCNDefaultAnimationDuration; + self.presentationTransition = CCNPresentationTransitionFade; + self.toolTip = nil; + self.backgroundColor = [NSColor windowBackgroundColor]; + self.pinned = NO; + } + return self; +} + +#pragma mark - Custom Accessors + +- (void)setPresentationTransition:(CCNPresentationTransition)presentationTransition { + if (_presentationTransition != presentationTransition) { + _presentationTransition = presentationTransition; + if (_presentationTransition == CCNPresentationTransitionNone) { + self.animationDuration = 0; + } + else { + self.animationDuration = CCNDefaultAnimationDuration; + } + } +} + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.h b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.h new file mode 100644 index 0000000..72a9c12 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.h @@ -0,0 +1,51 @@ +// +// Created by Frank Gregor on 23.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import +#import "CCNStatusItem.h" +#import "CCNStatusItemWindow.h" +#import "CCNStatusItemWindowConfiguration.h" + + +@interface CCNStatusItemWindowController : NSWindowController + +- (id)initWithConnectedStatusItem:(CCNStatusItem *)statusItem + contentViewController:(NSViewController *)contentViewController + windowConfiguration:(CCNStatusItemWindowConfiguration *)windowConfiguration; + +- (void)updateContenetViewController:(NSViewController *)contentViewController; + +@property (assign) BOOL windowIsOpen; +@property (assign) BOOL animationIsRunning; + +- (void)showStatusItemWindow; +- (void)dismissStatusItemWindow; + +@end diff --git a/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.m b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.m new file mode 100644 index 0000000..38cb8b2 --- /dev/null +++ b/MonashTimetable/CCNStatusItem/CCNStatusItem/CCNStatusItemWindowController.m @@ -0,0 +1,214 @@ +// +// Created by Frank Gregor on 23.12.14. +// Copyright (c) 2014 cocoa:naut. All rights reserved. +// + +/* + The MIT License (MIT) + Copyright © 2014 Frank Gregor, + http://cocoanaut.mit-license.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the “Software”), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + +#import +#import "CCNStatusItemWindowController.h" +#import "CCNStatusItemWindowConfiguration.h" + +NSString *const CCNStatusItemWindowWillShowNotification = @"CCNStatusItemWindowWillShowNotification"; +NSString *const CCNStatusItemWindowDidShowNotification = @"CCNStatusItemWindowDidShowNotification"; +NSString *const CCNStatusItemWindowWillDismissNotification = @"CCNStatusItemWindowWillDismissNotification"; +NSString *const CCNStatusItemWindowDidDismissNotification = @"CCNStatusItemWindowDidDismissNotification"; +NSString *const CCNSystemInterfaceThemeChangedNotification = @"CCNSystemInterfaceThemeChangedNotification"; + + +static const CGFloat CCNTransitionDistance = 8.0; +typedef NS_ENUM(NSUInteger, CCNFadeDirection) { + CCNFadeDirectionFadeIn = 0, + CCNFadeDirectionFadeOut +}; + +typedef void (^CCNStatusItemWindowAnimationCompletion)(void); + + +@interface CCNStatusItemWindowController () +@property (strong) CCNStatusItem *statusItemView; +@property (strong) CCNStatusItemWindowConfiguration *windowConfiguration; +@end + +@implementation CCNStatusItemWindowController + +- (id)initWithConnectedStatusItem:(CCNStatusItem *)statusItem + contentViewController:(NSViewController *)contentViewController + windowConfiguration:(CCNStatusItemWindowConfiguration *)windowConfiguration { + + if (!contentViewController) { + return nil; + } + + NSAssert(contentViewController.preferredContentSize.width != 0 && contentViewController.preferredContentSize.height != 0, @"[%@] The preferredContentSize of the contentViewController must not be NSZeroSize!", [self className]); + + self = [super init]; + if (self) { + self.windowIsOpen = NO; + self.statusItemView = statusItem; + self.windowConfiguration = windowConfiguration; + + // StatusItem Window + self.window = [CCNStatusItemWindow statusItemWindowWithConfiguration:windowConfiguration]; + self.contentViewController = contentViewController; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWindowDidResignKeyNotification:) name:NSWindowDidResignKeyNotification object:nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAppleInterfaceThemeChangedNotification:) name:@"AppleInterfaceThemeChangedNotification" object:nil]; + } + return self; +} + +- (void)updateContenetViewController:(NSViewController *)contentViewController { + // Set nil first to trigger window resize + self.contentViewController = nil; + self.contentViewController = contentViewController; + + [self updateWindowFrame]; +} + +#pragma mark - Helper + +- (void)updateWindowFrame { + CGRect statusItemRect = [[self.statusItemView.statusItem.button window] frame]; + CGRect windowFrame = NSMakeRect(NSMinX(statusItemRect) - NSWidth(self.window.frame)/2 + NSWidth(statusItemRect)/2, + NSMinY(statusItemRect) - NSHeight(self.window.frame) - self.windowConfiguration.windowToStatusItemMargin, + self.window.frame.size.width, + self.window.frame.size.height); + [self.window setFrame:windowFrame display:YES]; + [self.window setAppearance:[NSAppearance currentAppearance]]; +} + +#pragma mark - Handling Window Visibility + +- (void)showStatusItemWindow { + if (self.animationIsRunning) return; + + [self updateWindowFrame]; + [self.window setAlphaValue:0.0]; + [self showWindow:nil]; + + [self animateWindow:(CCNStatusItemWindow *)self.window withFadeDirection:CCNFadeDirectionFadeIn]; +} + +- (void)dismissStatusItemWindow { + if (self.animationIsRunning) return; + + [self animateWindow:(CCNStatusItemWindow *)self.window withFadeDirection:CCNFadeDirectionFadeOut]; +} + +- (void)animateWindow:(CCNStatusItemWindow *)window withFadeDirection:(CCNFadeDirection)fadeDirection { + switch (self.windowConfiguration.presentationTransition) { + case CCNPresentationTransitionNone: + case CCNPresentationTransitionFade: { + [self animateWindow:window withFadeTransitionUsingFadeDirection:fadeDirection]; + break; + } + case CCNPresentationTransitionSlideAndFade: { + [self animateWindow:window withSlideAndFadeTransitionUsingFadeDirection:fadeDirection]; + break; + } + } +} + +- (void)animateWindow:(CCNStatusItemWindow *)window withFadeTransitionUsingFadeDirection:(CCNFadeDirection)fadeDirection { + NSString *notificationName = (fadeDirection == CCNFadeDirectionFadeIn ? CCNStatusItemWindowWillShowNotification : CCNStatusItemWindowWillDismissNotification); + [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:window]; + + [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { + context.duration = self.windowConfiguration.animationDuration; + context.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + [[window animator] setAlphaValue:(fadeDirection == CCNFadeDirectionFadeIn ? 1.0 : 0.0)]; + + } completionHandler:[self animationCompletionForWindow:window fadeDirection:fadeDirection]]; +} + +- (void)animateWindow:(CCNStatusItemWindow *)window withSlideAndFadeTransitionUsingFadeDirection:(CCNFadeDirection)fadeDirection { + NSString *notificationName = (fadeDirection == CCNFadeDirectionFadeIn ? CCNStatusItemWindowWillShowNotification : CCNStatusItemWindowWillDismissNotification); + [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:window]; + + CGRect windowStartFrame, windowEndFrame; + CGRect calculatedFrame = NSMakeRect(NSMinX(window.frame), NSMinY(window.frame) + CCNTransitionDistance, NSWidth(window.frame), NSHeight(window.frame)); + + switch (fadeDirection) { + case CCNFadeDirectionFadeIn: { + windowStartFrame = calculatedFrame; + windowEndFrame = window.frame; + break; + } + case CCNFadeDirectionFadeOut: { + windowStartFrame = window.frame; + windowEndFrame = calculatedFrame; + break; + } + } + [window setFrame:windowStartFrame display:NO]; + + [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { + context.duration = self.windowConfiguration.animationDuration; + context.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + [[window animator] setFrame:windowEndFrame display:NO]; + [[window animator] setAlphaValue:(fadeDirection == CCNFadeDirectionFadeIn ? 1.0 : 0.0)]; + + } completionHandler:[self animationCompletionForWindow:window fadeDirection:fadeDirection]]; +} + +- (CCNStatusItemWindowAnimationCompletion)animationCompletionForWindow:(CCNStatusItemWindow *)window fadeDirection:(CCNFadeDirection)fadeDirection { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + __weak typeof(self) wSelf = self; + + return ^{ + wSelf.animationIsRunning = NO; + wSelf.windowIsOpen = (fadeDirection == CCNFadeDirectionFadeIn); + + if (fadeDirection == CCNFadeDirectionFadeIn) { + [window makeKeyWindow]; + [nc postNotificationName:CCNStatusItemWindowDidShowNotification object:window]; + } + else { + [window orderOut:wSelf]; + [window close]; + [nc postNotificationName:CCNStatusItemWindowDidDismissNotification object:window]; + } + }; +} + +#pragma mark - Notifications + +- (void)handleWindowDidResignKeyNotification:(NSNotification *)note { + if (![note.object isEqual:self.window]) return; + if (!self.windowConfiguration.isPinned) { + [self dismissStatusItemWindow]; + } +} + +#pragma mark - NSDistributedNotificationCenter + +- (void)handleAppleInterfaceThemeChangedNotification:(NSNotification *)note { + [[NSNotificationCenter defaultCenter] postNotificationName:CCNSystemInterfaceThemeChangedNotification object:nil]; +} + +@end + diff --git a/MonashTimetable/CCNStatusItem/LICENSE.txt b/MonashTimetable/CCNStatusItem/LICENSE.txt new file mode 100644 index 0000000..507b0fb --- /dev/null +++ b/MonashTimetable/CCNStatusItem/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright © 2015 Frank Gregor + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/MonashTimetable/CCNStatusItem/ReadMe.md b/MonashTimetable/CCNStatusItem/ReadMe.md new file mode 100644 index 0000000..b7fc24a --- /dev/null +++ b/MonashTimetable/CCNStatusItem/ReadMe.md @@ -0,0 +1,104 @@ +[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=phranck&url=https://github.com/phranck/CCNStatusItem&title=CCNStatusItem&tags=github&category=software) +![Travis Status](https://travis-ci.org/phranck/CCNStatusItem.png?branch=master) + + + +## Overview + +`CCNStatusItem` is a subclass of `NSObject` to act as a custom `NSStatusItem`. Running on Yosemite it has full support for the class `NSStatusBarButton` which is provided by `NSStatusItem` via the `button` property. + +Features: +* Yosemite's dark menu mode will be automatically handled +* Proximity drag detection +* Support for Drag&Drop + +It supports a customizable statusItemWindow that will manage any `NSViewController` instance for presenting the content. + +This screenshot presents the current example application: + +[![CCNStatusItem Example Application](http://share.gifyoutube.com/vpkXD9.gif +)](https://youtu.be/yejBocG9bMc) + +## Integration + +You can add `CCNStatusItem` by using CocoaPods. Just add this line to your Podfile: + +``` +pod 'CCNStatusItem' +``` + + +## Usage + +After it's integrated into your project you are just a few lines of code away from your (maybe) first `NSStatusItem` with a custom view and a beautiful looking popover window. A good place to add these lines of code is your AppDelegate: + +```Objective-C +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + ... + [[CCNStatusItem sharedInstance] presentStatusItemWithImage:[NSImage imageNamed:@"statusbar-icon"] + contentViewController:[ContentViewController viewController]]; + ... +} +``` + +That's all! You will have some options to change the design of this statusItem popover window using `CCNStatusItemWindowConfiguration`. In the example above internally `CCNStatusItem` uses `[CCNStatusItemWindowConfiguration defaultConfiguration]` to set a default design and behavior of the status bar popover window. The next example will show you how to change this design and behaviour: + +```Objective-C +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + ... + + // configure the status item + CCNStatusItem *sharedItem = [CCNStatusItem sharedInstance]; + sharedItem.windowConfiguration.presentationTransition = CCNPresentationTransitionSlideAndFade; + sharedItem.proximityDragDetectionHandler = ^(CCNStatusItem *item, NSPoint eventLocation, CCNStatusItemProximityDragStatus dragStatus) { + switch (dragStatus) { + case CCNProximityDragStatusEntered: + [item showStatusItemWindow]; + break; + + case CCNProximityDragStatusExited: + [item dismissStatusItemWindow]; + break; + } + }; + [sharedItem presentStatusItemWithImage:[NSImage imageNamed:@"statusbar-icon"] + contentViewController:[ContentViewController viewController]]; + ... +} +``` + + +## Some Side Notes + +The statusItem popover's frame size will be determined automatically by calling `preferedContentSize` on the `contentViewController`. So you shouldn't forget to set it to a reasonable value. Using XIB's for building the content a good war to do so is returning: + +```Objective-C +- (CGSize)preferredContentSize { + return self.view.frame.size; +} + +``` + + +## Requirements + +`CCNStatusItem` was written using ARC and "modern" Objective-C 2. At the moment it has only support for OS X 10.10 Yosemite. + + +## Contribution + +The code is provided as-is, and it is far off being complete or free of bugs. If you like this component feel free to support it. Make changes related to your needs, extend it or just use it in your own project. Pull-Requests and Feedbacks are very welcome. Just contact me at [phranck@cocoanaut.com](mailto:phranck@cocoanaut.com?Subject=[CCNStatusItem] Your component on Github) or send me a ping on Twitter [@TheCocoaNaut](http://twitter.com/TheCocoaNaut). + + +## Documentation +The complete documentation you will find on [CocoaDocs](http://cocoadocs.org/docsets/CCNStatusItem/). + + +## License +This software is published under the [MIT License](http://cocoanaut.mit-license.org). + + +## Software that uses CCNStatusItem + +* [Review Times](http://reviewtimes.cocoanaut.com) - A small Mac tool that shows you the calculated average of the review times for both the Mac App Store and the iOS App Store +* [SalesX](http://salesx.in) - SalesX is the simplest way to reach your iTC sales reports diff --git a/MonashTimetable/CCNStatusItem/Resources/CCNStatusItem.mov b/MonashTimetable/CCNStatusItem/Resources/CCNStatusItem.mov new file mode 100644 index 0000000..64b45ff Binary files /dev/null and b/MonashTimetable/CCNStatusItem/Resources/CCNStatusItem.mov differ diff --git a/MonashTimetable/CCNStatusItem/Resources/IconSet.sketch b/MonashTimetable/CCNStatusItem/Resources/IconSet.sketch new file mode 100644 index 0000000..8a7f84f Binary files /dev/null and b/MonashTimetable/CCNStatusItem/Resources/IconSet.sketch differ diff --git a/MonashTimetable/ClassViewController.h b/MonashTimetable/ClassViewController.h new file mode 100644 index 0000000..440f450 --- /dev/null +++ b/MonashTimetable/ClassViewController.h @@ -0,0 +1,30 @@ +// +// ClassViewController.h +// MonashTimetable +// +// Created by Josh Parnham on 26/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Cocoa; + +#import "UniversityClass.h" + +@interface ClassViewController : NSViewController + +@property (copy) NSString *classTitle; +@property (copy) NSString *classDuration; +@property (copy) NSString *classLocation; +@property (copy) NSString *classDescription; +@property (copy) NSColor *classColor; +@property (copy) NSString *unitCode; + +@property (weak) IBOutlet NSTextField *titleLabel; +@property (weak) IBOutlet NSTextField *durationLabel; +@property (weak) IBOutlet NSTextField *locationLabel; +@property (weak) IBOutlet NSTextField *descriptionLabel; +@property (weak) IBOutlet NSColorWell *unitColorWell; + +- (instancetype)initWithUniversityClass:(UniversityClass *)class NS_DESIGNATED_INITIALIZER; + +@end diff --git a/MonashTimetable/ClassViewController.m b/MonashTimetable/ClassViewController.m new file mode 100644 index 0000000..126ff70 --- /dev/null +++ b/MonashTimetable/ClassViewController.m @@ -0,0 +1,65 @@ +// +// ClassViewController.m +// MonashTimetable +// +// Created by Josh Parnham on 26/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "ClassViewController.h" + +#import "UnitColorManager.h" + +@implementation ClassViewController + +- (instancetype)initWithUniversityClass:(UniversityClass *)class +{ + // This call may not work on pre-Yosemite systems – see comments on API + self = [super initWithNibName:nil bundle:[NSBundle mainBundle]]; + if (self) { + if (class) { + self.classTitle = class.title; + self.classDuration = [NSString stringWithFormat:@"%@ Minutes", [class.duration stringValue]]; + self.classLocation = class.location; + self.classDescription = class.unitTitle; + self.unitCode = class.unitCode; + } + } + return self; +} + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + return [self initWithUniversityClass:nil]; +} + +- (instancetype)initWithCoder:(NSCoder *)coder +{ + return [self initWithUniversityClass:nil]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.titleLabel.stringValue = self.classTitle ? self.classTitle : @""; + self.durationLabel.stringValue = self.classDuration ? self.classDuration : @""; + self.locationLabel.stringValue = self.classLocation ? self.classLocation : @""; + self.descriptionLabel.stringValue = self.classDescription ? self.classDescription : @""; +} + +#pragma mark - Getters + +- (NSColor *)classColor +{ + return [UnitColorManager colorForUnitCode:self.unitCode]; +} + +#pragma mark - Setters + +- (void)setClassColor:(NSColor *)sender +{ + [UnitColorManager storeColor:sender forUnitCode:self.unitCode]; +} + +@end \ No newline at end of file diff --git a/MonashTimetable/ClassViewController.xib b/MonashTimetable/ClassViewController.xib new file mode 100644 index 0000000..4958069 --- /dev/null +++ b/MonashTimetable/ClassViewController.xib @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/CredentialsManager.h b/MonashTimetable/CredentialsManager.h new file mode 100644 index 0000000..d7052df --- /dev/null +++ b/MonashTimetable/CredentialsManager.h @@ -0,0 +1,20 @@ +// +// CredentialsManager.h +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Foundation; + +@interface CredentialsManager : NSObject + +- (void)authenticateCredentials:(NSString *)username password:(NSString *)password; + ++ (NSString *)normalisedUsername:(NSString *)username; ++ (BOOL)userLoggedIn; ++ (BOOL)validPortalAuthentication; ++ (NSString *)portalAuthentication; + +@end diff --git a/MonashTimetable/CredentialsManager.m b/MonashTimetable/CredentialsManager.m new file mode 100644 index 0000000..96c54ef --- /dev/null +++ b/MonashTimetable/CredentialsManager.m @@ -0,0 +1,114 @@ +// +// CredentialsManager.m +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "CredentialsManager.h" + +#import "SSKeychain.h" + +@implementation CredentialsManager + +- (void)authenticateCredentials:(NSString *)username password:(NSString *)password +{ + username = [self.class normalisedUsername:username]; + + NSURL *monashUrl = [NSURL URLWithString:@"https://my.monash.edu.au"]; + NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + + NSURLSessionDataTask *myMonashDataTask = [urlSession dataTaskWithURL:monashUrl completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + NSLog(@"%@", error.localizedDescription); + } + + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:response.URL]; + + [request setHTTPMethod:@"POST"]; + [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"]; + + NSString *authenticationBodyString = [NSString stringWithFormat:@"AuthMethod=FormsAuthentication&Kmsi=true&Password=%@&UserName=Monash\\%@", [password stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], [username stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + NSData *postBody = [authenticationBodyString dataUsingEncoding:NSUTF8StringEncoding]; + [request setHTTPBody:postBody]; + + NSURLSessionDataTask *cookieDataTask = [urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + NSString *portalAuthenticationCookie = ((NSHTTPURLResponse *)response).allHeaderFields[@"Set-Cookie"]; + + if (portalAuthenticationCookie) { + [self storeCredentials:username password:password]; + [self storeToken:portalAuthenticationCookie]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"AuthorizationStatusDidChange" object:nil]; + }); + } + else { + NSLog(@"Unable to authenticate with the specified credentials."); + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"AuthorizationDidFail" object:nil]; + }); + } + }]; + [cookieDataTask resume]; + }]; + [myMonashDataTask resume]; +} + +- (void)storeCredentials:(NSString *)username password:(NSString *)password +{ + [SSKeychain setPassword:password forService:@"Monash" account:username]; +} + +- (void)storeToken:(NSString *)token +{ + [SSKeychain setPassword:token forService:@"MonashPortalAuthentication" account:@"com.joshparnham.Monash"]; +} + +#pragma mark - Class methods + ++ (NSString *)normalisedUsername:(NSString *)username +{ + NSMutableString *normalisedUsername = [username mutableCopy]; + + NSRange emailRange = [normalisedUsername rangeOfString:@"@"]; + if (!(emailRange.location == NSNotFound)) { + [normalisedUsername deleteCharactersInRange:NSMakeRange(emailRange.location, (normalisedUsername.length - emailRange.location))]; + } + + NSRange backslashRange = [normalisedUsername rangeOfString:@"\\"]; + if (!(backslashRange.location == NSNotFound)) { + [normalisedUsername deleteCharactersInRange:NSMakeRange(0, backslashRange.location+1)]; + } + + return (NSString *)normalisedUsername; +} + ++ (BOOL)userLoggedIn +{ + NSArray *accounts = [SSKeychain accountsForService:@"Monash"]; + if (accounts) { + return YES; + } + else { + return NO; + } +} + ++ (BOOL)validPortalAuthentication +{ + NSString *portalAuthenticationCookie = [SSKeychain passwordForService:@"MonashPortalAuthentication" account:@"com.joshparnham.Monash"]; + if (portalAuthenticationCookie) { + return YES; + } + else { + return NO; + } +} + ++ (NSString *)portalAuthentication +{ + return [SSKeychain passwordForService:@"MonashPortalAuthentication" account:@"com.joshparnham.Monash"]; +} + +@end diff --git a/MonashTimetable/Credits.rtf b/MonashTimetable/Credits.rtf new file mode 100644 index 0000000..2ec6161 --- /dev/null +++ b/MonashTimetable/Credits.rtf @@ -0,0 +1,103 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw11900\paperh16840\margl1440\margr1440\vieww33320\viewh19580\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\b\fs24 \cf0 Acknowledgements\ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\b0 \cf0 MonashTimetable makes use of the following third-party frameworks & libraries under licence: +\b \ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural +\cf0 \ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural +{\field{\*\fldinst{HYPERLINK "https://github.com/gservera/ScheduleKit"}}{\fldrslt \cf0 ScheduleKit}}\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural + +\b0 \cf0 Copyright (c) 2014-2015 Guillem Servera Negre\ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\b \ +\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural +{\field{\*\fldinst{HYPERLINK "https://github.com/KiranPanesar/MXLCalendarManager"}}{\fldrslt \cf0 MXLCalendarManager}}\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural + +\b0 \cf0 Copyright (c) 2014 @KiranPanesar et al\ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\ +\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural +{\field{\*\fldinst{HYPERLINK "https://github.com/phranck/CCNStatusItem"}}{\fldrslt +\b \cf0 CCNStatusItem}} +\b \ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural + +\b0 \cf0 Copyright \'a9 2015 Frank Gregor \ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \'93Software\'94), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED \'93AS IS\'94, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\ +\ +{\field{\*\fldinst{HYPERLINK "https://github.com/soffes/sskeychain"}}{\fldrslt +\b SSKeychain}} +\b \ + +\b0 Copyright (c) 2010-2014 Sam Soffes, http://soff.es\ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\ +\ +{\field{\*\fldinst{HYPERLINK "https://github.com/sparkle-project/Sparkle"}}{\fldrslt +\b Sparkle}} +\b \ + +\b0 Copyright (c) 2006-2013 Andy Matuschak.\ +Copyright (c) 2009-2013 Elgato Systems GmbH.\ +Copyright (c) 2011-2014 Kornel Lesi\uc0\u324 ski.\ +Copyright (c) 2014 C.W. Betts.\ +Copyright (c) 2014 Petroules Corporation.\ +Copyright (c) 2014 Big Nerd Ranch.\ +All rights reserved.\ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\ +the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\ +\ +=================\ +EXTERNAL LICENSES\ +=================\ +\ +bspatch.c and bsdiff.c, from bsdiff 4.3 :\ + Copyright (c) 2003-2005 Colin Percival.\ +\ +sais.c and sais.c, from sais-lite (2010/08/07) :\ + Copyright (c) 2008-2010 Yuta Mori.\ +\ +SUDSAVerifier.m:\ + Copyright (c) 2011 Mark Hamlin.\ +\ +All rights reserved.\ +\ +Redistribution and use in source and binary forms, with or without modification, are permitted providing that the following conditions are met:\ +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\ +2. 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 AUTHOR ``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 AUTHOR 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.} \ No newline at end of file diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/128.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/128.png new file mode 100644 index 0000000..2649e25 Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/128.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/128@2x.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/128@2x.png new file mode 100644 index 0000000..03702bd Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/128@2x.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/16.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/16.png new file mode 100644 index 0000000..c8c42bf Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/16.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/16@2x.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/16@2x.png new file mode 100644 index 0000000..5850786 Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/16@2x.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/256.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/256.png new file mode 100644 index 0000000..249adb9 Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/256.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/256@2x.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/256@2x.png new file mode 100644 index 0000000..0910032 Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/256@2x.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/32.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/32.png new file mode 100644 index 0000000..9b35043 Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/32.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/32@2x.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/32@2x.png new file mode 100644 index 0000000..6ec222e Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/32@2x.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/512.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/512.png new file mode 100644 index 0000000..bb6063d Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/512.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/512@2x.png b/MonashTimetable/Images.xcassets/AppIcon.appiconset/512@2x.png new file mode 100644 index 0000000..d37076b Binary files /dev/null and b/MonashTimetable/Images.xcassets/AppIcon.appiconset/512@2x.png differ diff --git a/MonashTimetable/Images.xcassets/AppIcon.appiconset/Contents.json b/MonashTimetable/Images.xcassets/AppIcon.appiconset/Contents.json index 2db2b1c..2fe2dbc 100644 --- a/MonashTimetable/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/MonashTimetable/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,53 +1,63 @@ { "images" : [ { - "idiom" : "mac", "size" : "16x16", + "idiom" : "mac", + "filename" : "16.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "16x16", + "idiom" : "mac", + "filename" : "16@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "32x32", + "idiom" : "mac", + "filename" : "32.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "32x32", + "idiom" : "mac", + "filename" : "32@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "128x128", + "idiom" : "mac", + "filename" : "128.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "128x128", + "idiom" : "mac", + "filename" : "128@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "256x256", + "idiom" : "mac", + "filename" : "256.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "256x256", + "idiom" : "mac", + "filename" : "256@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "512x512", + "idiom" : "mac", + "filename" : "512.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "512x512", + "idiom" : "mac", + "filename" : "512@2x.png", "scale" : "2x" } ], diff --git a/MonashTimetable/Images.xcassets/StatusIcon.imageset/Contents.json b/MonashTimetable/Images.xcassets/StatusIcon.imageset/Contents.json new file mode 100644 index 0000000..fc15e84 --- /dev/null +++ b/MonashTimetable/Images.xcassets/StatusIcon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "StatusItem.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "StatusItem@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "StatusItem@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem.png b/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem.png new file mode 100644 index 0000000..5a258f4 Binary files /dev/null and b/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem.png differ diff --git a/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem@2x.png b/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem@2x.png new file mode 100644 index 0000000..40b0128 Binary files /dev/null and b/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem@2x.png differ diff --git a/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem@3x.png b/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem@3x.png new file mode 100644 index 0000000..319eadd Binary files /dev/null and b/MonashTimetable/Images.xcassets/StatusIcon.imageset/StatusItem@3x.png differ diff --git a/MonashTimetable/Info.plist b/MonashTimetable/Info.plist index cea2ef8..fc00f1a 100644 --- a/MonashTimetable/Info.plist +++ b/MonashTimetable/Info.plist @@ -30,5 +30,11 @@ MainMenu NSPrincipalClass NSApplication + LSUIElement + + SUFeedURL + http://joshparnham.com/projects/monash-timetable/appcast.xml + SUEnableAutomaticChecks + diff --git a/MonashTimetable/JPLaunchAtLoginManager.h b/MonashTimetable/JPLaunchAtLoginManager.h new file mode 100644 index 0000000..71c57da --- /dev/null +++ b/MonashTimetable/JPLaunchAtLoginManager.h @@ -0,0 +1,15 @@ +// +// JPLaunchAtLoginManager.h +// CloudyTabs +// +// Based on a modified version of this StackOverflow answer - http://stackoverflow.com/a/2318004/446039 +// + +#import + +@interface JPLaunchAtLoginManager : NSObject + ++ (BOOL)willStartAtLogin:(NSURL *)itemURL; ++ (void)setStartAtLogin:(NSURL *)itemURL enabled:(BOOL)enabled; + +@end diff --git a/MonashTimetable/JPLaunchAtLoginManager.m b/MonashTimetable/JPLaunchAtLoginManager.m new file mode 100644 index 0000000..9dc1bad --- /dev/null +++ b/MonashTimetable/JPLaunchAtLoginManager.m @@ -0,0 +1,73 @@ +// +// JPLaunchAtLoginManager.m +// CloudyTabs +// +// Based on a modified version of this StackOverflow answer - http://stackoverflow.com/a/2318004/446039 +// + +#import "JPLaunchAtLoginManager.h" + +@implementation JPLaunchAtLoginManager + ++ (BOOL)willStartAtLogin:(NSURL *)itemURL +{ + Boolean foundIt = false; + LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + if (loginItems) { + UInt32 seed = 0U; + NSArray *currentLoginItems = (__bridge NSArray *)(LSSharedFileListCopySnapshot(loginItems, &seed)); + for (id itemObject in currentLoginItems) { + LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject; + + UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; + CFURLRef URL = NULL; + OSStatus err = LSSharedFileListItemResolve(item, resolutionFlags, &URL, NULL); + if (err == noErr) { + foundIt = CFEqual(URL, (__bridge CFTypeRef)(itemURL)); + CFRelease(URL); + + if (foundIt) + break; + } + } + CFRelease(loginItems); + } + return (BOOL)foundIt; +} + ++ (void)setStartAtLogin:(NSURL *)itemURL enabled:(BOOL)enabled +{ + LSSharedFileListItemRef existingItem = NULL; + + LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + if (loginItems) { + UInt32 seed = 0U; + NSArray *currentLoginItems = (__bridge NSArray *)(LSSharedFileListCopySnapshot(loginItems, &seed)); + for (id itemObject in currentLoginItems) { + LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject; + + UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; + CFURLRef URL = NULL; + OSStatus err = LSSharedFileListItemResolve(item, resolutionFlags, &URL, NULL); + if (err == noErr) { + Boolean foundIt = CFEqual(URL, (__bridge CFTypeRef)(itemURL)); + CFRelease(URL); + + if (foundIt) { + existingItem = item; + break; + } + } + } + + if (enabled && (existingItem == NULL)) { + LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, (__bridge CFURLRef)itemURL, NULL, NULL); + + } else if (!enabled && (existingItem != NULL)) + LSSharedFileListItemRemove(loginItems, existingItem); + + CFRelease(loginItems); + } +} + +@end diff --git a/MonashTimetable/LaunchManager.h b/MonashTimetable/LaunchManager.h new file mode 100644 index 0000000..8bc5e2c --- /dev/null +++ b/MonashTimetable/LaunchManager.h @@ -0,0 +1,17 @@ +// +// LaunchManager.h +// MonashTimetable +// +// Created by Josh Parnham on 28/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Cocoa; + +#import "JPLaunchAtLoginManager.h" + +@interface LaunchManager : NSObject + +@property (nonatomic) BOOL launchAtLogin; + +@end diff --git a/MonashTimetable/LaunchManager.m b/MonashTimetable/LaunchManager.m new file mode 100644 index 0000000..b2e165e --- /dev/null +++ b/MonashTimetable/LaunchManager.m @@ -0,0 +1,28 @@ +// +// LaunchManager.m +// MonashTimetable +// +// Created by Josh Parnham on 28/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "LaunchManager.h" + +@implementation LaunchManager + +- (NSURL *)appURL +{ + return [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; +} + +- (BOOL)launchAtLogin +{ + return [JPLaunchAtLoginManager willStartAtLogin:[self appURL]]; +} + +- (void)setLaunchAtLogin:(BOOL)launchAtLogin +{ + [JPLaunchAtLoginManager setStartAtLogin:[self appURL] enabled:launchAtLogin]; +} + +@end diff --git a/MonashTimetable/LoginViewController.h b/MonashTimetable/LoginViewController.h new file mode 100644 index 0000000..cf1195c --- /dev/null +++ b/MonashTimetable/LoginViewController.h @@ -0,0 +1,20 @@ +// +// LoginViewController.h +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Cocoa; + +@interface LoginViewController : NSViewController + +@property (weak) IBOutlet NSTextField *usernameTextField; +@property (weak) IBOutlet NSTextField *passwordTextField; +@property (weak) IBOutlet NSButton *loginButton; +@property (weak) IBOutlet NSProgressIndicator *progressIndicator; + +- (IBAction)login:(id)sender; + +@end diff --git a/MonashTimetable/LoginViewController.m b/MonashTimetable/LoginViewController.m new file mode 100644 index 0000000..8530803 --- /dev/null +++ b/MonashTimetable/LoginViewController.m @@ -0,0 +1,88 @@ +// +// LoginViewController.m +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "LoginViewController.h" +#import "CredentialsManager.h" + +@implementation LoginViewController + +#pragma mark - View lifecycle + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(authorizationDidFail) name:@"AuthorizationDidFail" object:nil]; + self.view.window.initialFirstResponder = self.usernameTextField; +} + +#pragma mark - Methods + +- (IBAction)login:(NSButton *)sender +{ + [self setUserIsLoggingIn:YES]; + + CredentialsManager *credentialsManager = [[CredentialsManager alloc] init]; + [credentialsManager authenticateCredentials:self.usernameTextField.stringValue password:self.passwordTextField.stringValue]; +} + +- (void)setUserIsLoggingIn:(BOOL)loggingIn +{ + self.loginButton.enabled = !loggingIn; + + self.usernameTextField.enabled = !loggingIn; + self.passwordTextField.enabled = !loggingIn; + + self.progressIndicator.hidden = !loggingIn; + + if (loggingIn) { + [self.progressIndicator startAnimation:nil]; + } + else { + [self.progressIndicator stopAnimation:nil]; + } +} + +#pragma mark - Notification response + +- (void)authorizationDidFail +{ + [self setUserIsLoggingIn:NO]; + [self.passwordTextField becomeFirstResponder]; +} + +#pragma mark - Text delegate + +- (void)controlTextDidChange:(NSNotification *)notification +{ + if (self.usernameTextField.stringValue.length && self.passwordTextField.stringValue.length) { + self.loginButton.enabled = YES; + } + else { + self.loginButton.enabled = NO; + } +} + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector +{ + if (commandSelector == @selector(insertNewline:)) { + // Perform login when user presses "return" + if (self.usernameTextField.stringValue.length > 0 && self.passwordTextField.stringValue.length > 0) { + [self login:self]; + } + return YES; + } + else if (commandSelector == @selector(insertTab:)) { + // Hack to prevent "this method is supposed to only be invoked on top level items" exception + [self.passwordTextField becomeFirstResponder]; + return YES; + } + return NO; +} + +@end diff --git a/MonashTimetable/LoginViewController.xib b/MonashTimetable/LoginViewController.xib new file mode 100644 index 0000000..cb34f47 --- /dev/null +++ b/MonashTimetable/LoginViewController.xib @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/MXLCalendarManager b/MonashTimetable/MXLCalendarManager new file mode 160000 index 0000000..a48b323 --- /dev/null +++ b/MonashTimetable/MXLCalendarManager @@ -0,0 +1 @@ +Subproject commit a48b323d8b52730e64c0e63959006c826f0a267e diff --git a/MonashTimetable/MonashTimetable.xcdatamodeld/.xccurrentversion b/MonashTimetable/MonashTimetable.xcdatamodeld/.xccurrentversion deleted file mode 100644 index 25760c4..0000000 --- a/MonashTimetable/MonashTimetable.xcdatamodeld/.xccurrentversion +++ /dev/null @@ -1,8 +0,0 @@ - - - - - _XCCurrentVersionName - MonashTimetable.xcdatamodel - - diff --git a/MonashTimetable/MonashTimetable.xcdatamodeld/MonashTimetable.xcdatamodel/contents b/MonashTimetable/MonashTimetable.xcdatamodeld/MonashTimetable.xcdatamodel/contents deleted file mode 100644 index fd3d23f..0000000 --- a/MonashTimetable/MonashTimetable.xcdatamodeld/MonashTimetable.xcdatamodel/contents +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MonashTimetable/NSColor+DefaultColor.h b/MonashTimetable/NSColor+DefaultColor.h new file mode 100644 index 0000000..3bf5121 --- /dev/null +++ b/MonashTimetable/NSColor+DefaultColor.h @@ -0,0 +1,15 @@ +// +// NSColor+DefaultColor.h +// MonashTimetable +// +// Created by Josh Parnham on 28/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Cocoa; + +@interface NSColor (NSColor_DefaultColor) + ++ (NSColor *)defaultClassColor; + +@end diff --git a/MonashTimetable/NSColor+DefaultColor.m b/MonashTimetable/NSColor+DefaultColor.m new file mode 100644 index 0000000..b8ed1b0 --- /dev/null +++ b/MonashTimetable/NSColor+DefaultColor.m @@ -0,0 +1,18 @@ +// +// NSColor+DefaultColor.m +// MonashTimetable +// +// Created by Josh Parnham on 28/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "NSColor+DefaultColor.h" + +@implementation NSColor (NSColor_DefaultColor) + ++ (NSColor *)defaultClassColor +{ + return [NSColor colorWithRed:0.2 green:0.75 blue:1 alpha:1]; +} + +@end diff --git a/MonashTimetable/NSDate+DateBetween.h b/MonashTimetable/NSDate+DateBetween.h new file mode 100644 index 0000000..d1e2c98 --- /dev/null +++ b/MonashTimetable/NSDate+DateBetween.h @@ -0,0 +1,15 @@ +// +// NSDate+DateBetween.h +// MonashTimetable +// +// Created by Josh Parnham on 24/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import + +@interface NSDate (NSDate_DateBetween) + ++ (BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate; + +@end diff --git a/MonashTimetable/NSDate+DateBetween.m b/MonashTimetable/NSDate+DateBetween.m new file mode 100644 index 0000000..9c26886 --- /dev/null +++ b/MonashTimetable/NSDate+DateBetween.m @@ -0,0 +1,25 @@ +// +// NSDate+DateBetween.m +// MonashTimetable +// +// Created by Josh Parnham on 24/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "NSDate+DateBetween.h" + +@implementation NSDate (NSDate_DateBetween) + +// From http://stackoverflow.com/a/1072993/446039 ++ (BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate +{ + if ([date compare:beginDate] == NSOrderedAscending) + return NO; + + if ([date compare:endDate] == NSOrderedDescending) + return NO; + + return YES; +} + +@end diff --git a/MonashTimetable/NSEvent+KeyCodes.h b/MonashTimetable/NSEvent+KeyCodes.h new file mode 100644 index 0000000..fc09cb9 --- /dev/null +++ b/MonashTimetable/NSEvent+KeyCodes.h @@ -0,0 +1,77 @@ +// +// NSEvent+KeyCodes.h +// MonashTimetable +// +// Created by Josh Parnham on 30/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + + +// List of key codes compiled by Mark Helenurm from http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes +typedef NS_OPTIONS(NSUInteger, NSEventKeyCodes) { + NSEventKeyCodeA = 0, + NSEventKeyCodeS = 1, + NSEventKeyCodeD = 2, + NSEventKeyCodeF = 3, + NSEventKeyCodeH = 4, + NSEventKeyCodeG = 5, + NSEventKeyCodeZ = 6, + NSEventKeyCodeX = 7, + NSEventKeyCodeC = 8, + NSEventKeyCodeV = 9, + + NSEventKeyCodeB = 11, + NSEventKeyCodeQ = 12, + NSEventKeyCodeW = 13, + NSEventKeyCodeE = 14, + NSEventKeyCodeR = 15, + NSEventKeyCodeY = 16, + NSEventKeyCodeT = 17, + NSEventKeyCode1 = 18, + NSEventKeyCode2 = 19, + NSEventKeyCode3 = 20, + NSEventKeyCode4 = 21, + NSEventKeyCode6 = 22, + NSEventKeyCode5 = 23, + NSEventKeyCodeEquals = 24, + NSEventKeyCode9 = 25, + NSEventKeyCode7 = 26, + NSEventKeyCodeMinus = 27, + NSEventKeyCode8 = 28, + NSEventKeyCode0 = 29, + NSEventKeyCodeRightBracket = 30, + NSEventKeyCodeO = 31, + NSEventKeyCodeU = 32, + NSEventKeyCodeLeftBracket = 33, + NSEventKeyCodeI = 34, + NSEventKeyCodeP = 35, + NSEventKeyCodeReturn = 36, + NSEventKeyCodeL = 37, + NSEventKeyCodeJ = 38, + NSEventKeyCodeApostrophe = 39, + NSEventKeyCodeK = 40, + NSEventKeyCodeSemicolon = 41, + NSEventKeyCodeFrontslash = 42, + NSEventKeyCodeCOMMA = 43, + NSEventKeyCodeBackslash = 44, + NSEventKeyCodeN = 45, + NSEventKeyCodeM = 46, + NSEventKeyCodePeriod = 47, + NSEventKeyCodeTab = 48, + + NSEventKeyCodeBackapostrope = 50, + NSEventKeyCodeDelete = 51, + + NSEventKeyCodeEscape = 53, + + NSEventKeyCodeCommand = 55, + NSEventKeyCodeShift = 56, + NSEventKeyCodeCapslock = 57, + NSEventKeyCodeOption = 58, + NSEventKeyCodeCcontrol = 59, + + NSEventKeyCodeUp = 126, + NSEventKeyCodeDown = 125, + NSEventKeyCodeLeft = 123, + NSEventKeyCodeRight = 124 +}; diff --git a/MonashTimetable/NSFileManager+ApplicationSupport.h b/MonashTimetable/NSFileManager+ApplicationSupport.h new file mode 100644 index 0000000..244e4e8 --- /dev/null +++ b/MonashTimetable/NSFileManager+ApplicationSupport.h @@ -0,0 +1,15 @@ +// +// NSFileManager+ApplicationSupport.h +// MonashTimetable +// +// Created by Josh Parnham on 26/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import + +@interface NSFileManager (NSFileManager_ApplicationSupport) + ++ (NSString *)applicationSupportDirectory; + +@end diff --git a/MonashTimetable/NSFileManager+ApplicationSupport.m b/MonashTimetable/NSFileManager+ApplicationSupport.m new file mode 100644 index 0000000..0c139cd --- /dev/null +++ b/MonashTimetable/NSFileManager+ApplicationSupport.m @@ -0,0 +1,31 @@ +// +// NSFileManager+ApplicationSupport.m +// MonashTimetable +// +// Created by Josh Parnham on 26/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "NSFileManager+ApplicationSupport.h" + +@implementation NSFileManager (NSFileManager_ApplicationSupport) + ++ (NSString *)appBundleName +{ + return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; +} + ++ (NSString *)applicationSupportDirectory +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *applicationSupportPath = [paths[0] stringByAppendingPathComponent:[NSFileManager appBundleName]]; + + BOOL directory; + if (![[NSFileManager defaultManager] fileExistsAtPath:applicationSupportPath isDirectory:&directory]) { + [[NSFileManager defaultManager] createDirectoryAtPath:applicationSupportPath withIntermediateDirectories:YES attributes:nil error:nil]; + } + + return [paths[0] stringByAppendingPathComponent:[NSFileManager appBundleName]]; +} + +@end diff --git a/MonashTimetable/NSGeometry+Additions.h b/MonashTimetable/NSGeometry+Additions.h new file mode 100644 index 0000000..3a9e38c --- /dev/null +++ b/MonashTimetable/NSGeometry+Additions.h @@ -0,0 +1,15 @@ +// +// NSGeometry+Additions.h +// MonashTimetable +// +// Created by Josh Parnham on 27/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +NS_INLINE NSPoint NSPointFromRect(NSRect aRect) { + return NSMakePoint(aRect.origin.x, aRect.origin.y); +} + +NS_INLINE NSRect NSRectFromPoint(NSPoint aPoint) { + return NSMakeRect(aPoint.x, aPoint.y, 0, 0); +} diff --git a/MonashTimetable/SSKeychain b/MonashTimetable/SSKeychain new file mode 160000 index 0000000..7684ba6 --- /dev/null +++ b/MonashTimetable/SSKeychain @@ -0,0 +1 @@ +Subproject commit 7684ba6ef45520084c733acb8611e95cdfc304cf diff --git a/MonashTimetable/ScheduleKit.framework/Headers b/MonashTimetable/ScheduleKit.framework/Headers new file mode 120000 index 0000000..a177d2a --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Modules b/MonashTimetable/ScheduleKit.framework/Modules new file mode 120000 index 0000000..5736f31 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Modules @@ -0,0 +1 @@ +Versions/Current/Modules \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/PrivateHeaders b/MonashTimetable/ScheduleKit.framework/PrivateHeaders new file mode 120000 index 0000000..d8e5645 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/PrivateHeaders @@ -0,0 +1 @@ +Versions/Current/PrivateHeaders \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Resources b/MonashTimetable/ScheduleKit.framework/Resources new file mode 120000 index 0000000..953ee36 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/ScheduleKit b/MonashTimetable/ScheduleKit.framework/ScheduleKit new file mode 120000 index 0000000..5733eac --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/ScheduleKit @@ -0,0 +1 @@ +Versions/Current/ScheduleKit \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKDayView.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKDayView.h new file mode 100755 index 0000000..f5e3fe6 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKDayView.h @@ -0,0 +1,17 @@ +// +// SCKDayView.h +// ScheduleKit +// +// Created by Guillem on 31/12/14. +// Copyright (c) 2014 Guillem Servera. All rights reserved. +// + +#import "SCKGridView.h" + +@interface SCKDayView : SCKGridView + +- (IBAction)increaseDayOffset:(id)sender; +- (IBAction)decreaseDayOffset:(id)sender; +- (IBAction)resetDayOffset:(id)sender; + +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEvent.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEvent.h new file mode 100755 index 0000000..9b74422 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEvent.h @@ -0,0 +1,115 @@ +/* + * SCKEvent.h + * ScheduleKit + * + * Created: Guillem Servera on 24/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +@import Cocoa; + +/** A set of values used to distinguish between different event types. + * Actual values are related to different events on the medical field, since this + * framework was first intended to be used with medical apps, but feel free to include + * any other event types you need (try to keep the default and special values though). */ +typedef NS_ENUM(NSUInteger, SCKEventType) { + SCKEventTypeDefault = 0, /**< A generic type of event. */ + SCKEventTypeVisit = 1, /**< An event type for medical visits. */ + SCKEventTypeSurgery = 2, /**< An event type for surgeries. */ + //Feel free to add any event types you need here. + SCKEventTypeSpecial = NSUIntegerMax /**< A special event type for transitory events */ +}; + +/** + * The SCKUser protocol declares the expected interface for SCKEvent's @c user + * property values. + */ +@protocol SCKUser + +/** + * This method or property should return a color that will be used to draw SCKEventView's + * background when color mode is set to 'by user'. + * @return The requested NSColor object. + */ +- (NSColor*)labelColor; + +@end + + +/** + * The SCKEvent protocol declares the expected interface for objects being represented + * in any of the SCKView subclasses, that is, the set of methods needed for an object + * to be considered a valid ScheduleKit event. + */ +@protocol SCKEvent + +/** + * This method or property should return an event type that will be used to draw + * SCKEventView's background when color mode is set to 'by event type' + * @return The requested SCKEventType value + */ +- (SCKEventType)eventType; + +/** + * This method or property should return the user object associated with the event, + * that is, the event's owner. + * @return The requested user object. It must conform to the @c SCKUser protocol. + */ +- (id )user; + +/** + * This method or property should return the patient object associated with the event + * if any. It's not being used at the time. + * @return The patient object. + */ +- (id)patient; + +/** + * This method or property should return the string that will be drawn inside of the + * SCKEventView's frame, which allows the user to better identify each event. + * @return The requested NSString object. + */ +- (NSString*)title; + +/** + * Returns the event's duration in minutes. + * @return A NSNumber object representing the event duration in minutes. + */ +- (NSNumber*)duration; + +/** + * Called to set the event's duration. + * @param duration The new event duration in minutes. + */ +- (void)setDuration:(NSNumber*)duration; + +/** + * Returns the event's date and time. + * @return A NSDate object representing the event's start date. + */ +- (NSDate*)scheduledDate; + +/** + * Called to set the event's start date. + * @param scheduledDate The new event's start date. + */ +- (void)setScheduledDate:(NSDate*)scheduledDate; + +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventHolder.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventHolder.h new file mode 100755 index 0000000..beaf870 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventHolder.h @@ -0,0 +1,109 @@ +/* + * SCKEventHolder.h + * ScheduleKit + * + * Created: Guillem Servera on 24/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "SCKEvent.h" +#import "ScheduleKitDefinitions.h" + +@class SCKEventView; + +/** Instances of this class work in conjunction with an @c SCKEventView + * representing an object conforming to the @c SCKEvent protocol. */ +@interface SCKEventHolder : NSObject + +/** + * SCKEventHolder designated initializer. Sets up a new instance + * representing any object conforming to the @c SCKEvent protocol + * for the specified @c SCKEventView. + * + * @param e The represented object. Can't be nil. + * @param v The owning view for this instance. Must have been already + * added to a view hierarchy. Can't be nil. */ +- (nonnull instancetype)initWithEvent:(nonnull id )e owner:(nonnull SCKEventView*)v NS_DESIGNATED_INITIALIZER; + +/** + * Configures this instance to ignore observed @c representedObject changes + * until the @c -resumeObservingRepresentedObjectChanges method is called. + * This method gets called before changes triggered by the @c owningView in + * order to prevent observing of our own changes. Don't call this method + * yourself. + */ +- (void)stopObservingRepresentedObjectChanges; + +/** + * Configures this instance to resume tracking observed @c representedObject + * changes after a previous @c -stopObservingRepresentedObjectChanges call. + * This method gets called after changes triggered by the @c owningView. + * Don't call this method yourself. + */ +- (void)resumeObservingRepresentedObjectChanges; + +/** + * Begins delaying updates from represented object. Called by SCKView + * on every @c SCKEventHolder object at the beginning of a relayout or + * drag to prevent conflict-related errors in case these properties + * change during the process. Also called by SCKEventManager before + * invalidating an instance. Don't call this method yourself. */ +- (void)lock; + + +/** + * Stops delaying updates from represented object. Called by SCKView + * on every @c SCKEventHolder item at the end of a relayout or drag + * to prevent conflict-related errors in case these properties change + * during the process. Don't call this method yourself. + * @discussion In the case any change was observed while the event + * holder was locked, it finally will get applied when this method is + * called.*/ +- (void)unlock; + + +/** + * Recalculates @c cachedRelativeStart, @c cachedRelativeEnd and @c + * cachedRelativeLength according to the values set for properties + * @c duration and @c scheduledDate, based on the owning view limits + * (@c startDate and @c endDate). This is called automatically: + * - Immediatly after initialization. + * - Whenever @c scheduledDate and/or @c duration change if unlocked. + * - When the owning view ends either content or duration dragging. + * - NOT when owningView's @c startDate or @endDate change, because + * SCKEventManager's @c reloadData gets called instead. */ +- (void)recalculateRelativeValues; + +/** Indicates wether cached relative values are valid so drawing is safe.*/ +@property (readonly, getter=isReady) BOOL ready; +@property (readonly, getter=isLocked) BOOL locked; +@property (readonly, nonnull) id representedObject; +@property (readonly, weak, nullable) SCKEventView *owningView; + +// Cached values +@property (assign) SCKRelativeTimeLocation cachedRelativeStart; +@property (assign) SCKRelativeTimeLocation cachedRelativeEnd; +@property (assign) SCKRelativeTimeLength cachedRelativeLength; +@property (strong, nullable) NSColor *cachedUserLabelColor; +@property (strong, nullable) NSString *cachedTitle; +@property (strong, nullable) NSDate *cachedScheduleDate; +@property (assign) NSInteger cachedDuration; +@end \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventManager.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventManager.h new file mode 100755 index 0000000..659ca38 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventManager.h @@ -0,0 +1,52 @@ +// +// SCKEventManager.h +// ScheduleKit +// +// Created by Guillem on 28/12/14. +// Copyright (c) 2014 Guillem Servera. All rights reserved. +// + +#import "SCKEvent.h" +#import "SCKEventRequest.h" + +@class SCKEventManager, SCKEventHolder, SCKView; + +/** The SCKEventManagerDataSource protocol includes two methods that can be used by an event + * manager to retrieve its contents from an auxiliary object. The method that will be invoked + * depends on the value of the `loadsEventsAsynchronously` property. */ +@protocol SCKEventManagerDataSource +@optional +- (NSArray *)eventManager:(SCKEventManager *)eM requestsEventsBetweenDate:(NSDate*)sD andDate:(NSDate*)eD; +- (void)eventManager:(SCKEventManager *)eM didMakeEventRequest:(SCKEventRequest*)request; +@end + +@protocol SCKEventManagerDelegate +@optional + +- (void)eventManager:(SCKEventManager*)eM didSelectEvent:(id )e; +- (void)eventManagerDidClearSelection:(SCKEventManager*)eM; +- (void)eventManager:(SCKEventManager *)eM didDoubleClickEvent:(id )e; +- (void)eventManager:(SCKEventManager *)eM didDoubleClickBlankDate:(NSDate*)d; +- (BOOL)eventManager:(SCKEventManager *)eM shouldAllowChangesToEvent:(id )event; +- (NSColor *)eventManager:(SCKEventManager *)eM colorForEvent:(id )event; +- (BOOL)eventManager:(SCKEventManager *)eM shouldChangeLengthOfEvent:(id )e fromValue:(NSInteger)oV toValue:(NSInteger)fV; +- (BOOL)eventManager:(SCKEventManager *)eM shouldChangeDateOfEvent:(id )e fromValue:(NSDate*)oD toValue:(NSDate*)fD; + +@end + +@interface SCKEventManager : NSObject { + NSMutableArray * _managedContainers; + NSPointerArray * _lastRequest; + NSMutableArray * _asynchronousEventRequests; +} + +- (NSInteger)positionInConflictForEventHolder:(SCKEventHolder*)e holdersInConflict:(NSArray**)conflictsPtr; + +- (void)reloadData; +- (void)reset; + +@property (nonatomic, assign) BOOL loadsEventsAsynchronously; +@property (nonatomic, weak) id dataSource; +@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) SCKView * view; +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventRequest.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventRequest.h new file mode 100644 index 0000000..8fdd12c --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventRequest.h @@ -0,0 +1,77 @@ +/* + * SCKEventRequest.h + * ScheduleKit + * + * Created: Guillem Servera on 16/07/2015. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +@import Foundation; + +@class SCKEventManager; + +/** + * The SCKEventRequest class represents a structure used by an + * SCKEventManager object to encapsulate relevant info and to handle + * new events when reloading events asynchronously. + * + * Asynchronous event loading is disabled by default. You may enable it + * by setting SCKEventManager's @c loadsEventsAsynchronously to YES. When + * this is set, @c -eventManager:requestsEventsBetweenDate:andDate: won't + * be called on data source. Instead, @c -eventManager:didMakeEventRequest: + * will get called with an SCKEventRequest object as a parameter. Then, the + * data source is responsible of keeping a (weak) reference to this + * request, loading the apropiated events asynchronously and, when done, + * passing them back to the request via @c -completeWithEvents: on the + * main queue. + */ +@interface SCKEventRequest : NSObject + +/** + * Cancels the request if not canceled yet. This will make it ignore any + * @c -completeWithEvents: calls made afterwards. Additionally, the request + * will be released by its owning SCKEventManager (If you don't own any + * strong references to it, it will be deallocated and your weak references + * will become nil. + */ +- (void)cancel; + +/** + * If not cancelled, completes the request passing the provided events back + * to the owning SCKEventManager. Any future call to this method will be + * ignored. Additionally, the request will be released by its owning + * SCKEventManager (If you don't own any strong references to it, it will + * be deallocated and your weak references will become nil. + * + * @warning This method MUST be called from the main thread. + * @param events The asynchronously loaded events. + */ +- (void)completeWithEvents:(nonnull NSArray*)events; + +/** Returns whether the request has been canceled */ +@property (readonly, assign, getter=isCanceled) BOOL canceled; +/** The SCKEventManager object that issued the request */ +@property (readonly, weak, nullable) SCKEventManager *eventManager; +/** The requested start date parameter for the event fetch criteria */ +@property (readonly, strong, nonnull) NSDate *startDate; +/** The requested end date parameter for the event fetch criteria */ +@property (readonly, strong, nonnull) NSDate *endDate; +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventView.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventView.h new file mode 100755 index 0000000..5c4a500 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKEventView.h @@ -0,0 +1,75 @@ +/* + * SCKEventView.h + * ScheduleKit + * + * Created: Guillem Servera on 24/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "SCKEventHolder.h" +#import "SCKTextField.h" + +/** SCKEventView is the NSView subclass used to display events as subviews of + * an SCKView instance. Its functions include: + * - Managing an inner label (SCKTextField subclass) which shows info about + * the represented event and drag and drop actions. + * - Handling click, double click and drag and drop events to allow selection + * and conditional modification of the represented object's duration and/or + * scheduledDate. + */ +@interface SCKEventView : NSView { +@private + SCKActionContext _actionContext; +} + +/** Called from @c -drawRect when superview's @c colorMode is set to + * `SCKEventColorModeByEventType`. Returns a different fill color for each + * value defined in the `SCKEventType` enum. + * + * @param type The type for which to return a fill color + * @return The fill color for events of type `type`. + */ ++ (nonnull NSColor*)colorForEventType:(SCKEventType)type; + +/** Called from @c -drawRect when superview's @c colorMode is set to + * `SCKEventColorModeByEventType`. Returns a different stroke color for each + * value defined in the `SCKEventType` enum. + * + * @param type The type for which to return a stroke color + * @return The stroke color for events of type `type`. + */ ++ (nonnull NSColor*)strokeColorForEventType:(SCKEventType)type; + +/** Sent to all SCKEventView's in a SCKView instance before + * scheduling a redistribution process (movement of overlapping + * events. TODO: The whole redistribution process should be + * improved. */ +- (void)prepareForRedistribution; + +/** Indicates whether the view has passed the redistribution process. */ +@property (nonatomic, assign) BOOL layoutDone; + +/** The view's represented event holder */ +@property (nonatomic, strong, nonnull) SCKEventHolder * eventHolder; + +/** The view's inner label */ +@property (nonatomic, strong, nonnull) SCKTextField * innerLabel; +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKGridView.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKGridView.h new file mode 100755 index 0000000..018a0df --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKGridView.h @@ -0,0 +1,43 @@ +// +// SCKGridView.h +// ScheduleKit +// +// Created by Guillem on 30/12/14. +// Copyright (c) 2014 Guillem Servera. All rights reserved. +// + +#import "SCKView.h" +#import "SCKUnavailableTimeRange.h" + +@class SCKGridView; + +@protocol SCKGridViewDelegate +@optional +- (NSArray*)unavailableTimeRangesForGridView:(SCKGridView*)view; +@end + +@interface SCKGridView : SCKView { + NSCalendar * _calendar; + NSTimer *_minuteTimer; + NSArray *_unavailableTimeRanges; + NSInteger _dayCount; + NSInteger _hourCount; + NSInteger _firstHour; + + NSDateFormatter * _dayLabelDateFormatter; + NSDateFormatter * _monthLabelDateFormatter; +} + +- (void)readDefaultsFromDelegate; +- (void)invalidateUserDefaults; + + +- (NSRect)rectForUnavailableTimeRange:(SCKUnavailableTimeRange*)rng; + +- (IBAction)increaseZoomFactor:(id)sender; +- (IBAction)decreaseZoomFactor:(id)sender; + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign) CGFloat hourHeight; +@property (readonly) NSRect contentRect; +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKTextField.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKTextField.h new file mode 100755 index 0000000..08621d5 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKTextField.h @@ -0,0 +1,34 @@ +/* + * SCKTextField.h + * ScheduleKit + * + * Created: Guillem Servera on 01/01/2015. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +@import Cocoa; + +/** + * This class provides a custom NSTextField whose cell renders its string value + * vertically centered when the actual text is not being selected and/or edited. + */ +@interface SCKTextField : NSTextField +@end \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKUnavailableTimeRange.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKUnavailableTimeRange.h new file mode 100755 index 0000000..4e89f0b --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKUnavailableTimeRange.h @@ -0,0 +1,71 @@ +/* + * SCKUnavailableTimeRange.h + * ScheduleKit + * + * Created: Guillem Servera on 31/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +@import Foundation; + +// NSCoding support keys: +extern NSString * __nonnull const SCKBreakWeekdayKey; +extern NSString * __nonnull const SCKBreakStartHourKey; +extern NSString * __nonnull const SCKBreakStartMinuteKey; +extern NSString * __nonnull const SCKBreakEndHourKey; +extern NSString * __nonnull const SCKBreakEndMinuteKey; + +/** + This class can be used to represent (and to make persistent copies) a break or + unavailable time range withing a day being represented by a subclass of @c + SCKGridView. This class supports testing for equalty. + */ +@interface SCKUnavailableTimeRange : NSObject + +/** + * Initializes a new @c SCKUnavailableTimeRange object representing a specified + * time range within a day. + * + * @param weekday A weekday index for @c SCKWeekView or -1 for @c SCKDayView. + * @param startHour The time range's start hour. + * @param startMinute The time range's start minute. + * @param endHour The time range's end hour. + * @param endMinute The time range's end minute. + * + * @return The initialized @c SCKUnavailableTimeRange + */ +- (nonnull instancetype)initWithWeekday:(NSInteger)weekday startHour:(NSInteger)startHour startMinute:(NSInteger)startMinute endHour:(NSInteger)endHour endMinute:(NSInteger)endMinute NS_DESIGNATED_INITIALIZER; + +/** + * Compares two @c SCKUnavailableTimeRange objects + * + * @param range A range to be compared with self. + * + * @return YES if the ranges are equal. NO instead. + */ +- (BOOL)isEqualToUnavailableTimeRange:(nonnull SCKUnavailableTimeRange *)range; + +@property (assign) NSInteger weekday; /**< Weekday index in @c SCKView*/ +@property (assign) NSInteger startHour; /**< Break's start hour */ +@property (assign) NSInteger startMinute; /**< Break's start minute */ +@property (assign) NSInteger endHour; /**< Break's ending hour */ +@property (assign) NSInteger endMinute; /**< Break's ending minute */ +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKView.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKView.h new file mode 100755 index 0000000..f29b412 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKView.h @@ -0,0 +1,130 @@ +/* + * SCKView.h + * ScheduleKit + * + * Created: Guillem Servera on 24/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "SCKEventView.h" + +@class SCKEventManager; + +/** SCKView is an abstract NSView subclass which implements common functionality for any + * subclasses that display a collection of @c SCKEventView subviews provided by the + * delegate of an associated @c SCKEventManager object. This base class provides: + * - Basic date scope management via @c startDate, @c endDate and @c absoluteTimeInterval. + * - Functional conversion between @c NSDate and @c SCKRelativeTimeLocation values, and + * also the @c relativeTimeLocationForPoint: which subclasses should override. + * - Ability to get/set the coloring policy used to draw subviews' background. + * - Basic event selection and deselection handling. + * - Handling of double click on an empty space. + * - Drag and drop feedback methods for SCKEventView class. + * - Common event view (un)locking and relayout workflow. + */ +@interface SCKView : NSView { + double _absoluteStartTimeRef; /**< Absolute value for @c startDate */ + double _absoluteEndTimeRef; /**< Absolute value for @c endDate */ + NSMutableArray * _eventViews; /**< SCKEventView subviews */ + SCKEventView * _eventViewBeingDragged; /**< When dragging, the subview being dragged */ + NSArray * _otherEventViews; /**< When dragging, SCKEventView(s) NOT being dragged */ +} + +#pragma mark - Time-based calculations + +/** + * Calculates the date represented by a specific relative time location between @c + * startDate and @c endDate. Note that seconds are rounded so they'll be zero. + * @param offset The relative time location. Should be a value between 0.0 and 1.0. + * @return The calculated NSDate object or nil if @c offset is not valid. + */ +- (NSDate*)calculateDateForRelativeTimeLocation:(SCKRelativeTimeLocation)offset; + + +/** + * Calculates the relative time location between @c startDate and @c endDate for a given + * NSDate object. + * + * @param date The date from which to perform the calculation. Should not be nil. + * @return A double value between 0.0 and 1.0 representing the relative position of @c + * date between @c startDate and @c endDate; or @c SCKRelativeTimeLocationNotFound if @c + * date is before @c startDate or after @c endDate. + */ +- (SCKRelativeTimeLocation)calculateRelativeTimeLocationForDate:(NSDate *)date; + +/** + * Calculates the relative time location between @c startDate and @c for a given point + * inside the view coordinates. Default implementation always returns + * SCKRelativeLocationNotFound, consider overriding this method in subclasses. + * + * @param location The NSPoint for which to perform the calculation. + * @return In subclasses, a double value between 0.0 and 1.0 representing the relative + * position of @c location between @c startDate and @c endDate; or @c + * SCKRelativeTimeLocationNotFound if @c location falls out of the content rect. + */ +- (SCKRelativeTimeLocation)relativeTimeLocationForPoint:(NSPoint)location; + +#pragma mark - Event view layout + +/** + * This methods performs a series of operations in order to relayout an array of + * SCKEventView objects according to their date, duration and other events in conflict. + * The full process implies locking all subviews' event holder (as to prevent changes + * on their properties while conflict calculations take place), calling + * @c relayoutEventView:animated: for each SCKEventView in @c eventViews and finally + * unlocking the previously locked event holders. + * + * @discussion When an event view is being dragged, its event holder does not get locked + * or unlocked. + * @discussion Don't override this method. See @c beginRelayout and @c endRelayout instead. + * + * @param eventViews The array of SCKEventView objects to be redrawn. + * @param animation Pass YES if you want relayout to have animation. Pass no instead. + */ +- (void)triggerRelayoutForEventViews:(NSArray*)eventViews animated:(BOOL)animation; + +/** + * Calls @c triggerRelayoutForEventViews:animated: passing all event views and NO as + * parameters. + */ +- (void)triggerRelayoutForAllEventViews; + +#pragma mark - Properties + +/** This property is set to YES when a relayout has been triggered and back to NO when the + process finishes. Mind that relayout methods are invoked quite often. */ +@property (readonly) BOOL relayoutInProgress; + +/** Returns the number of seconds between @c startDate and @c endDate. */ +@property (readonly) NSTimeInterval absoluteTimeInterval; + +/** The minimum date being repesented. Setter sets view as needing display. Call super. */ +@property (nonatomic, strong) NSDate * startDate; + +/** The maximum date being repesented. Setter sets view as needing display. Call super. */ +@property (nonatomic, strong) NSDate * endDate; + +/** The style used by subviews to draw their background. @see ScheduleKitDefinitions.h */ +@property (nonatomic, assign) SCKEventColorMode colorMode; + +@property (nonatomic, weak) SCKEventView * selectedEventView; +@property (nonatomic, weak) IBOutlet SCKEventManager * eventManager; +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKWeekView.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKWeekView.h new file mode 100755 index 0000000..646ab21 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/SCKWeekView.h @@ -0,0 +1,33 @@ +// +// SCKWeekView.h +// ScheduleKit +// +// Created by Guillem on 31/12/14. +// Copyright (c) 2014 Guillem Servera. All rights reserved. +// + +#import "SCKGridView.h" + +@class SCKWeekView, SCKDayPoint; + +@protocol SCKWeekViewDelegate +- (NSInteger)dayStartHourForWeekView:(SCKWeekView*)wView; +- (NSInteger)dayEndHourForWeekView:(SCKWeekView*)wView; +@optional +- (NSInteger)dayCountForWeekView:(SCKWeekView*)wView; +@end + + +@interface SCKWeekView : SCKGridView { + SCKDayPoint *_dayStartPoint; + SCKDayPoint *_dayEndPoint; +} + + + +- (IBAction)increaseWeekOffset:(id)sender; +- (IBAction)decreaseWeekOffset:(id)sender; +- (IBAction)resetWeekOffset:(id)sender; + +@property (nonatomic, weak) id delegate; +@end diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/ScheduleKit.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/ScheduleKit.h new file mode 100755 index 0000000..03174be --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/ScheduleKit.h @@ -0,0 +1,47 @@ +/* + * ScheduleKit.h + * ScheduleKit + * + * Created: Guillem Servera on 24/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +@import Cocoa; + +//! Project version number for ScheduleKit. +FOUNDATION_EXPORT double ScheduleKitVersionNumber; + +//! Project version string for ScheduleKit. +FOUNDATION_EXPORT const unsigned char ScheduleKitVersionString[]; + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +extern NSString * const SCKDefaultsGridViewZoomLevelKey; \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/ScheduleKitDefinitions.h b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/ScheduleKitDefinitions.h new file mode 100755 index 0000000..216d35f --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Headers/ScheduleKitDefinitions.h @@ -0,0 +1,70 @@ +/* + * ScheduleKitDefinitions.h + * ScheduleKit + * + * Created: Guillem Servera on 24/12/2014. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** A type to represent relative time points between the lower and upper limits in a + @c SCKView subclass, where a value of 0.0 represents the lower limit and a value of + 1.0 represents the upper limit. */ +typedef double SCKRelativeTimeLocation; + +/** A type to represent the relative length (in percentage) of an event in a concrete + @c SCKView subclass. */ +typedef double SCKRelativeTimeLength; + +/** Used to represent not found or invalid @c SCKRelativeTimeLocation values */ +#define SCKRelativeTimeLocationNotFound (SCKRelativeTimeLocation)NSNotFound + +/** Possible color styles for drawing event view background. */ +typedef NS_ENUM(NSUInteger, SCKEventColorMode){ + /** The 'by event type' mode sets event views' background color according to their + * event holder's event type. */ + SCKEventColorModeByEventType = 0, + /** The 'by event owner' mode sets event views' background color according to the + * label color of their event holder's user. */ + SCKEventColorModeByEventOwner = 1, + /** The 'ask' mode asks the event manager delegate what color each event should be */ + SCKEventColorModeAskForEachEvent = 2 +}; + +typedef NS_ENUM(NSInteger, SCKDraggingStatus) { + SCKDraggingStatusIlde = -1, + SCKDraggingStatusDraggingDuration = 1, + SCKDraggingStatusDraggingContent = 2 +}; + +typedef struct SCKActionContext { + SCKDraggingStatus status; + BOOL doubleClick; + NSInteger oldDuration; + NSInteger lastDuration; + NSInteger newDuration; + SCKRelativeTimeLocation oldRelativeStart; + SCKRelativeTimeLocation newRelativeStart; + CGFloat internalDelta; + NSTimeInterval oldDateRef; +} SCKActionContext; + +/** Initializes a new SCKActionContext with all values set to zero. */ +SCKActionContext SCKActionContextZero(); \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Modules/module.modulemap b/MonashTimetable/ScheduleKit.framework/Versions/A/Modules/module.modulemap new file mode 100644 index 0000000..dddc94b --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module ScheduleKit { + umbrella header "ScheduleKit.h" + + export * + module * { export * } +} diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKEventManagerPrivate.h b/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKEventManagerPrivate.h new file mode 100755 index 0000000..9629805 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKEventManagerPrivate.h @@ -0,0 +1,18 @@ +// +// SCKEventManagerPrivate.h +// ScheduleKit +// +// Created by Guillem on 14/1/15. +// Copyright (c) 2015 Guillem Servera. All rights reserved. +// + +#import "SCKEventManager.h" +#import "SCKEventRequest.h" + +@interface SCKEventManager (Private) + +- (NSMutableArray*)asynchronousEventRequests; +- (NSArray*)managedEventHolders; +- (void)reloadDataWithAsynchronouslyLoadedEvents:(NSArray*)events request:(SCKEventRequest*)req; + +@end \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKEventRequestPrivate.h b/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKEventRequestPrivate.h new file mode 100644 index 0000000..2f3200f --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKEventRequestPrivate.h @@ -0,0 +1,44 @@ +/* + * SCKEventRequestPrivate.h + * ScheduleKit + * + * Created: Guillem Servera on 16/07/2015. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "SCKEventRequest.h" + +@class SCKEventManager; +@interface SCKEventRequest (Private) + +/** + * Initializes a new SCKEventRequest with the specified properties. This method + * should only be called from the owning SCKEventManager. + * + * @param eM The owning SCKEventManager. Can't be nil. + * @param sD The start date for an event fetch criteria. Can't be nil. + * @param eD The end date for an event fetch criteria. Can't be nil. + * + * @return The initialized SCKEventRequest object. + */ +- (instancetype)initWithEventManager:(SCKEventManager*)eM startDate:(NSDate*)sD endDate:(NSDate*)eD; + +@end \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKViewPrivate.h b/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKViewPrivate.h new file mode 100755 index 0000000..135081e --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/PrivateHeaders/SCKViewPrivate.h @@ -0,0 +1,119 @@ +/* + * SCKViewPrivate.h + * ScheduleKit + * + * Created: Guillem Servera on 28/01/2015. + * Copyright: © 2014-2015 Guillem Servera (http://github.com/gservera) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "SCKView.h" + +@class SCKEventView; + +@interface SCKView (Private) + +/** Convenienve method called from both @c -initWithCoder: and @c + * -initWithFrame. Default implementation initializes an array used to + * store the @c SCKEventView subviews contained in this view. + * @discussion You should always call super when subclassing. */ +- (void)customInit; + +#pragma mark - Subview management + +/** + * Adds an SCKEventView to the array of subviews managed by this + * instance. This method is typically called from the event manager. + * @param eventView The view to be added. Must already be a subview of self. + */ +- (void)addEventView:(SCKEventView*)eventView; + +/** + * Removes an SCKEventView from the array of subviews managed by + * this instance. This method is typically called from the event manager. + * @param eventView The view to be removed. + * @discussion @c -removeFromSuperview should also be called on @c eventView. + */ +- (void)removeEventView:(SCKEventView*)eventView; + +#pragma mark - Drag & drop support + +/** + * Called from an @c SCKEventView subview when a drag action begins. + * This method sets @c _eventViewBeingDragged and @c _otherEventViews, + * and also calls @c -lock on the event view's event holder. + * @discussion Locking and unlocking for SCKEventView subviews being dragged are + * handled here (and not during successive relayout processes) in order to avoid + * inconsistencies between the drag & drop action and changes that could be + * observed while the @c SCKEventView is being dragged. + * @param eV The @c SCKEventView being dragged. + */ +- (void)beginDraggingEventView:(SCKEventView*)eV; + +/** + * Called from an @c SCKEventView subview when a drag action moves. + * This method sets this view as needing display (to make dragging guides appear) + * and triggers a relayout for other event views (since conflicts may have changed). + * @param eV The @c SCKEventView being dragged. + */ +- (void)continueDraggingEventView:(SCKEventView*)eV; + +/** + * Called from an @c SCKEventView subview when a drag action ends. + * This method clears @c _eventViewBeingDragged and @c _otherEventViews, + * calls @c -unlock on the event view's event holder, triggers a final relayout + * and finally sets this view as needing display (to clear dragging guides). + * @discussion Locking and unlocking for SCKEventView subviews being dragged are + * handled here (and not during successive relayout processes) in order to avoid + * inconsistencies between the drag & drop action and changes that could be + * observed while the @c SCKEventView is being dragged. + * @param eV The @c SCKEventView being dragged. + */ +- (void)endDraggingEventView:(SCKEventView*)eV; + +#pragma mark - Event view layout + +/** + * This method is called when a relayout is triggered. You may override it to + * perform additional tasks before the actual relayout process takes place. In + * that case, you must call super. + */ +- (void)beginRelayout; + +/** + * SCKView subclasses override this method to implement positioning (updating + * frame) of their SCKEventView subviews when a relayout process is triggered. + * The ultimate objective of this method is to calculate a new frame for a + * concrete subview based on the properties of its holder. Conflict calculations + * should also be performed here. Default implementation does nothing. + * + * @param eventView The event view whose frame needs to be updated. + * @param animation YES if change should be animated, NO instead. + */ +- (void)relayoutEventView:(SCKEventView*)eventView animated:(BOOL)animation; + +/** + * This method is called when a relayout finishes. You may override it to + * perform additional tasks after the actual relayout process takes place. In + * that case, you must call super. + */ +- (void)endRelayout; + +@end \ No newline at end of file diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Resources/Info.plist b/MonashTimetable/ScheduleKit.framework/Versions/A/Resources/Info.plist new file mode 100644 index 0000000..cb721e1 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,42 @@ + + + + + BuildMachineOSBuild + 14E46 + CFBundleDevelopmentRegion + en + CFBundleExecutable + ScheduleKit + CFBundleIdentifier + com.guillemservera.ScheduleKit + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ScheduleKit + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 6E35b + DTPlatformVersion + GM + DTSDKBuild + 14D125 + DTSDKName + macosx10.10 + DTXcode + 0640 + DTXcodeBuild + 6E35b + NSHumanReadableCopyright + Copyright © 2015 Guillem Servera. All rights reserved. + + diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/Resources/LICENSE b/MonashTimetable/ScheduleKit.framework/Versions/A/Resources/LICENSE new file mode 100755 index 0000000..456cc18 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/A/Resources/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015 Guillem Servera Negre + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MonashTimetable/ScheduleKit.framework/Versions/A/ScheduleKit b/MonashTimetable/ScheduleKit.framework/Versions/A/ScheduleKit new file mode 100755 index 0000000..6771e7e Binary files /dev/null and b/MonashTimetable/ScheduleKit.framework/Versions/A/ScheduleKit differ diff --git a/MonashTimetable/ScheduleKit.framework/Versions/Current b/MonashTimetable/ScheduleKit.framework/Versions/Current new file mode 120000 index 0000000..8c7e5a6 --- /dev/null +++ b/MonashTimetable/ScheduleKit.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Headers b/MonashTimetable/Sparkle.framework/Headers new file mode 120000 index 0000000..a177d2a --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Modules b/MonashTimetable/Sparkle.framework/Modules new file mode 120000 index 0000000..5736f31 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Modules @@ -0,0 +1 @@ +Versions/Current/Modules \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/PrivateHeaders b/MonashTimetable/Sparkle.framework/PrivateHeaders new file mode 120000 index 0000000..d8e5645 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/PrivateHeaders @@ -0,0 +1 @@ +Versions/Current/PrivateHeaders \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Resources b/MonashTimetable/Sparkle.framework/Resources new file mode 120000 index 0000000..953ee36 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Sparkle b/MonashTimetable/Sparkle.framework/Sparkle new file mode 120000 index 0000000..b2c5273 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Sparkle @@ -0,0 +1 @@ +Versions/Current/Sparkle \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUAppcast.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUAppcast.h new file mode 100644 index 0000000..9e9acd5 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUAppcast.h @@ -0,0 +1,26 @@ +// +// SUAppcast.h +// Sparkle +// +// Created by Andy Matuschak on 3/12/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUAPPCAST_H +#define SUAPPCAST_H + +#import +#import "SUExport.h" + +@class SUAppcastItem; +SU_EXPORT @interface SUAppcast : NSObject + +@property (copy) NSString *userAgentString; +@property (copy) NSDictionary *httpHeaders; + +- (void)fetchAppcastFromURL:(NSURL *)url completionBlock:(void (^)(NSError *))err; + +@property (readonly, copy) NSArray *items; +@end + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h new file mode 100644 index 0000000..551d389 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h @@ -0,0 +1,42 @@ +// +// SUAppcastItem.h +// Sparkle +// +// Created by Andy Matuschak on 3/12/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUAPPCASTITEM_H +#define SUAPPCASTITEM_H + +#include "SUExport.h" + +SU_EXPORT @interface SUAppcastItem : NSObject +@property (copy, readonly) NSString *title; +@property (copy, readonly) NSDate *date; +@property (copy, readonly) NSString *itemDescription; +@property (strong, readonly) NSURL *releaseNotesURL; +@property (copy, readonly) NSString *DSASignature; +@property (copy, readonly) NSString *minimumSystemVersion; +@property (copy, readonly) NSString *maximumSystemVersion; +@property (strong, readonly) NSURL *fileURL; +@property (copy, readonly) NSString *versionString; +@property (copy, readonly) NSString *displayVersionString; +@property (copy, readonly) NSDictionary *deltaUpdates; +@property (strong, readonly) NSURL *infoURL; + +// Initializes with data from a dictionary provided by the RSS class. +- (instancetype)initWithDictionary:(NSDictionary *)dict; +- (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString **)error; + +@property (getter=isDeltaUpdate, readonly) BOOL deltaUpdate; +@property (getter=isCriticalUpdate, readonly) BOOL criticalUpdate; + +// Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. +@property (readonly, copy) NSDictionary *propertiesDictionary; + +- (NSURL *)infoURL; + +@end + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUErrors.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUErrors.h new file mode 100644 index 0000000..e624bb0 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUErrors.h @@ -0,0 +1,44 @@ +// +// SUErrors.h +// Sparkle +// +// Created by C.W. Betts on 10/13/14. +// Copyright (c) 2014 Sparkle Project. All rights reserved. +// + +#ifndef SUERRORS_H +#define SUERRORS_H + +#import +#import "SUExport.h" + +/** + * Error domain used by Sparkle + */ +SU_EXPORT extern NSString *const SUSparkleErrorDomain; + +typedef NS_ENUM(OSStatus, SUError) { + // Appcast phase errors. + SUAppcastParseError = 1000, + SUNoUpdateError = 1001, + SUAppcastError = 1002, + SURunningFromDiskImageError = 1003, + + // Downlaod phase errors. + SUTemporaryDirectoryError = 2000, + + // Extraction phase errors. + SUUnarchivingError = 3000, + SUSignatureError = 3001, + + // Installation phase errors. + SUFileCopyFailure = 4000, + SUAuthenticationFailure = 4001, + SUMissingUpdateError = 4002, + SUMissingInstallerToolError = 4003, + SURelaunchError = 4004, + SUInstallationError = 4005, + SUDowngradeError = 4006 +}; + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUExport.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUExport.h new file mode 100644 index 0000000..3e3f8a1 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUExport.h @@ -0,0 +1,18 @@ +// +// SUExport.h +// Sparkle +// +// Created by Jake Petroules on 2014-08-23. +// Copyright (c) 2014 Sparkle Project. All rights reserved. +// + +#ifndef SUEXPORT_H +#define SUEXPORT_H + +#ifdef BUILDING_SPARKLE +#define SU_EXPORT __attribute__((visibility("default"))) +#else +#define SU_EXPORT +#endif + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h new file mode 100644 index 0000000..73ac968 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h @@ -0,0 +1,37 @@ +// +// SUStandardVersionComparator.h +// Sparkle +// +// Created by Andy Matuschak on 12/21/07. +// Copyright 2007 Andy Matuschak. All rights reserved. +// + +#ifndef SUSTANDARDVERSIONCOMPARATOR_H +#define SUSTANDARDVERSIONCOMPARATOR_H + +#import "SUExport.h" +#import "SUVersionComparisonProtocol.h" + +/*! + Sparkle's default version comparator. + + This comparator is adapted from MacPAD, by Kevin Ballard. + It's "dumb" in that it does essentially string comparison, + in components split by character type. +*/ +SU_EXPORT @interface SUStandardVersionComparator : NSObject + +/*! + Returns a singleton instance of the comparator. +*/ ++ (SUStandardVersionComparator *)defaultComparator; + +/*! + Compares version strings through textual analysis. + + See the implementation for more details. +*/ +- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; +@end + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUUpdater.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUUpdater.h new file mode 100644 index 0000000..90d606f --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUUpdater.h @@ -0,0 +1,327 @@ +// +// SUUpdater.h +// Sparkle +// +// Created by Andy Matuschak on 1/4/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUUPDATER_H +#define SUUPDATER_H + +#import "SUExport.h" +#import "SUVersionComparisonProtocol.h" +#import "SUVersionDisplayProtocol.h" + +@class SUUpdateDriver, SUAppcastItem, SUHost, SUAppcast; + +@protocol SUUpdaterDelegate; + +/*! + The main API in Sparkle for controlling the update mechanism. + + This class is used to configure the update paramters as well as manually + and automatically schedule and control checks for updates. + */ +SU_EXPORT @interface SUUpdater : NSObject + +@property (unsafe_unretained) IBOutlet id delegate; + ++ (SUUpdater *)sharedUpdater; ++ (SUUpdater *)updaterForBundle:(NSBundle *)bundle; +- (instancetype)initForBundle:(NSBundle *)bundle; + +@property (readonly, strong) NSBundle *hostBundle; + +@property BOOL automaticallyChecksForUpdates; + +@property NSTimeInterval updateCheckInterval; + +/*! + * The URL of the appcast used to download update information. + * + * This property must be called on the main thread. + */ +@property (copy) NSURL *feedURL; + +@property (nonatomic, copy) NSString *userAgentString; + +@property (copy) NSDictionary *httpHeaders; + +@property BOOL sendsSystemProfile; + +@property BOOL automaticallyDownloadsUpdates; + +/*! + Explicitly checks for updates and displays a progress dialog while doing so. + + This method is meant for a main menu item. + Connect any menu item to this action in Interface Builder, + and Sparkle will check for updates and report back its findings verbosely + when it is invoked. + */ +- (IBAction)checkForUpdates:(id)sender; + +/*! + Checks for updates, but does not display any UI unless an update is found. + + This is meant for programmatically initating a check for updates. That is, + it will display no UI unless it actually finds an update, in which case it + proceeds as usual. + + If the fully automated updating is turned on, however, this will invoke that + behavior, and if an update is found, it will be downloaded and prepped for + installation. + */ +- (void)checkForUpdatesInBackground; + +/*! + Returns the date of last update check. + + \returns \c nil if no check has been performed. + */ +@property (readonly, copy) NSDate *lastUpdateCheckDate; + +/*! + Begins a "probing" check for updates which will not actually offer to + update to that version. + + However, the delegate methods + SUUpdaterDelegate::updater:didFindValidUpdate: and + SUUpdaterDelegate::updaterDidNotFindUpdate: will be called, + so you can use that information in your UI. + */ +- (void)checkForUpdateInformation; + +/*! + Appropriately schedules or cancels the update checking timer according to + the preferences for time interval and automatic checks. + + This call does not change the date of the next check, + but only the internal NSTimer. + */ +- (void)resetUpdateCycle; + +@property (readonly) BOOL updateInProgress; + +@end + +// ----------------------------------------------------------------------------- +// SUUpdater Notifications for events that might be interesting to more than just the delegate +// The updater will be the notification object +// ----------------------------------------------------------------------------- +SU_EXPORT extern NSString *const SUUpdaterDidFinishLoadingAppCastNotification; +SU_EXPORT extern NSString *const SUUpdaterDidFindValidUpdateNotification; +SU_EXPORT extern NSString *const SUUpdaterDidNotFindUpdateNotification; +SU_EXPORT extern NSString *const SUUpdaterWillRestartNotification; +#define SUUpdaterWillRelaunchApplicationNotification SUUpdaterWillRestartNotification; +#define SUUpdaterWillInstallUpdateNotification SUUpdaterWillRestartNotification; + +// Key for the SUAppcastItem object in the SUUpdaterDidFindValidUpdateNotification userInfo +SU_EXPORT extern NSString *const SUUpdaterAppcastItemNotificationKey; +// Key for the SUAppcast object in the SUUpdaterDidFinishLoadingAppCastNotification userInfo +SU_EXPORT extern NSString *const SUUpdaterAppcastNotificationKey; + +// ----------------------------------------------------------------------------- +// SUUpdater Delegate: +// ----------------------------------------------------------------------------- + +/*! + Provides methods to control the behavior of an SUUpdater object. + */ +@protocol SUUpdaterDelegate +@optional + +/*! + Returns whether to allow Sparkle to pop up. + + For example, this may be used to prevent Sparkle from interrupting a setup assistant. + + \param updater The SUUpdater instance. + */ +- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)updater; + +/*! + Returns additional parameters to append to the appcast URL's query string. + + This is potentially based on whether or not Sparkle will also be sending along the system profile. + + \param updater The SUUpdater instance. + \param sendingProfile Whether the system profile will also be sent. + + \return An array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user. + */ +- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile; + +/*! + Returns a custom appcast URL. + + Override this to dynamically specify the entire URL. + + \param updater The SUUpdater instance. + */ +- (NSString *)feedURLStringForUpdater:(SUUpdater *)updater; + +/*! + Returns whether Sparkle should prompt the user about automatic update checks. + + Use this to override the default behavior. + + \param updater The SUUpdater instance. + */ +- (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)updater; + +/*! + Called after Sparkle has downloaded the appcast from the remote server. + + Implement this if you want to do some special handling with the appcast once it finishes loading. + + \param updater The SUUpdater instance. + \param appcast The appcast that was downloaded from the remote server. + */ +- (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast; + +/*! + Returns the item in the appcast corresponding to the update that should be installed. + + If you're using special logic or extensions in your appcast, + implement this to use your own logic for finding a valid update, if any, + in the given appcast. + + \param appcast The appcast that was downloaded from the remote server. + \param updater The SUUpdater instance. + */ +- (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast forUpdater:(SUUpdater *)updater; + +/*! + Called when a valid update is found by the update driver. + + \param updater The SUUpdater instance. + \param item The appcast item corresponding to the update that is proposed to be installed. + */ +- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)item; + +/*! + Called when a valid update is not found. + + \param updater The SUUpdater instance. + */ +- (void)updaterDidNotFindUpdate:(SUUpdater *)updater; + +/*! + Called immediately before installing the specified update. + + \param updater The SUUpdater instance. + \param item The appcast item corresponding to the update that is proposed to be installed. + */ +- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)item; + +/*! + Returns whether the relaunch should be delayed in order to perform other tasks. + + This is not called if the user didn't relaunch on the previous update, + in that case it will immediately restart. + + \param updater The SUUpdater instance. + \param item The appcast item corresponding to the update that is proposed to be installed. + \param invocation The invocation that must be completed before continuing with the relaunch. + + \return \c YES to delay the relaunch until \p invocation is invoked. + */ +- (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)item untilInvoking:(NSInvocation *)invocation; + +/*! + Returns whether the application should be relaunched at all. + + Some apps \b cannot be relaunched under certain circumstances. + This method can be used to explicitly prevent a relaunch. + + \param updater The SUUpdater instance. + */ +- (BOOL)updaterShouldRelaunchApplication:(SUUpdater *)updater; + +/*! + Called immediately before relaunching. + + \param updater The SUUpdater instance. + */ +- (void)updaterWillRelaunchApplication:(SUUpdater *)updater; + +/*! + Returns an object that compares version numbers to determine their arithmetic relation to each other. + + This method allows you to provide a custom version comparator. + If you don't implement this method or return \c nil, + the standard version comparator will be used. + + \sa SUStandardVersionComparator + + \param updater The SUUpdater instance. + */ +- (id)versionComparatorForUpdater:(SUUpdater *)updater; + +/*! + Returns an object that formats version numbers for display to the user. + + If you don't implement this method or return \c nil, + the standard version formatter will be used. + + \sa SUUpdateAlert + + \param updater The SUUpdater instance. + */ +- (id)versionDisplayerForUpdater:(SUUpdater *)updater; + +/*! + Returns the path which is used to relaunch the client after the update is installed. + + The default is the path of the host bundle. + + \param updater The SUUpdater instance. + */ +- (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater; + +/*! + Called before an updater shows a modal alert window, + to give the host the opportunity to hide attached windows that may get in the way. + + \param updater The SUUpdater instance. + */ +- (void)updaterWillShowModalAlert:(SUUpdater *)updater; + +/*! + Called after an updater shows a modal alert window, + to give the host the opportunity to hide attached windows that may get in the way. + + \param updater The SUUpdater instance. + */ +- (void)updaterDidShowModalAlert:(SUUpdater *)updater; + +/*! + Called when an update is scheduled to be silently installed on quit. + + \param updater The SUUpdater instance. + \param item The appcast item corresponding to the update that is proposed to be installed. + \param invocation Can be used to trigger an immediate silent install and relaunch. + */ +- (void)updater:(SUUpdater *)updater willInstallUpdateOnQuit:(SUAppcastItem *)item immediateInstallationInvocation:(NSInvocation *)invocation; + +/*! + Calls after an update that was scheduled to be silently installed on quit has been canceled. + + \param updater The SUUpdater instance. + \param item The appcast item corresponding to the update that was proposed to be installed. + */ +- (void)updater:(SUUpdater *)updater didCancelInstallUpdateOnQuit:(SUAppcastItem *)item; + +/*! + Called after an update is aborted due to an error. + + \param updater The SUUpdater instance. + \param error The error that caused the abort + */ +- (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error; + +@end + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h new file mode 100644 index 0000000..10c4266 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h @@ -0,0 +1,30 @@ +// +// SUVersionComparisonProtocol.h +// Sparkle +// +// Created by Andy Matuschak on 12/21/07. +// Copyright 2007 Andy Matuschak. All rights reserved. +// + +#ifndef SUVERSIONCOMPARISONPROTOCOL_H +#define SUVERSIONCOMPARISONPROTOCOL_H + +#import +#import "SUExport.h" + +/*! + Provides version comparison facilities for Sparkle. +*/ +@protocol SUVersionComparison + +/*! + An abstract method to compare two version strings. + + Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, + and NSOrderedSame if they are equivalent. +*/ +- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; // *** MAY BE CALLED ON NON-MAIN THREAD! + +@end + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h new file mode 100644 index 0000000..97fae4c --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h @@ -0,0 +1,25 @@ +// +// SUVersionDisplayProtocol.h +// EyeTV +// +// Created by Uli Kusterer on 08.12.09. +// Copyright 2009 Elgato Systems GmbH. All rights reserved. +// + +#import +#import "SUExport.h" + +/*! + Applies special display formatting to version numbers. +*/ +@protocol SUVersionDisplay + +/*! + Formats two version strings. + + Both versions are provided so that important distinguishing information + can be displayed while also leaving out unnecessary/confusing parts. +*/ +- (void)formatVersion:(NSString **)inOutVersionA andVersion:(NSString **)inOutVersionB; + +@end diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Headers/Sparkle.h b/MonashTimetable/Sparkle.framework/Versions/A/Headers/Sparkle.h new file mode 100644 index 0000000..fe97bae --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Headers/Sparkle.h @@ -0,0 +1,23 @@ +// +// Sparkle.h +// Sparkle +// +// Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07) +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SPARKLE_H +#define SPARKLE_H + +// This list should include the shared headers. It doesn't matter if some of them aren't shared (unless +// there are name-space collisions) so we can list all of them to start with: + +#import +#import +#import +#import +#import +#import +#import + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Modules/module.modulemap b/MonashTimetable/Sparkle.framework/Versions/A/Modules/module.modulemap new file mode 100644 index 0000000..af3fe6d --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module Sparkle { + umbrella header "Sparkle.h" + + export * + module * { export * } +} diff --git a/MonashTimetable/Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h b/MonashTimetable/Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h new file mode 100644 index 0000000..136484b --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h @@ -0,0 +1,33 @@ +// +// SUUnarchiver.h +// Sparkle +// +// Created by Andy Matuschak on 3/16/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUUNARCHIVER_H +#define SUUNARCHIVER_H + +@class SUHost; +@protocol SUUnarchiverDelegate; + +@interface SUUnarchiver : NSObject + +@property (copy, readonly) NSString *archivePath; +@property (weak, readonly) NSString *updateHostBundlePath; +@property (weak) id delegate; + ++ (SUUnarchiver *)unarchiverForPath:(NSString *)path updatingHostBundlePath:(NSString *)host; + +- (void)start; +@end + +@protocol SUUnarchiverDelegate +- (void)unarchiverDidFinish:(SUUnarchiver *)unarchiver; +- (void)unarchiverDidFail:(SUUnarchiver *)unarchiver; +@optional +- (void)unarchiver:(SUUnarchiver *)unarchiver extractedProgress:(double)progress; +@end + +#endif diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Info.plist b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Info.plist new file mode 100644 index 0000000..4f4aeb1 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Info.plist @@ -0,0 +1,50 @@ + + + + + BuildMachineOSBuild + 14E7f + CFBundleDevelopmentRegion + English + CFBundleExecutable + Autoupdate + CFBundleIconFile + AppIcon + CFBundleIdentifier + org.sparkle-project.Sparkle.Autoupdate + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.10.0 git-9646b0b + CFBundleSignature + ???? + CFBundleVersion + 1.10.0 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 6D1002 + DTPlatformVersion + GM + DTSDKBuild + 14D125 + DTSDKName + macosx10.10 + DTXcode + 0631 + DTXcodeBuild + 6D1002 + LSBackgroundOnly + 1 + LSMinimumSystemVersion + 10.7 + LSUIElement + 1 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/MacOS/Autoupdate b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/MacOS/Autoupdate new file mode 100755 index 0000000..64d8838 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/MacOS/Autoupdate differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/PkgInfo b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/PkgInfo new file mode 100644 index 0000000..bd04210 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/AppIcon.icns b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/AppIcon.icns new file mode 100644 index 0000000..93fb79e Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/AppIcon.icns differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/SUStatus.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/SUStatus.nib new file mode 100644 index 0000000..2a63346 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/SUStatus.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ar.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ar.lproj/Sparkle.strings new file mode 100644 index 0000000..28c2c21 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ar.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/cs.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/cs.lproj/Sparkle.strings new file mode 100644 index 0000000..a50d6bf Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/cs.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/da.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/da.lproj/Sparkle.strings new file mode 100644 index 0000000..8c349bd Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/da.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/de.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/de.lproj/Sparkle.strings new file mode 100644 index 0000000..fe50db5 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/de.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/el.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/el.lproj/Sparkle.strings new file mode 100644 index 0000000..015c213 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/el.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/en.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/en.lproj/Sparkle.strings new file mode 100644 index 0000000..d2e5e5c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/en.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/es.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/es.lproj/Sparkle.strings new file mode 100644 index 0000000..ee69407 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/es.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/fr.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/fr.lproj/Sparkle.strings new file mode 100644 index 0000000..c7b221b Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/fr.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/is.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/is.lproj/Sparkle.strings new file mode 100644 index 0000000..68ae6e0 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/is.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/it.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/it.lproj/Sparkle.strings new file mode 100644 index 0000000..99955af Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/it.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ja.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ja.lproj/Sparkle.strings new file mode 100644 index 0000000..faa546c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ja.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ko.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ko.lproj/Sparkle.strings new file mode 100644 index 0000000..d5df79d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ko.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nb.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nb.lproj/Sparkle.strings new file mode 100644 index 0000000..05a426d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nb.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nl.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nl.lproj/Sparkle.strings new file mode 100644 index 0000000..95923ee Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nl.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pl.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pl.lproj/Sparkle.strings new file mode 100644 index 0000000..d10801f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pl.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_BR.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_BR.lproj/Sparkle.strings new file mode 100644 index 0000000..0f2ef4d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_BR.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_PT.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_PT.lproj/Sparkle.strings new file mode 100644 index 0000000..69853a3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_PT.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ro.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ro.lproj/Sparkle.strings new file mode 100644 index 0000000..3cd694d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ro.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ru.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ru.lproj/Sparkle.strings new file mode 100644 index 0000000..349f17f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ru.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sk.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sk.lproj/Sparkle.strings new file mode 100644 index 0000000..38bb70d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sk.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sl.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sl.lproj/Sparkle.strings new file mode 100644 index 0000000..889a658 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sl.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sv.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sv.lproj/Sparkle.strings new file mode 100644 index 0000000..e7e9307 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sv.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/th.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/th.lproj/Sparkle.strings new file mode 100644 index 0000000..323bb70 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/th.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/tr.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/tr.lproj/Sparkle.strings new file mode 100644 index 0000000..74e17e4 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/tr.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/uk.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/uk.lproj/Sparkle.strings new file mode 100644 index 0000000..bf13d96 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/uk.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_CN.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_CN.lproj/Sparkle.strings new file mode 100644 index 0000000..49b68ce Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_CN.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_TW.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_TW.lproj/Sparkle.strings new file mode 100644 index 0000000..d9229c9 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_TW.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/Info.plist b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Info.plist new file mode 100644 index 0000000..8c21f16 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,48 @@ + + + + + BuildMachineOSBuild + 14E7f + CFBundleDevelopmentRegion + en + CFBundleExecutable + Sparkle + CFBundleIdentifier + org.andymatuschak.Sparkle + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Sparkle + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.10.0 git-9646b0b + CFBundleSignature + ???? + CFBundleVersion + 1.10.0rc1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 6D1002 + DTPlatformVersion + GM + DTSDKBuild + 14D125 + DTSDKName + macosx10.10 + DTXcode + 0631 + DTXcodeBuild + 6D1002 + SUAppendVersionNumber + 1 + SUEnableAutomatedDowngrades + 0 + SUNormalizeInstalledApplicationName + 0 + SURelaunchToolName + Autoupdate + + diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist b/MonashTimetable/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist new file mode 100644 index 0000000..74db0ff --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist @@ -0,0 +1,228 @@ + + + + + ADP2,1 + Developer Transition Kit + iMac1,1 + iMac G3 (Rev A-D) + iMac4,1 + iMac (Core Duo) + iMac4,2 + iMac for Education (17 inch, Core Duo) + iMac5,1 + iMac (Core 2 Duo, 17 or 20 inch, SuperDrive) + iMac5,2 + iMac (Core 2 Duo, 17 inch, Combo Drive) + iMac6,1 + iMac (Core 2 Duo, 24 inch, SuperDrive) + iMac8,1 + iMac (Core 2 Duo, 20 or 24 inch, Early 2008 ) + iMac9,1 + iMac (Core 2 Duo, 20 or 24 inch, Early or Mid 2009 ) + iMac10,1 + iMac (Core 2 Duo, 21.5 or 27 inch, Late 2009 ) + iMac11,1 + iMac (Core i5 or i7, 27 inch Late 2009) + iMac11,2 + iMac (Core i3 or i5, 27 inch Mid 2010) + iMac11,3 + iMac (Core i5 or i7, 27 inch Mid 2010) + iMac12,1 + iMac (Core i3 or i5 or i7, 21.5 inch Mid 2010 or Late 2011) + iMac12,2 + iMac (Core i5 or i7, 27 inch Mid 2011) + iMac13,1 + iMac (Core i3 or i5 or i7, 21.5 inch Late 2012 or Early 2013) + iMac13,2 + iMac (Core i5 or i7, 27 inch Late 2012) + iMac14,1 + iMac (Core i5, 21.5 inch Late 2013) + iMac14,2 + iMac (Core i5 or i7, 27 inch Late 2013) + iMac14,3 + iMac (Core i5 or i7, 21.5 inch Late 2013) + MacBook1,1 + MacBook (Core Duo) + MacBook2,1 + MacBook (Core 2 Duo) + MacBook4,1 + MacBook (Core 2 Duo Feb 2008) + MacBook5,1 + MacBook (Core 2 Duo, Late 2008, Unibody) + MacBook5,2 + MacBook (Core 2 Duo, Early 2009, White) + MacBook6,1 + MacBook (Core 2 Duo, Late 2009, Unibody) + MacBook7,1 + MacBook (Core 2 Duo, Mid 2010, White) + MacBookAir1,1 + MacBook Air (Core 2 Duo, 13 inch, Early 2008) + MacBookAir2,1 + MacBook Air (Core 2 Duo, 13 inch, Mid 2009) + MacBookAir3,1 + MacBook Air (Core 2 Duo, 11 inch, Late 2010) + MacBookAir3,2 + MacBook Air (Core 2 Duo, 13 inch, Late 2010) + MacBookAir4,1 + MacBook Air (Core i5 or i7, 11 inch, Mid 2011) + MacBookAir4,2 + MacBook Air (Core i5 or i7, 13 inch, Mid 2011) + MacBookAir5,1 + MacBook Air (Core i5 or i7, 11 inch, Mid 2012) + MacBookAir5,2 + MacBook Air (Core i5 or i7, 13 inch, Mid 2012) + MacBookAir6,1 + MacBook Air (Core i5 or i7, 11 inch, Mid 2013 or Early 2014) + MacBookAir6,2 + MacBook Air (Core i5 or i7, 13 inch, Mid 2013 or Early 2014) + MacBookPro1,1 + MacBook Pro Core Duo (15-inch) + MacBookPro1,2 + MacBook Pro Core Duo (17-inch) + MacBookPro2,1 + MacBook Pro Core 2 Duo (17-inch) + MacBookPro2,2 + MacBook Pro Core 2 Duo (15-inch) + MacBookPro3,1 + MacBook Pro Core 2 Duo (15-inch LED, Core 2 Duo) + MacBookPro3,2 + MacBook Pro Core 2 Duo (17-inch HD, Core 2 Duo) + MacBookPro4,1 + MacBook Pro (Core 2 Duo Feb 2008) + Macmini1,1 + Mac Mini (Core Solo/Duo) + MacPro1,1 + Mac Pro (four-core) + MacPro2,1 + Mac Pro (eight-core) + MacPro3,1 + Mac Pro (January 2008 4- or 8- core "Harpertown") + MacPro4,1 + Mac Pro (March 2009) + MacPro5,1 + Mac Pro (August 2010) + PowerBook1,1 + PowerBook G3 + PowerBook2,1 + iBook G3 + PowerBook2,2 + iBook G3 (FireWire) + PowerBook2,3 + iBook G3 + PowerBook2,4 + iBook G3 + PowerBook3,1 + PowerBook G3 (FireWire) + PowerBook3,2 + PowerBook G4 + PowerBook3,3 + PowerBook G4 (Gigabit Ethernet) + PowerBook3,4 + PowerBook G4 (DVI) + PowerBook3,5 + PowerBook G4 (1GHz / 867MHz) + PowerBook4,1 + iBook G3 (Dual USB, Late 2001) + PowerBook4,2 + iBook G3 (16MB VRAM) + PowerBook4,3 + iBook G3 Opaque 16MB VRAM, 32MB VRAM, Early 2003) + PowerBook5,1 + PowerBook G4 (17 inch) + PowerBook5,2 + PowerBook G4 (15 inch FW 800) + PowerBook5,3 + PowerBook G4 (17-inch 1.33GHz) + PowerBook5,4 + PowerBook G4 (15 inch 1.5/1.33GHz) + PowerBook5,5 + PowerBook G4 (17-inch 1.5GHz) + PowerBook5,6 + PowerBook G4 (15 inch 1.67GHz/1.5GHz) + PowerBook5,7 + PowerBook G4 (17-inch 1.67GHz) + PowerBook5,8 + PowerBook G4 (Double layer SD, 15 inch) + PowerBook5,9 + PowerBook G4 (Double layer SD, 17 inch) + PowerBook6,1 + PowerBook G4 (12 inch) + PowerBook6,2 + PowerBook G4 (12 inch, DVI) + PowerBook6,3 + iBook G4 + PowerBook6,4 + PowerBook G4 (12 inch 1.33GHz) + PowerBook6,5 + iBook G4 (Early-Late 2004) + PowerBook6,7 + iBook G4 (Mid 2005) + PowerBook6,8 + PowerBook G4 (12 inch 1.5GHz) + PowerMac1,1 + Power Macintosh G3 (Blue & White) + PowerMac1,2 + Power Macintosh G4 (PCI Graphics) + PowerMac10,1 + Mac Mini G4 + PowerMac10,2 + Mac Mini (Late 2005) + PowerMac11,2 + Power Macintosh G5 (Late 2005) + PowerMac12,1 + iMac G5 (iSight) + PowerMac2,1 + iMac G3 (Slot-loading CD-ROM) + PowerMac2,2 + iMac G3 (Summer 2000) + PowerMac3,1 + Power Macintosh G4 (AGP Graphics) + PowerMac3,2 + Power Macintosh G4 (AGP Graphics) + PowerMac3,3 + Power Macintosh G4 (Gigabit Ethernet) + PowerMac3,4 + Power Macintosh G4 (Digital Audio) + PowerMac3,5 + Power Macintosh G4 (Quick Silver) + PowerMac3,6 + Power Macintosh G4 (Mirrored Drive Door) + PowerMac4,1 + iMac G3 (Early/Summer 2001) + PowerMac4,2 + iMac G4 (Flat Panel) + PowerMac4,4 + eMac + PowerMac4,5 + iMac G4 (17-inch Flat Panel) + PowerMac5,1 + Power Macintosh G4 Cube + PowerMac6,1 + iMac G4 (USB 2.0) + PowerMac6,3 + iMac G4 (20-inch Flat Panel) + PowerMac6,4 + eMac (USB 2.0, 2005) + PowerMac7,2 + Power Macintosh G5 + PowerMac7,3 + Power Macintosh G5 + PowerMac8,1 + iMac G5 + PowerMac8,2 + iMac G5 (Ambient Light Sensor) + PowerMac9,1 + Power Macintosh G5 (Late 2005) + RackMac1,1 + Xserve G4 + RackMac1,2 + Xserve G4 (slot-loading, cluster node) + RackMac3,1 + Xserve G5 + Xserve1,1 + Xserve (Intel Xeon) + Xserve2,1 + Xserve (January 2008 quad-core) + + diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/SUStatus.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/SUStatus.nib new file mode 100644 index 0000000..2a63346 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/SUStatus.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..f91cb9d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..88fe442 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..89b7c48 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings new file mode 100644 index 0000000..28c2c21 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..4ff8afe Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..e23cfa1 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..0947d7f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings new file mode 100644 index 0000000..a50d6bf Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..3fc9d17 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..73595ca Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..826a977 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings new file mode 100644 index 0000000..8c349bd Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..b2b9554 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..c31ac42 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..5d2cdb1 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings new file mode 100644 index 0000000..fe50db5 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..229df3c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..0d43c97 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..7f53f7e Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings new file mode 100644 index 0000000..015c213 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..a5a019b Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..832ec29 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..78f217a Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings new file mode 100644 index 0000000..d2e5e5c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..b2666b7 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..0dab596 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..06586bd Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings new file mode 100644 index 0000000..ee69407 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..52eca82 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..cae35bf Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..df2841d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings new file mode 100644 index 0000000..c7b221b Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr_CA.lproj b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr_CA.lproj new file mode 120000 index 0000000..f9834a3 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Resources/fr_CA.lproj @@ -0,0 +1 @@ +fr.lproj \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..68083c2 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..b6b74f3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..b50374c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings new file mode 100644 index 0000000..68ae6e0 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..9c257be Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..d559eeb Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..8ab6435 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings new file mode 100644 index 0000000..99955af Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..7e4b758 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..bbafb69 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..504677d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings new file mode 100644 index 0000000..faa546c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..4012e8c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..5b35ce4 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..5600ae3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings new file mode 100644 index 0000000..d5df79d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..fe29652 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..a58e36c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..1b39b84 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings new file mode 100644 index 0000000..05a426d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..67b36a8 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..9bdf54b Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..c064d1e Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings new file mode 100644 index 0000000..95923ee Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..ec1ad6d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..c2d1cae Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..50406ab Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings new file mode 100644 index 0000000..d10801f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt.lproj b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt.lproj new file mode 120000 index 0000000..3c1c9f6 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt.lproj @@ -0,0 +1 @@ +pt_BR.lproj \ No newline at end of file diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..4eb1c1a Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..13f3374 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..9fa7506 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings new file mode 100644 index 0000000..0f2ef4d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..8add884 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..1b678d3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..bf6d1be Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings new file mode 100644 index 0000000..69853a3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..3200815 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..91f4335 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..c93746d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings new file mode 100644 index 0000000..3cd694d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..f501887 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..3d961ce Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..0ea7a5f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings new file mode 100644 index 0000000..349f17f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..6de310e Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..3ef6fb0 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..ec77f89 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings new file mode 100644 index 0000000..38bb70d Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..3c922a9 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..2957889 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..9e1c1a0 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings new file mode 100644 index 0000000..889a658 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..44caab3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..4c803c1 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..a94c004 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings new file mode 100644 index 0000000..e7e9307 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..5dd71dc Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..de5d239 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..dd0df43 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings new file mode 100644 index 0000000..323bb70 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..285513a Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..9339388 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..cd259c5 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings new file mode 100644 index 0000000..74e17e4 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..3d1c58b Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..639d2c3 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..af37a0f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings new file mode 100644 index 0000000..bf13d96 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..6533a98 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..f10d922 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..903c6ce Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings new file mode 100644 index 0000000..49b68ce Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 0000000..3d0448f Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib new file mode 100644 index 0000000..5566620 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 0000000..470407c Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings new file mode 100644 index 0000000..d9229c9 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings differ diff --git a/MonashTimetable/Sparkle.framework/Versions/A/Sparkle b/MonashTimetable/Sparkle.framework/Versions/A/Sparkle new file mode 100755 index 0000000..23f7820 Binary files /dev/null and b/MonashTimetable/Sparkle.framework/Versions/A/Sparkle differ diff --git a/MonashTimetable/Sparkle.framework/Versions/Current b/MonashTimetable/Sparkle.framework/Versions/Current new file mode 120000 index 0000000..8c7e5a6 --- /dev/null +++ b/MonashTimetable/Sparkle.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/MonashTimetable/TimetableManager.h b/MonashTimetable/TimetableManager.h new file mode 100644 index 0000000..ee13ab9 --- /dev/null +++ b/MonashTimetable/TimetableManager.h @@ -0,0 +1,41 @@ +// +// TimetableManager.h +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Foundation; + +#import "UniversityClass.h" + +@protocol TimetableManagerDelegate + +- (void)timetableManagerDidStartDownloadingTimetable; +- (void)timetableManagerDidFinishDownloadingTimetable; + +/** Called when the timetable has finished being parsed and an array of UniversityClass objects is available. */ +- (void)timetableManagerClassesDidBecomeAvailable:(NSArray *)classes; + +@end + +@interface TimetableManager : NSObject + +@property (weak, nonatomic) id delegate; + +/** Checks if a timetable has already been downloaded. If so, starts processing it. If no timetable is found on disk, it triggers a download of the timetable. */ +- (void)manageTimetable; + +/** Downloads a user's timetable and caches it to disk. */ +- (void)downloadTimetable; + +/** Parses a ICS file and creates an array of UniversityClass objects that are sent to the delegate method. + @see timetableManagerClassesDidBecomeAvailable: + @param path A NSString filepath of a valid ICS file. */ +- (void)processTimetableAtPath:(NSString *)path; + +/** Removes a users credentials, authentication token, timetable file and unit colors. */ +- (void)signOut; + +@end diff --git a/MonashTimetable/TimetableManager.m b/MonashTimetable/TimetableManager.m new file mode 100644 index 0000000..75bce10 --- /dev/null +++ b/MonashTimetable/TimetableManager.m @@ -0,0 +1,139 @@ +// +// TimetableManager.m +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "TimetableManager.h" + +#import "CredentialsManager.h" +#import "MXLCalendarManager.h" +#import "SSKeychain.h" + +#import "NSFileManager+ApplicationSupport.h" + +#define TIMETABLE_FILENAME @"timetable.ics" + +@implementation TimetableManager + +- (void)manageTimetable +{ + NSString *filepath = [[NSFileManager applicationSupportDirectory] stringByAppendingPathComponent:TIMETABLE_FILENAME]; + if ([[NSFileManager defaultManager] fileExistsAtPath:filepath]) { + [self processTimetableAtPath:filepath]; + } + else { + [self downloadTimetable]; + } +} + +- (void)downloadTimetable +{ + if ([self.delegate respondsToSelector:@selector(timetableManagerDidStartDownloadingTimetable)]) { + [self.delegate timetableManagerDidStartDownloadingTimetable]; + } + + if ([CredentialsManager validPortalAuthentication]) { + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://my.monash.edu.au/json/app/"]]; + + [request setValue:[CredentialsManager portalAuthentication] forHTTPHeaderField:@"Cookie"]; + NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + + NSURLSessionDataTask *dataTask = [urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + NSError *jsonError; + NSDictionary *appData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError]; + if (!jsonError) { + NSString *timetableICalFeedURL = appData[@"timetableICalFeedUrl"]; + + NSURLSessionDataTask *dataTask = [urlSession dataTaskWithURL:[NSURL URLWithString:timetableICalFeedURL] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + NSLog(@"%@", error.localizedDescription); + } + + NSString *filepath = [[NSFileManager applicationSupportDirectory] stringByAppendingPathComponent:TIMETABLE_FILENAME]; + NSError *writeError; + [data writeToFile:filepath options:NSDataWritingAtomic error:&writeError]; + if (!writeError) { + dispatch_async(dispatch_get_main_queue(), ^{ + if ([self.delegate respondsToSelector:@selector(timetableManagerDidFinishDownloadingTimetable)]) { + [self.delegate timetableManagerDidFinishDownloadingTimetable]; + } + [self processTimetableAtPath:filepath]; + }); + } + else { + NSLog(@"Error writing ICS file to filepath."); + } + }]; + [dataTask resume]; + } + else { + NSLog(@"Parsing JSON returned an error. Signing out."); + [self signOut]; + } + }]; + [dataTask resume]; + } + else { + NSLog(@"Nil MonashPortalAuthentication cookie. Signing out."); + // TODO: Regenerage portalAuthenticationCookie based on stored credentials + [self signOut]; + } +} + +- (void)processTimetableAtPath:(NSString *)path +{ + NSMutableArray *classArray = [[NSMutableArray alloc] init]; + + MXLCalendarManager *calendarManager = [[MXLCalendarManager alloc] init]; + [calendarManager scanICSFileAtLocalPath:path withCompletionHandler:^(MXLCalendar *calendar, NSError *error) + { + if (!error) { + for (MXLCalendarEvent *event in calendar.events) { + NSNumber *duration = [NSNumber numberWithInt:([event.eventEndDate timeIntervalSinceDate:event.eventStartDate])/60]; + + UniversityClass *class = [[UniversityClass alloc] initWithUser:nil title:event.eventSummary duration:duration scheduledDate:event.eventStartDate location:event.eventLocation unitTitle:event.eventDescription]; + [classArray addObject:class]; + } + if ([self.delegate respondsToSelector:@selector(timetableManagerClassesDidBecomeAvailable:)]) { + [self.delegate timetableManagerClassesDidBecomeAvailable:classArray]; + } + } + else { + NSLog(@"Error parsing ICS file. Signing out."); + [self signOut]; + } + }]; +} + +- (void)signOut +{ + // Delete credentials and authentication cookie + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + NSArray *accounts = [query fetchAll:nil]; + for (id account in accounts) { + SSKeychainQuery *usernamePasswordQuery = [[SSKeychainQuery alloc] init]; + usernamePasswordQuery.service = @"Monash"; + usernamePasswordQuery.account = [account valueForKey:@"acct"]; + [usernamePasswordQuery deleteItem:nil]; + } + [SSKeychain deletePasswordForService:@"MonashPortalAuthentication" account:@"com.joshparnham.Monash"]; + + // Remove timetable ICS file + NSError *error; + [[NSFileManager defaultManager] removeItemAtPath:[[NSFileManager applicationSupportDirectory] stringByAppendingPathComponent:TIMETABLE_FILENAME] error:&error]; + if (error) { + NSLog(@"%@", error.localizedDescription); + } + + // Clear unit colors + [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"AuthorizationStatusDidChange" object:nil]; + }); +} + +@end diff --git a/MonashTimetable/TimetableViewController.h b/MonashTimetable/TimetableViewController.h new file mode 100644 index 0000000..ef96c5a --- /dev/null +++ b/MonashTimetable/TimetableViewController.h @@ -0,0 +1,24 @@ +// +// TimetableViewController.h +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Cocoa; +@import ScheduleKit; + +#import "TimetableManager.h" + +@interface TimetableViewController : NSViewController + +@property (weak) IBOutlet SCKEventManager *weekEventManager; +@property IBOutlet SCKWeekView *weekView; + +@property (weak) IBOutlet NSButton *statusButton; + +- (IBAction)refreshTimetable:(id)sender; +- (IBAction)signOut:(id)sender; + +@end diff --git a/MonashTimetable/TimetableViewController.m b/MonashTimetable/TimetableViewController.m new file mode 100644 index 0000000..ff99547 --- /dev/null +++ b/MonashTimetable/TimetableViewController.m @@ -0,0 +1,203 @@ +// +// TimetableViewController.m +// MonashTimetable +// +// Created by Josh Parnham on 8/05/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "TimetableViewController.h" + +#import "ClassViewController.h" +#import "UniversityClass.h" +#import "UnitColorManager.h" + +#import "NSDate+DateBetween.h" +#import "NSGeometry+Additions.h" +#import "NSEvent+KeyCodes.h" + +@interface TimetableViewController () + +@property (strong, nonatomic) NSArray *classes; + +@property (strong, nonatomic) TimetableManager *timetableManager; + +@end + +@implementation TimetableViewController + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + NSEvent *(^monitorHandler)(NSEvent *); + monitorHandler = ^NSEvent *(NSEvent *event){ + switch (event.keyCode) { + // Handle left & right keys to move the weekView between weeks + case NSEventKeyCodeLeft: + [self.weekView decreaseWeekOffset:self]; + break; + case NSEventKeyCodeRight: + [self.weekView increaseWeekOffset:self]; + break; + // Handle ⌘+ & ⌘- to magnify and shrink the weekview + case NSEventKeyCodeEquals: + if (event.modifierFlags & NSCommandKeyMask) { + [self.weekView increaseZoomFactor:self]; + } + break; + case NSEventKeyCodeMinus: + if (event.modifierFlags & NSCommandKeyMask) { + [self.weekView decreaseZoomFactor:self]; + } + break; + default: + break; + } + return event; + }; + + id eventMonitor __unused = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:monitorHandler]; + } + return self; +} + +- (instancetype)init +{ + return [self initWithNibName:nil bundle:nil]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.weekEventManager.view = self.weekView; +// ((SCKWeekView *)self.view).eventManager = self.weekEventManager; + self.weekView.eventManager = self.weekEventManager; + + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSDate *weekBeginning; + [calendar rangeOfUnit:NSCalendarUnitWeekOfYear startDate:&weekBeginning interval:nil forDate:[NSDate date]]; + NSDate *weekEnding = [calendar dateByAddingUnit:NSCalendarUnitWeekOfYear value:1 toDate:weekBeginning options:0]; + + self.weekEventManager.view.startDate = weekBeginning; + self.weekEventManager.view.endDate = weekEnding; + + self.weekEventManager.dataSource = self; + self.weekEventManager.delegate = self; + + [self.weekEventManager reloadData]; + + ((SCKWeekView *)self.weekEventManager.view).delegate = self; + + ((SCKWeekView *)self.weekEventManager.view).colorMode = SCKEventColorModeAskForEachEvent; + + self.timetableManager = [[TimetableManager alloc] init]; + self.timetableManager.delegate = self; + [self.timetableManager manageTimetable]; +} + +#pragma mark - Actions + +- (IBAction)changeWeekOffset:(id)sender +{ + switch (((NSSegmentedControl*)sender).selectedSegment) { + case 0: + [self.weekView decreaseWeekOffset:sender]; + break; + case 1: + [self.weekView increaseWeekOffset:sender]; + break; + } +} + +- (IBAction)refreshTimetable:(id)sender +{ + [self.timetableManager downloadTimetable]; +} + +- (IBAction)signOut:(id)sender; +{ + [self.timetableManager signOut]; +} + +#pragma mark - Week view delegate +- (NSInteger)dayStartHourForWeekView:(SCKWeekView*)wView +{ + return 8; +} + +- (NSInteger)dayEndHourForWeekView:(SCKWeekView*)wView +{ + return 20; +} + +#pragma mark - Event manager data source +- (NSArray *)eventManager:(SCKEventManager *)eM requestsEventsBetweenDate:(NSDate*)sD andDate:(NSDate*)eD +{ + NSMutableArray *classesToDisplay = [[NSMutableArray alloc] init]; + for (UniversityClass *class in self.classes) { + if ([NSDate date:class.scheduledDate isBetweenDate:sD andDate:eD]) { + [classesToDisplay addObject:class]; + } + } + return classesToDisplay; +} + +- (NSColor *)eventManager:(SCKEventManager *)eM colorForEvent:(id )event +{ + return [UnitColorManager colorForUnitCode:((UniversityClass *)event).unitCode]; +} + +#pragma mark - Event manager delegate + +- (void)eventManager:(SCKEventManager *)eM didDoubleClickEvent:(id)e +{ + NSPopover *popover = [[NSPopover alloc] init]; + ClassViewController *classViewController = [[ClassViewController alloc] initWithUniversityClass:e]; + popover.contentViewController = classViewController; + popover.behavior = NSPopoverBehaviorTransient; + + NSPoint mouseLocation = [NSEvent mouseLocation]; + NSPoint windowLocation = NSPointFromRect([[self.weekView window] convertRectFromScreen:NSRectFromPoint(mouseLocation)]); + NSPoint viewLocation = [self.weekView convertPoint:windowLocation fromView:nil]; + if(NSPointInRect(viewLocation, [self.weekView bounds])) { + [popover showRelativeToRect:NSMakeRect(viewLocation.x, viewLocation.y, 10, 10) ofView:self.weekView preferredEdge:NSMaxXEdge]; + } +} + +- (BOOL)eventManager:(SCKEventManager *)eM shouldChangeLengthOfEvent:(id )e fromValue:(NSInteger)oV toValue:(NSInteger)fV +{ + return NO; +} + +- (BOOL)eventManager:(SCKEventManager *)eM shouldChangeDateOfEvent:(id )e fromValue:(NSDate*)oD toValue:(NSDate*)fD +{ + return NO; +} + +- (BOOL)eventManager:(SCKEventManager *)eM shouldAllowChangesToEvent:(id )e +{ + return NO; +} + +#pragma mark - Timetable manager delegate + +- (void)timetableManagerDidStartDownloadingTimetable +{ + self.statusButton.title = @"Downloading Timetable..."; +} + +- (void)timetableManagerDidFinishDownloadingTimetable +{ + self.statusButton.title = @""; +} + +- (void)timetableManagerClassesDidBecomeAvailable:(NSArray *)classes +{ + self.classes = classes; + + [self.weekEventManager reloadData]; +} + +@end diff --git a/MonashTimetable/TimetableViewController.xib b/MonashTimetable/TimetableViewController.xib new file mode 100644 index 0000000..f98058e --- /dev/null +++ b/MonashTimetable/TimetableViewController.xib @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonashTimetable/UnitColorManager.h b/MonashTimetable/UnitColorManager.h new file mode 100644 index 0000000..ec1cdf3 --- /dev/null +++ b/MonashTimetable/UnitColorManager.h @@ -0,0 +1,16 @@ +// +// UnitColorManager.h +// MonashTimetable +// +// Created by Josh Parnham on 28/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Cocoa; + +@interface UnitColorManager : NSObject + ++ (NSColor *)colorForUnitCode:(NSString *)unitCode; ++ (void)storeColor:(NSColor *)color forUnitCode:(NSString *)unitCode; + +@end diff --git a/MonashTimetable/UnitColorManager.m b/MonashTimetable/UnitColorManager.m new file mode 100644 index 0000000..f63878c --- /dev/null +++ b/MonashTimetable/UnitColorManager.m @@ -0,0 +1,30 @@ +// +// UnitColorManager.m +// MonashTimetable +// +// Created by Josh Parnham on 28/07/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "UnitColorManager.h" + +#import "NSColor+DefaultColor.h" + +@implementation UnitColorManager + ++ (NSColor *)colorForUnitCode:(NSString *)unitCode +{ + NSData *colorArchive = [[NSUserDefaults standardUserDefaults] dataForKey:unitCode]; + if (colorArchive != nil) { + return (NSColor *)[NSUnarchiver unarchiveObjectWithData:colorArchive]; + } + return [NSColor defaultClassColor]; +} + ++ (void)storeColor:(NSColor *)color forUnitCode:(NSString *)unitCode +{ + NSData *colorArchive = [NSArchiver archivedDataWithRootObject:color]; + [[NSUserDefaults standardUserDefaults] setObject:colorArchive forKey:unitCode]; +} + +@end diff --git a/MonashTimetable/UniversityClass.h b/MonashTimetable/UniversityClass.h new file mode 100644 index 0000000..b33ed00 --- /dev/null +++ b/MonashTimetable/UniversityClass.h @@ -0,0 +1,27 @@ +// +// UniversityClass.h +// MonashTimetable +// +// Created by Josh Parnham on 28/06/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +@import Foundation; +@import ScheduleKit; + +@interface UniversityClass : NSObject + +- (instancetype)initWithUser:(id)user title:(NSString *)title duration:(NSNumber *)duration scheduledDate:(NSDate *)scheduledDate location:(NSString *)location unitTitle:(NSString *)unitTitle; + +@property SCKEventType eventType; +@property id user; +@property id patient; +@property NSString *title; +@property NSNumber *duration; +@property NSDate *scheduledDate; +@property NSString *location; +@property NSString *unitTitle; + +@property (readonly) NSString *unitCode; + +@end diff --git a/MonashTimetable/UniversityClass.m b/MonashTimetable/UniversityClass.m new file mode 100644 index 0000000..c072d72 --- /dev/null +++ b/MonashTimetable/UniversityClass.m @@ -0,0 +1,45 @@ +// +// UniversityClass.m +// MonashTimetable +// +// Created by Josh Parnham on 28/06/2015. +// Copyright (c) 2015 Josh Parnham. All rights reserved. +// + +#import "UniversityClass.h" + +@implementation UniversityClass + +- (instancetype)initWithUser:(id)user title:(NSString *)title duration:(NSNumber *)duration scheduledDate:(NSDate *)scheduledDate location:(NSString *)location unitTitle:(NSString *)unitTitle +{ + self = [super init]; + if (self) { + self.eventType = SCKEventTypeDefault; + self.patient = nil; + + self.title = title; + self.duration = duration; + self.scheduledDate = scheduledDate; + self.location = location; + self.unitTitle = unitTitle; + } + return self; +} + +- (instancetype)init +{ + return [self initWithUser:nil title:nil duration:nil scheduledDate:nil location:nil unitTitle:nil]; +} + +#pragma mark - Methods + +- (NSString *)unitCode +{ + if (self.title) { + // Should match regex: ([A-Z]){3}([0-9]){4} + return [self.title componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]][0]; + } + return nil; +} + +@end