diff --git a/.gitignore b/.gitignore index 7a83bb580..d09c1be77 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.perspective *.perspectivev3 *.pbxuser +*.xcworkspace xcuserdata ControlPlane.xcodeproj/xcuserdata/dustin.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist @@ -36,4 +37,3 @@ Backup[ ]of[ ]*.pages/ Backup[ ]of[ ]*.key/ Backup[ ]of[ ]*.numbers/ - diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index eacdb59c5..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "Source/QuincyKit"] - path = Source/QuincyKit - url = git://github.com/TheRealKerni/QuincyKit.git diff --git a/ControlPlane.xcodeproj/project.pbxproj b/ControlPlane.xcodeproj/project.pbxproj index 8a98e8dc2..34f03c08f 100644 --- a/ControlPlane.xcodeproj/project.pbxproj +++ b/ControlPlane.xcodeproj/project.pbxproj @@ -7,148 +7,84 @@ objects = { /* Begin PBXBuildFile section */ - 732A58DF1484300A0011019C /* ShellScriptEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 732A58DE1484300A0011019C /* ShellScriptEvidenceSource.m */; }; - 732A58F21484336C0011019C /* Quincy.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DA8064AB1479910E00267B5A /* Quincy.framework */; }; - 739492E2146B8018003C94DE /* DisplaySleepTimeAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 739492E1146B8018003C94DE /* DisplaySleepTimeAction.m */; }; - 73A5092F14849405007D22B5 /* ShellScriptRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = 73A5092714849405007D22B5 /* ShellScriptRule.xib */; }; - 8D01634F0C029913004AD8DB /* DNDArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D01634D0C029913004AD8DB /* DNDArrayController.m */; }; - 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; - 8D1493F70C824B6D00D29FE8 /* BonjourEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D1493F50C824B6D00D29FE8 /* BonjourEvidenceSource.m */; }; + 8D01634F0C029913004AD8DB /* DNDArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D01634D0C029913004AD8DB /* DNDArrayController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 8D11072D0486CEB800E47090 /* Main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* Main.m */; settings = {ATTRIBUTES = (); }; }; 8D185DC60BF428CF00A06B03 /* AdvancedPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D185DC50BF428CF00A06B03 /* AdvancedPrefs.png */; }; 8D1A455B0BA00DE2004A6BC4 /* minus-8.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D1A45590BA00DE2004A6BC4 /* minus-8.png */; }; 8D1A455C0BA00DE2004A6BC4 /* plus-8.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D1A455A0BA00DE2004A6BC4 /* plus-8.png */; }; - 8D2072110B86AB0000D61A9E /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D20720E0B86AB0000D61A9E /* Sparkle.framework */; }; - 8D2073890B86AB8000D61A9E /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8D20720E0B86AB0000D61A9E /* Sparkle.framework */; }; 8D232F800BD9D228006A3963 /* GeneralPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D232F7F0BD9D228006A3963 /* GeneralPrefs.png */; }; 8D232FB50BD9D507006A3963 /* ActionsPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D232FB30BD9D507006A3963 /* ActionsPrefs.png */; }; 8D232FB60BD9D507006A3963 /* RulesPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D232FB40BD9D507006A3963 /* RulesPrefs.png */; }; - 8D27ECB00C4456A300AE1929 /* AudioOutputEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D27ECAE0C4456A300AE1929 /* AudioOutputEvidenceSource.m */; }; - 8D2BAAAD0C56E26200A50777 /* NetworkLinkEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D2BAAAB0C56E26100A50777 /* NetworkLinkEvidenceSource.m */; }; - 8D3453C40C18E5C1006011D0 /* IChatAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D3453C20C18E5C1006011D0 /* IChatAction.m */; }; - 8D38B66C0C49D50200290F47 /* SliderWithValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D38B66A0C49D50200290F47 /* SliderWithValue.m */; }; + 8D38B66C0C49D50200290F47 /* SliderWithValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D38B66A0C49D50200290F47 /* SliderWithValue.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 8D3A3D5F0C012565008EBF2A /* EvidenceSourcesPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D3A3D5E0C012564008EBF2A /* EvidenceSourcesPrefs.png */; }; - 8D3BFF3F0C61BE4500B9B910 /* AboutPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D3BFF3D0C61BE4500B9B910 /* AboutPanel.m */; }; - 8D3BFFB20C61CA5300B9B910 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D3BFFB10C61CA5300B9B910 /* WebKit.framework */; }; - 8D3C85150CDD8546009DBCD9 /* ScreenSaverStartAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D3C85130CDD8546009DBCD9 /* ScreenSaverStartAction.m */; }; - 8D447DF90C3E65D000DAB17A /* ContextSelectionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D447DF70C3E65CF00DAB17A /* ContextSelectionButton.m */; }; - 8D481B0A0B6098DD0097CF9C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D481B070B6098DD0097CF9C /* IOKit.framework */; }; + 8D3BFF3F0C61BE4500B9B910 /* AboutPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D3BFF3D0C61BE4500B9B910 /* AboutPanel.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 8D447DF90C3E65D000DAB17A /* ContextSelectionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D447DF70C3E65CF00DAB17A /* ContextSelectionButton.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 8D4DBDC30BE1E3C00024DEA0 /* gear.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D4DBDC20BE1E3C00024DEA0 /* gear.png */; }; 8D4E5CB30C48AE9F0054A67C /* ContextsPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D4E5CB20C48AE9F0054A67C /* ContextsPrefs.png */; }; - 8D57B1440C4457AB00EC620D /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D57B1430C4457AB00EC620D /* CoreAudio.framework */; }; - 8D643C680C4EF197006D8ECC /* GenericLoopingEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D643C660C4EF197006D8ECC /* GenericLoopingEvidenceSource.m */; }; - 8D643CDD0C4EF6FD006D8ECC /* LoopingEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D643CDB0C4EF6FD006D8ECC /* LoopingEvidenceSource.m */; }; - 8D643DDD0C4F1F0D006D8ECC /* VPNAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D643DDB0C4F1F0D006D8ECC /* VPNAction.m */; }; - 8D649BA50BE8033A00716059 /* ToggleWiFiAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D649BA30BE8033A00716059 /* ToggleWiFiAction.m */; }; - 8D6762170C3B8D8D000B63EC /* NetworkLocationAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D6762150C3B8D8D000B63EC /* NetworkLocationAction.m */; }; - 8D68EBDF0C460BF800F25744 /* IPEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8C9EBB0BBB8DAC0074D5B3 /* IPEvidenceSource.m */; }; - 8D71CAEF0C17BA7900E56526 /* ToggleableAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D71CAED0C17BA7900E56526 /* ToggleableAction.m */; }; - 8D71CB790C17C01700E56526 /* ScreenSaverPasswordAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D71CB770C17C01700E56526 /* ScreenSaverPasswordAction.m */; }; - 8D73CB8D0C46FD5200DF839E /* MonitorEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D5684B30C38711D00881E32 /* MonitorEvidenceSource.m */; }; - 8D73CBB30C46FEC800DF839E /* PowerEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DCBF4FD0BE5B11F00A01414 /* PowerEvidenceSource.m */; }; - 8D73CC140C470FE000DF839E /* RunningApplicationEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D341CD10C0459D0008A7B4F /* RunningApplicationEvidenceSource.m */; }; - 8D73CC700C47125300DF839E /* WiFiEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D35A30B0BBB9CFD006ACBB0 /* WiFiEvidenceSource.m */; }; - 8D75A6200BE6F68B0069DF3F /* ToggleBluetoothAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D75A61E0BE6F68B0069DF3F /* ToggleBluetoothAction.m */; }; + 8D71CAEF0C17BA7900E56526 /* ToggleableAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D71CAED0C17BA7900E56526 /* ToggleableAction.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 8D80BB980B8B033400104A87 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D80BB950B8B033400104A87 /* Growl.framework */; }; - 8D80BBA30B8B036C00104A87 /* Growl.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8D80BB950B8B033400104A87 /* Growl.framework */; }; - 8D8155D00C3A304E00228463 /* ContextsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8155CE0C3A304E00228463 /* ContextsDataSource.m */; }; - 8D82F06D0AA811CE009ADA44 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D82F05B0AA811CE009ADA44 /* SystemConfiguration.framework */; }; - 8D82F0A30AA81411009ADA44 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D82F0A20AA81411009ADA44 /* PrefsWindowController.m */; }; + 8D8155D00C3A304E00228463 /* ContextsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8155CE0C3A304E00228463 /* ContextsDataSource.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 8D82F0A30AA81411009ADA44 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D82F0A20AA81411009ADA44 /* PrefsWindowController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 8D88FE2A0C534737007A14D6 /* pause.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D88FE290C534737007A14D6 /* pause.png */; }; - 8D8C9BAB0BBB3ADB0074D5B3 /* Apple80211.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D8C9BA90BBB3ADB0074D5B3 /* Apple80211.framework */; }; - 8D8C9CA60BBB74E70074D5B3 /* EvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8C9CA40BBB74E70074D5B3 /* EvidenceSource.m */; }; - 8D8C9CE70BBB7BE00074D5B3 /* BluetoothEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8C9CE50BBB7BE00074D5B3 /* BluetoothEvidenceSource.m */; }; - 8D8C9E350BBB89320074D5B3 /* DB.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8C9E330BBB89320074D5B3 /* DB.m */; }; - 8D90E51F0B71C4C9007D39FD /* CPController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D90E51E0B71C4C9007D39FD /* CPController.m */; }; - 8D91F17D0C47148200D9FC0F /* USBEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D35A34D0BBBA0CB006ACBB0 /* USBEvidenceSource.m */; }; + 8D90E51F0B71C4C9007D39FD /* CPController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D90E51E0B71C4C9007D39FD /* CPController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 8D9AE3790BE0D11800D4D4E4 /* plus-arrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D9AE3780BE0D11800D4D4E4 /* plus-arrow.png */; }; - 8D9AE3A60BE0DA7E00D4D4E4 /* PopButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D9AE3A40BE0DA7E00D4D4E4 /* PopButton.m */; }; - 8DA2F4150CE8630200F92D4D /* DesktopBackgroundAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DA2F4130CE8630200F92D4D /* DesktopBackgroundAction.m */; }; - 8DB1EF240C6C60A300586F84 /* MailIMAPServerAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB1EF220C6C60A300586F84 /* MailIMAPServerAction.m */; }; - 8DB8917C0BB89BD8005347C2 /* oui.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8DB8917B0BB89BD8005347C2 /* oui.txt */; }; - 8DBAFAFC0BDC3B7B00BE0747 /* ShellScriptAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DBAFAFA0BDC3B7B00BE0747 /* ShellScriptAction.m */; }; - 8DBB44980C530F7600064010 /* DSLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DBB44960C530F7600064010 /* DSLogger.m */; }; + 8D9AE3A60BE0DA7E00D4D4E4 /* PopButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D9AE3A40BE0DA7E00D4D4E4 /* PopButton.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 8DC410FB0C64665E00393759 /* AboutPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8DC410FA0C64665E00393759 /* AboutPanel.xib */; }; - 8DC4E7FD0C178917007E7E41 /* MuteAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DC4E7F90C178917007E7E41 /* MuteAction.m */; }; - 8DC4E8000C17891D007E7E41 /* MailSMTPServerAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DD790C20BC28C4E00705346 /* MailSMTPServerAction.m */; }; - 8DCB43580C4DBABD00E71D28 /* FirewallRuleAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DCB43560C4DBABD00E71D28 /* FirewallRuleAction.m */; }; - 8DCBE96C0C1A7ECE008260EF /* MountAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DCBE96A0C1A7ECE008260EF /* MountAction.m */; }; - 8DD790AD0BC28A9F00705346 /* OpenAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DD790AB0BC28A9F00705346 /* OpenAction.m */; }; - 8DE13F0E0C460E1700AEC949 /* FireWireEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DCBF4900BE5622600A01414 /* FireWireEvidenceSource.m */; }; - 8DE428FC0C5084D00073499A /* TimeOfDayEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DE428FA0C5084D00073499A /* TimeOfDayEvidenceSource.m */; }; - 8DE4C0110C4EE60700511590 /* GenericEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DE4C00F0C4EE60700511590 /* GenericEvidenceSource.m */; }; - 8DE4EE470C4B2A6F00A5B559 /* ScreenSaverTimeAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DE4EE450C4B2A6F00A5B559 /* ScreenSaverTimeAction.m */; }; - 8DF5A4180BC2353D00CBEB4B /* Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF5A4160BC2353D00CBEB4B /* Action.m */; }; - 8DF5A4610BC239B100CBEB4B /* DefaultPrinterAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF5A45F0BC239B100CBEB4B /* DefaultPrinterAction.m */; }; - 8DFA46170CC33E46003EAC16 /* QuitApplicationAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DFA46150CC33E46003EAC16 /* QuitApplicationAction.m */; }; - 8DFD0DA60CEBBC8A00E79049 /* UnmountAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DFD0DA40CEBBC8A00E79049 /* UnmountAction.m */; }; + 8DF5A4180BC2353D00CBEB4B /* Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF5A4160BC2353D00CBEB4B /* Action.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; DA16392613D4B14A00E3F421 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = DA16392513D4B14A00E3F421 /* dsa_pub.pem */; }; - DA4411A514EE03C9005E7B3B /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4411A414EE03C9005E7B3B /* MapKit.framework */; }; - DA461C0C14C33E3C0019594A /* NSString+ShellScriptHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DA461C0B14C33E3B0019594A /* NSString+ShellScriptHelper.m */; }; - DA49AF6C14C3E0AB00D03D6A /* TogglePrinterSharingAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DA49AF6B14C3E0AB00D03D6A /* TogglePrinterSharingAction.m */; }; DA4A629313E2546800CE976F /* ControlPlane Help in Resources */ = {isa = PBXBuildFile; fileRef = DA4A629213E2546800CE976F /* ControlPlane Help */; }; DA4A629513E25C9D00CE976F /* Credits.html in Resources */ = {isa = PBXBuildFile; fileRef = DA4A629413E25C9D00CE976F /* Credits.html */; }; - DA5B01E61412B86400E19C50 /* CPHelperInstallTool in CopyFiles */ = {isa = PBXBuildFile; fileRef = DA5B01D71412B6A700E19C50 /* CPHelperInstallTool */; }; - DA5B01F31412BAEC00E19C50 /* BetterAuthorizationSampleLib.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B01F21412BAEC00E19C50 /* BetterAuthorizationSampleLib.c */; }; - DA5B01F61412BB0D00E19C50 /* BetterAuthorizationSampleLibInstallTool.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B01F41412BAF400E19C50 /* BetterAuthorizationSampleLibInstallTool.c */; }; + DA5B01E61412B86400E19C50 /* CPHelperInstallTool in Copy Helper Tool */ = {isa = PBXBuildFile; fileRef = DA5B01D71412B6A700E19C50 /* CPHelperInstallTool */; }; + DA5B01F31412BAEC00E19C50 /* BetterAuthorizationLib.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B01F21412BAEC00E19C50 /* BetterAuthorizationLib.c */; }; + DA5B01F61412BB0D00E19C50 /* BetterAuthorizationLibInstallTool.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B01F41412BAF400E19C50 /* BetterAuthorizationLibInstallTool.c */; }; DA5B020A1412BBF200E19C50 /* CPHelperTool.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B02091412BBF200E19C50 /* CPHelperTool.c */; }; DA5B020C1412BDEF00E19C50 /* CPHelperToolCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B020B1412BDEF00E19C50 /* CPHelperToolCommon.c */; }; - DA5B020D1412BDFC00E19C50 /* BetterAuthorizationSampleLib.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B01F21412BAEC00E19C50 /* BetterAuthorizationSampleLib.c */; }; - DA648AEE1412C15D00532B2C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD8274FA141177750098FA6E /* Security.framework */; }; - DA648AF11412C19800532B2C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA648AEF1412C17A00532B2C /* CoreFoundation.framework */; }; - DA72BF9413CD317B002D27DD /* CoreWLAN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA72BF9313CD317B002D27DD /* CoreWLAN.framework */; }; - DA8064A3147990FD00267B5A /* BWQuincyMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = DA8064A0147990FD00267B5A /* BWQuincyMain.nib */; }; - DA8064A4147990FD00267B5A /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8064A2147990FD00267B5A /* BWQuincyManager.m */; }; - DA8064BF1479911B00267B5A /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8064A2147990FD00267B5A /* BWQuincyManager.m */; }; - DA8064C01479912400267B5A /* BWQuincyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8064A1147990FD00267B5A /* BWQuincyManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DA8064C11479913500267B5A /* BWQuincyMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = DA8064A0147990FD00267B5A /* BWQuincyMain.nib */; }; - DA8064C41479927500267B5A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; - DA8064C51479927600267B5A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97325FDCFA39411CA2CEA /* Foundation.framework */; }; - DA812E83140681D2006869F7 /* AppleScript.m in Sources */ = {isa = PBXBuildFile; fileRef = DA812E82140681D2006869F7 /* AppleScript.m */; }; - DA83A21D13D0FE8F00074503 /* CoreWLANEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DA83A21C13D0FE8F00074503 /* CoreWLANEvidenceSource.m */; }; + DA5B020D1412BDFC00E19C50 /* BetterAuthorizationLib.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B01F21412BAEC00E19C50 /* BetterAuthorizationLib.c */; }; + DA812E83140681D2006869F7 /* AppleScript.m in Sources */ = {isa = PBXBuildFile; fileRef = DA812E82140681D2006869F7 /* AppleScript.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; DA83A21F13D12A3200074503 /* cp-icon-active.icns in Resources */ = {isa = PBXBuildFile; fileRef = DA83A21E13D12A3200074503 /* cp-icon-active.icns */; }; DA83A22113D13C8300074503 /* cp-icon-inactive.icns in Resources */ = {isa = PBXBuildFile; fileRef = DA83A22013D13C8300074503 /* cp-icon-inactive.icns */; }; DA83A22313D13DF300074503 /* cp-icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = DA83A22213D13DF300074503 /* cp-icon.icns */; }; - DA83A22713D1430000074503 /* usb-vendors.txt in Resources */ = {isa = PBXBuildFile; fileRef = DA83A22613D1430000074503 /* usb-vendors.txt */; }; - DA87D18014EE0E8300E46DFF /* MapKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DA4411A414EE03C9005E7B3B /* MapKit.framework */; }; - DA8B17351149AD0C00417D4F /* LightEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D91F1F80C4772FF00D9FC0F /* LightEvidenceSource.m */; }; - DA922E9D144FC95200920B40 /* ToggleInternetSharingAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DA922E9C144FC95200920B40 /* ToggleInternetSharingAction.m */; }; - DAAF16B11412D8A200F5D915 /* CPHelperTool in CopyFiles */ = {isa = PBXBuildFile; fileRef = DA5B01FB1412BB1700E19C50 /* CPHelperTool */; }; - DAAF16B61413174400F5D915 /* ToggleTimeMachineAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DAAF16B51413174400F5D915 /* ToggleTimeMachineAction.m */; }; + DAAF16B11412D8A200F5D915 /* CPHelperTool in Copy Helper Tool */ = {isa = PBXBuildFile; fileRef = DA5B01FB1412BB1700E19C50 /* CPHelperTool */; }; DAAF16B714131CDE00F5D915 /* CPHelperToolCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B020B1412BDEF00E19C50 /* CPHelperToolCommon.c */; }; - DAC45F2014CDEC170007F5EF /* TimeMachineDestinationAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC45F1F14CDEC170007F5EF /* TimeMachineDestinationAction.m */; }; - DAE893EE1454FFFB005FA13C /* ToggleFirewallAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE893E514546897005FA13C /* ToggleFirewallAction.m */; }; - DAF36ECA143E7C5700350991 /* CoreLocationSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAE004C141521EF00FDADE8 /* CoreLocationSource.m */; }; - DAFC0E4514788ACB00DA6139 /* DisplayServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAFC0E3D14788A5000DA6139 /* DisplayServices.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - DAFC0E4614788B0500DA6139 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DB8911C0BB88D0B005347C2 /* IOBluetooth.framework */; }; - DD06E811140C661700059764 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD06E810140C661600059764 /* AudioToolbox.framework */; }; + DD1CD01614F40F8B0036E659 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD1CD01314F40F580036E659 /* MapKit.framework */; }; + DD1CD01914F40FF10036E659 /* MapKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DD1CD01314F40F580036E659 /* MapKit.framework */; }; + DD23F8571460E2BD000665ED /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAC86C1143C107A00682538 /* Cocoa.framework */; }; + DD23F8581460E2EC000665ED /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD23F8491460E222000665ED /* CoreFoundation.framework */; }; + DD23F8591460E2EC000665ED /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD23F8471460E216000665ED /* Security.framework */; }; + DD23F88B1460E70E000665ED /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD23F8471460E216000665ED /* Security.framework */; }; + DD23F88D1460E899000665ED /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD23F88C1460E898000665ED /* IOKit.framework */; }; + DD2A78C114855A640010AFE0 /* ShellScriptRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD2A78BF14855A640010AFE0 /* ShellScriptRule.xib */; }; + DD334A3714A7B073000F960A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAC86C1143C107A00682538 /* Cocoa.framework */; }; + DD334A5214A7B0F5000F960A /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD334A4714A7B0C1000F960A /* Sparkle.framework */; }; + DD334A5314A7B1F7000F960A /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DD334A4714A7B0C1000F960A /* Sparkle.framework */; }; DD3BAB8314163C6B000D5F88 /* CoreLocationRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD3BAB8514163C6B000D5F88 /* CoreLocationRule.xib */; }; - DD44B57E141417E40016BF6B /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD44B57D141417E40016BF6B /* CoreServices.framework */; }; DD44B59F14142D2D0016BF6B /* CPHelperToolAuthorizationPrompts.strings in Resources */ = {isa = PBXBuildFile; fileRef = DD44B5A114142D2D0016BF6B /* CPHelperToolAuthorizationPrompts.strings */; }; - DD5BD20B141614C4007BA88C /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DD5BD20A141614C4007BA88C /* JSONKit.m */; }; - DD6FCC691413EF6B0095E64F /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD6FCC681413EF6B0095E64F /* CoreLocation.framework */; }; - DD7D2539149C338300BE7C8B /* NSTimer+Invalidation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7D2538149C338300BE7C8B /* NSTimer+Invalidation.m */; }; DD8274E6141147BB0098FA6E /* controlplane.icns in Resources */ = {isa = PBXBuildFile; fileRef = DD8274E5141147BB0098FA6E /* controlplane.icns */; }; - DD8274F0141154780098FA6E /* MailIntervalAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274EF141154780098FA6E /* MailIntervalAction.m */; }; - DD8274F314115EE50098FA6E /* StartTimeMachineAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274F214115EE40098FA6E /* StartTimeMachineAction.m */; }; - DD8274F614116CC90098FA6E /* OpenURLAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274F514116CC80098FA6E /* OpenURLAction.m */; }; - DD8274F91411748C0098FA6E /* LockKeychainAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274F81411748B0098FA6E /* LockKeychainAction.m */; }; - DD8274FB141177750098FA6E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD8274FA141177750098FA6E /* Security.framework */; }; - DD8274FE14117C590098FA6E /* SpeakAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274FD14117C580098FA6E /* SpeakAction.m */; }; - DD827507141188890098FA6E /* DisplayBrightnessAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD827506141188880098FA6E /* DisplayBrightnessAction.m */; }; DDA2013A1411C0FB00DE570E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDA2013C1411C0FB00DE570E /* Localizable.strings */; }; DDA201441411C25A00DE570E /* GenericRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA201461411C25A00DE570E /* GenericRule.xib */; }; DDA2014E1411C32F00DE570E /* IPRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA201501411C32F00DE570E /* IPRule.xib */; }; DDA201581411C35700DE570E /* LightRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA2015A1411C35700DE570E /* LightRule.xib */; }; DDA201621411C37300DE570E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA201641411C37300DE570E /* MainMenu.xib */; }; DDA2016C1411C38D00DE570E /* TimeOfDayRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA2016E1411C38D00DE570E /* TimeOfDayRule.xib */; }; - DDAA9A181402FAAD00D4757E /* SleepEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAA9A171402FAAD00D4757E /* SleepEvidenceSource.m */; }; - DDAC3C55140D866200FBF29E /* ScriptingBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAC3C54140D866200FBF29E /* ScriptingBridge.framework */; }; - DDAE0017141474DC00FDADE8 /* CPController+SleepThread.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAE0016141474DC00FDADE8 /* CPController+SleepThread.m */; }; - DDAEFFFB1414714F00FDADE8 /* Action+HelperTool.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAEFFFA1414714F00FDADE8 /* Action+HelperTool.m */; }; + DDAC64F11461018000B5B279 /* Growl.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8D80BB950B8B033400104A87 /* Growl.framework */; }; + DDAC86C2143C107A00682538 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAC86C1143C107A00682538 /* Cocoa.framework */; }; + DDAE0017141474DC00FDADE8 /* CPController+SleepThread.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAE0016141474DC00FDADE8 /* CPController+SleepThread.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DDAEFFFB1414714F00FDADE8 /* Action+HelperTool.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAEFFFA1414714F00FDADE8 /* Action+HelperTool.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DDB151BE146EEB4C00FA7835 /* Core.plugin in Copy Plugins */ = {isa = PBXBuildFile; fileRef = DDB15178146EE4C000FA7835 /* Core.plugin */; }; + DDB151CA146EEB9500FA7835 /* NSLogger.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DDB151C5146EEB7C00FA7835 /* NSLogger.framework */; }; + DDB151CB146EEB9500FA7835 /* Plugins.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DDB151C7146EEB7C00FA7835 /* Plugins.framework */; }; + DDB151CC146EEBAE00FA7835 /* NSLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDB151C5146EEB7C00FA7835 /* NSLogger.framework */; }; + DDB151E0146EEC1600FA7835 /* Plugins.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDB151C7146EEB7C00FA7835 /* Plugins.framework */; }; + DDB15211146F050C00FA7835 /* BWQuincyMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = DDB1520E146F050C00FA7835 /* BWQuincyMain.nib */; }; + DDB15212146F050D00FA7835 /* BWQuincyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DDB1520F146F050C00FA7835 /* BWQuincyManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDB15213146F050D00FA7835 /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DDB15210146F050C00FA7835 /* BWQuincyManager.m */; }; + DDB1521B146F090200FA7835 /* Quincy.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = DDB151F9146F02BF00FA7835 /* Quincy.framework */; }; + DDB1522F146F0F5100FA7835 /* Quincy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDB151F9146F02BF00FA7835 /* Quincy.framework */; }; DDC3C2A21412A82000655F34 /* Growl Registration Ticket.growlRegDict in Resources */ = {isa = PBXBuildFile; fileRef = DDC3C2A11412A82000655F34 /* Growl Registration Ticket.growlRegDict */; }; - DDDF1C2B1411D49300DB0018 /* DefaultBrowserAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDF1C2A1411D49300DB0018 /* DefaultBrowserAction.m */; }; - DDDF1C2F1411E08000DB0018 /* ITunesPlaylistAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDF1C2E1411E07F00DB0018 /* ITunesPlaylistAction.m */; }; + DDD1A364142BD65600341B75 /* KVOAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1A363142BD65600341B75 /* KVOAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DDD1A367142CC81200341B75 /* Context.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1A366142CC80F00341B75 /* Context.m */; }; + DDD1A370142CD55E00341B75 /* ContextGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1A36F142CD55E00341B75 /* ContextGroup.m */; }; + DDD1A375142CD81900341B75 /* ContextsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1A374142CD81900341B75 /* ContextsManager.m */; }; DDE1B068140438DB006564A6 /* ControlPlane.sdef in Resources */ = {isa = PBXBuildFile; fileRef = DDE1B067140438DB006564A6 /* ControlPlane.sdef */; }; DDF4E595141588E80028DF4A /* CoreLocationMap.html in Resources */ = {isa = PBXBuildFile; fileRef = DDF4E594141588E80028DF4A /* CoreLocationMap.html */; }; DDFF423114156B0A0047D311 /* location.png in Resources */ = {isa = PBXBuildFile; fileRef = DDFF423014156B0A0047D311 /* location.png */; }; @@ -169,12 +105,117 @@ remoteGlobalIDString = DA5B01FA1412BB1700E19C50; remoteInfo = CPHelperTool; }; - DA8064C21479915100267B5A /* PBXContainerItemProxy */ = { + DD1CD01014F40F580036E659 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD1CD00614F40F580036E659 /* MapKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5F6EF13511F13B0D0077E84F; + remoteInfo = DemoApp; + }; + DD1CD01214F40F580036E659 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD1CD00614F40F580036E659 /* MapKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5F6EF17D11F13F690077E84F; + remoteInfo = MapKitFramework; + }; + DD1CD01414F40F580036E659 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD1CD00614F40F580036E659 /* MapKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5FB7435711FE6E4A00AB2079; + remoteInfo = MapKit; + }; + DD1CD01714F40FCC0036E659 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD1CD00614F40F580036E659 /* MapKit.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 5F6EF17C11F13F690077E84F; + remoteInfo = MapKitFramework; + }; + DD334A4614A7B0C1000F960A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8DC2EF5B0486A6940098B216; + remoteInfo = Sparkle; + }; + DD334A4814A7B0C1000F960A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 61B5F90209C4CEE200B25A18; + remoteInfo = "Sparkle Test App"; + }; + DD334A4A14A7B0C1000F960A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 612279D90DB5470200AB99EA; + remoteInfo = "Sparkle Unit Tests"; + }; + DD334A4C14A7B0C1000F960A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5D06E8D00FD68C7C005AE3F6; + remoteInfo = BinaryDelta; + }; + DD334A4E14A7B0C1000F960A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 55C14BB7136EEF1500649790; + remoteInfo = finish_installation; + }; + DD334A5014A7B0E6000F960A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = Sparkle; + }; + DDB15177146EE4C000FA7835 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DDF52E9E1460BDA700A42B09 /* Core.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DDF52D8E1460B54D00A42B09; + remoteInfo = Core; + }; + DDB15179146EE4C000FA7835 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DDF52E9E1460BDA700A42B09 /* Core.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DDF52D6A1460B3C900A42B09; + remoteInfo = JSONKit; + }; + DDB151BC146EEB4200FA7835 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DDF52E9E1460BDA700A42B09 /* Core.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = DDF52D8D1460B54D00A42B09; + remoteInfo = Core; + }; + DDB151C4146EEB7C00FA7835 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DDB151BF146EEB7C00FA7835 /* Framework.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DDB15085146ECDF000FA7835; + remoteInfo = NSLogger; + }; + DDB151C6146EEB7C00FA7835 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DDB151BF146EEB7C00FA7835 /* Framework.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DDB150E0146ED2EA00FA7835; + remoteInfo = Plugins; + }; + DDB15218146F08D000FA7835 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = DA8064AA1479910E00267B5A; - remoteInfo = Quincy; + remoteGlobalIDString = DDB151F8146F02BF00FA7835; + remoteInfo = QuincyKit; }; /* End PBXContainerItemProxy section */ @@ -185,10 +226,12 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 732A58F21484336C0011019C /* Quincy.framework in Copy Frameworks */, - 8D80BBA30B8B036C00104A87 /* Growl.framework in Copy Frameworks */, - 8D2073890B86AB8000D61A9E /* Sparkle.framework in Copy Frameworks */, - DA87D18014EE0E8300E46DFF /* MapKit.framework in Copy Frameworks */, + DD1CD01914F40FF10036E659 /* MapKit.framework in Copy Frameworks */, + DD334A5314A7B1F7000F960A /* Sparkle.framework in Copy Frameworks */, + DDB1521B146F090200FA7835 /* Quincy.framework in Copy Frameworks */, + DDB151CA146EEB9500FA7835 /* NSLogger.framework in Copy Frameworks */, + DDB151CB146EEB9500FA7835 /* Plugins.framework in Copy Frameworks */, + DDAC64F11461018000B5B279 /* Growl.framework in Copy Frameworks */, ); name = "Copy Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -202,15 +245,16 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - DA5B01E51412B85600E19C50 /* CopyFiles */ = { + DA5B01E51412B85600E19C50 /* Copy Helper Tool */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 6; files = ( - DAAF16B11412D8A200F5D915 /* CPHelperTool in CopyFiles */, - DA5B01E61412B86400E19C50 /* CPHelperInstallTool in CopyFiles */, + DAAF16B11412D8A200F5D915 /* CPHelperTool in Copy Helper Tool */, + DA5B01E61412B86400E19C50 /* CPHelperInstallTool in Copy Helper Tool */, ); + name = "Copy Helper Tool"; runOnlyForDeploymentPostprocessing = 0; }; DA5B01F91412BB1700E19C50 /* CopyFiles */ = { @@ -222,78 +266,44 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + DDAC8668143C03CE00682538 /* Copy Plugins */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + DDB151BE146EEB4C00FA7835 /* Core.plugin in Copy Plugins */, + ); + name = "Copy Plugins"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Source/main.m; sourceTree = ""; }; - 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* ControlPlane_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ControlPlane_Prefix.pch; path = Source/ControlPlane_Prefix.pch; sourceTree = ""; }; - 732A58DD1484300A0011019C /* ShellScriptEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ShellScriptEvidenceSource.h; path = Source/ShellScriptEvidenceSource.h; sourceTree = ""; }; - 732A58DE1484300A0011019C /* ShellScriptEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ShellScriptEvidenceSource.m; path = Source/ShellScriptEvidenceSource.m; sourceTree = ""; }; - 732A58E91484311C0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/CoreLocationRule.xib"; sourceTree = ""; }; - 732A58EA1484311C0011019C /* pt-PT */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/CPHelperToolAuthorizationPrompts.strings"; sourceTree = ""; }; - 732A58EB1484311D0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/GenericRule.xib"; sourceTree = ""; }; - 732A58EC1484311D0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/IPRule.xib"; sourceTree = ""; }; - 732A58ED1484311D0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/LightRule.xib"; sourceTree = ""; }; - 732A58EE1484311D0011019C /* pt-PT */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; - 732A58EF1484311D0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/MainMenu.xib"; sourceTree = ""; }; - 732A58F01484311D0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/TimeOfDayRule.xib"; sourceTree = ""; }; - 739492E0146B8018003C94DE /* DisplaySleepTimeAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DisplaySleepTimeAction.h; path = Source/DisplaySleepTimeAction.h; sourceTree = ""; }; - 739492E1146B8018003C94DE /* DisplaySleepTimeAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DisplaySleepTimeAction.m; path = Source/DisplaySleepTimeAction.m; sourceTree = ""; }; - 73A5092814849405007D22B5 /* da-DK */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "da-DK"; path = "Resources/da-DK.lproj/ShellScriptRule.xib"; sourceTree = ""; }; - 73A5092914849405007D22B5 /* de */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = de; path = Resources/de.lproj/ShellScriptRule.xib; sourceTree = ""; }; - 73A5092A14849405007D22B5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = Resources/en.lproj/ShellScriptRule.xib; sourceTree = ""; }; - 73A5092B14849405007D22B5 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = Resources/fr.lproj/ShellScriptRule.xib; sourceTree = ""; }; - 73A5092C14849405007D22B5 /* it */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = it; path = Resources/it.lproj/ShellScriptRule.xib; sourceTree = ""; }; - 73A5092D14849405007D22B5 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-BR"; path = "Resources/pt-BR.lproj/ShellScriptRule.xib"; sourceTree = ""; }; - 73A5092E14849405007D22B5 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "Resources/pt-PT.lproj/ShellScriptRule.xib"; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* Main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Main.m; path = Source/Main.m; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Prefix.pch; path = Source/Prefix.pch; sourceTree = ""; }; 8D01634C0C029913004AD8DB /* DNDArrayController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DNDArrayController.h; path = Source/DNDArrayController.h; sourceTree = ""; }; 8D01634D0C029913004AD8DB /* DNDArrayController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = DNDArrayController.m; path = Source/DNDArrayController.m; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; - 8D1493F40C824B6D00D29FE8 /* BonjourEvidenceSource.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 30; name = BonjourEvidenceSource.h; path = Source/BonjourEvidenceSource.h; sourceTree = ""; }; - 8D1493F50C824B6D00D29FE8 /* BonjourEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = BonjourEvidenceSource.m; path = Source/BonjourEvidenceSource.m; sourceTree = ""; }; - 8D185DC50BF428CF00A06B03 /* AdvancedPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = AdvancedPrefs.png; path = Resources/AdvancedPrefs.png; sourceTree = ""; }; - 8D1A45590BA00DE2004A6BC4 /* minus-8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "minus-8.png"; path = "Resources/minus-8.png"; sourceTree = ""; }; - 8D1A455A0BA00DE2004A6BC4 /* plus-8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "plus-8.png"; path = "Resources/plus-8.png"; sourceTree = ""; }; - 8D20720E0B86AB0000D61A9E /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Frameworks/Sparkle.framework; sourceTree = ""; }; - 8D232F7F0BD9D228006A3963 /* GeneralPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = GeneralPrefs.png; path = Resources/GeneralPrefs.png; sourceTree = ""; }; - 8D232FB30BD9D507006A3963 /* ActionsPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ActionsPrefs.png; path = Resources/ActionsPrefs.png; sourceTree = ""; }; - 8D232FB40BD9D507006A3963 /* RulesPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = RulesPrefs.png; path = Resources/RulesPrefs.png; sourceTree = ""; }; - 8D27ECAD0C4456A300AE1929 /* AudioOutputEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AudioOutputEvidenceSource.h; path = Source/AudioOutputEvidenceSource.h; sourceTree = ""; }; - 8D27ECAE0C4456A300AE1929 /* AudioOutputEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = AudioOutputEvidenceSource.m; path = Source/AudioOutputEvidenceSource.m; sourceTree = ""; }; - 8D2BAAAA0C56E26100A50777 /* NetworkLinkEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = NetworkLinkEvidenceSource.h; path = Source/NetworkLinkEvidenceSource.h; sourceTree = ""; }; - 8D2BAAAB0C56E26100A50777 /* NetworkLinkEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = NetworkLinkEvidenceSource.m; path = Source/NetworkLinkEvidenceSource.m; sourceTree = ""; }; - 8D341CD00C0459D0008A7B4F /* RunningApplicationEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = RunningApplicationEvidenceSource.h; path = Source/RunningApplicationEvidenceSource.h; sourceTree = ""; }; - 8D341CD10C0459D0008A7B4F /* RunningApplicationEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = RunningApplicationEvidenceSource.m; path = Source/RunningApplicationEvidenceSource.m; sourceTree = ""; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8D185DC50BF428CF00A06B03 /* AdvancedPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AdvancedPrefs.png; sourceTree = ""; }; + 8D1A45590BA00DE2004A6BC4 /* minus-8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "minus-8.png"; sourceTree = ""; }; + 8D1A455A0BA00DE2004A6BC4 /* plus-8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "plus-8.png"; sourceTree = ""; }; + 8D232F7F0BD9D228006A3963 /* GeneralPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = GeneralPrefs.png; sourceTree = ""; }; + 8D232FB30BD9D507006A3963 /* ActionsPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ActionsPrefs.png; sourceTree = ""; }; + 8D232FB40BD9D507006A3963 /* RulesPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = RulesPrefs.png; sourceTree = ""; }; 8D3453C10C18E5C1006011D0 /* IChatAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = IChatAction.h; path = Source/IChatAction.h; sourceTree = ""; }; 8D3453C20C18E5C1006011D0 /* IChatAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = IChatAction.m; path = Source/IChatAction.m; sourceTree = ""; }; - 8D35A30A0BBB9CFD006ACBB0 /* WiFiEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = WiFiEvidenceSource.h; path = Source/WiFiEvidenceSource.h; sourceTree = ""; }; - 8D35A30B0BBB9CFD006ACBB0 /* WiFiEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = WiFiEvidenceSource.m; path = Source/WiFiEvidenceSource.m; sourceTree = ""; }; - 8D35A34C0BBBA0CB006ACBB0 /* USBEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = USBEvidenceSource.h; path = Source/USBEvidenceSource.h; sourceTree = ""; }; - 8D35A34D0BBBA0CB006ACBB0 /* USBEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = USBEvidenceSource.m; path = Source/USBEvidenceSource.m; sourceTree = ""; }; 8D38B6690C49D50200290F47 /* SliderWithValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SliderWithValue.h; path = Source/SliderWithValue.h; sourceTree = ""; }; 8D38B66A0C49D50200290F47 /* SliderWithValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SliderWithValue.m; path = Source/SliderWithValue.m; sourceTree = ""; }; - 8D3A3D5E0C012564008EBF2A /* EvidenceSourcesPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = EvidenceSourcesPrefs.png; path = Resources/EvidenceSourcesPrefs.png; sourceTree = ""; }; + 8D3A3D5E0C012564008EBF2A /* EvidenceSourcesPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = EvidenceSourcesPrefs.png; sourceTree = ""; }; 8D3BFF3C0C61BE4500B9B910 /* AboutPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AboutPanel.h; path = Source/AboutPanel.h; sourceTree = ""; }; 8D3BFF3D0C61BE4500B9B910 /* AboutPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AboutPanel.m; path = Source/AboutPanel.m; sourceTree = ""; }; - 8D3BFFB10C61CA5300B9B910 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = ""; }; 8D3C85120CDD8546009DBCD9 /* ScreenSaverStartAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ScreenSaverStartAction.h; path = Source/ScreenSaverStartAction.h; sourceTree = ""; }; 8D3C85130CDD8546009DBCD9 /* ScreenSaverStartAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ScreenSaverStartAction.m; path = Source/ScreenSaverStartAction.m; sourceTree = ""; }; 8D447DF60C3E65CF00DAB17A /* ContextSelectionButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContextSelectionButton.h; path = Source/ContextSelectionButton.h; sourceTree = ""; }; 8D447DF70C3E65CF00DAB17A /* ContextSelectionButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContextSelectionButton.m; path = Source/ContextSelectionButton.m; sourceTree = ""; }; - 8D481B070B6098DD0097CF9C /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; - 8D4DBDC20BE1E3C00024DEA0 /* gear.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = gear.png; path = Resources/gear.png; sourceTree = ""; }; - 8D4E5CB20C48AE9F0054A67C /* ContextsPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ContextsPrefs.png; path = Resources/ContextsPrefs.png; sourceTree = ""; }; - 8D5684B20C38711D00881E32 /* MonitorEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MonitorEvidenceSource.h; path = Source/MonitorEvidenceSource.h; sourceTree = ""; }; - 8D5684B30C38711D00881E32 /* MonitorEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MonitorEvidenceSource.m; path = Source/MonitorEvidenceSource.m; sourceTree = ""; }; - 8D57B1430C4457AB00EC620D /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; - 8D643C650C4EF197006D8ECC /* GenericLoopingEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GenericLoopingEvidenceSource.h; path = Source/GenericLoopingEvidenceSource.h; sourceTree = ""; }; - 8D643C660C4EF197006D8ECC /* GenericLoopingEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GenericLoopingEvidenceSource.m; path = Source/GenericLoopingEvidenceSource.m; sourceTree = ""; }; - 8D643CDA0C4EF6FD006D8ECC /* LoopingEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = LoopingEvidenceSource.h; path = Source/LoopingEvidenceSource.h; sourceTree = ""; }; - 8D643CDB0C4EF6FD006D8ECC /* LoopingEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = LoopingEvidenceSource.m; path = Source/LoopingEvidenceSource.m; sourceTree = ""; }; + 8D4DBDC20BE1E3C00024DEA0 /* gear.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gear.png; sourceTree = ""; }; + 8D4E5CB20C48AE9F0054A67C /* ContextsPrefs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ContextsPrefs.png; sourceTree = ""; }; 8D643DDA0C4F1F0D006D8ECC /* VPNAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = VPNAction.h; path = Source/VPNAction.h; sourceTree = ""; }; 8D643DDB0C4F1F0D006D8ECC /* VPNAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = VPNAction.m; path = Source/VPNAction.m; sourceTree = ""; }; 8D649BA20BE8033A00716059 /* ToggleWiFiAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ToggleWiFiAction.h; path = Source/ToggleWiFiAction.h; sourceTree = ""; }; @@ -309,56 +319,31 @@ 8D80BB950B8B033400104A87 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = Frameworks/Growl.framework; sourceTree = ""; }; 8D8155CD0C3A304E00228463 /* ContextsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContextsDataSource.h; path = Source/ContextsDataSource.h; sourceTree = ""; }; 8D8155CE0C3A304E00228463 /* ContextsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContextsDataSource.m; path = Source/ContextsDataSource.m; sourceTree = ""; }; - 8D82F05B0AA811CE009ADA44 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = ""; }; 8D82F0A10AA81411009ADA44 /* PrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PrefsWindowController.h; path = Source/PrefsWindowController.h; sourceTree = ""; }; 8D82F0A20AA81411009ADA44 /* PrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PrefsWindowController.m; path = Source/PrefsWindowController.m; sourceTree = ""; }; - 8D88FE290C534737007A14D6 /* pause.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pause.png; path = Resources/pause.png; sourceTree = ""; }; - 8D8C9BA70BBB3AAC0074D5B3 /* Apple80211.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Apple80211.h; path = Source/Apple80211.h; sourceTree = ""; }; - 8D8C9BA90BBB3ADB0074D5B3 /* Apple80211.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Apple80211.framework; path = /System/Library/PrivateFrameworks/Apple80211.framework; sourceTree = ""; }; - 8D8C9CA30BBB74E70074D5B3 /* EvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EvidenceSource.h; path = Source/EvidenceSource.h; sourceTree = ""; }; - 8D8C9CA40BBB74E70074D5B3 /* EvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EvidenceSource.m; path = Source/EvidenceSource.m; sourceTree = ""; }; - 8D8C9CE40BBB7BE00074D5B3 /* BluetoothEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothEvidenceSource.h; path = Source/BluetoothEvidenceSource.h; sourceTree = ""; }; - 8D8C9CE50BBB7BE00074D5B3 /* BluetoothEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BluetoothEvidenceSource.m; path = Source/BluetoothEvidenceSource.m; sourceTree = ""; }; - 8D8C9E320BBB89320074D5B3 /* DB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DB.h; path = Source/DB.h; sourceTree = ""; }; - 8D8C9E330BBB89320074D5B3 /* DB.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DB.m; path = Source/DB.m; sourceTree = ""; }; - 8D8C9EBA0BBB8DAC0074D5B3 /* IPEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = IPEvidenceSource.h; path = Source/IPEvidenceSource.h; sourceTree = ""; }; - 8D8C9EBB0BBB8DAC0074D5B3 /* IPEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = IPEvidenceSource.m; path = Source/IPEvidenceSource.m; sourceTree = ""; }; + 8D88FE290C534737007A14D6 /* pause.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pause.png; sourceTree = ""; }; 8D90E51D0B71C4C9007D39FD /* CPController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPController.h; path = Source/CPController.h; sourceTree = ""; }; 8D90E51E0B71C4C9007D39FD /* CPController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CPController.m; path = Source/CPController.m; sourceTree = ""; }; - 8D91F1F70C4772FF00D9FC0F /* LightEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = LightEvidenceSource.h; path = Source/LightEvidenceSource.h; sourceTree = ""; }; - 8D91F1F80C4772FF00D9FC0F /* LightEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = LightEvidenceSource.m; path = Source/LightEvidenceSource.m; sourceTree = ""; }; - 8D9AE3780BE0D11800D4D4E4 /* plus-arrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "plus-arrow.png"; path = "Resources/plus-arrow.png"; sourceTree = ""; }; + 8D9AE3780BE0D11800D4D4E4 /* plus-arrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "plus-arrow.png"; sourceTree = ""; }; 8D9AE3A30BE0DA7E00D4D4E4 /* PopButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PopButton.h; path = Source/PopButton.h; sourceTree = ""; }; 8D9AE3A40BE0DA7E00D4D4E4 /* PopButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PopButton.m; path = Source/PopButton.m; sourceTree = ""; }; 8DA2F4120CE8630200F92D4D /* DesktopBackgroundAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DesktopBackgroundAction.h; path = Source/DesktopBackgroundAction.h; sourceTree = ""; }; 8DA2F4130CE8630200F92D4D /* DesktopBackgroundAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = DesktopBackgroundAction.m; path = Source/DesktopBackgroundAction.m; sourceTree = ""; }; 8DB1EF210C6C60A300586F84 /* MailIMAPServerAction.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 30; name = MailIMAPServerAction.h; path = Source/MailIMAPServerAction.h; sourceTree = ""; }; 8DB1EF220C6C60A300586F84 /* MailIMAPServerAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MailIMAPServerAction.m; path = Source/MailIMAPServerAction.m; sourceTree = ""; }; - 8DB8911C0BB88D0B005347C2 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = /System/Library/Frameworks/IOBluetooth.framework; sourceTree = ""; }; - 8DB8917B0BB89BD8005347C2 /* oui.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = oui.txt; path = Resources/oui.txt; sourceTree = ""; }; 8DBAFAF90BDC3B7B00BE0747 /* ShellScriptAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ShellScriptAction.h; path = Source/ShellScriptAction.h; sourceTree = ""; }; 8DBAFAFA0BDC3B7B00BE0747 /* ShellScriptAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ShellScriptAction.m; path = Source/ShellScriptAction.m; sourceTree = ""; }; - 8DBB44950C530F7600064010 /* DSLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DSLogger.h; path = Source/DSLogger.h; sourceTree = ""; }; - 8DBB44960C530F7600064010 /* DSLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DSLogger.m; path = Source/DSLogger.m; sourceTree = ""; }; - 8DC410FA0C64665E00393759 /* AboutPanel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = AboutPanel.xib; path = Resources/AboutPanel.xib; sourceTree = ""; }; + 8DC410FA0C64665E00393759 /* AboutPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AboutPanel.xib; path = Resources/AboutPanel.xib; sourceTree = ""; }; 8DC4E7F80C178917007E7E41 /* MuteAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MuteAction.h; path = Source/MuteAction.h; sourceTree = ""; }; 8DC4E7F90C178917007E7E41 /* MuteAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MuteAction.m; path = Source/MuteAction.m; sourceTree = ""; }; 8DCB43550C4DBABD00E71D28 /* FirewallRuleAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FirewallRuleAction.h; path = Source/FirewallRuleAction.h; sourceTree = ""; }; 8DCB43560C4DBABD00E71D28 /* FirewallRuleAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = FirewallRuleAction.m; path = Source/FirewallRuleAction.m; sourceTree = ""; }; 8DCBE9690C1A7ECE008260EF /* MountAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MountAction.h; path = Source/MountAction.h; sourceTree = ""; }; 8DCBE96A0C1A7ECE008260EF /* MountAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MountAction.m; path = Source/MountAction.m; sourceTree = ""; }; - 8DCBF48F0BE5622600A01414 /* FireWireEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FireWireEvidenceSource.h; path = Source/FireWireEvidenceSource.h; sourceTree = ""; }; - 8DCBF4900BE5622600A01414 /* FireWireEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = FireWireEvidenceSource.m; path = Source/FireWireEvidenceSource.m; sourceTree = ""; }; - 8DCBF4FC0BE5B11F00A01414 /* PowerEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PowerEvidenceSource.h; path = Source/PowerEvidenceSource.h; sourceTree = ""; }; - 8DCBF4FD0BE5B11F00A01414 /* PowerEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PowerEvidenceSource.m; path = Source/PowerEvidenceSource.m; sourceTree = ""; }; 8DD790AA0BC28A9F00705346 /* OpenAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = OpenAction.h; path = Source/OpenAction.h; sourceTree = ""; }; 8DD790AB0BC28A9F00705346 /* OpenAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = OpenAction.m; path = Source/OpenAction.m; sourceTree = ""; }; 8DD790C10BC28C4E00705346 /* MailSMTPServerAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MailSMTPServerAction.h; path = Source/MailSMTPServerAction.h; sourceTree = ""; }; 8DD790C20BC28C4E00705346 /* MailSMTPServerAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MailSMTPServerAction.m; path = Source/MailSMTPServerAction.m; sourceTree = ""; }; - 8DE428F90C5084D00073499A /* TimeOfDayEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimeOfDayEvidenceSource.h; path = Source/TimeOfDayEvidenceSource.h; sourceTree = ""; }; - 8DE428FA0C5084D00073499A /* TimeOfDayEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TimeOfDayEvidenceSource.m; path = Source/TimeOfDayEvidenceSource.m; sourceTree = ""; }; - 8DE4C00E0C4EE60700511590 /* GenericEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = GenericEvidenceSource.h; path = Source/GenericEvidenceSource.h; sourceTree = ""; }; - 8DE4C00F0C4EE60700511590 /* GenericEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = GenericEvidenceSource.m; path = Source/GenericEvidenceSource.m; sourceTree = ""; }; 8DE4EE440C4B2A6F00A5B559 /* ScreenSaverTimeAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ScreenSaverTimeAction.h; path = Source/ScreenSaverTimeAction.h; sourceTree = ""; }; 8DE4EE450C4B2A6F00A5B559 /* ScreenSaverTimeAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ScreenSaverTimeAction.m; path = Source/ScreenSaverTimeAction.m; sourceTree = ""; }; 8DF5A4150BC2353D00CBEB4B /* Action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Action.h; path = Source/Action.h; sourceTree = ""; }; @@ -370,68 +355,55 @@ 8DFD0DA30CEBBC8A00E79049 /* UnmountAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = UnmountAction.h; path = Source/UnmountAction.h; sourceTree = ""; }; 8DFD0DA40CEBBC8A00E79049 /* UnmountAction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = UnmountAction.m; path = Source/UnmountAction.m; sourceTree = ""; }; DA1204DA13D0E5C800CDA091 /* ControlPlane.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ControlPlane.app; sourceTree = BUILT_PRODUCTS_DIR; }; - DA146F7B143F3C4000906DBF /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-BR"; path = "pt-BR.lproj/CoreLocationRule.xib"; sourceTree = ""; }; - DA146F7C143F3C4000906DBF /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CoreLocationRule.xib; sourceTree = ""; }; - DA146F7D143F3C4000906DBF /* it */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = it; path = it.lproj/CoreLocationRule.xib; sourceTree = ""; }; - DA146F7E143F3C4000906DBF /* da-DK */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "da-DK"; path = "da-DK.lproj/CoreLocationRule.xib"; sourceTree = ""; }; - DA146F7F143F3C4000906DBF /* de */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = de; path = de.lproj/CoreLocationRule.xib; sourceTree = ""; }; - DA16392513D4B14A00E3F421 /* dsa_pub.pem */ = {isa = PBXFileReference; lastKnownFileType = text; name = dsa_pub.pem; path = Resources/dsa_pub.pem; sourceTree = ""; }; - DA4411A414EE03C9005E7B3B /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = Frameworks/MapKit.framework; sourceTree = ""; }; - DA461C0A14C33E3B0019594A /* NSString+ShellScriptHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+ShellScriptHelper.h"; path = "Source/NSString+ShellScriptHelper.h"; sourceTree = ""; }; - DA461C0B14C33E3B0019594A /* NSString+ShellScriptHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+ShellScriptHelper.m"; path = "Source/NSString+ShellScriptHelper.m"; sourceTree = ""; }; - DA48F2E3140AD2FC00B000D3 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; - DA49AF6A14C3E0AB00D03D6A /* TogglePrinterSharingAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TogglePrinterSharingAction.h; path = Source/TogglePrinterSharingAction.h; sourceTree = ""; }; - DA49AF6B14C3E0AB00D03D6A /* TogglePrinterSharingAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TogglePrinterSharingAction.m; path = Source/TogglePrinterSharingAction.m; sourceTree = ""; }; - DA4A629213E2546800CE976F /* ControlPlane Help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "ControlPlane Help"; path = "Resources/ControlPlane Help"; sourceTree = ""; }; - DA4A629413E25C9D00CE976F /* Credits.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Credits.html; path = Resources/Credits.html; sourceTree = ""; }; + DA16392513D4B14A00E3F421 /* dsa_pub.pem */ = {isa = PBXFileReference; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = ""; }; + DA4A629213E2546800CE976F /* ControlPlane Help */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "ControlPlane Help"; sourceTree = ""; }; + DA4A629413E25C9D00CE976F /* Credits.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = Credits.html; sourceTree = ""; }; DA5B01D71412B6A700E19C50 /* CPHelperInstallTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CPHelperInstallTool; sourceTree = BUILT_PRODUCTS_DIR; }; - DA5B01EB1412BA6700E19C50 /* BetterAuthorizationSampleLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BetterAuthorizationSampleLib.h; sourceTree = ""; }; - DA5B01F21412BAEC00E19C50 /* BetterAuthorizationSampleLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BetterAuthorizationSampleLib.c; sourceTree = ""; }; - DA5B01F41412BAF400E19C50 /* BetterAuthorizationSampleLibInstallTool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BetterAuthorizationSampleLibInstallTool.c; sourceTree = ""; }; + DA5B01EB1412BA6700E19C50 /* BetterAuthorizationLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BetterAuthorizationLib.h; sourceTree = ""; }; + DA5B01F21412BAEC00E19C50 /* BetterAuthorizationLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BetterAuthorizationLib.c; sourceTree = ""; }; + DA5B01F41412BAF400E19C50 /* BetterAuthorizationLibInstallTool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BetterAuthorizationLibInstallTool.c; sourceTree = ""; }; DA5B01FB1412BB1700E19C50 /* CPHelperTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CPHelperTool; sourceTree = BUILT_PRODUCTS_DIR; }; DA5B02091412BBF200E19C50 /* CPHelperTool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CPHelperTool.c; sourceTree = ""; }; DA5B020B1412BDEF00E19C50 /* CPHelperToolCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CPHelperToolCommon.c; sourceTree = ""; }; DA5B020E1412BE4F00E19C50 /* CPHelperToolCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPHelperToolCommon.h; sourceTree = ""; }; - DA648AEF1412C17A00532B2C /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; - DA6D184A1154581000347E93 /* LmuTracker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = LmuTracker.c; path = Source/LmuTracker/LmuTracker.c; sourceTree = ""; }; - DA6D184C1154581700347E93 /* LmuTrackerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LmuTrackerCommon.h; path = Source/LmuTracker/LmuTrackerCommon.h; sourceTree = ""; }; - DA72BF9313CD317B002D27DD /* CoreWLAN.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreWLAN.framework; path = SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreWLAN.framework; sourceTree = DEVELOPER_DIR; }; - DA8064A0147990FD00267B5A /* BWQuincyMain.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = BWQuincyMain.nib; sourceTree = ""; }; - DA8064A1147990FD00267B5A /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWQuincyManager.h; sourceTree = ""; }; - DA8064A2147990FD00267B5A /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWQuincyManager.m; sourceTree = ""; }; - DA8064AB1479910E00267B5A /* Quincy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quincy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DA812E81140681D2006869F7 /* AppleScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppleScript.h; path = Source/AppleScript.h; sourceTree = ""; }; DA812E82140681D2006869F7 /* AppleScript.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppleScript.m; path = Source/AppleScript.m; sourceTree = ""; }; - DA83A21B13D0FE8F00074503 /* CoreWLANEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreWLANEvidenceSource.h; path = Source/CoreWLANEvidenceSource.h; sourceTree = ""; }; - DA83A21C13D0FE8F00074503 /* CoreWLANEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CoreWLANEvidenceSource.m; path = Source/CoreWLANEvidenceSource.m; sourceTree = ""; }; - DA83A21E13D12A3200074503 /* cp-icon-active.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = "cp-icon-active.icns"; path = "Resources/cp-icon-active.icns"; sourceTree = ""; }; - DA83A22013D13C8300074503 /* cp-icon-inactive.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = "cp-icon-inactive.icns"; path = "Resources/cp-icon-inactive.icns"; sourceTree = ""; }; - DA83A22213D13DF300074503 /* cp-icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = "cp-icon.icns"; path = "Resources/cp-icon.icns"; sourceTree = ""; }; - DA83A22613D1430000074503 /* usb-vendors.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "usb-vendors.txt"; path = "Resources/usb-vendors.txt"; sourceTree = ""; }; - DA922E9B144FC95200920B40 /* ToggleInternetSharingAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToggleInternetSharingAction.h; path = Source/ToggleInternetSharingAction.h; sourceTree = ""; }; - DA922E9C144FC95200920B40 /* ToggleInternetSharingAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ToggleInternetSharingAction.m; path = Source/ToggleInternetSharingAction.m; sourceTree = ""; }; + DA83A21E13D12A3200074503 /* cp-icon-active.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "cp-icon-active.icns"; sourceTree = ""; }; + DA83A22013D13C8300074503 /* cp-icon-inactive.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "cp-icon-inactive.icns"; sourceTree = ""; }; + DA83A22213D13DF300074503 /* cp-icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "cp-icon.icns"; sourceTree = ""; }; DAAF16B41413174400F5D915 /* ToggleTimeMachineAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToggleTimeMachineAction.h; path = Source/ToggleTimeMachineAction.h; sourceTree = ""; }; DAAF16B51413174400F5D915 /* ToggleTimeMachineAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ToggleTimeMachineAction.m; path = Source/ToggleTimeMachineAction.m; sourceTree = ""; }; - DAC45F1E14CDEC170007F5EF /* TimeMachineDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimeMachineDestinationAction.h; path = Source/TimeMachineDestinationAction.h; sourceTree = ""; }; - DAC45F1F14CDEC170007F5EF /* TimeMachineDestinationAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TimeMachineDestinationAction.m; path = Source/TimeMachineDestinationAction.m; sourceTree = ""; }; - DAE893E414546897005FA13C /* ToggleFirewallAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToggleFirewallAction.h; path = Source/ToggleFirewallAction.h; sourceTree = ""; }; - DAE893E514546897005FA13C /* ToggleFirewallAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ToggleFirewallAction.m; path = Source/ToggleFirewallAction.m; sourceTree = ""; }; - DAFC0E3D14788A5000DA6139 /* DisplayServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DisplayServices.framework; path = /System/Library/PrivateFrameworks/DisplayServices.framework; sourceTree = ""; }; - DD06E810140C661600059764 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + DD1CD00614F40F580036E659 /* MapKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapKit.xcodeproj; path = "External Source/MacMapKit/Source/MapKit.xcodeproj"; sourceTree = ""; }; + DD23F8471460E216000665ED /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + DD23F8491460E222000665ED /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + DD23F88C1460E898000665ED /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + DD2A78C014855A640010AFE0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = Resources/en.lproj/ShellScriptRule.xib; sourceTree = ""; }; + DD2A78C714855AF80010AFE0 /* de */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = de; path = Resources/de.lproj/ShellScriptRule.xib; sourceTree = ""; }; + DD2A78C914855B050010AFE0 /* da-DK */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "da-DK"; path = "Resources/da-DK.lproj/ShellScriptRule.xib"; sourceTree = ""; }; + DD2A78CB14855B120010AFE0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = Resources/fr.lproj/ShellScriptRule.xib; sourceTree = ""; }; + DD2A78CD14855B1C0010AFE0 /* it */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = it; path = Resources/it.lproj/ShellScriptRule.xib; sourceTree = ""; }; + DD2A78CF14855B240010AFE0 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-BR"; path = "Resources/pt-BR.lproj/ShellScriptRule.xib"; sourceTree = ""; }; + DD2A78D114855B430010AFE0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/MainMenu.xib"; sourceTree = ""; }; + DD2A78D314855B4C0010AFE0 /* pt-PT */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; + DD2A78D514855B730010AFE0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/GenericRule.xib"; sourceTree = ""; }; + DD2A78D714855B7A0010AFE0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/IPRule.xib"; sourceTree = ""; }; + DD2A78D914855B800010AFE0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/LightRule.xib"; sourceTree = ""; }; + DD2A78DB14855B880010AFE0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "Resources/pt-PT.lproj/ShellScriptRule.xib"; sourceTree = ""; }; + DD2A78DD14855B8D0010AFE0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/TimeOfDayRule.xib"; sourceTree = ""; }; + DD2A78DF14855B9B0010AFE0 /* pt-PT */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/CPHelperToolAuthorizationPrompts.strings"; sourceTree = ""; }; + DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sparkle.xcodeproj; path = "External Source/Sparkle/Sparkle.xcodeproj"; sourceTree = ""; }; DD3BAB8414163C6B000D5F88 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CoreLocationRule.xib; sourceTree = ""; }; - DD44B57D141417E40016BF6B /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; + DD4364BD145E13A500A716A1 /* ToggleFirewallAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToggleFirewallAction.h; path = Source/ToggleFirewallAction.h; sourceTree = ""; }; + DD4364BE145E13A500A716A1 /* ToggleFirewallAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ToggleFirewallAction.m; path = Source/ToggleFirewallAction.m; sourceTree = ""; }; DD44B5A014142D2D0016BF6B /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/CPHelperToolAuthorizationPrompts.strings; sourceTree = ""; }; DD44B5A214142D4D0016BF6B /* da-DK */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = "da-DK"; path = "da-DK.lproj/CPHelperToolAuthorizationPrompts.strings"; sourceTree = ""; }; DD44B5A314142D4D0016BF6B /* fr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/CPHelperToolAuthorizationPrompts.strings; sourceTree = ""; }; DD44B5A414142D4D0016BF6B /* pt-BR */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/CPHelperToolAuthorizationPrompts.strings"; sourceTree = ""; }; DD44B5A514142D4D0016BF6B /* it */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/CPHelperToolAuthorizationPrompts.strings; sourceTree = ""; }; DD44B5A614142D4D0016BF6B /* de */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/CPHelperToolAuthorizationPrompts.strings; sourceTree = ""; }; - DD5BD209141614C4007BA88C /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONKit.h; path = Source/JSONKit/JSONKit.h; sourceTree = ""; }; - DD5BD20A141614C4007BA88C /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSONKit.m; path = Source/JSONKit/JSONKit.m; sourceTree = ""; }; - DD6FCC681413EF6B0095E64F /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; - DD7D2537149C338200BE7C8B /* NSTimer+Invalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSTimer+Invalidation.h"; path = "Source/NSTimer+Invalidation.h"; sourceTree = ""; }; - DD7D2538149C338300BE7C8B /* NSTimer+Invalidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSTimer+Invalidation.m"; path = "Source/NSTimer+Invalidation.m"; sourceTree = ""; }; - DD8274E5141147BB0098FA6E /* controlplane.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = controlplane.icns; path = Resources/controlplane.icns; sourceTree = ""; }; + DD7D24DC149A086400BE7C8B /* DisplaySleepTimeAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DisplaySleepTimeAction.h; path = Source/DisplaySleepTimeAction.h; sourceTree = ""; }; + DD7D24DD149A086400BE7C8B /* DisplaySleepTimeAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DisplaySleepTimeAction.m; path = Source/DisplaySleepTimeAction.m; sourceTree = ""; }; + DD8274E5141147BB0098FA6E /* controlplane.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = controlplane.icns; sourceTree = ""; }; DD8274EE141154780098FA6E /* MailIntervalAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MailIntervalAction.h; path = Source/MailIntervalAction.h; sourceTree = ""; }; DD8274EF141154780098FA6E /* MailIntervalAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MailIntervalAction.m; path = Source/MailIntervalAction.m; sourceTree = ""; }; DD8274F114115EE40098FA6E /* StartTimeMachineAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StartTimeMachineAction.h; path = Source/StartTimeMachineAction.h; sourceTree = ""; }; @@ -440,7 +412,6 @@ DD8274F514116CC80098FA6E /* OpenURLAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenURLAction.m; path = Source/OpenURLAction.m; sourceTree = ""; }; DD8274F71411748B0098FA6E /* LockKeychainAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LockKeychainAction.h; path = Source/LockKeychainAction.h; sourceTree = ""; }; DD8274F81411748B0098FA6E /* LockKeychainAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LockKeychainAction.m; path = Source/LockKeychainAction.m; sourceTree = ""; }; - DD8274FA141177750098FA6E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; DD8274FC14117C570098FA6E /* SpeakAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SpeakAction.h; path = Source/SpeakAction.h; sourceTree = ""; }; DD8274FD14117C580098FA6E /* SpeakAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SpeakAction.m; path = Source/SpeakAction.m; sourceTree = ""; }; DD827505141188880098FA6E /* DisplayBrightnessAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DisplayBrightnessAction.h; path = Source/DisplayBrightnessAction.h; sourceTree = ""; }; @@ -481,23 +452,42 @@ DDA201711411C39400DE570E /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-BR"; path = "pt-BR.lproj/TimeOfDayRule.xib"; sourceTree = ""; }; DDA201721411C39400DE570E /* de */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = de; path = de.lproj/TimeOfDayRule.xib; sourceTree = ""; }; DDA201731411C39400DE570E /* it */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = it; path = it.lproj/TimeOfDayRule.xib; sourceTree = ""; }; - DDAA9A161402FAAD00D4757E /* SleepEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SleepEvidenceSource.h; path = Source/SleepEvidenceSource.h; sourceTree = ""; }; - DDAA9A171402FAAD00D4757E /* SleepEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SleepEvidenceSource.m; path = Source/SleepEvidenceSource.m; sourceTree = ""; }; - DDAC3C54140D866200FBF29E /* ScriptingBridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScriptingBridge.framework; path = System/Library/Frameworks/ScriptingBridge.framework; sourceTree = SDKROOT; }; + DDAC86C1143C107A00682538 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; DDAE0015141474DC00FDADE8 /* CPController+SleepThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CPController+SleepThread.h"; path = "Source/CPController+SleepThread.h"; sourceTree = ""; }; DDAE0016141474DC00FDADE8 /* CPController+SleepThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CPController+SleepThread.m"; path = "Source/CPController+SleepThread.m"; sourceTree = ""; }; - DDAE004B141521EF00FDADE8 /* CoreLocationSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreLocationSource.h; path = Source/CoreLocationSource.h; sourceTree = ""; }; - DDAE004C141521EF00FDADE8 /* CoreLocationSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CoreLocationSource.m; path = Source/CoreLocationSource.m; sourceTree = ""; }; DDAEFFF91414714F00FDADE8 /* Action+HelperTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Action+HelperTool.h"; path = "Source/Action+HelperTool.h"; sourceTree = ""; }; DDAEFFFA1414714F00FDADE8 /* Action+HelperTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "Action+HelperTool.m"; path = "Source/Action+HelperTool.m"; sourceTree = ""; }; - DDC3C2A11412A82000655F34 /* Growl Registration Ticket.growlRegDict */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "Growl Registration Ticket.growlRegDict"; path = "Resources/Growl Registration Ticket.growlRegDict"; sourceTree = ""; }; + DDB151BF146EEB7C00FA7835 /* Framework.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Framework.xcodeproj; path = "Plug-ins/Framework/Framework.xcodeproj"; sourceTree = ""; }; + DDB151F9146F02BF00FA7835 /* Quincy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quincy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DDB1520E146F050C00FA7835 /* BWQuincyMain.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = BWQuincyMain.nib; path = "External Source/QuincyKit/client/Mac/BWQuincyMain.nib"; sourceTree = SOURCE_ROOT; }; + DDB1520F146F050C00FA7835 /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BWQuincyManager.h; path = "External Source/QuincyKit/client/Mac/BWQuincyManager.h"; sourceTree = SOURCE_ROOT; }; + DDB15210146F050C00FA7835 /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BWQuincyManager.m; path = "External Source/QuincyKit/client/Mac/BWQuincyManager.m"; sourceTree = SOURCE_ROOT; }; + DDB15214146F05A600FA7835 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "External Source/QuincyKit/demo/Mac/Info.plist"; sourceTree = SOURCE_ROOT; }; + DDB15216146F078300FA7835 /* Quincy.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Quincy.xcconfig; path = xcconfigs/Quincy.xcconfig; sourceTree = ""; }; + DDC3C2A11412A82000655F34 /* Growl Registration Ticket.growlRegDict */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Growl Registration Ticket.growlRegDict"; sourceTree = ""; }; + DDD1A362142BD65600341B75 /* KVOAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVOAdditions.h; sourceTree = ""; }; + DDD1A363142BD65600341B75 /* KVOAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KVOAdditions.m; sourceTree = ""; }; + DDD1A365142CC80E00341B75 /* Context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Context.h; path = Source/Context.h; sourceTree = ""; }; + DDD1A366142CC80F00341B75 /* Context.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Context.m; path = Source/Context.m; sourceTree = ""; }; + DDD1A36E142CD55E00341B75 /* ContextGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContextGroup.h; path = Source/ContextGroup.h; sourceTree = ""; }; + DDD1A36F142CD55E00341B75 /* ContextGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContextGroup.m; path = Source/ContextGroup.m; sourceTree = ""; }; + DDD1A373142CD81900341B75 /* ContextsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContextsManager.h; path = Source/ContextsManager.h; sourceTree = ""; }; + DDD1A374142CD81900341B75 /* ContextsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContextsManager.m; path = Source/ContextsManager.m; sourceTree = ""; }; DDDF1C291411D49300DB0018 /* DefaultBrowserAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DefaultBrowserAction.h; path = Source/DefaultBrowserAction.h; sourceTree = ""; }; DDDF1C2A1411D49300DB0018 /* DefaultBrowserAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DefaultBrowserAction.m; path = Source/DefaultBrowserAction.m; sourceTree = ""; }; DDDF1C2D1411E07F00DB0018 /* ITunesPlaylistAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ITunesPlaylistAction.h; path = Source/ITunesPlaylistAction.h; sourceTree = ""; }; DDDF1C2E1411E07F00DB0018 /* ITunesPlaylistAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ITunesPlaylistAction.m; path = Source/ITunesPlaylistAction.m; sourceTree = ""; }; - DDE1B067140438DB006564A6 /* ControlPlane.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = ControlPlane.sdef; path = Resources/ControlPlane.sdef; sourceTree = ""; }; - DDF4E594141588E80028DF4A /* CoreLocationMap.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = CoreLocationMap.html; path = Resources/CoreLocationMap.html; sourceTree = ""; }; - DDFF423014156B0A0047D311 /* location.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = location.png; path = Resources/location.png; sourceTree = ""; }; + DDE1B067140438DB006564A6 /* ControlPlane.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = ControlPlane.sdef; sourceTree = ""; }; + DDF4E594141588E80028DF4A /* CoreLocationMap.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = CoreLocationMap.html; sourceTree = ""; }; + DDF52E9E1460BDA700A42B09 /* Core.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Core.xcodeproj; path = "Plug-ins/Core/Core.xcodeproj"; sourceTree = ""; }; + DDFAEFE1144FD2EC006472EE /* ToggleInternetSharingAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToggleInternetSharingAction.h; path = Source/ToggleInternetSharingAction.h; sourceTree = ""; }; + DDFAEFE2144FD2EC006472EE /* ToggleInternetSharingAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ToggleInternetSharingAction.m; path = Source/ToggleInternetSharingAction.m; sourceTree = ""; }; + DDFB061C1440F7CF000689E4 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = xcconfigs/Debug.xcconfig; sourceTree = ""; }; + DDFB061D1440F7CF000689E4 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = xcconfigs/Release.xcconfig; sourceTree = ""; }; + DDFB06261440FE1B000689E4 /* ControlPlane.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = ControlPlane.xcconfig; path = xcconfigs/ControlPlane.xcconfig; sourceTree = ""; }; + DDFB06281440FE1B000689E4 /* CPHelperInstallTool.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = CPHelperInstallTool.xcconfig; path = xcconfigs/CPHelperInstallTool.xcconfig; sourceTree = ""; }; + DDFB06291440FE1B000689E4 /* CPHelperTool.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = CPHelperTool.xcconfig; path = xcconfigs/CPHelperTool.xcconfig; sourceTree = ""; }; + DDFF423014156B0A0047D311 /* location.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = location.png; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -505,22 +495,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8D8C9BAB0BBB3ADB0074D5B3 /* Apple80211.framework in Frameworks */, - DD06E811140C661700059764 /* AudioToolbox.framework in Frameworks */, - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, - 8D57B1440C4457AB00EC620D /* CoreAudio.framework in Frameworks */, - DD6FCC691413EF6B0095E64F /* CoreLocation.framework in Frameworks */, - DA72BF9413CD317B002D27DD /* CoreWLAN.framework in Frameworks */, - DAFC0E4514788ACB00DA6139 /* DisplayServices.framework in Frameworks */, + DDAC86C2143C107A00682538 /* Cocoa.framework in Frameworks */, 8D80BB980B8B033400104A87 /* Growl.framework in Frameworks */, - DAFC0E4614788B0500DA6139 /* IOBluetooth.framework in Frameworks */, - 8D481B0A0B6098DD0097CF9C /* IOKit.framework in Frameworks */, - DDAC3C55140D866200FBF29E /* ScriptingBridge.framework in Frameworks */, - DD8274FB141177750098FA6E /* Security.framework in Frameworks */, - 8D2072110B86AB0000D61A9E /* Sparkle.framework in Frameworks */, - 8D82F06D0AA811CE009ADA44 /* SystemConfiguration.framework in Frameworks */, - 8D3BFFB20C61CA5300B9B910 /* WebKit.framework in Frameworks */, - DA4411A514EE03C9005E7B3B /* MapKit.framework in Frameworks */, + DD23F88D1460E899000665ED /* IOKit.framework in Frameworks */, + DD1CD01614F40F8B0036E659 /* MapKit.framework in Frameworks */, + DDB151CC146EEBAE00FA7835 /* NSLogger.framework in Frameworks */, + DDB151E0146EEC1600FA7835 /* Plugins.framework in Frameworks */, + DDB1522F146F0F5100FA7835 /* Quincy.framework in Frameworks */, + DD23F88B1460E70E000665ED /* Security.framework in Frameworks */, + DD334A5214A7B0F5000F960A /* Sparkle.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -535,29 +518,28 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DD44B57E141417E40016BF6B /* CoreServices.framework in Frameworks */, - DA648AEE1412C15D00532B2C /* Security.framework in Frameworks */, - DA648AF11412C19800532B2C /* CoreFoundation.framework in Frameworks */, + DD23F8571460E2BD000665ED /* Cocoa.framework in Frameworks */, + DD23F8581460E2EC000665ED /* CoreFoundation.framework in Frameworks */, + DD23F8591460E2EC000665ED /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - DA8064A71479910E00267B5A /* Frameworks */ = { + DDB151F5146F02BF00FA7835 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DA8064C41479927500267B5A /* Cocoa.framework in Frameworks */, - DA8064C51479927600267B5A /* Foundation.framework in Frameworks */, + DD334A3714A7B073000F960A /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { + 080E96DDFE201D6D7F000001 /* ControlPlane */ = { isa = PBXGroup; children = ( - 8DAD148E0BBCA40700F93914 /* Evidence Sources */, - 8DF5A4130BC2350000CBEB4B /* Actions */, + DDD1A372142CD6A000341B75 /* Contexts */, + 8DF5A4130BC2350000CBEB4B /* Actions (old) */, 8D0164850C02AB08004AD8DB /* UI Utilities */, 8D3BFF3C0C61BE4500B9B910 /* AboutPanel.h */, 8D3BFF3D0C61BE4500B9B910 /* AboutPanel.m */, @@ -565,55 +547,33 @@ DA812E82140681D2006869F7 /* AppleScript.m */, 8D8155CD0C3A304E00228463 /* ContextsDataSource.h */, 8D8155CE0C3A304E00228463 /* ContextsDataSource.m */, - 8D8C9E320BBB89320074D5B3 /* DB.h */, - 8D8C9E330BBB89320074D5B3 /* DB.m */, - 8DBB44950C530F7600064010 /* DSLogger.h */, - 8DBB44960C530F7600064010 /* DSLogger.m */, 8D90E51D0B71C4C9007D39FD /* CPController.h */, 8D90E51E0B71C4C9007D39FD /* CPController.m */, DDAE0015141474DC00FDADE8 /* CPController+SleepThread.h */, DDAE0016141474DC00FDADE8 /* CPController+SleepThread.m */, 8D82F0A10AA81411009ADA44 /* PrefsWindowController.h */, 8D82F0A20AA81411009ADA44 /* PrefsWindowController.m */, - DD7D2537149C338200BE7C8B /* NSTimer+Invalidation.h */, - DD7D2538149C338300BE7C8B /* NSTimer+Invalidation.m */, - DA461C0A14C33E3B0019594A /* NSString+ShellScriptHelper.h */, - DA461C0B14C33E3B0019594A /* NSString+ShellScriptHelper.m */, ); - name = Classes; + name = ControlPlane; sourceTree = ""; }; - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + 1058C7A0FEA54F0111CA2CBB /* Other Frameworks */ = { isa = PBXGroup; children = ( - DA4411A414EE03C9005E7B3B /* MapKit.framework */, + DD1CD00614F40F580036E659 /* MapKit.xcodeproj */, + DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */, 8D80BB950B8B033400104A87 /* Growl.framework */, - 8D20720E0B86AB0000D61A9E /* Sparkle.framework */, ); - name = "Linked Frameworks"; + name = "Other Frameworks"; sourceTree = ""; }; 1058C7A2FEA54F0111CA2CBB /* Apple Frameworks */ = { isa = PBXGroup; children = ( - 29B97324FDCFA39411CA2CEA /* AppKit.framework */, - 8D8C9BA90BBB3ADB0074D5B3 /* Apple80211.framework */, - DD06E810140C661600059764 /* AudioToolbox.framework */, - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, - 8D57B1430C4457AB00EC620D /* CoreAudio.framework */, - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, - DA648AEF1412C17A00532B2C /* CoreFoundation.framework */, - DD6FCC681413EF6B0095E64F /* CoreLocation.framework */, - DD44B57D141417E40016BF6B /* CoreServices.framework */, - DA72BF9313CD317B002D27DD /* CoreWLAN.framework */, - 29B97325FDCFA39411CA2CEA /* Foundation.framework */, - 8DB8911C0BB88D0B005347C2 /* IOBluetooth.framework */, - 8D481B070B6098DD0097CF9C /* IOKit.framework */, - DA48F2E3140AD2FC00B000D3 /* Kernel.framework */, - DDAC3C54140D866200FBF29E /* ScriptingBridge.framework */, - DD8274FA141177750098FA6E /* Security.framework */, - 8D82F05B0AA811CE009ADA44 /* SystemConfiguration.framework */, - 8D3BFFB10C61CA5300B9B910 /* WebKit.framework */, + DDAC86C1143C107A00682538 /* Cocoa.framework */, + DD23F8491460E222000665ED /* CoreFoundation.framework */, + DD23F88C1460E898000665ED /* IOKit.framework */, + DD23F8471460E216000665ED /* Security.framework */, ); name = "Apple Frameworks"; sourceTree = ""; @@ -624,7 +584,7 @@ DA1204DA13D0E5C800CDA091 /* ControlPlane.app */, DA5B01D71412B6A700E19C50 /* CPHelperInstallTool */, DA5B01FB1412BB1700E19C50 /* CPHelperTool */, - DA8064AB1479910E00267B5A /* Quincy.framework */, + DDB151F9146F02BF00FA7835 /* Quincy.framework */, ); name = Products; sourceTree = ""; @@ -632,11 +592,14 @@ 29B97314FDCFA39411CA2CEA /* ControlPlane */ = { isa = PBXGroup; children = ( + DDF52E9E1460BDA700A42B09 /* Core.xcodeproj */, + DDB151BF146EEB7C00FA7835 /* Framework.xcodeproj */, + 080E96DDFE201D6D7F000001 /* ControlPlane */, DA5B01E91412BA6700E19C50 /* HelperTool */, - 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, DDFF422F14153F650047D311 /* UI */, + DDFB06191440F7B4000689E4 /* Configurations */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); @@ -646,12 +609,10 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( - DA80649F147990FD00267B5A /* Mac */, - DD5BD2071416149B007BA88C /* JNI LmuTracker */, - DD5BD20C141614CA007BA88C /* JSONKit */, - 8D8C9BA70BBB3AAC0074D5B3 /* Apple80211.h */, - 32CA4F630368D1EE00C91783 /* ControlPlane_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, + DDD1A361142BD65600341B75 /* KVOAdditions */, + DDB151FF146F02BF00FA7835 /* QuincyKit */, + 29B97316FDCFA39411CA2CEA /* Main.m */, + 32CA4F630368D1EE00C91783 /* Prefix.pch */, ); name = "Other Sources"; sourceTree = ""; @@ -678,21 +639,18 @@ 8D1107310486CEB800E47090 /* Info.plist */, DDFF423014156B0A0047D311 /* location.png */, 8D1A45590BA00DE2004A6BC4 /* minus-8.png */, - 8DB8917B0BB89BD8005347C2 /* oui.txt */, 8D88FE290C534737007A14D6 /* pause.png */, 8D1A455A0BA00DE2004A6BC4 /* plus-8.png */, 8D9AE3780BE0D11800D4D4E4 /* plus-arrow.png */, 8D232FB40BD9D507006A3963 /* RulesPrefs.png */, - DA83A22613D1430000074503 /* usb-vendors.txt */, ); - name = Resources; + path = Resources; sourceTree = SOURCE_ROOT; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( - DAFC0E4014788A6000DA6139 /* Apple Private Frameworks */, - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A0FEA54F0111CA2CBB /* Other Frameworks */, 1058C7A2FEA54F0111CA2CBB /* Apple Frameworks */, ); name = Frameworks; @@ -713,64 +671,7 @@ name = "UI Utilities"; sourceTree = ""; }; - 8DAD148E0BBCA40700F93914 /* Evidence Sources */ = { - isa = PBXGroup; - children = ( - 8DE4C0C00C4EEE3E00511590 /* Concrete Evidence Sources */, - 8D8C9CA30BBB74E70074D5B3 /* EvidenceSource.h */, - 8D8C9CA40BBB74E70074D5B3 /* EvidenceSource.m */, - 8DE4C00E0C4EE60700511590 /* GenericEvidenceSource.h */, - 8DE4C00F0C4EE60700511590 /* GenericEvidenceSource.m */, - 8D643C650C4EF197006D8ECC /* GenericLoopingEvidenceSource.h */, - 8D643C660C4EF197006D8ECC /* GenericLoopingEvidenceSource.m */, - 8D643CDA0C4EF6FD006D8ECC /* LoopingEvidenceSource.h */, - 8D643CDB0C4EF6FD006D8ECC /* LoopingEvidenceSource.m */, - ); - name = "Evidence Sources"; - sourceTree = ""; - }; - 8DE4C0C00C4EEE3E00511590 /* Concrete Evidence Sources */ = { - isa = PBXGroup; - children = ( - 8D27ECAD0C4456A300AE1929 /* AudioOutputEvidenceSource.h */, - 8D27ECAE0C4456A300AE1929 /* AudioOutputEvidenceSource.m */, - 8D8C9CE40BBB7BE00074D5B3 /* BluetoothEvidenceSource.h */, - 8D8C9CE50BBB7BE00074D5B3 /* BluetoothEvidenceSource.m */, - 8D1493F40C824B6D00D29FE8 /* BonjourEvidenceSource.h */, - 8D1493F50C824B6D00D29FE8 /* BonjourEvidenceSource.m */, - DDAE004B141521EF00FDADE8 /* CoreLocationSource.h */, - DDAE004C141521EF00FDADE8 /* CoreLocationSource.m */, - DA83A21B13D0FE8F00074503 /* CoreWLANEvidenceSource.h */, - DA83A21C13D0FE8F00074503 /* CoreWLANEvidenceSource.m */, - 8DCBF48F0BE5622600A01414 /* FireWireEvidenceSource.h */, - 8DCBF4900BE5622600A01414 /* FireWireEvidenceSource.m */, - 8D8C9EBA0BBB8DAC0074D5B3 /* IPEvidenceSource.h */, - 8D8C9EBB0BBB8DAC0074D5B3 /* IPEvidenceSource.m */, - 8D91F1F70C4772FF00D9FC0F /* LightEvidenceSource.h */, - 8D91F1F80C4772FF00D9FC0F /* LightEvidenceSource.m */, - 8D5684B20C38711D00881E32 /* MonitorEvidenceSource.h */, - 8D5684B30C38711D00881E32 /* MonitorEvidenceSource.m */, - 8D2BAAAA0C56E26100A50777 /* NetworkLinkEvidenceSource.h */, - 8D2BAAAB0C56E26100A50777 /* NetworkLinkEvidenceSource.m */, - 8DCBF4FC0BE5B11F00A01414 /* PowerEvidenceSource.h */, - 8DCBF4FD0BE5B11F00A01414 /* PowerEvidenceSource.m */, - 8D341CD00C0459D0008A7B4F /* RunningApplicationEvidenceSource.h */, - 8D341CD10C0459D0008A7B4F /* RunningApplicationEvidenceSource.m */, - 732A58DD1484300A0011019C /* ShellScriptEvidenceSource.h */, - 732A58DE1484300A0011019C /* ShellScriptEvidenceSource.m */, - DDAA9A161402FAAD00D4757E /* SleepEvidenceSource.h */, - DDAA9A171402FAAD00D4757E /* SleepEvidenceSource.m */, - 8DE428F90C5084D00073499A /* TimeOfDayEvidenceSource.h */, - 8DE428FA0C5084D00073499A /* TimeOfDayEvidenceSource.m */, - 8D35A34C0BBBA0CB006ACBB0 /* USBEvidenceSource.h */, - 8D35A34D0BBBA0CB006ACBB0 /* USBEvidenceSource.m */, - 8D35A30A0BBB9CFD006ACBB0 /* WiFiEvidenceSource.h */, - 8D35A30B0BBB9CFD006ACBB0 /* WiFiEvidenceSource.m */, - ); - name = "Concrete Evidence Sources"; - sourceTree = ""; - }; - 8DF5A4130BC2350000CBEB4B /* Actions */ = { + 8DF5A4130BC2350000CBEB4B /* Actions (old) */ = { isa = PBXGroup; children = ( DD8274EB14114CFF0098FA6E /* Application Actions */, @@ -782,14 +683,14 @@ 8D71CAEC0C17BA7900E56526 /* ToggleableAction.h */, 8D71CAED0C17BA7900E56526 /* ToggleableAction.m */, ); - name = Actions; + name = "Actions (old)"; sourceTree = ""; }; DA5B01E91412BA6700E19C50 /* HelperTool */ = { isa = PBXGroup; children = ( DA5B01EA1412BA6700E19C50 /* AuthorizationLib */, - DA5B01F41412BAF400E19C50 /* BetterAuthorizationSampleLibInstallTool.c */, + DA5B01F41412BAF400E19C50 /* BetterAuthorizationLibInstallTool.c */, DA5B02091412BBF200E19C50 /* CPHelperTool.c */, DA5B020E1412BE4F00E19C50 /* CPHelperToolCommon.h */, DA5B020B1412BDEF00E19C50 /* CPHelperToolCommon.c */, @@ -801,47 +702,32 @@ DA5B01EA1412BA6700E19C50 /* AuthorizationLib */ = { isa = PBXGroup; children = ( - DA5B01F21412BAEC00E19C50 /* BetterAuthorizationSampleLib.c */, - DA5B01EB1412BA6700E19C50 /* BetterAuthorizationSampleLib.h */, + DA5B01F21412BAEC00E19C50 /* BetterAuthorizationLib.c */, + DA5B01EB1412BA6700E19C50 /* BetterAuthorizationLib.h */, ); path = AuthorizationLib; sourceTree = ""; }; - DA80649F147990FD00267B5A /* Mac */ = { + DD1CD00714F40F580036E659 /* Products */ = { isa = PBXGroup; children = ( - DA8064A0147990FD00267B5A /* BWQuincyMain.nib */, - DA8064A1147990FD00267B5A /* BWQuincyManager.h */, - DA8064A2147990FD00267B5A /* BWQuincyManager.m */, + DD1CD01114F40F580036E659 /* DemoApp.app */, + DD1CD01314F40F580036E659 /* MapKit.framework */, + DD1CD01514F40F580036E659 /* MapKit.ibplugin */, ); - name = Mac; - path = Source/QuincyKit/client/Mac; - sourceTree = ""; - }; - DAFC0E4014788A6000DA6139 /* Apple Private Frameworks */ = { - isa = PBXGroup; - children = ( - DAFC0E3D14788A5000DA6139 /* DisplayServices.framework */, - ); - name = "Apple Private Frameworks"; - sourceTree = ""; - }; - DD5BD2071416149B007BA88C /* JNI LmuTracker */ = { - isa = PBXGroup; - children = ( - DA6D184C1154581700347E93 /* LmuTrackerCommon.h */, - DA6D184A1154581000347E93 /* LmuTracker.c */, - ); - name = "JNI LmuTracker"; + name = Products; sourceTree = ""; }; - DD5BD20C141614CA007BA88C /* JSONKit */ = { + DD334A3914A7B0C0000F960A /* Products */ = { isa = PBXGroup; children = ( - DD5BD209141614C4007BA88C /* JSONKit.h */, - DD5BD20A141614C4007BA88C /* JSONKit.m */, + DD334A4714A7B0C1000F960A /* Sparkle.framework */, + DD334A4914A7B0C1000F960A /* Sparkle Test App.app */, + DD334A4B14A7B0C1000F960A /* Sparkle Unit Tests.octest */, + DD334A4D14A7B0C1000F960A /* BinaryDelta */, + DD334A4F14A7B0C1000F960A /* finish_installation.app */, ); - name = JSONKit; + name = Products; sourceTree = ""; }; DD8274EB14114CFF0098FA6E /* Application Actions */ = { @@ -869,8 +755,6 @@ 8DBAFAFA0BDC3B7B00BE0747 /* ShellScriptAction.m */, DD8274FC14117C570098FA6E /* SpeakAction.h */, DD8274FD14117C580098FA6E /* SpeakAction.m */, - DAC45F1E14CDEC170007F5EF /* TimeMachineDestinationAction.h */, - DAC45F1F14CDEC170007F5EF /* TimeMachineDestinationAction.m */, ); name = "Application Actions"; sourceTree = ""; @@ -884,8 +768,8 @@ 8DA2F4130CE8630200F92D4D /* DesktopBackgroundAction.m */, DD827505141188880098FA6E /* DisplayBrightnessAction.h */, DD827506141188880098FA6E /* DisplayBrightnessAction.m */, - 739492E0146B8018003C94DE /* DisplaySleepTimeAction.h */, - 739492E1146B8018003C94DE /* DisplaySleepTimeAction.m */, + DD7D24DC149A086400BE7C8B /* DisplaySleepTimeAction.h */, + DD7D24DD149A086400BE7C8B /* DisplaySleepTimeAction.m */, 8DCB43550C4DBABD00E71D28 /* FirewallRuleAction.h */, 8DCB43560C4DBABD00E71D28 /* FirewallRuleAction.m */, DD8274F71411748B0098FA6E /* LockKeychainAction.h */, @@ -906,12 +790,10 @@ DD8274F214115EE40098FA6E /* StartTimeMachineAction.m */, 8D75A61D0BE6F68B0069DF3F /* ToggleBluetoothAction.h */, 8D75A61E0BE6F68B0069DF3F /* ToggleBluetoothAction.m */, - DAE893E414546897005FA13C /* ToggleFirewallAction.h */, - DAE893E514546897005FA13C /* ToggleFirewallAction.m */, - DA922E9B144FC95200920B40 /* ToggleInternetSharingAction.h */, - DA922E9C144FC95200920B40 /* ToggleInternetSharingAction.m */, - DA49AF6A14C3E0AB00D03D6A /* TogglePrinterSharingAction.h */, - DA49AF6B14C3E0AB00D03D6A /* TogglePrinterSharingAction.m */, + DD4364BD145E13A500A716A1 /* ToggleFirewallAction.h */, + DD4364BE145E13A500A716A1 /* ToggleFirewallAction.m */, + DDFAEFE1144FD2EC006472EE /* ToggleInternetSharingAction.h */, + DDFAEFE2144FD2EC006472EE /* ToggleInternetSharingAction.m */, DAAF16B41413174400F5D915 /* ToggleTimeMachineAction.h */, DAAF16B51413174400F5D915 /* ToggleTimeMachineAction.m */, 8D649BA20BE8033A00716059 /* ToggleWiFiAction.h */, @@ -924,16 +806,97 @@ name = "System Actions"; sourceTree = ""; }; + DDB15173146EE4C000FA7835 /* Products */ = { + isa = PBXGroup; + children = ( + DDB15178146EE4C000FA7835 /* Core.plugin */, + DDB1517A146EE4C000FA7835 /* libJSONKit.a */, + ); + name = Products; + sourceTree = ""; + }; + DDB151C0146EEB7C00FA7835 /* Products */ = { + isa = PBXGroup; + children = ( + DDB151C5146EEB7C00FA7835 /* NSLogger.framework */, + DDB151C7146EEB7C00FA7835 /* Plugins.framework */, + ); + name = Products; + sourceTree = ""; + }; + DDB151FF146F02BF00FA7835 /* QuincyKit */ = { + isa = PBXGroup; + children = ( + DDB1520D146F04E600FA7835 /* Source */, + DDB1520C146F04E300FA7835 /* Resource */, + ); + path = QuincyKit; + sourceTree = ""; + }; + DDB1520C146F04E300FA7835 /* Resource */ = { + isa = PBXGroup; + children = ( + DDB15214146F05A600FA7835 /* Info.plist */, + DDB1520E146F050C00FA7835 /* BWQuincyMain.nib */, + ); + name = Resource; + sourceTree = ""; + }; + DDB1520D146F04E600FA7835 /* Source */ = { + isa = PBXGroup; + children = ( + DDB1520F146F050C00FA7835 /* BWQuincyManager.h */, + DDB15210146F050C00FA7835 /* BWQuincyManager.m */, + ); + name = Source; + sourceTree = ""; + }; + DDD1A361142BD65600341B75 /* KVOAdditions */ = { + isa = PBXGroup; + children = ( + DDD1A362142BD65600341B75 /* KVOAdditions.h */, + DDD1A363142BD65600341B75 /* KVOAdditions.m */, + ); + name = KVOAdditions; + path = "External Source/KVOAdditions"; + sourceTree = ""; + }; + DDD1A372142CD6A000341B75 /* Contexts */ = { + isa = PBXGroup; + children = ( + DDD1A365142CC80E00341B75 /* Context.h */, + DDD1A366142CC80F00341B75 /* Context.m */, + DDD1A36E142CD55E00341B75 /* ContextGroup.h */, + DDD1A36F142CD55E00341B75 /* ContextGroup.m */, + DDD1A373142CD81900341B75 /* ContextsManager.h */, + DDD1A374142CD81900341B75 /* ContextsManager.m */, + ); + name = Contexts; + sourceTree = ""; + }; + DDFB06191440F7B4000689E4 /* Configurations */ = { + isa = PBXGroup; + children = ( + DDFB06261440FE1B000689E4 /* ControlPlane.xcconfig */, + DDFB06281440FE1B000689E4 /* CPHelperInstallTool.xcconfig */, + DDFB06291440FE1B000689E4 /* CPHelperTool.xcconfig */, + DDFB061C1440F7CF000689E4 /* Debug.xcconfig */, + DDB15216146F078300FA7835 /* Quincy.xcconfig */, + DDFB061D1440F7CF000689E4 /* Release.xcconfig */, + ); + name = Configurations; + sourceTree = ""; + }; DDFF422F14153F650047D311 /* UI */ = { isa = PBXGroup; children = ( - 73A5092714849405007D22B5 /* ShellScriptRule.xib */, 8DC410FA0C64665E00393759 /* AboutPanel.xib */, DD3BAB8514163C6B000D5F88 /* CoreLocationRule.xib */, DDA201461411C25A00DE570E /* GenericRule.xib */, DDA201501411C32F00DE570E /* IPRule.xib */, DDA2015A1411C35700DE570E /* LightRule.xib */, DDA201641411C37300DE570E /* MainMenu.xib */, + DD2A78BF14855A640010AFE0 /* ShellScriptRule.xib */, DDA2016E1411C38D00DE570E /* TimeOfDayRule.xib */, DDA2013C1411C0FB00DE570E /* Localizable.strings */, DD44B5A114142D2D0016BF6B /* CPHelperToolAuthorizationPrompts.strings */, @@ -944,11 +907,11 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - DA8064A81479910E00267B5A /* Headers */ = { + DDB151F6146F02BF00FA7835 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - DA8064C01479912400267B5A /* BWQuincyManager.h in Headers */, + DDB15212146F050D00FA7835 /* BWQuincyManager.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -965,14 +928,18 @@ 8DEF43B20BAA072400F87273 /* Index Help */, 8D11072E0486CEB800E47090 /* Frameworks */, 8D2073870B86AB5100D61A9E /* Copy Frameworks */, - DA5B01E51412B85600E19C50 /* CopyFiles */, + DA5B01E51412B85600E19C50 /* Copy Helper Tool */, + DDAC8668143C03CE00682538 /* Copy Plugins */, ); buildRules = ( ); dependencies = ( - DA8064C31479915100267B5A /* PBXTargetDependency */, + DDB151BD146EEB4200FA7835 /* PBXTargetDependency */, DA5B02071412BB3A00E19C50 /* PBXTargetDependency */, DA5B01E31412B78900E19C50 /* PBXTargetDependency */, + DD1CD01814F40FCC0036E659 /* PBXTargetDependency */, + DD334A5114A7B0E6000F960A /* PBXTargetDependency */, + DDB15219146F08D000FA7835 /* PBXTargetDependency */, ); name = ControlPlane; productInstallPath = "$(HOME)/Applications"; @@ -1014,22 +981,22 @@ productReference = DA5B01FB1412BB1700E19C50 /* CPHelperTool */; productType = "com.apple.product-type.tool"; }; - DA8064AA1479910E00267B5A /* Quincy */ = { + DDB151F8146F02BF00FA7835 /* Quincy */ = { isa = PBXNativeTarget; - buildConfigurationList = DA8064BC1479910E00267B5A /* Build configuration list for PBXNativeTarget "Quincy" */; + buildConfigurationList = DDB15209146F02BF00FA7835 /* Build configuration list for PBXNativeTarget "Quincy" */; buildPhases = ( - DA8064A61479910E00267B5A /* Sources */, - DA8064A71479910E00267B5A /* Frameworks */, - DA8064A81479910E00267B5A /* Headers */, - DA8064A91479910E00267B5A /* Resources */, + DDB151F4146F02BF00FA7835 /* Sources */, + DDB151F5146F02BF00FA7835 /* Frameworks */, + DDB151F6146F02BF00FA7835 /* Headers */, + DDB151F7146F02BF00FA7835 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Quincy; - productName = Quincy; - productReference = DA8064AB1479910E00267B5A /* Quincy.framework */; + productName = QuincyKit; + productReference = DDB151F9146F02BF00FA7835 /* Quincy.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -1077,16 +1044,121 @@ ); mainGroup = 29B97314FDCFA39411CA2CEA /* ControlPlane */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = DDB15173146EE4C000FA7835 /* Products */; + ProjectRef = DDF52E9E1460BDA700A42B09 /* Core.xcodeproj */; + }, + { + ProductGroup = DDB151C0146EEB7C00FA7835 /* Products */; + ProjectRef = DDB151BF146EEB7C00FA7835 /* Framework.xcodeproj */; + }, + { + ProductGroup = DD1CD00714F40F580036E659 /* Products */; + ProjectRef = DD1CD00614F40F580036E659 /* MapKit.xcodeproj */; + }, + { + ProductGroup = DD334A3914A7B0C0000F960A /* Products */; + ProjectRef = DD334A3814A7B0C0000F960A /* Sparkle.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 8D1107260486CEB800E47090 /* ControlPlane */, DA5B01D61412B6A700E19C50 /* CPHelperInstallTool */, DA5B01FA1412BB1700E19C50 /* CPHelperTool */, - DA8064AA1479910E00267B5A /* Quincy */, + DDB151F8146F02BF00FA7835 /* Quincy */, ); }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + DD1CD01114F40F580036E659 /* DemoApp.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = DemoApp.app; + remoteRef = DD1CD01014F40F580036E659 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD1CD01314F40F580036E659 /* MapKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = MapKit.framework; + remoteRef = DD1CD01214F40F580036E659 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD1CD01514F40F580036E659 /* MapKit.ibplugin */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = MapKit.ibplugin; + remoteRef = DD1CD01414F40F580036E659 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD334A4714A7B0C1000F960A /* Sparkle.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Sparkle.framework; + remoteRef = DD334A4614A7B0C1000F960A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD334A4914A7B0C1000F960A /* Sparkle Test App.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = "Sparkle Test App.app"; + remoteRef = DD334A4814A7B0C1000F960A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD334A4B14A7B0C1000F960A /* Sparkle Unit Tests.octest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "Sparkle Unit Tests.octest"; + remoteRef = DD334A4A14A7B0C1000F960A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD334A4D14A7B0C1000F960A /* BinaryDelta */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = BinaryDelta; + remoteRef = DD334A4C14A7B0C1000F960A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DD334A4F14A7B0C1000F960A /* finish_installation.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = finish_installation.app; + remoteRef = DD334A4E14A7B0C1000F960A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DDB15178146EE4C000FA7835 /* Core.plugin */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = Core.plugin; + remoteRef = DDB15177146EE4C000FA7835 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DDB1517A146EE4C000FA7835 /* libJSONKit.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libJSONKit.a; + remoteRef = DDB15179146EE4C000FA7835 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DDB151C5146EEB7C00FA7835 /* NSLogger.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = NSLogger.framework; + remoteRef = DDB151C4146EEB7C00FA7835 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + DDB151C7146EEB7C00FA7835 /* Plugins.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Plugins.framework; + remoteRef = DDB151C6146EEB7C00FA7835 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 8D1107290486CEB800E47090 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -1098,7 +1170,6 @@ DA83A21F13D12A3200074503 /* cp-icon-active.icns in Resources */, 8D1A455B0BA00DE2004A6BC4 /* minus-8.png in Resources */, 8D1A455C0BA00DE2004A6BC4 /* plus-8.png in Resources */, - 8DB8917C0BB89BD8005347C2 /* oui.txt in Resources */, 8D232F800BD9D228006A3963 /* GeneralPrefs.png in Resources */, 8D232FB50BD9D507006A3963 /* ActionsPrefs.png in Resources */, 8D232FB60BD9D507006A3963 /* RulesPrefs.png in Resources */, @@ -1110,7 +1181,6 @@ 8D88FE2A0C534737007A14D6 /* pause.png in Resources */, 8DC410FB0C64665E00393759 /* AboutPanel.xib in Resources */, DA83A22313D13DF300074503 /* cp-icon.icns in Resources */, - DA83A22713D1430000074503 /* usb-vendors.txt in Resources */, DA4A629313E2546800CE976F /* ControlPlane Help in Resources */, DDE1B068140438DB006564A6 /* ControlPlane.sdef in Resources */, DD8274E6141147BB0098FA6E /* controlplane.icns in Resources */, @@ -1125,16 +1195,15 @@ DD3BAB8314163C6B000D5F88 /* CoreLocationRule.xib in Resources */, DDFF423114156B0A0047D311 /* location.png in Resources */, DDF4E595141588E80028DF4A /* CoreLocationMap.html in Resources */, - DA8064A3147990FD00267B5A /* BWQuincyMain.nib in Resources */, - 73A5092F14849405007D22B5 /* ShellScriptRule.xib in Resources */, + DD2A78C114855A640010AFE0 /* ShellScriptRule.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - DA8064A91479910E00267B5A /* Resources */ = { + DDB151F7146F02BF00FA7835 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA8064C11479913500267B5A /* BWQuincyMain.nib in Resources */, + DDB15211146F050C00FA7835 /* BWQuincyMain.nib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1188,82 +1257,26 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DAE893EE1454FFFB005FA13C /* ToggleFirewallAction.m in Sources */, - DAF36ECA143E7C5700350991 /* CoreLocationSource.m in Sources */, + DA5B01F31412BAEC00E19C50 /* BetterAuthorizationLib.c in Sources */, DAAF16B714131CDE00F5D915 /* CPHelperToolCommon.c in Sources */, - 8D11072D0486CEB800E47090 /* main.m in Sources */, + 8D11072D0486CEB800E47090 /* Main.m in Sources */, 8D82F0A30AA81411009ADA44 /* PrefsWindowController.m in Sources */, 8D90E51F0B71C4C9007D39FD /* CPController.m in Sources */, - 8D8C9CA60BBB74E70074D5B3 /* EvidenceSource.m in Sources */, - 8D8C9CE70BBB7BE00074D5B3 /* BluetoothEvidenceSource.m in Sources */, - 8D8C9E350BBB89320074D5B3 /* DB.m in Sources */, 8DF5A4180BC2353D00CBEB4B /* Action.m in Sources */, - 8DF5A4610BC239B100CBEB4B /* DefaultPrinterAction.m in Sources */, - 8DD790AD0BC28A9F00705346 /* OpenAction.m in Sources */, - 8DBAFAFC0BDC3B7B00BE0747 /* ShellScriptAction.m in Sources */, 8D9AE3A60BE0DA7E00D4D4E4 /* PopButton.m in Sources */, - 8D75A6200BE6F68B0069DF3F /* ToggleBluetoothAction.m in Sources */, - 8D649BA50BE8033A00716059 /* ToggleWiFiAction.m in Sources */, 8D01634F0C029913004AD8DB /* DNDArrayController.m in Sources */, - 8DC4E7FD0C178917007E7E41 /* MuteAction.m in Sources */, - 8DC4E8000C17891D007E7E41 /* MailSMTPServerAction.m in Sources */, 8D71CAEF0C17BA7900E56526 /* ToggleableAction.m in Sources */, - 8D71CB790C17C01700E56526 /* ScreenSaverPasswordAction.m in Sources */, - 8D3453C40C18E5C1006011D0 /* IChatAction.m in Sources */, - 8DCBE96C0C1A7ECE008260EF /* MountAction.m in Sources */, 8D8155D00C3A304E00228463 /* ContextsDataSource.m in Sources */, - 8D6762170C3B8D8D000B63EC /* NetworkLocationAction.m in Sources */, 8D447DF90C3E65D000DAB17A /* ContextSelectionButton.m in Sources */, - 8D27ECB00C4456A300AE1929 /* AudioOutputEvidenceSource.m in Sources */, - 8D68EBDF0C460BF800F25744 /* IPEvidenceSource.m in Sources */, - 8DE13F0E0C460E1700AEC949 /* FireWireEvidenceSource.m in Sources */, - 8D73CB8D0C46FD5200DF839E /* MonitorEvidenceSource.m in Sources */, - 8D73CBB30C46FEC800DF839E /* PowerEvidenceSource.m in Sources */, - 8D73CC140C470FE000DF839E /* RunningApplicationEvidenceSource.m in Sources */, - 8D73CC700C47125300DF839E /* WiFiEvidenceSource.m in Sources */, - 8D91F17D0C47148200D9FC0F /* USBEvidenceSource.m in Sources */, 8D38B66C0C49D50200290F47 /* SliderWithValue.m in Sources */, - 8DE4EE470C4B2A6F00A5B559 /* ScreenSaverTimeAction.m in Sources */, - 8DCB43580C4DBABD00E71D28 /* FirewallRuleAction.m in Sources */, - 8DE4C0110C4EE60700511590 /* GenericEvidenceSource.m in Sources */, - 8D643C680C4EF197006D8ECC /* GenericLoopingEvidenceSource.m in Sources */, - 8D643CDD0C4EF6FD006D8ECC /* LoopingEvidenceSource.m in Sources */, - 8D643DDD0C4F1F0D006D8ECC /* VPNAction.m in Sources */, - 8DE428FC0C5084D00073499A /* TimeOfDayEvidenceSource.m in Sources */, - 8DBB44980C530F7600064010 /* DSLogger.m in Sources */, - 8D2BAAAD0C56E26200A50777 /* NetworkLinkEvidenceSource.m in Sources */, 8D3BFF3F0C61BE4500B9B910 /* AboutPanel.m in Sources */, - 8DB1EF240C6C60A300586F84 /* MailIMAPServerAction.m in Sources */, - 8D1493F70C824B6D00D29FE8 /* BonjourEvidenceSource.m in Sources */, - 8DFA46170CC33E46003EAC16 /* QuitApplicationAction.m in Sources */, - 8D3C85150CDD8546009DBCD9 /* ScreenSaverStartAction.m in Sources */, - 8DA2F4150CE8630200F92D4D /* DesktopBackgroundAction.m in Sources */, - 8DFD0DA60CEBBC8A00E79049 /* UnmountAction.m in Sources */, - DA8B17351149AD0C00417D4F /* LightEvidenceSource.m in Sources */, - DA83A21D13D0FE8F00074503 /* CoreWLANEvidenceSource.m in Sources */, - DDAA9A181402FAAD00D4757E /* SleepEvidenceSource.m in Sources */, DA812E83140681D2006869F7 /* AppleScript.m in Sources */, - DD8274F0141154780098FA6E /* MailIntervalAction.m in Sources */, - DD8274F314115EE50098FA6E /* StartTimeMachineAction.m in Sources */, - DD8274F614116CC90098FA6E /* OpenURLAction.m in Sources */, - DD8274F91411748C0098FA6E /* LockKeychainAction.m in Sources */, - DD8274FE14117C590098FA6E /* SpeakAction.m in Sources */, - DD827507141188890098FA6E /* DisplayBrightnessAction.m in Sources */, - DDDF1C2B1411D49300DB0018 /* DefaultBrowserAction.m in Sources */, - DDDF1C2F1411E08000DB0018 /* ITunesPlaylistAction.m in Sources */, - DA5B01F31412BAEC00E19C50 /* BetterAuthorizationSampleLib.c in Sources */, - DAAF16B61413174400F5D915 /* ToggleTimeMachineAction.m in Sources */, DDAEFFFB1414714F00FDADE8 /* Action+HelperTool.m in Sources */, DDAE0017141474DC00FDADE8 /* CPController+SleepThread.m in Sources */, - DD5BD20B141614C4007BA88C /* JSONKit.m in Sources */, - DA922E9D144FC95200920B40 /* ToggleInternetSharingAction.m in Sources */, - 739492E2146B8018003C94DE /* DisplaySleepTimeAction.m in Sources */, - DA8064A4147990FD00267B5A /* BWQuincyManager.m in Sources */, - 732A58DF1484300A0011019C /* ShellScriptEvidenceSource.m in Sources */, - DD7D2539149C338300BE7C8B /* NSTimer+Invalidation.m in Sources */, - DA461C0C14C33E3C0019594A /* NSString+ShellScriptHelper.m in Sources */, - DA49AF6C14C3E0AB00D03D6A /* TogglePrinterSharingAction.m in Sources */, - DAC45F2014CDEC170007F5EF /* TimeMachineDestinationAction.m in Sources */, + DDD1A364142BD65600341B75 /* KVOAdditions.m in Sources */, + DDD1A367142CC81200341B75 /* Context.m in Sources */, + DDD1A370142CD55E00341B75 /* ContextGroup.m in Sources */, + DDD1A375142CD81900341B75 /* ContextsManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1271,7 +1284,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA5B01F61412BB0D00E19C50 /* BetterAuthorizationSampleLibInstallTool.c in Sources */, + DA5B01F61412BB0D00E19C50 /* BetterAuthorizationLibInstallTool.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1279,17 +1292,17 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA5B020D1412BDFC00E19C50 /* BetterAuthorizationSampleLib.c in Sources */, + DA5B020D1412BDFC00E19C50 /* BetterAuthorizationLib.c in Sources */, DA5B020A1412BBF200E19C50 /* CPHelperTool.c in Sources */, DA5B020C1412BDEF00E19C50 /* CPHelperToolCommon.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - DA8064A61479910E00267B5A /* Sources */ = { + DDB151F4146F02BF00FA7835 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA8064BF1479911B00267B5A /* BWQuincyManager.m in Sources */, + DDB15213146F050D00FA7835 /* BWQuincyManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1306,24 +1319,39 @@ target = DA5B01FA1412BB1700E19C50 /* CPHelperTool */; targetProxy = DA5B02061412BB3A00E19C50 /* PBXContainerItemProxy */; }; - DA8064C31479915100267B5A /* PBXTargetDependency */ = { + DD1CD01814F40FCC0036E659 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MapKitFramework; + targetProxy = DD1CD01714F40FCC0036E659 /* PBXContainerItemProxy */; + }; + DD334A5114A7B0E6000F960A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DA8064AA1479910E00267B5A /* Quincy */; - targetProxy = DA8064C21479915100267B5A /* PBXContainerItemProxy */; + name = Sparkle; + targetProxy = DD334A5014A7B0E6000F960A /* PBXContainerItemProxy */; + }; + DDB151BD146EEB4200FA7835 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Core; + targetProxy = DDB151BC146EEB4200FA7835 /* PBXContainerItemProxy */; + }; + DDB15219146F08D000FA7835 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DDB151F8146F02BF00FA7835 /* Quincy */; + targetProxy = DDB15218146F08D000FA7835 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 73A5092714849405007D22B5 /* ShellScriptRule.xib */ = { + DD2A78BF14855A640010AFE0 /* ShellScriptRule.xib */ = { isa = PBXVariantGroup; children = ( - 73A5092814849405007D22B5 /* da-DK */, - 73A5092914849405007D22B5 /* de */, - 73A5092A14849405007D22B5 /* en */, - 73A5092B14849405007D22B5 /* fr */, - 73A5092C14849405007D22B5 /* it */, - 73A5092D14849405007D22B5 /* pt-BR */, - 73A5092E14849405007D22B5 /* pt-PT */, + DD2A78C014855A640010AFE0 /* en */, + DD2A78C714855AF80010AFE0 /* de */, + DD2A78C914855B050010AFE0 /* da-DK */, + DD2A78CB14855B120010AFE0 /* fr */, + DD2A78CD14855B1C0010AFE0 /* it */, + DD2A78CF14855B240010AFE0 /* pt-BR */, + DD2A78DB14855B880010AFE0 /* pt-PT */, ); name = ShellScriptRule.xib; sourceTree = ""; @@ -1332,12 +1360,6 @@ isa = PBXVariantGroup; children = ( DD3BAB8414163C6B000D5F88 /* en */, - DA146F7B143F3C4000906DBF /* pt-BR */, - DA146F7C143F3C4000906DBF /* fr */, - DA146F7D143F3C4000906DBF /* it */, - DA146F7E143F3C4000906DBF /* da-DK */, - DA146F7F143F3C4000906DBF /* de */, - 732A58E91484311C0011019C /* pt-PT */, ); name = CoreLocationRule.xib; path = Resources; @@ -1352,7 +1374,7 @@ DD44B5A414142D4D0016BF6B /* pt-BR */, DD44B5A514142D4D0016BF6B /* it */, DD44B5A614142D4D0016BF6B /* de */, - 732A58EA1484311C0011019C /* pt-PT */, + DD2A78DF14855B9B0010AFE0 /* pt-PT */, ); name = CPHelperToolAuthorizationPrompts.strings; path = Resources; @@ -1367,7 +1389,7 @@ DDA2013F1411C11600DE570E /* de */, DDA201401411C12800DE570E /* da-DK */, DDA201411411C16700DE570E /* pt-BR */, - 732A58EE1484311D0011019C /* pt-PT */, + DD2A78D314855B4C0010AFE0 /* pt-PT */, ); name = Localizable.strings; path = Resources; @@ -1382,7 +1404,7 @@ DDA201491411C27000DE570E /* da-DK */, DDA2014A1411C27000DE570E /* de */, DDA2014B1411C27000DE570E /* pt-BR */, - 732A58EB1484311D0011019C /* pt-PT */, + DD2A78D514855B730010AFE0 /* pt-PT */, ); name = GenericRule.xib; path = Resources; @@ -1397,7 +1419,7 @@ DDA201531411C33600DE570E /* da-DK */, DDA201541411C33600DE570E /* it */, DDA201551411C33600DE570E /* pt-BR */, - 732A58EC1484311D0011019C /* pt-PT */, + DD2A78D714855B7A0010AFE0 /* pt-PT */, ); name = IPRule.xib; path = Resources; @@ -1412,7 +1434,7 @@ DDA2015D1411C35F00DE570E /* fr */, DDA2015E1411C35F00DE570E /* pt-BR */, DDA2015F1411C35F00DE570E /* da-DK */, - 732A58ED1484311D0011019C /* pt-PT */, + DD2A78D914855B800010AFE0 /* pt-PT */, ); name = LightRule.xib; path = Resources; @@ -1427,7 +1449,7 @@ DDA201671411C37900DE570E /* de */, DDA201681411C37900DE570E /* da-DK */, DDA201691411C37900DE570E /* pt-BR */, - 732A58EF1484311D0011019C /* pt-PT */, + DD2A78D114855B430010AFE0 /* pt-PT */, ); name = MainMenu.xib; path = Resources; @@ -1442,7 +1464,7 @@ DDA201711411C39400DE570E /* pt-BR */, DDA201721411C39400DE570E /* de */, DDA201731411C39400DE570E /* it */, - 732A58F01484311D0011019C /* pt-PT */, + DD2A78DD14855B8D0010AFE0 /* pt-PT */, ); name = TimeOfDayRule.xib; path = Resources; @@ -1453,10 +1475,10 @@ /* Begin XCBuildConfiguration section */ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB06261440FE1B000689E4 /* ControlPlane.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", "\"$(SRCROOT)/Frameworks\"", ); }; @@ -1464,192 +1486,70 @@ }; C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB06261440FE1B000689E4 /* ControlPlane.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", "\"$(SRCROOT)/Frameworks\"", ); - STRIP_INSTALLED_PRODUCT = YES; }; name = Release; }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB061C1440F7CF000689E4 /* Debug.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = ""; - COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/Frameworks\"", - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\"", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_SSE3_EXTENSIONS = YES; - GCC_ENABLE_SSE41_EXTENSIONS = YES; - GCC_ENABLE_SSE42_EXTENSIONS = YES; - GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = Source/ControlPlane_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - DEBUG, - DEBUG_MODE, - ); - GCC_STRICT_ALIASING = YES; - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.6; - ONLY_ACTIVE_ARCH = NO; - PRODUCT_NAME = ControlPlane; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - VALIDATE_PRODUCT = YES; }; name = Debug; }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB061D1440F7CF000689E4 /* Release.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = ""; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/Frameworks\"", - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\"", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = YES; - GCC_ENABLE_SSE3_EXTENSIONS = YES; - GCC_ENABLE_SSE41_EXTENSIONS = YES; - GCC_ENABLE_SSE42_EXTENSIONS = YES; - GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = Source/ControlPlane_Prefix.pch; - GCC_STRICT_ALIASING = YES; - GCC_SYMBOLS_PRIVATE_EXTERN = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.6; - ONLY_ACTIVE_ARCH = NO; - PRODUCT_NAME = ControlPlane; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - VALIDATE_PRODUCT = YES; - VALID_ARCHS = "i386 x86_64"; }; name = Release; }; DA5B01DF1412B6A700E19C50 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB06281440FE1B000689E4 /* CPHelperInstallTool.xcconfig */; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; DA5B01E01412B6A700E19C50 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB06281440FE1B000689E4 /* CPHelperInstallTool.xcconfig */; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; DA5B02031412BB1800E19C50 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB06291440FE1B000689E4 /* CPHelperTool.xcconfig */; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; DA5B02041412BB1800E19C50 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDFB06291440FE1B000689E4 /* CPHelperTool.xcconfig */; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - DA8064BD1479910E00267B5A /* Debug */ = { + DDB1520A146F02BF00FA7835 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDB15216146F078300FA7835 /* Quincy.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Source/Quincy/Quincy-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = "Source/Quincy/Quincy-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.6; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - WRAPPER_EXTENSION = framework; + INFOPLIST_FILE = "External Source/QuincyKit/demo/Mac/Info.plist"; }; name = Debug; }; - DA8064BE1479910E00267B5A /* Release */ = { + DDB1520B146F02BF00FA7835 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DDB15216146F078300FA7835 /* Quincy.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Source/Quincy/Quincy-Prefix.pch"; - INFOPLIST_FILE = "Source/Quincy/Quincy-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.6; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - WRAPPER_EXTENSION = framework; + INFOPLIST_FILE = "External Source/QuincyKit/demo/Mac/Info.plist"; }; name = Release; }; @@ -1692,11 +1592,11 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - DA8064BC1479910E00267B5A /* Build configuration list for PBXNativeTarget "Quincy" */ = { + DDB15209146F02BF00FA7835 /* Build configuration list for PBXNativeTarget "Quincy" */ = { isa = XCConfigurationList; buildConfigurations = ( - DA8064BD1479910E00267B5A /* Debug */, - DA8064BE1479910E00267B5A /* Release */, + DDB1520A146F02BF00FA7835 /* Debug */, + DDB1520B146F02BF00FA7835 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Source/JSONKit/CHANGELOG.md b/External Source/JSONKit/CHANGELOG.md similarity index 100% rename from Source/JSONKit/CHANGELOG.md rename to External Source/JSONKit/CHANGELOG.md diff --git a/Source/JSONKit/JSONKit.h b/External Source/JSONKit/JSONKit.h similarity index 100% rename from Source/JSONKit/JSONKit.h rename to External Source/JSONKit/JSONKit.h diff --git a/Source/JSONKit/JSONKit.m b/External Source/JSONKit/JSONKit.m similarity index 97% rename from Source/JSONKit/JSONKit.m rename to External Source/JSONKit/JSONKit.m index 3ee1dad8c..9f27f47f4 100644 --- a/Source/JSONKit/JSONKit.m +++ b/External Source/JSONKit/JSONKit.m @@ -692,14 +692,14 @@ + (id)allocWithZone:(NSZone *)zone static void _JKArrayInsertObjectAtIndex(JKArray *array, id newObject, NSUInteger objectIndex) { NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count <= array->capacity) && (objectIndex <= array->count) && (newObject != NULL)); if(!((array != NULL) && (array->objects != NULL) && (objectIndex <= array->count) && (newObject != NULL))) { [newObject autorelease]; return; } - array->count++; - if(array->count >= array->capacity) { - array->capacity += 16UL; + if((array->count + 1UL) >= array->capacity) { id *newObjects = NULL; - if((newObjects = (id *)realloc(array->objects, sizeof(id) * array->capacity)) == NULL) { [NSException raise:NSMallocException format:@"Unable to resize objects array."]; } + if((newObjects = (id *)realloc(array->objects, sizeof(id) * (array->capacity + 16UL))) == NULL) { [NSException raise:NSMallocException format:@"Unable to resize objects array."]; } array->objects = newObjects; + array->capacity += 16UL; memset(&array->objects[array->count], 0, sizeof(id) * (array->capacity - array->count)); } + array->count++; if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex + 1UL], &array->objects[objectIndex], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[objectIndex] = NULL; } array->objects[objectIndex] = newObject; } @@ -714,11 +714,11 @@ static void _JKArrayReplaceObjectAtIndexWithObject(JKArray *array, NSUInteger ob } static void _JKArrayRemoveObjectAtIndex(JKArray *array, NSUInteger objectIndex) { - NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL)); - if(!((array != NULL) && (array->objects != NULL) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL))) { return; } + NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count > 0UL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL)); + if(!((array != NULL) && (array->objects != NULL) && (array->count > 0UL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL))) { return; } CFRelease(array->objects[objectIndex]); array->objects[objectIndex] = NULL; - if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex], &array->objects[objectIndex + 1UL], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[array->count] = NULL; } + if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex], &array->objects[objectIndex + 1UL], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[array->count - 1UL] = NULL; } array->count--; } @@ -805,13 +805,13 @@ - (void)replaceObjectAtIndex:(NSUInteger)objectIndex withObject:(id)anObject - (id)copyWithZone:(NSZone *)zone { NSParameterAssert((objects != NULL) && (count <= capacity)); - return((mutations == 0UL) ? [self retain] : [[NSArray allocWithZone:zone] initWithObjects:objects count:count]); + return((mutations == 0UL) ? [self retain] : [(NSArray *)[NSArray allocWithZone:zone] initWithObjects:objects count:count]); } - (id)mutableCopyWithZone:(NSZone *)zone { NSParameterAssert((objects != NULL) && (count <= capacity)); - return([[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]); + return([(NSMutableArray *)[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]); } @end @@ -848,7 +848,7 @@ - (void)dealloc - (NSArray *)allObjects { NSParameterAssert(collection != NULL); - NSUInteger count = [collection count], atObject = 0UL; + NSUInteger count = [(NSDictionary *)collection count], atObject = 0UL; id objects[count]; while((objects[atObject] = [self nextObject]) != NULL) { NSParameterAssert(atObject < count); atObject++; } @@ -2004,7 +2004,7 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { for(x = 0UL; x < JK_CACHE_PROBES; x++) { if(JK_EXPECT_F(parseState->cache.items[bucket].object == NULL)) { setBucket = 1UL; useableBucket = bucket; break; } - if((JK_EXPECT_T(parseState->cache.items[bucket].hash == parseState->token.value.hash)) && (JK_EXPECT_T(parseState->cache.items[bucket].size == parseState->token.value.ptrRange.length)) && (JK_EXPECT_T(parseState->cache.items[bucket].type == parseState->token.value.type)) && (JK_EXPECT_T(parseState->cache.items[bucket].bytes != NULL)) && (JK_EXPECT_T(strncmp((const char *)parseState->cache.items[bucket].bytes, (const char *)parseState->token.value.ptrRange.ptr, parseState->token.value.ptrRange.length) == 0U))) { + if((JK_EXPECT_T(parseState->cache.items[bucket].hash == parseState->token.value.hash)) && (JK_EXPECT_T(parseState->cache.items[bucket].size == parseState->token.value.ptrRange.length)) && (JK_EXPECT_T(parseState->cache.items[bucket].type == parseState->token.value.type)) && (JK_EXPECT_T(parseState->cache.items[bucket].bytes != NULL)) && (JK_EXPECT_T(memcmp(parseState->cache.items[bucket].bytes, parseState->token.value.ptrRange.ptr, parseState->token.value.ptrRange.length) == 0U))) { parseState->cache.age[bucket] = (parseState->cache.age[bucket] << 1) | 1U; parseState->token.value.cacheItem = &parseState->cache.items[bucket]; NSCParameterAssert(parseState->cache.items[bucket].object != NULL); @@ -2556,20 +2556,57 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object // When we encounter a class that we do not handle, and we have either a delegate or block that the user supplied to format unsupported classes, // we "re-run" the object check. However, we re-run the object check exactly ONCE. If the user supplies an object that isn't one of the - // supported classes, we fail the second type (i.e., double fault error). + // supported classes, we fail the second time (i.e., double fault error). BOOL rerunningAfterClassFormatter = NO; -rerunAfterClassFormatter: + rerunAfterClassFormatter:; + + // XXX XXX XXX XXX + // + // We need to work around a bug in 10.7, which breaks ABI compatibility with Objective-C going back not just to 10.0, but OpenStep and even NextStep. + // + // It has long been documented that "the very first thing that a pointer to an Objective-C object "points to" is a pointer to that objects class". + // + // This is euphemistically called "tagged pointers". There are a number of highly technical problems with this, most involving long passages from + // the C standard(s). In short, one can make a strong case, couched from the perspective of the C standard(s), that that 10.7 "tagged pointers" are + // fundamentally Wrong and Broken, and should have never been implemented. Assuming those points are glossed over, because the change is very clearly + // breaking ABI compatibility, this should have resulted in a minimum of a "minimum version required" bump in various shared libraries to prevent + // causes code that used to work just fine to suddenly break without warning. + // + // In fact, the C standard says that the hack below is "undefined behavior"- there is no requirement that the 10.7 tagged pointer hack of setting the + // "lower, unused bits" must be preserved when casting the result to an integer type, but this "works" because for most architectures + // `sizeof(long) == sizeof(void *)` and the compiler uses the same representation for both. (note: this is informal, not meant to be + // normative or pedantically correct). + // + // In other words, while this "works" for now, technically the compiler is not obligated to do "what we want", and a later version of the compiler + // is not required in any way to produce the same results or behavior that earlier versions of the compiler did for the statement below. + // + // Fan-fucking-tastic. + // + // Why not just use `object_getClass()`? Because `object->isa` reduces to (typically) a *single* instruction. Calling `object_getClass()` requires + // that the compiler potentially spill registers, establish a function call frame / environment, and finally execute a "jump subroutine" instruction. + // Then, the called subroutine must spend half a dozen instructions in its prolog, however many instructions doing whatever it does, then half a dozen + // instructions in its prolog. One instruction compared to dozens, maybe a hundred instructions. + // + // Yes, that's one to two orders of magnitude difference. Which is compelling in its own right. When going for performance, you're often happy with + // gains in the two to three percent range. + // + // XXX XXX XXX XXX + + BOOL workAroundMacOSXABIBreakingBug = NO; + if(JK_EXPECT_F(((NSUInteger)object) & 0x1)) { workAroundMacOSXABIBreakingBug = YES; goto slowClassLookup; } + if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.stringClass)) { isClass = JKClassString; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.numberClass)) { isClass = JKClassNumber; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.dictionaryClass)) { isClass = JKClassDictionary; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.arrayClass)) { isClass = JKClassArray; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.nullClass)) { isClass = JKClassNull; } else { - if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { encodeState->fastClassLookup.stringClass = object->isa; isClass = JKClassString; } - else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { encodeState->fastClassLookup.numberClass = object->isa; isClass = JKClassNumber; } - else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { encodeState->fastClassLookup.dictionaryClass = object->isa; isClass = JKClassDictionary; } - else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { encodeState->fastClassLookup.arrayClass = object->isa; isClass = JKClassArray; } - else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { encodeState->fastClassLookup.nullClass = object->isa; isClass = JKClassNull; } + slowClassLookup: + if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.stringClass = object->isa; } isClass = JKClassString; } + else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.numberClass = object->isa; } isClass = JKClassNumber; } + else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.dictionaryClass = object->isa; } isClass = JKClassDictionary; } + else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.arrayClass = object->isa; } isClass = JKClassArray; } + else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.nullClass = object->isa; } isClass = JKClassNull; } else { if((rerunningAfterClassFormatter == NO) && ( #ifdef __BLOCKS__ diff --git a/Source/JSONKit/README.md b/External Source/JSONKit/README.md similarity index 98% rename from Source/JSONKit/README.md rename to External Source/JSONKit/README.md index 56c5e2a62..8b4a4d94f 100644 --- a/Source/JSONKit/README.md +++ b/External Source/JSONKit/README.md @@ -5,6 +5,8 @@ Copyright © 2011, John Engelhart. ### A Very High Performance Objective-C JSON Library +**UPDATE:** (2011/12/18) The benchmarks below were performed before Apples [`NSJSONSerialization`][NSJSONSerialization] was available (as of Mac OS X 10.7 and iOS 5). The obvious question is: Which is faster, [`NSJSONSerialization`][NSJSONSerialization] or JSONKit? According to [this site](http://www.bonto.ch/blog/2011/12/08/json-libraries-for-ios-comparison-updated/), JSONKit is faster than [`NSJSONSerialization`][NSJSONSerialization]. Some quick "back of the envelope" calculations using the numbers reported, JSONKit appears to be approximately 25% to 40% faster than [`NSJSONSerialization`][NSJSONSerialization], which is pretty significant. + Parsing | Serializing :---------:|:-------------: Deserialize from JSON | Serialize to JSON @@ -305,3 +307,4 @@ Example | Result | Argument [strtoull]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/strtoull.3.html [getrusage]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/getrusage.2.html [printf]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/printf.3.html +[NSJSONSerialization]: http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html diff --git a/External Source/KVOAdditions/KVOAdditions.h b/External Source/KVOAdditions/KVOAdditions.h new file mode 100644 index 000000000..ac1b1f671 --- /dev/null +++ b/External Source/KVOAdditions/KVOAdditions.h @@ -0,0 +1,108 @@ +/* + * KVOAdditions.h + * "THE BEER-WARE LICENSE" (Revision 42): + * (Devin Lane) wrote this file. + * As long as you retain this notice you can do whatever you want with this + * stuff. If we meet some day, and you think this stuff is worth it, you can + * buy me a beer in return. + * + * Version 1.2.1: + * - Now runs on iPhone OS 2.0 + * + * Version 1.2: + * - Added automatic -KVODealloc invocation + * - The selector is now considered in the uniqueness of an observation + * - New removeObserver:forKeyPath:selector: method + * + * Version 1.1: Two critical bug fixes. + * - Multiple observers for the same key path are now handled correctly. + * - Subclasses that override removeObserver:forKeyPath: are no longer + * swizzled incorrectly. + * Version 1.0: Initial release + */ + +#import + +@interface NSObject (KVOAdditions) + +/* Register `observer' for changes of the value at `keyPath` relative to the + * receiver. `selector' is invoked on `observer' when the value is modified + * according to the specified options. A single observer can observe a single + * keyPath with multiple selectors. This allows a class and a subclass to + * observe the same key path on an object. Due to this, it is recommended + * that externally available classes that use this observation mechanism + * use __ as a prefix to their observation selectors to avoid naming + * conflicts. + * + * `selector' should have one of the following signatures: + * + * 1. - (void)valueDidChange; + * Receive nothing about the observed change. + * + * 2. - (void)valueDidChange:(NSDictionary *)change; + * Receive the raw change dictionary. + * + * In addition, if NSKeyValueObservingOptionOld or NSKeyValueObservingOptionNew + * is included in options, the following can be used: + * + * 3. - (void)valueDidChange:(id)oldValue newValue:(id)newValue + * Receive the old and new values, both of which can be nil. + * + * 4. - (void)valueDidChange:(id)oldValue newValue:(id)newValue isPrior:(BOOL)prior + * Receive the old and new values, both of which can be nil. `prior' is true + * if this is a prior notification (if NSKeyValueChangeNotificationIsPriorKey is + * included in the change dictionary.) + */ + +- (void)addObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + selector:(SEL)selector; + +/* Deregister `observer' of the value at `keyPath', relative to the receiver, + * for which notifications are sent to `selector'. Pass NULL for `selector' + * to remove notifications for all registered selectors. */ + +- (void)removeObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector; + +/* Return YES if observations on the receiver by the receiver + * should be automatically removed when the receiver is deallocated + * or finalized. Defaults to YES. */ + ++ (BOOL)automaticallyRemoveSelfObservations; + +/* Sent right before an object will deallocate. When received, the receiver + * should deregister itself as an observer for any properties it is observing + * on itself. This message is not sent under GC. */ + +- (void)KVODealloc; + +@end + +@interface NSArray (KVOAdditions) + +/* Adds observer `observer' for keyPath `keyPath' with options `options' to + * the objects at indices `indexes' in the receiving array. This is the + * equivalent of adding the observer using the method above for each of the + * objects in `indexes'. Using this method, unlike + * addObserver:toObjectsAtIndexes:forKeyPath:options:context: is not faster + * than individually observing the desired objects. */ + +- (void)addObserver:(NSObject *)observer + toObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + selector:(SEL)selector; + +/* Deregister `observer' of the value at `keyPath', relative to the objects + * in the receiver at `indexes', for which notifications are sent to + * `selector'. Pass NULL for `selector' to remove notifications for all + * registered selectors. */ + +- (void)removeObserver:(NSObject *)observer + fromObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath + selector:(SEL)selector; +@end diff --git a/External Source/KVOAdditions/KVOAdditions.m b/External Source/KVOAdditions/KVOAdditions.m new file mode 100644 index 000000000..9f797941c --- /dev/null +++ b/External Source/KVOAdditions/KVOAdditions.m @@ -0,0 +1,572 @@ +/* + * KVOAdditions.m + * "THE BEER-WARE LICENSE" (Revision 42): + * (Devin Lane) wrote this file. + * As long as you retain this notice you can do whatever you want with this + * stuff. If we meet some day, and you think this stuff is worth it, you can + * buy me a beer in return. + * + * Version 1.2.2: + * - Fixed crash due to missing __KVOAdditions__dealloc__original__ + * method on NSObject. + * + * Version 1.2.1: + * - Now runs on iPhone OS 2.0 + * + * Version 1.2: + * - Added automatic -KVODealloc invocation + * - The selector is now considered in the uniqueness of an observation + * - New removeObserver:forKeyPath:selector: method + * + * Version 1.1: Two critical bug fixes. + * - Multiple observers for the same key path are now handled correctly. + * - Subclasses that override removeObserver:forKeyPath: are no longer + * swizzled incorrectly. + * Version 1.0: Initial release + */ + +#import "KVOAdditions.h" +#import +#import +#import +#import + +/* Because NSMapTable not available on iPhone OS 2.0, and we want to use it + * on Mac OS X to take advantage of zeroed weak memory under GC, we make a + * set of map table functions that use NSMapTable on Mac OS X, and CFDictionary + * on iPhone OS. */ + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_2_0 + +#define MapTableWithWeakToStrong() \ + (CFMutableDictionaryRef)[(id)CFDictionaryCreateMutable(kCFAllocatorDefault, \ + 0, NULL, &kCFTypeDictionaryValueCallBacks) autorelease] + +#define MapTableWithStrongCopyInToStrong() \ + (CFMutableDictionaryRef)[(id)CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) autorelease] + +#define MapTableWithOpaqueToStrong() MapTableWithWeakToStrong() + +#define MapTableGet(table, key) \ + (void *)CFDictionaryGetValue(table, key) + +#define MapTableInsert(table, key, value) \ + CFDictionarySetValue(table, (const void *)key, (const void *)value) + +#define MapTableRemove(table, key) \ + CFDictionaryRemoveValue(table, (const void *)key) + +#define MapTableGetCount(table) \ + CFDictionaryGetCount(table) + +#define EnumerateMapTable(table) \ + NSUInteger table##count__ = CFDictionaryGetCount(table); \ + const void **table##keys__ = calloc(1, sizeof(void *) * table##count__); \ + const void **table##values__ = calloc(1, sizeof(void *) * table##count__); \ + CFDictionaryGetKeysAndValues(table, table##keys__, table##values__); \ + NSUInteger table##i__ = 0 \ + +#define NextMapEnumeratorPair(table, keyPtr, valuePtr) \ + ((table##i__ < table##count__) && ((*(keyPtr) = ((void **)table##keys__)[table##i__], \ + *(valuePtr) = ((void **)table##values__)[table##i__]), ++table##i__)) + +#define EndMapTableEnumeration(table) \ + free((void *)table##keys__); \ + free((void *)table##values__) + +#define MapTable CFMutableDictionaryRef + +#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) + +#define MapTableWithWeakToStrong() \ + [[[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsObjectPersonality | NSPointerFunctionsZeroingWeakMemory \ + valueOptions:NSPointerFunctionsObjectPersonality | NSPointerFunctionsStrongMemory \ + capacity:0] autorelease] + +#define MapTableWithStrongCopyInToStrong() \ + [[[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsObjectPersonality | NSPointerFunctionsStrongMemory | NSPointerFunctionsCopyIn \ + valueOptions:NSPointerFunctionsObjectPersonality | NSPointerFunctionsStrongMemory \ + capacity:0] autorelease] + +#define MapTableWithOpaqueToStrong() \ + [[[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsOpaquePersonality | NSPointerFunctionsOpaqueMemory \ + valueOptions:NSPointerFunctionsObjectPersonality | NSPointerFunctionsStrongMemory \ + capacity:0] autorelease] + +#define MapTableGet(table, key) \ + [table objectForKey:(id)key] + +#define MapTableInsert(table, key, value) \ + [table setObject:(id)value forKey:(id)key] + +#define MapTableRemove(table, key) \ + [table removeObjectForKey:(id)key] + +#define MapTableGetCount(table) \ + [table count] + +#define EnumerateMapTable(table) \ + NSMapEnumerator table##enu__ = NSEnumerateMapTable(table) \ + +#define NextMapEnumeratorPair(table, keyPtr, valuePtr) \ + NSNextMapEnumeratorPair(&table##enu__, (void **)(keyPtr), (void **)(valuePtr)) + +#define EndMapTableEnumeration(table) \ + NSEndMapTableEnumeration(&table##enu__) + +#define MapTable NSMapTable* + +#else +#error Platform should be either Mac OS X or iPhone OS +#endif + +static __strong MapTable receiverToKeyPathToObserverToSelectorToSurrogate = nil; +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* The surrogate object is used as the actual observer. When it receives + * -[NSObject observeValueForKeyPath:ofObject:change:context:], it fires `selector' + * on `target'. */ + +@interface Surrogate : NSObject { + __weak id target; + __weak SEL selector; + NSKeyValueObservingOptions options; +} + +@property(assign) SEL selector; + +- (id)initWithTarget:(id)aTarget + selector:(SEL)aSelector + options:(NSKeyValueObservingOptions)theOptions; + +@end + +@implementation Surrogate +- (id)initWithTarget:(id)aTarget + selector:(SEL)aSelector + options:(NSKeyValueObservingOptions)theOptions +{ + if ((self = [super init])) { + /* None of these are retained */ + target = aTarget; + selector = aSelector; + options = theOptions; + } + + return self; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + if (!target || !selector) return; + + NSMethodSignature *sig = [target methodSignatureForSelector:selector]; + if (!sig) return; + + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + if (!invocation) return; + + /* Receiving methods can have the following signatures: + * - (void)valueDidChange; + * - (void)valueDidChange:(NSDictionary *)change; + * + * In addition, if NSKeyValueObservingOptionOld or NSKeyValueObservingOptionNew + * is included in options, the following can be used: + * + * - (void)valueDidChange:(id)oldValue newValue:(id)newValue + * - (void)valueDidChange:(id)oldValue newValue:(id)newValue isPrior:(BOOL)prior + */ + + id old, new; + BOOL prior; + if ([sig numberOfArguments] == 3) { + [invocation setArgument:&change atIndex:2]; + } else if ((options & NSKeyValueObservingOptionOld) || + (options & NSKeyValueObservingOptionNew)) { + if ([sig numberOfArguments] >= 4) { + old = [change objectForKey:NSKeyValueChangeOldKey]; + new = [change objectForKey:NSKeyValueChangeNewKey]; + [invocation setArgument:&old atIndex:2]; + [invocation setArgument:&new atIndex:3]; + } + if ([sig numberOfArguments] >= 5) { + prior = [[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue]; + [invocation setArgument:&prior atIndex:4]; + } + } + + [invocation setSelector:selector]; + [invocation invokeWithTarget:target]; +} + +@synthesize selector; +@end + + + +@interface NSObject (KVOAdditionsPrivate) +- (void)__KVOAdditions__dealloc__; +- (void)__KVOAdditions__dealloc__original__; ++ (CFMutableSetRef)__deallocClasses; +@end + +static void initialize(void) +{ + receiverToKeyPathToObserverToSelectorToSurrogate = MapTableWithWeakToStrong(); + [(id)receiverToKeyPathToObserverToSelectorToSurrogate retain]; +} + +/* Adds `observer' to `receiver' for `keyPath', with options `options'. When a property change + * occurs, `selector' is fired. The observer is recorded such that it can be found by + * receiver.keyPath.observer.selector. This is required to allow a class to observe a property on a single + * object and receive notification messages on different selectors, such as to support superclass observation. */ + +static void AddObserver(NSObject *receiver, NSObject *surrogate, + NSObject *observer, SEL selector, NSString *keyPath, NSKeyValueObservingOptions options) +{ + pthread_once(&once, &initialize); + pthread_mutex_lock(&mutex); + + MapTable keyPathToObserverToSelectorToSurrogate = + MapTableGet(receiverToKeyPathToObserverToSelectorToSurrogate, receiver); + if (!keyPathToObserverToSelectorToSurrogate) { + keyPathToObserverToSelectorToSurrogate = MapTableWithStrongCopyInToStrong(); + MapTableInsert(receiverToKeyPathToObserverToSelectorToSurrogate, receiver, keyPathToObserverToSelectorToSurrogate); + } + + MapTable observerToSelectorToSurrogate = MapTableGet(keyPathToObserverToSelectorToSurrogate, keyPath); + if (!observerToSelectorToSurrogate) { + /* The observer is not retained */ + observerToSelectorToSurrogate = MapTableWithWeakToStrong(); + MapTableInsert(keyPathToObserverToSelectorToSurrogate, keyPath, observerToSelectorToSurrogate); + } + + MapTable selectorToSurrogate = MapTableGet(observerToSelectorToSurrogate, observer); + if (!selectorToSurrogate) { + selectorToSurrogate = MapTableWithOpaqueToStrong(); + MapTableInsert(observerToSelectorToSurrogate, observer, selectorToSurrogate); + } + + Surrogate *existingSurrogate = MapTableGet(selectorToSurrogate, selector); + if (existingSurrogate) { + /* Just call the new selector when the observation is triggered */ + existingSurrogate.selector = selector; + } else { + MapTableInsert(selectorToSurrogate, selector, surrogate); + [receiver addObserver:surrogate forKeyPath:keyPath options:options context:NULL]; + } + + pthread_mutex_unlock(&mutex); +} + +static BOOL RemoveSelfObservations(NSObject *object) +{ + pthread_once(&once, &initialize); + pthread_mutex_lock(&mutex); + + BOOL removed = NO; + + do { + MapTable keyPathToObserverToSelectorToSurrogate = + MapTableGet(receiverToKeyPathToObserverToSelectorToSurrogate, object); + if (!keyPathToObserverToSelectorToSurrogate) break; + + NSMutableArray *expiredMapTableKeys = [NSMutableArray array]; + + EnumerateMapTable(keyPathToObserverToSelectorToSurrogate); + MapTable observerToSelectorToSurrogate; + NSString *keyPath; + while (NextMapEnumeratorPair(keyPathToObserverToSelectorToSurrogate, + &keyPath, &observerToSelectorToSurrogate)) { + MapTable selectorToSurrogate = MapTableGet(observerToSelectorToSurrogate, object); + if (!selectorToSurrogate) continue; + + /* Remove every observed selector */ + EnumerateMapTable(selectorToSurrogate); + SEL aSelector; + Surrogate *aSurrogate; + while (NextMapEnumeratorPair(selectorToSurrogate, &aSelector, &aSurrogate)) { + [object removeObserver:aSurrogate forKeyPath:keyPath]; + } + EndMapTableEnumeration(selectorToSurrogate); + + /* Remove all selectors */ + MapTableRemove(observerToSelectorToSurrogate, object); + + /* We can't remove these while enumerating, so we mark + * them and remove them later */ + if (!MapTableGetCount(observerToSelectorToSurrogate)) { + [expiredMapTableKeys addObject:keyPath]; + } + } + EndMapTableEnumeration(keyPathToObserverToSelectorToSurrogate); + + for (keyPath in expiredMapTableKeys) { + MapTableRemove(keyPathToObserverToSelectorToSurrogate, keyPath); + } + + if (!MapTableGetCount(keyPathToObserverToSelectorToSurrogate)) { + MapTableRemove(receiverToKeyPathToObserverToSelectorToSurrogate, object); + } + + removed = YES; + } while (0); + + pthread_mutex_unlock(&mutex); + + return removed; +} + +/* Removes `observer' observing `keyPath' on `receiver', notified by selector `selector'. + * The surrogate observer object is removed and released. Returns YES if an + * observer was removed. A `selector' value of NULL will remove all selectors on `observer.' */ + +static BOOL RemoveObserver(NSObject *receiver, NSString *keyPath, + NSObject *observer, SEL selector) +{ + if (receiver == nil || observer == nil || keyPath == nil) return NO; + + pthread_once(&once, &initialize); + pthread_mutex_lock(&mutex); + + BOOL removed = NO; + + do { + MapTable keyPathToObserverToSelectorToSurrogate = + MapTableGet(receiverToKeyPathToObserverToSelectorToSurrogate, receiver); + if (!keyPathToObserverToSelectorToSurrogate) break; + + MapTable observerToSelectorToSurrogate = + MapTableGet(keyPathToObserverToSelectorToSurrogate, keyPath); + if (!observerToSelectorToSurrogate) break; + + MapTable selectorToSurrogate = + MapTableGet(observerToSelectorToSurrogate, observer); + if (!selectorToSurrogate) break; + + if (!selector) { + if (!MapTableGetCount(selectorToSurrogate)) break; + + /* Remove every observed selector */ + EnumerateMapTable(selectorToSurrogate); + SEL aSelector; + Surrogate *aSurrogate; + while (NextMapEnumeratorPair(selectorToSurrogate, &aSelector, &aSurrogate)) { + [receiver removeObserver:aSurrogate forKeyPath:keyPath]; + } + EndMapTableEnumeration(selectorToSurrogate); + + /* Remove all selectors */ + MapTableRemove(observerToSelectorToSurrogate, observer); + } else { + Surrogate *aSurrogate = MapTableGet(selectorToSurrogate, selector); + if (!aSurrogate) break; + + /* We were observing this key path, remove the observer */ + [receiver removeObserver:aSurrogate forKeyPath:keyPath]; + MapTableRemove(selectorToSurrogate, selector); + } + + /* Clean up unused state */ + if (!MapTableGetCount(selectorToSurrogate)) { + MapTableRemove(observerToSelectorToSurrogate, observer); + } + + if (!MapTableGetCount(observerToSelectorToSurrogate)) { + MapTableRemove(keyPathToObserverToSelectorToSurrogate, keyPath); + } + + if (!MapTableGetCount(keyPathToObserverToSelectorToSurrogate)) { + MapTableRemove(receiverToKeyPathToObserverToSelectorToSurrogate, receiver); + } + + removed = YES; + } while (0); + + pthread_mutex_unlock(&mutex); + + return removed; +} + +@implementation NSObject (KVOAdditions) + +/* For every implementation of `selector' in the superclass tree starting at `klass', replace + * its implementation with `replacement'. The method identified by `selector' is + * duplicated to `newSelector'. Return YES if the implementations on `klass' are + * already switched. */ ++ (void)_replaceSelector:(SEL)selector + withMethod:(Method)replacement + duplicatingTo:(SEL)newSelector + forAncestorsOfClass:(Class)klass + swizzledClasses:(CFMutableSetRef)swizzledClasses +{ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&lock); + + if (CFSetContainsValue(swizzledClasses, klass)) return; + + Method m = class_getInstanceMethod(klass, selector); + + /* If the subclass doesn't implement the method, + * the superclass certainly doesn't */ + if (!m) return; + + Method superMethod = NULL; + if (class_getSuperclass(klass)) { + superMethod = class_getInstanceMethod(class_getSuperclass(klass), selector); + } + + /* If klass's implementation is different than its superclass's + * implementation, we need to swizzle it. */ + if (superMethod && (method_getImplementation(m) != method_getImplementation(superMethod))) { + if (newSelector) { + /* Duplicate original method to new selector */ + class_addMethod(klass, newSelector, method_getImplementation(m), method_getTypeEncoding(m)); + } + + /* And replace old method implementation */ + method_setImplementation(m, method_getImplementation(replacement)); + } + + /* Make sure we don't swizzle for this class again */ + CFSetAddValue(swizzledClasses, klass); + + pthread_mutex_unlock(&lock); +} + ++ (CFMutableSetRef)__deallocClasses +{ + static CFMutableSetRef deallocClasses = nil; + if (deallocClasses == NULL) { + deallocClasses = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL); + } + + return deallocClasses; +} + ++ (void)_insertDealloc +{ + CFMutableSetRef deallocClasses = [self __deallocClasses]; + if (!CFSetContainsValue(deallocClasses, self)) { + Method dealloc = class_getInstanceMethod([NSObject class], @selector(__KVOAdditions__dealloc__)); + [self _replaceSelector:@selector(dealloc) + withMethod:dealloc + duplicatingTo:@selector(__KVOAdditions__dealloc__original__) + forAncestorsOfClass:self + swizzledClasses:deallocClasses]; + } +} + +- (void)addObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + selector:(SEL)selector +{ + Surrogate *sur = nil; + + @try { + /* Make a new surrogate for this keyPath and receiver. This object will receive + * the observation message */ + sur = [[Surrogate alloc] initWithTarget:observer selector:selector options:options]; + AddObserver(self, sur, observer, selector, keyPath, options); + + /* Replace the dealloc method so that we can auto-remove + * self observers and notify an object before it will be deallocated. + * No need to override -finalize, as zeroing weak references eliminate + * the need to remove observers! */ + [object_getClass(observer) _insertDealloc]; + } @finally { + [sur release]; + } +} + +/* This empty implemention is required because we remain + * swizzled even after an observer has removed itself + * from all observed objects. In this case, the + * __KVOAdditions__dealloc__original__ method that was added + * to the KVO swizzled class is no longer present. This method + * will get called instead in this case. */ + +- (void)__KVOAdditions__dealloc__original__ +{ +} + +- (void)__KVOAdditions__dealloc__ +{ + /* Let the class remove it's observers before it is destroyed */ + if ([[self class] automaticallyRemoveSelfObservations]) { + RemoveSelfObservations(self); + } + + [self KVODealloc]; + + /* Call through to KVODeallocate */ + [self __KVOAdditions__dealloc__original__]; +} + +- (void)KVODealloc +{ +} + +- (void)removeObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector +{ + RemoveObserver(self, keyPath, observer, selector); +} + ++ (BOOL)automaticallyRemoveSelfObservations +{ + return YES; +} + +@end + +@implementation NSArray (KVOAdditions) + +- (void)addObserver:(NSObject *)observer + toObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + selector:(SEL)selector +{ + Surrogate *sur = nil; + + @try { + for (NSObject *receiver in [self objectsAtIndexes:indexes]) { + /* Make a new surrogate for this keyPath and receiver. This object + * will receive the observation message */ + sur = [[Surrogate alloc] initWithTarget:observer + selector:selector + options:options]; + AddObserver(receiver, sur, observer, selector, keyPath, options); + [sur release]; + sur = nil; + } + + /* Replace the dealloc method so that we can auto-remove + * self observers and notify an object before it will be deallocated. + * No need to override -finalize, as zeroing weak references eliminate + * the need to remove observers! */ + [object_getClass(observer) _insertDealloc]; + } @finally { + [sur release]; + } +} + +- (void)removeObserver:(NSObject *)observer + fromObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath + selector:(SEL)selector +{ + for (NSObject *receiver in [self objectsAtIndexes:indexes]) { + RemoveObserver(receiver, keyPath, observer, selector); + } +} + +@end diff --git a/External Source/KVOAdditions/observer.m b/External Source/KVOAdditions/observer.m new file mode 100644 index 000000000..43c34badc --- /dev/null +++ b/External Source/KVOAdditions/observer.m @@ -0,0 +1,212 @@ +#import +#import "KVOAdditions.h" + +@interface Person : NSObject { + NSString *name; + NSString *phone; + NSString *address; + NSString *city; +} + +@property(retain) NSString *name; +@property(retain) NSString *phone; +@property(retain) NSString *address; +@property(retain) NSString *city; + +@end + +@implementation Person +@synthesize name, phone, address, city; +@end + +@interface Programmer : Person { + NSUInteger loc; +} + +@property NSUInteger loc; +@end + +@implementation Programmer +@synthesize loc; +@end + +@interface A : NSObject { + Person *person; +} + +- (id)initWithPerson:(Person *)person; + +@property(retain) Person *person; +@end + +@implementation A + +- (id)initWithPerson:(Person *)aPerson +{ + if ((self = [super init])) { + self.person = aPerson; + [self.person addObserver:self forKeyPath:@"name" options:0 selector:@selector(_a_nameChanged)]; + [self.person addObserver:self forKeyPath:@"phone" options:NSKeyValueObservingOptionNew selector:@selector(_a_phoneChanged:)]; + [self.person addObserver:self forKeyPath:@"address" options:NSKeyValueObservingOptionNew selector:@selector(_a_addressChangedWithOld:andNew:)]; + [self.person addObserver:self forKeyPath:@"city" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew | NSKeyValueObservingOptionPrior selector:@selector(_a_addressChangedWithOld:andNew:prior:)]; + + [self addObserver:self forKeyPath:@"person" options:0 selector:@selector(_a_personDidChange)]; + [self addObserver:self forKeyPath:@"person2" options:0 selector:@selector(_a_personDidChange2)]; + } + + return self; +} + +- (void)KVODealloc +{ + [self.person removeObserver:self forKeyPath:@"name" selector:@selector(_a_nameChanged)]; + [self.person removeObserver:self forKeyPath:@"phone" selector:@selector(_a_phoneChanged:)]; + [self.person removeObserver:self forKeyPath:@"address" selector:@selector(_a_addressChangedWithOld:andNew:)]; + [self.person removeObserver:self forKeyPath:@"city" selector:@selector(_a_addressChangedWithOld:andNew:prior:)]; + + [super KVODealloc]; +} + +- (void)dealloc +{ + NSLog(@"A dealloc"); + + + self.person = nil; + [super dealloc]; +} + +- (void)finalize +{ + NSLog(@"A finalize"); + [super finalize]; +} + +- (void)_a_nameChanged +{ + NSLog(@"%s", _cmd); +} + +- (void)_a_phoneChanged:(NSDictionary *)change +{ + NSLog(@"%s %@", _cmd, change); +} + +- (void)_a_addressChangedWithOld:(NSString *)old andNew:(NSString *)new +{ + NSLog(@"%s '%@' to '%@'", _cmd, old, new); +} + +- (void)_a_addressChangedWithOld:(NSString *)old andNew:(NSString *)new prior:(BOOL)prior +{ + NSLog(@"%s '%@' to '%@' %d", _cmd, old, new, prior); +} + +- (void)_a_personDidChange +{ + NSLog(@"%s", _cmd); + [self removeObserver:self forKeyPath:@"person" selector:_cmd]; +} + +@synthesize person; +@end + +@interface B : A {} +@end + +@implementation B + +- (id)initWithProgrammer:(Programmer *)programmer +{ + if ((self = [super initWithPerson:programmer])) { + [self.person addObserver:self forKeyPath:@"name" options:0 selector:@selector(_nameChanged)]; + [self.person addObserver:self forKeyPath:@"loc" options:0 selector:@selector(_locChanged)]; + } + + return self; +} + +- (void)_nameChanged +{ + NSLog(@"%s", _cmd); +} + +- (void)_locChanged +{ + NSLog(@"%s", _cmd); +} + +- (void)arrayChanged:(NSString *)old withNew:(NSString *)new +{ + NSLog(@"%s %@ %@", _cmd, old, new); +} + +- (void)KVODealloc +{ + [self.person removeObserver:self forKeyPath:@"name" selector:@selector(_nameChanged)]; + [self.person removeObserver:self forKeyPath:@"loc" selector:@selector(_locChanged)]; + + [super KVODealloc]; +} + +- (void)finalize +{ + NSLog(@"b finalize"); + [super finalize]; +} + +- (void)dealloc +{ + NSLog(@"B dealloc"); + + [super dealloc]; +} + +@end + + + +void doStuff() { + + + for (int i = 0; i < 3; i++) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + [[NSGarbageCollector defaultCollector] collectExhaustively]; + + Programmer *p = [[[Programmer alloc] init] autorelease]; + B *object = [[B alloc] initWithProgrammer:p]; + + p.name = @"A Cool Dude"; + p.phone = @"555-555-5555"; + p.address = @"5934 NE 23rd St"; + p.city = @"Columbus"; + p.loc = 5000; + object.person = p; + + NSArray *array = [NSArray arrayWithObject:p]; + [array addObserver:object toObjectsAtIndexes:[NSIndexSet indexSetWithIndex:0] forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld selector:@selector(arrayChanged:withNew:)]; + + [array setValue:@"a new name!" forKeyPath:@"name"]; + [array removeObserver:object fromObjectsAtIndexes:[NSIndexSet indexSetWithIndex:0] forKeyPath:@"name" selector:@selector(arrayChanged:withNew:)]; + + [object release]; + [pool drain]; + } + + [[NSGarbageCollector defaultCollector] collectExhaustively]; +} + +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + doStuff(); + + + + [[NSGarbageCollector defaultCollector] collectExhaustively]; + + [pool drain]; + + [[NSRunLoop currentRunLoop] run]; + return 0; +} diff --git a/External Source/KVOAdditions/observer.xcodeproj/TemplateIcon.icns b/External Source/KVOAdditions/observer.xcodeproj/TemplateIcon.icns new file mode 100644 index 000000000..62cb7015e Binary files /dev/null and b/External Source/KVOAdditions/observer.xcodeproj/TemplateIcon.icns differ diff --git a/External Source/KVOAdditions/observer.xcodeproj/project.pbxproj b/External Source/KVOAdditions/observer.xcodeproj/project.pbxproj new file mode 100644 index 000000000..9411e67c5 --- /dev/null +++ b/External Source/KVOAdditions/observer.xcodeproj/project.pbxproj @@ -0,0 +1,331 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 03BDD66B0E73A565005B7064 /* KVOAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 03CDAC3C0E30675C0064A3F3 /* KVOAdditions.m */; }; + 03BDD66C0E73A565005B7064 /* observer.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* observer.m */; }; + 03CDAC3D0E30675C0064A3F3 /* KVOAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 03CDAC3C0E30675C0064A3F3 /* KVOAdditions.m */; }; + 8DD76F9A0486AA7600D96B5E /* observer.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* observer.m */; settings = {ATTRIBUTES = (); }; }; + 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F9E0486AA7600D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 03BDD6650E73A557005B7064 /* phone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = phone.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 03BDD6670E73A557005B7064 /* phone-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "phone-Info.plist"; sourceTree = ""; }; + 03CDAC3B0E30675C0064A3F3 /* KVOAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVOAdditions.h; sourceTree = ""; }; + 03CDAC3C0E30675C0064A3F3 /* KVOAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KVOAdditions.m; sourceTree = ""; }; + 08FB7796FE84155DC02AAC07 /* observer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = observer.m; sourceTree = ""; }; + 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 32A70AAB03705E1F00C91783 /* observer_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = observer_Prefix.pch; sourceTree = ""; }; + 8DD76FA10486AA7600D96B5E /* observer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = observer; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 03BDD6630E73A557005B7064 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DD76F9B0486AA7600D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* observer */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + 03BDD6670E73A557005B7064 /* phone-Info.plist */, + ); + name = observer; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 32A70AAB03705E1F00C91783 /* observer_Prefix.pch */, + 03CDAC3B0E30675C0064A3F3 /* KVOAdditions.h */, + 03CDAC3C0E30675C0064A3F3 /* KVOAdditions.m */, + 08FB7796FE84155DC02AAC07 /* observer.m */, + ); + name = Source; + sourceTree = ""; + }; + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 08FB779EFE84155DC02AAC07 /* Foundation.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76FA10486AA7600D96B5E /* observer */, + 03BDD6650E73A557005B7064 /* phone.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 03BDD6640E73A557005B7064 /* phone */ = { + isa = PBXNativeTarget; + buildConfigurationList = 03BDD66A0E73A559005B7064 /* Build configuration list for PBXNativeTarget "phone" */; + buildPhases = ( + 03BDD6610E73A557005B7064 /* Resources */, + 03BDD6620E73A557005B7064 /* Sources */, + 03BDD6630E73A557005B7064 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = phone; + productName = phone; + productReference = 03BDD6650E73A557005B7064 /* phone.app */; + productType = "com.apple.product-type.application"; + }; + 8DD76F960486AA7600D96B5E /* observer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "observer" */; + buildPhases = ( + 8DD76F990486AA7600D96B5E /* Sources */, + 8DD76F9B0486AA7600D96B5E /* Frameworks */, + 8DD76F9E0486AA7600D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = observer; + productInstallPath = "$(HOME)/bin"; + productName = observer; + productReference = 8DD76FA10486AA7600D96B5E /* observer */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "observer" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* observer */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F960486AA7600D96B5E /* observer */, + 03BDD6640E73A557005B7064 /* phone */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 03BDD6610E73A557005B7064 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 03BDD6620E73A557005B7064 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 03BDD66B0E73A565005B7064 /* KVOAdditions.m in Sources */, + 03BDD66C0E73A565005B7064 /* observer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DD76F990486AA7600D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DD76F9A0486AA7600D96B5E /* observer.m in Sources */, + 03CDAC3D0E30675C0064A3F3 /* KVOAdditions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 03BDD6680E73A558005B7064 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/UIKit.framework/Headers/UIKit.h"; + INFOPLIST_FILE = "phone-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + UIKit, + ); + PREBINDING = NO; + PRODUCT_NAME = phone; + SDKROOT = iphoneos2.0; + }; + name = Debug; + }; + 03BDD6690E73A558005B7064 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/UIKit.framework/Headers/UIKit.h"; + INFOPLIST_FILE = "phone-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + UIKit, + ); + PREBINDING = NO; + PRODUCT_NAME = phone; + SDKROOT = iphoneos2.0; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB927508733DD40010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = unsupported; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = observer_Prefix.pch; + GCC_VERSION = 4.2; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = observer; + WARNING_CFLAGS = "-Wall"; + }; + name = Debug; + }; + 1DEB927608733DD40010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_GC = unsupported; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = observer_Prefix.pch; + GCC_VERSION = 4.2; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = observer; + WARNING_CFLAGS = "-Wall"; + }; + name = Release; + }; + 1DEB927908733DD40010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.5; + }; + name = Debug; + }; + 1DEB927A08733DD40010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.5; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 03BDD66A0E73A559005B7064 /* Build configuration list for PBXNativeTarget "phone" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 03BDD6680E73A558005B7064 /* Debug */, + 03BDD6690E73A558005B7064 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "observer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB927508733DD40010E9CD /* Debug */, + 1DEB927608733DD40010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "observer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB927908733DD40010E9CD /* Debug */, + 1DEB927A08733DD40010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/External Source/KVOAdditions/observer_Prefix.pch b/External Source/KVOAdditions/observer_Prefix.pch new file mode 100644 index 000000000..f1b63107c --- /dev/null +++ b/External Source/KVOAdditions/observer_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'observer' target in the 'observer' project. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/External Source/MacMapKit/LICENSE b/External Source/MacMapKit/LICENSE new file mode 100644 index 000000000..6e28232f2 --- /dev/null +++ b/External Source/MacMapKit/LICENSE @@ -0,0 +1,10 @@ +Copyright (c) 2011, Oomph Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +- Neither the name of the Oomph Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/External Source/MacMapKit/README.mdown b/External Source/MacMapKit/README.mdown new file mode 100644 index 000000000..985e30c84 --- /dev/null +++ b/External Source/MacMapKit/README.mdown @@ -0,0 +1,22 @@ +MapKit for Mac +------------- +MapKit for Mac is a framework for displaying maps in a Cocoa application that is API-compatible with Apple's [MapKit framework for iOS](http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MapKit_Framework_Reference/_index.html). + +It Works +-------- +MapKit for Mac implements nearly 100% of MK* functionality. It's been tested on Snow Leopard and Lion, and is currently in use by thousands of [Sidekick](http://oomphalot.com/sidekick) users. + +What's Provided +--------------- +There's currently a framework, an IBPlugin for XCode3 users, and a small demo application. + + +Documentation +--------------- +Because the framework is API compatible with Apple's, you can use [their documentation](http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MapKit_Framework_Reference/_index.html) as a reference. + + +Licensing +---------- +MapKit for Mac is distributed under the BSD license. However, MapKit for Mac uses Google services to provide map data. Use of specific classes of this framework (and their associated interfaces) binds you to the Google Maps/Google Earth API terms of service. You can find these terms of service at [http://code.google.com/apis/maps/terms.html](http://code.google.com/apis/maps/terms.html). + diff --git a/External Source/MacMapKit/Source/DemoApp/Classes/DemoAppApplicationDelegate.h b/External Source/MacMapKit/Source/DemoApp/Classes/DemoAppApplicationDelegate.h new file mode 100644 index 000000000..f8005eccf --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/Classes/DemoAppApplicationDelegate.h @@ -0,0 +1,33 @@ +// +// DemoAppApplicationDelegate.h +// MapKit +// +// Created by Rick Fillion on 7/16/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import + +@class MKMapView; + +@interface DemoAppApplicationDelegate : NSObject { + NSWindow *window; + IBOutlet MKMapView *mapView; + IBOutlet NSTextField *addressTextField; + NSNumber *circleRadius; + NSString *pinTitle; + NSArray *pinNames; +} + +@property (assign) IBOutlet NSWindow *window; +@property (retain) NSString *pinTitle; + +- (IBAction)setMapType:(id)sender; +- (IBAction)addCircle:(id)sender; +- (IBAction)addPin:(id)sender; +- (IBAction)searchAddress:(id)sender; +- (IBAction)demo:(id)sender; +- (IBAction)addAdditionalCSS:(id)sender; + +@end diff --git a/External Source/MacMapKit/Source/DemoApp/Classes/DemoAppApplicationDelegate.m b/External Source/MacMapKit/Source/DemoApp/Classes/DemoAppApplicationDelegate.m new file mode 100644 index 000000000..b5a7ea52d --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/Classes/DemoAppApplicationDelegate.m @@ -0,0 +1,272 @@ +// +// DemoAppApplicationDelegate.m +// MapKit +// +// Created by Rick Fillion on 7/16/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "DemoAppApplicationDelegate.h" +#import +#import + +@implementation DemoAppApplicationDelegate + +@synthesize window; +@synthesize pinTitle; + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + //NSLog(@"applicationDidFinishLaunching:"); + [mapView setShowsUserLocation: YES]; + [mapView setDelegate: self]; + + pinNames = [[NSArray arrayWithObjects:@"One", @"Two", @"Three", @"Four", @"Five", @"Six", @"Seven", @"Eight", @"Nine", @"Ten", @"Eleven", @"Twelve", nil] retain]; + + + CLLocationCoordinate2D coordinate; + coordinate.latitude = 49.8578255; + coordinate.longitude = -97.16531639999999; + MKReverseGeocoder *reverseGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate: coordinate]; + reverseGeocoder.delegate = self; + [reverseGeocoder start]; + + MKGeocoder *geocoderNoCoord = [[MKGeocoder alloc] initWithAddress:@"777 Corydon Ave, Winnipeg MB"]; + geocoderNoCoord.delegate = self; + [geocoderNoCoord start]; + + MKGeocoder *geocoderCoord = [[MKGeocoder alloc] initWithAddress:@"1250 St. James St" nearCoordinate:coordinate]; + geocoderCoord.delegate = self; + [geocoderCoord start]; + +} + +- (IBAction)setMapType:(id)sender +{ + NSSegmentedControl *segmentedControl = (NSSegmentedControl *)sender; + [mapView setMapType:[segmentedControl selectedSegment]]; +} + +- (IBAction)addCircle:(id)sender +{ + MKCircle *circle = [[MKCircle circleWithCenterCoordinate:[mapView centerCoordinate] radius:[circleRadius intValue]] autorelease]; + [mapView addOverlay:circle]; +} + +- (IBAction)addPin:(id)sender +{ + MKPointAnnotation *pin = [[[MKPointAnnotation alloc] init] autorelease]; + pin.coordinate = [mapView centerCoordinate]; + pin.title = self.pinTitle; + [mapView addAnnotation:pin]; +} + +- (IBAction)searchAddress:(id)sender +{ + [mapView showAddress:[addressTextField stringValue]]; +} + +- (IBAction)demo:(id)sender +{ + for (int i = 0; i<[pinNames count]; i++) + { + [self performSelector:@selector(addPinForIndex:) withObject:[NSNumber numberWithInt:i] afterDelay: i * 0.25]; + } +} + +- (void)addPinForIndex:(NSNumber *)indexNumber +{ + CLLocationCoordinate2D centerCoordinate = [mapView centerCoordinate]; + NSUInteger total = [pinNames count]; + NSUInteger index = [indexNumber intValue]; + double maxLatOffset = 0.01; + double maxLngOffset = 0.02; + NSString *name = [pinNames objectAtIndex:[indexNumber intValue]]; + + MKPointAnnotation *pin = [[[MKPointAnnotation alloc] init] autorelease]; + CLLocationCoordinate2D pinCoord = centerCoordinate; + double latOffset = maxLatOffset * cosf(2*M_PI * ((double)index/(double)total)); + double lngOffset = maxLngOffset * sinf(2*M_PI * ((double)index/(double)total)); + pinCoord.latitude += latOffset; + pinCoord.longitude += lngOffset; + pin.coordinate = pinCoord; + pin.title = name; + [mapView addAnnotation:pin]; + +} + +- (IBAction)addAdditionalCSS:(id)sender +{ + NSString *path = [[NSBundle mainBundle] pathForResource:@"MapViewAdditions" ofType:@"css"]; + [mapView performSelector:@selector(addStylesheetTag:) withObject:path afterDelay:1.0]; +} + +#pragma mark MKReverseGeocoderDelegate + +- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark +{ + //NSLog(@"found placemark: %@", placemark); +} + +- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error +{ + //NSLog(@"MKReverseGeocoder didFailWithError: %@", error); +} + +#pragma mark MKGeocoderDelegate + +- (void)geocoder:(MKGeocoder *)geocoder didFindCoordinate:(CLLocationCoordinate2D)coordinate +{ + //NSLog(@"MKGeocoder found (%f, %f) for %@", coordinate.latitude, coordinate.longitude, geocoder.address); +} + +- (void)geocoder:(MKGeocoder *)geocoder didFailWithError:(NSError *)error +{ + //NSLog(@"MKGeocoder didFailWithError: %@", error); +} + +#pragma mark MapView Delegate + +// Responding to Map Position Changes + +- (void)mapView:(MKMapView *)aMapView regionWillChangeAnimated:(BOOL)animated +{ + //NSLog(@"mapView: %@ regionWillChangeAnimated: %d", aMapView, animated); +} + +- (void)mapView:(MKMapView *)aMapView regionDidChangeAnimated:(BOOL)animated +{ + //NSLog(@"mapView: %@ regionDidChangeAnimated: %d", aMapView, animated); +} + +//Loading the Map Data +- (void)mapViewWillStartLoadingMap:(MKMapView *)aMapView +{ + //NSLog(@"mapViewWillStartLoadingMap: %@", aMapView); +} + +- (void)mapViewDidFinishLoadingMap:(MKMapView *)aMapView +{ + //NSLog(@"mapViewDidFinishLoadingMap: %@", aMapView); +} + +- (void)mapViewDidFailLoadingMap:(MKMapView *)aMapView withError:(NSError *)error +{ + //NSLog(@"mapViewDidFailLoadingMap: %@ withError: %@", aMapView, error); +} + +// Tracking the User Location +- (void)mapViewWillStartLocatingUser:(MKMapView *)aMapView +{ + //NSLog(@"mapViewWillStartLocatingUser: %@", aMapView); +} + +- (void)mapViewDidStopLocatingUser:(MKMapView *)aMapView +{ + //NSLog(@"mapViewDidStopLocatingUser: %@", aMapView); +} + +- (void)mapView:(MKMapView *)aMapView didUpdateUserLocation:(MKUserLocation *)userLocation +{ + //NSLog(@"mapView: %@ didUpdateUserLocation: %@", aMapView, userLocation); +} + +- (void)mapView:(MKMapView *)aMapView didFailToLocateUserWithError:(NSError *)error +{ + // NSLog(@"mapView: %@ didFailToLocateUserWithError: %@", aMapView, error); +} + +// Managing Annotation Views + + +- (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id )annotation +{ + //NSLog(@"mapView: %@ viewForAnnotation: %@", aMapView, annotation); + //MKAnnotationView *view = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"blah"] autorelease]; + MKPinAnnotationView *view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"blah"] autorelease]; + view.draggable = YES; + //NSString *path = [[NSBundle mainBundle] pathForResource:@"MarkerTest" ofType:@"png"]; + //NSURL *url = [NSURL fileURLWithPath:path]; + //view.imageUrl = [url absoluteString]; + return view; +} + +- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views +{ + //NSLog(@"mapView: %@ didAddAnnotationViews: %@", aMapView, views); +} + /* + - (void)mapView:(MKMapView *)aMapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control + { + NSLog(@"mapView: %@ annotationView: %@ calloutAccessoryControlTapped: %@", aMapView, view, control); + } + */ + +// Dragging an Annotation View +/* + - (void)mapView:(MKMapView *)aMapView annotationView:(MKAnnotationView *)annotationView + didChangeDragState:(MKAnnotationViewDragState)newState + fromOldState:(MKAnnotationViewDragState)oldState + { + NSLog(@"mapView: %@ annotationView: %@ didChangeDragState: %d fromOldState: %d", aMapView, annotationView, newState, oldState); + } + */ + + +// Selecting Annotation Views + +- (void)mapView:(MKMapView *)aMapView didSelectAnnotationView:(MKAnnotationView *)view +{ + //NSLog(@"mapView: %@ didSelectAnnotationView: %@", aMapView, view); +} + +- (void)mapView:(MKMapView *)aMapView didDeselectAnnotationView:(MKAnnotationView *)view +{ + //NSLog(@"mapView: %@ didDeselectAnnotationView: %@", aMapView, view); +} + + +// Managing Overlay Views + +- (MKOverlayView *)mapView:(MKMapView *)aMapView viewForOverlay:(id )overlay +{ + //NSLog(@"mapView: %@ viewForOverlay: %@", aMapView, overlay); + MKCircleView *circleView = [[[MKCircleView alloc] initWithCircle:overlay] autorelease]; + return circleView; + // MKPolylineView *polylineView = [[[MKPolylineView alloc] initWithPolyline:overlay] autorelease]; + // return polylineView; + MKPolygonView *polygonView = [[[MKPolygonView alloc] initWithPolygon:overlay] autorelease]; + return polygonView; +} + +- (void)mapView:(MKMapView *)aMapView didAddOverlayViews:(NSArray *)overlayViews +{ + //NSLog(@"mapView: %@ didAddOverlayViews: %@", aMapView, overlayViews); +} + +- (void)mapView:(MKMapView *)aMapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState +{ + //NSLog(@"mapView: %@ annotationView: %@ didChangeDragState:%d fromOldState:%d", aMapView, annotationView, newState, oldState); + //MKPointAnnotation *annotation = annotationView.annotation; + //NSLog(@"annotation = %@", annotation); + +} + +// MacMapKit additions +- (void)mapView:(MKMapView *)aMapView userDidClickAndHoldAtCoordinate:(CLLocationCoordinate2D)coordinate; +{ + //NSLog(@"mapView: %@ userDidClickAndHoldAtCoordinate: (%f, %f)", aMapView, coordinate.latitude, coordinate.longitude); + MKPointAnnotation *pin = [[[MKPointAnnotation alloc] init] autorelease]; + pin.coordinate = coordinate; + pin.title = @"Hi."; + [mapView addAnnotation:pin]; +} + +- (NSArray *)mapView:(MKMapView *)mapView contextMenuItemsForAnnotationView:(MKAnnotationView *)view +{ + NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:@"Delete It" action:@selector(delete:) keyEquivalent:@""] autorelease]; + return [NSArray arrayWithObject:item]; +} + + +@end diff --git a/External Source/MacMapKit/Source/DemoApp/DemoApp-Info.plist b/External Source/MacMapKit/Source/DemoApp/DemoApp-Info.plist new file mode 100644 index 000000000..3ba93b5fd --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/DemoApp-Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/External Source/MacMapKit/Source/DemoApp/DemoApp_Prefix.pch b/External Source/MacMapKit/Source/DemoApp/DemoApp_Prefix.pch new file mode 100644 index 000000000..3885c18a7 --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/DemoApp_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'DemoApp' target in the 'MapKit' project +// + +#ifdef __OBJC__ +#import +#endif diff --git a/External Source/MacMapKit/Source/DemoApp/MainMenu.xib b/External Source/MacMapKit/Source/DemoApp/MainMenu.xib new file mode 100644 index 000000000..049122516 --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/MainMenu.xib @@ -0,0 +1,5362 @@ + + + + 1060 + 10J567 + 823 + 1038.35 + 462.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 823 + + + YES + + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + NSFontManager + + + Main Menu + + YES + + + New Application + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + New Application + + YES + + + About New Application + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide New Application + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit New Application + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1048576 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + + 2147483647 + + + + + + Smart Quotes + + 2147483647 + + + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + + 2147483647 + + + + + + Data Detectors + + 2147483647 + + + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 2147483647 + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + New Application Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{571, 86}, {663, 576}} + 611844096 + Window + NSWindow + + {3.40282e+38, 3.40282e+38} + + + 256 + + YES + + + 274 + {{20, 196}, {623, 360}} + + MKMapView + + + + 37 + + YES + + + 256 + + YES + + + 293 + {{303, 58}, {105, 32}} + + YES + + 67239424 + 134217728 + Add Pin + + LucidaGrande + 13 + 1044 + + + -2038284033 + 129 + + + 200 + 25 + + + + + 293 + {{100, 101}, {201, 22}} + + YES + + -1804468671 + 272630784 + + + 123 Fake St. City, State + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + + + + 292 + {{222, 28}, {58, 22}} + + YES + + -1803944383 + 272630784 + + + + YES + + YES + allowsFloats + formatterBehavior + locale + maximum + minimum + negativeInfinitySymbol + nilSymbol + numberStyle + positiveInfinitySymbol + + + YES + + + + + + + + -∞ + + + +∞ + + + #,##0.### + #,##0.### + + + + + + + + NaN + + YES + + YES + + + YES + + + + + + + 3 + YES + YES + YES + + . + , + YES + NO + YES + + + YES + + + + + + + 293 + {{100, 66}, {201, 22}} + + YES + + -1804468671 + 272630784 + + + Pin Title + + YES + + + + + + + 293 + {{303, 20}, {105, 32}} + + YES + + 67239424 + 134217728 + Add Overlay + + + -2038284033 + 129 + + + 200 + 25 + + + + + 293 + {{98, 133}, {306, 24}} + + YES + + 67239424 + 0 + + LucidaGrande + 13 + 16 + + + + YES + + 100 + Standard + 1 + YES + 0 + + + 99 + Satellite + 2 + 0 + + + 99 + Hybrid + 3 + 0 + + + 1 + + + + + 293 + {{303, 95}, {105, 32}} + + YES + + 67239424 + 134217728 + Search + + + -2038284033 + 129 + + + 200 + 25 + + + + + 292 + {{164, 31}, {47, 17}} + + YES + + 68288064 + 272630784 + Radius + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2ODY1AA + + + + 6 + System + controlTextColor + + + + + + + 292 + {{285, 26}, {19, 27}} + + YES + + 917024 + 0 + + 10 + 10 + 1000 + 1 + YES + + + + + 293 + {{408, 59}, {105, 32}} + + YES + + 67239424 + 134217728 + Demo + + + -2038284033 + 129 + + + 200 + 25 + + + + + 268 + {{408, 20}, {105, 32}} + + YES + + 67239424 + 134217728 + Add CSS + + + -2038284033 + 129 + + + 200 + 25 + + + + {{1, 1}, {525, 172}} + + + + {{68, 16}, {527, 174}} + + {0, 0} + + 67239424 + 0 + + + LucidaGrande + 11 + 3100 + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 0 + NO + + + {663, 576} + + + {{0, 0}, {1680, 1028}} + {3.40282e+38, 3.40282e+38} + + + DemoAppApplicationDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + performZoom: + + + + 240 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 369 + + + + hideOtherApplications: + + + + 370 + + + + unhideAllApplications: + + + + 372 + + + + addFontTrait: + + + + 420 + + + + addFontTrait: + + + + 421 + + + + modifyFont: + + + + 422 + + + + orderFrontFontPanel: + + + + 423 + + + + modifyFont: + + + + 424 + + + + raiseBaseline: + + + + 425 + + + + lowerBaseline: + + + + 426 + + + + copyFont: + + + + 427 + + + + subscript: + + + + 428 + + + + superscript: + + + + 429 + + + + tightenKerning: + + + + 430 + + + + underline: + + + + 431 + + + + orderFrontColorPanel: + + + + 432 + + + + useAllLigatures: + + + + 433 + + + + loosenKerning: + + + + 434 + + + + pasteFont: + + + + 435 + + + + unscript: + + + + 436 + + + + useStandardKerning: + + + + 437 + + + + useStandardLigatures: + + + + 438 + + + + turnOffLigatures: + + + + 439 + + + + turnOffKerning: + + + + 440 + + + + terminate: + + + + 448 + + + + capitalizeWord: + + + + 740 + + + + cut: + + + + 741 + + + + paste: + + + + 742 + + + + toggleSmartInsertDelete: + + + + 743 + + + + toggleAutomaticQuoteSubstitution: + + + + 744 + + + + redo: + + + + 745 + + + + toggleAutomaticDashSubstitution: + + + + 746 + + + + toggleContinuousSpellChecking: + + + + 747 + + + + toggleAutomaticDataDetection: + + + + 748 + + + + undo: + + + + 749 + + + + toggleGrammarChecking: + + + + 750 + + + + startSpeaking: + + + + 751 + + + + showGuessPanel: + + + + 752 + + + + checkSpelling: + + + + 753 + + + + pasteAsPlainText: + + + + 754 + + + + copy: + + + + 755 + + + + delete: + + + + 756 + + + + lowercaseWord: + + + + 757 + + + + selectAll: + + + + 758 + + + + stopSpeaking: + + + + 759 + + + + orderFrontSubstitutionsPanel: + + + + 760 + + + + toggleAutomaticTextReplacement: + + + + 761 + + + + toggleAutomaticLinkDetection: + + + + 762 + + + + toggleAutomaticSpellingCorrection: + + + + 763 + + + + uppercaseWord: + + + + 764 + + + + performFindPanelAction: + + + + 771 + + + + performFindPanelAction: + + + + 772 + + + + performFindPanelAction: + + + + 773 + + + + centerSelectionInVisibleArea: + + + + 774 + + + + performFindPanelAction: + + + + 775 + + + + toggleRuler: + + + + 798 + + + + pasteRuler: + + + + 799 + + + + alignCenter: + + + + 800 + + + + copyRuler: + + + + 801 + + + + alignJustified: + + + + 802 + + + + alignRight: + + + + 803 + + + + alignLeft: + + + + 804 + + + + makeBaseWritingDirectionNatural: + + + + 805 + + + + makeBaseWritingDirectionLeftToRight: + + + + 806 + + + + makeBaseWritingDirectionRightToLeft: + + + + 807 + + + + makeTextWritingDirectionNatural: + + + + 808 + + + + makeTextWritingDirectionLeftToRight: + + + + 809 + + + + makeTextWritingDirectionRightToLeft: + + + + 810 + + + + delegate + + + + 812 + + + + mapView + + + + 816 + + + + window + + + + 817 + + + + setMapType: + + + + 818 + + + + takeIntValueFrom: + + + + 854 + + + + takeIntValueFrom: + + + + 855 + + + + addCircle: + + + + 858 + + + + addPin: + + + + 859 + + + + value: circleRadius + + + + + + value: circleRadius + value + circleRadius + + NSContinuouslyUpdatesValue + + + 2 + + + 861 + + + + value: circleRadius + + + + + + value: circleRadius + value + circleRadius + 2 + + + 862 + + + + addressTextField + + + + 867 + + + + searchAddress: + + + + 868 + + + + takeStringValueFrom: + + + + 869 + + + + value: pinTitle + + + + + + value: pinTitle + value + pinTitle + + YES + + YES + NSContinuouslyUpdatesValue + NSNullPlaceholder + + + YES + + Pin Title + + + 2 + + + 876 + + + + demo: + + + + 880 + + + + addAdditionalCSS: + + + + 884 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 106 + + + YES + + + + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 367 + + + YES + + + + + + 368 + + + YES + + + + + + + 373 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 79 + + + + + 684 + + + YES + + + + + + 685 + + + YES + + + + + + + + + + + + + + + + + + + + 686 + + + + + 687 + + + + + 688 + + + + + 689 + + + + + 690 + + + + + 691 + + + + + 692 + + + + + 693 + + + + + 694 + + + + + 695 + + + + + 696 + + + YES + + + + + + 697 + + + YES + + + + + + 698 + + + YES + + + + + + 699 + + + YES + + + + + + 700 + + + YES + + + + + + 711 + + + YES + + + + + + + 712 + + + + + 713 + + + + + 714 + + + YES + + + + + + + + 715 + + + + + 716 + + + + + 717 + + + + + 718 + + + YES + + + + + + + + + + + + + 719 + + + + + 720 + + + + + 721 + + + + + 722 + + + + + 723 + + + + + 724 + + + + + 725 + + + + + 726 + + + + + 727 + + + YES + + + + + + + + + + + 728 + + + + + 729 + + + + + 730 + + + + + 731 + + + + + 732 + + + + + 733 + + + + + 734 + + + YES + + + + + + + + + + 735 + + + + + 736 + + + + + 737 + + + + + 738 + + + + + 739 + + + + + 776 + + + YES + + + + + + 777 + + + YES + + + + + + + + + + + + + + + 778 + + + + + 779 + + + + + 780 + + + + + 781 + + + + + 782 + + + + + 783 + + + YES + + + + + + 784 + + + + + 785 + + + + + 786 + + + + + 787 + + + + + 788 + + + YES + + + + + + + + + + + + + + 789 + + + + + 790 + + + + + 791 + + + + + 792 + + + + + 793 + + + + + 794 + + + + + 795 + + + + + 796 + + + + + 797 + + + + + 811 + + + App Delegate + + + 813 + + + + + 881 + + + YES + + + + + + + + + + + + + + + + 856 + + + YES + + + + + + 857 + + + + + 863 + + + YES + + + + + + 864 + + + + + 847 + + + YES + + + + + + 850 + + + YES + + + + + + 851 + + + + + 871 + + + YES + + + + + + 872 + + + + + 845 + + + YES + + + + + + 853 + + + + + 814 + + + YES + + + + + + 815 + + + + + 865 + + + YES + + + + + + 866 + + + + + 846 + + + YES + + + + + + 852 + + + + + 848 + + + YES + + + + + + 849 + + + + + 877 + + + YES + + + + + + 878 + + + + + 882 + + + YES + + + + + + 883 + + + + + + + YES + + YES + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBEditorWindowLastContentRect + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBEditorWindowLastContentRect + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 367.IBEditorWindowLastContentRect + 367.IBPluginDependency + 367.IBWindowTemplateEditedContentRect + 367.NSWindowTemplate.visibleAtLaunch + 367.editorWindowContentRectSynchronizationRect + 367.windowTemplate.maxSize + 368.IBPluginDependency + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 684.IBPluginDependency + 685.IBEditorWindowLastContentRect + 685.IBPluginDependency + 686.IBPluginDependency + 687.IBPluginDependency + 688.IBPluginDependency + 689.IBPluginDependency + 690.IBPluginDependency + 691.IBPluginDependency + 692.IBPluginDependency + 693.IBPluginDependency + 694.IBPluginDependency + 695.IBPluginDependency + 696.IBPluginDependency + 697.IBPluginDependency + 698.IBPluginDependency + 699.IBPluginDependency + 700.IBPluginDependency + 711.IBPluginDependency + 712.IBPluginDependency + 713.IBPluginDependency + 714.IBPluginDependency + 715.IBPluginDependency + 716.IBPluginDependency + 717.IBPluginDependency + 718.IBPluginDependency + 719.IBPluginDependency + 72.IBPluginDependency + 72.ImportedFromIB2 + 720.IBPluginDependency + 721.IBPluginDependency + 722.IBPluginDependency + 723.IBPluginDependency + 724.IBPluginDependency + 725.IBPluginDependency + 726.IBPluginDependency + 727.IBPluginDependency + 728.IBPluginDependency + 729.IBPluginDependency + 73.IBPluginDependency + 73.ImportedFromIB2 + 730.IBPluginDependency + 731.IBPluginDependency + 732.IBPluginDependency + 733.IBPluginDependency + 734.IBPluginDependency + 735.IBPluginDependency + 736.IBPluginDependency + 737.IBPluginDependency + 738.IBPluginDependency + 739.IBPluginDependency + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 776.IBPluginDependency + 777.IBEditorWindowLastContentRect + 777.IBPluginDependency + 778.IBPluginDependency + 779.IBPluginDependency + 78.IBPluginDependency + 78.ImportedFromIB2 + 780.IBPluginDependency + 781.IBPluginDependency + 782.IBPluginDependency + 783.IBPluginDependency + 784.IBPluginDependency + 785.IBPluginDependency + 786.IBPluginDependency + 787.IBPluginDependency + 788.IBEditorWindowLastContentRect + 788.IBPluginDependency + 789.IBPluginDependency + 79.IBPluginDependency + 79.ImportedFromIB2 + 790.IBPluginDependency + 791.IBPluginDependency + 792.IBPluginDependency + 793.IBPluginDependency + 794.IBPluginDependency + 795.IBPluginDependency + 796.IBPluginDependency + 797.IBPluginDependency + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 813.IBPluginDependency + 813.IBViewBoundsToFrameTransform + 814.IBPluginDependency + 814.IBSegmentedControlTracker.RoundRobinState + 814.IBSegmentedControlTracker.WasGrowing + 814.IBViewBoundsToFrameTransform + 815.IBPluginDependency + 815.IBSegmentedControlInspectorSelectedSegmentMetadataKey + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 845.IBPluginDependency + 845.IBViewBoundsToFrameTransform + 846.IBPluginDependency + 846.IBViewBoundsToFrameTransform + 847.IBPluginDependency + 847.IBViewBoundsToFrameTransform + 848.IBPluginDependency + 848.IBViewBoundsToFrameTransform + 849.IBPluginDependency + 850.IBPluginDependency + 851.IBNumberFormatterBehaviorMetadataKey + 851.IBNumberFormatterLocalizesFormatMetadataKey + 851.IBPluginDependency + 852.IBPluginDependency + 853.IBPluginDependency + 856.IBPluginDependency + 856.IBViewBoundsToFrameTransform + 857.IBPluginDependency + 863.IBPluginDependency + 863.IBViewBoundsToFrameTransform + 864.IBPluginDependency + 865.IBPluginDependency + 865.IBViewBoundsToFrameTransform + 866.IBPluginDependency + 871.IBPluginDependency + 871.IBViewBoundsToFrameTransform + 872.IBPluginDependency + 877.IBPluginDependency + 877.IBViewBoundsToFrameTransform + 878.IBPluginDependency + 881.IBViewBoundsToFrameTransform + 882.IBPluginDependency + 883.IBPluginDependency + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{743, 629}, {217, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{449, 589}, {132, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{509, 573}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{452, 579}, {197, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{427, 836}, {482, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{402, 609}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{429, 109}, {663, 576}} + com.apple.InterfaceBuilder.CocoaPlugin + {{429, 109}, {663, 576}} + + {{11, 666}, {480, 270}} + {3.40282e+38, 3.40282e+38} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{583, 1041}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{422, 369}, {178, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{334, 469}, {246, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{539, 801}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{666, 881}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{870, 801}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{470, 449}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + AUGgAABDgQAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + + + P4AAAL+AAABBkAAAwzQAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDroAAwqoAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDTwAAwqAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDhIAAwqQAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + AUOkAABCcAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDv4AAwp4AAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDNAAAwxcAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDaAAAwxsAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDOQAAwxIAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDwgAAwpQAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + AUKIAABBgAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 884 + + + + YES + + DemoAppApplicationDelegate + NSObject + + YES + + YES + addAdditionalCSS: + addCircle: + addPin: + demo: + searchAddress: + setMapType: + + + YES + id + id + id + id + id + id + + + + YES + + YES + addAdditionalCSS: + addCircle: + addPin: + demo: + searchAddress: + setMapType: + + + YES + + addAdditionalCSS: + id + + + addCircle: + id + + + addPin: + id + + + demo: + id + + + searchAddress: + id + + + setMapType: + id + + + + + YES + + YES + addressTextField + mapView + window + + + YES + NSTextField + MKMapView + NSWindow + + + + YES + + YES + addressTextField + mapView + window + + + YES + + addressTextField + NSTextField + + + mapView + MKMapView + + + window + NSWindow + + + + + IBProjectSource + DemoApp/Classes/DemoAppApplicationDelegate.h + + + + MKMapView + + takeStringValueFrom: + id + + + takeStringValueFrom: + + takeStringValueFrom: + id + + + + IBProjectSource + Framework/Classes/MKMapView+Additions.h + + + + MKMapView + + IBProjectSource + Framework/Classes/MKMapView+DelegateWrappers.h + + + + MKMapView + + IBProjectSource + Framework/Classes/MKMapView+WebViewIntegration.h + + + + MKMapView + NSView + + delegate + id + + + delegate + + delegate + id + + + + IBProjectSource + Framework/Classes/MKMapView.h + + + + NSObject + + IBProjectSource + Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.h + + + + NSObject + + IBProjectSource + Framework/Classes/Third Party/SBJSON/SBJsonWriter.h + + + + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBox + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSBox.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + + clearRecentDocuments: + id + + + newDocument: + id + + + openDocument: + id + + + saveAllDocuments: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSNumberFormatter + NSFormatter + + IBFrameworkSource + Foundation.framework/Headers/NSNumberFormatter.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBObjectIntegration.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebDownload.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebEditingDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebFrameLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebJavaPlugIn.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPlugin.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPluginContainer.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPolicyDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebResourceLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebScriptObject.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebUIDelegate.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSSegmentedCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSSegmentedCell.h + + + + NSSegmentedControl + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSSegmentedControl.h + + + + NSStepper + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSStepper.h + + + + NSStepperCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSStepperCell.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSView + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBViewIntegration.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + WebView + NSView + + YES + + YES + goBack: + goForward: + makeTextLarger: + makeTextSmaller: + makeTextStandardSize: + reload: + reloadFromOrigin: + stopLoading: + takeStringURLFrom: + toggleContinuousSpellChecking: + toggleSmartInsertDelete: + + + YES + id + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + goBack: + goForward: + makeTextLarger: + makeTextSmaller: + makeTextStandardSize: + reload: + reloadFromOrigin: + stopLoading: + takeStringURLFrom: + toggleContinuousSpellChecking: + toggleSmartInsertDelete: + + + YES + + goBack: + id + + + goForward: + id + + + makeTextLarger: + id + + + makeTextSmaller: + id + + + makeTextStandardSize: + id + + + reload: + id + + + reloadFromOrigin: + id + + + stopLoading: + id + + + takeStringURLFrom: + id + + + toggleContinuousSpellChecking: + id + + + toggleSmartInsertDelete: + id + + + + + IBFrameworkSource + WebKit.framework/Headers/WebView.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../MapKit.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/External Source/MacMapKit/Source/DemoApp/MapViewAdditions.css b/External Source/MacMapKit/Source/DemoApp/MapViewAdditions.css new file mode 100644 index 000000000..9ea60aabc --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/MapViewAdditions.css @@ -0,0 +1,4 @@ +div#MKMapViewTopLayer { + -webkit-box-shadow:inset 0 0 10px #000000; + pointer-events: none; +} \ No newline at end of file diff --git a/External Source/MacMapKit/Source/DemoApp/main.m b/External Source/MacMapKit/Source/DemoApp/main.m new file mode 100644 index 000000000..ad3182aa1 --- /dev/null +++ b/External Source/MacMapKit/Source/DemoApp/main.m @@ -0,0 +1,16 @@ +/* + * main.m + * MapKit + * + * Created by Rick Fillion on 7/16/10. + * Copyright 2010 Centrix.ca. All rights reserved. + * + */ + + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKAnnotation.h b/External Source/MacMapKit/Source/Framework/Classes/MKAnnotation.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKAnnotation.h rename to External Source/MacMapKit/Source/Framework/Classes/MKAnnotation.h diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKAnnotationView.h b/External Source/MacMapKit/Source/Framework/Classes/MKAnnotationView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKAnnotationView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKAnnotationView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKAnnotationView.m b/External Source/MacMapKit/Source/Framework/Classes/MKAnnotationView.m new file mode 100644 index 000000000..638fb4449 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKAnnotationView.m @@ -0,0 +1,93 @@ +// +// MKAnnotationView.m +// MapKit +// +// Created by Rick Fillion on 7/18/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKAnnotationView.h" +#import + + + + +@implementation MKAnnotationView + +@synthesize reuseIdentifier; +@synthesize annotation; +@synthesize imageUrl; +@synthesize centerOffset; +@synthesize calloutOffset; +@synthesize enabled; +@synthesize highlighted; +@synthesize selected; +@synthesize canShowCallout; +@synthesize draggable; +@synthesize dragState; + +- (id)initWithAnnotation:(id )anAnnotation reuseIdentifier:(NSString *)aReuseIdentifier +{ + if (self = [super init]) + { + reuseIdentifier = [aReuseIdentifier retain]; + self.annotation = anAnnotation; + } + return self; +} + +- (void)dealloc +{ + [reuseIdentifier release]; + [(id)annotation release]; + [markerImage release]; + [latlngCenter release]; + [super dealloc]; +} + +- (void)prepareForReuse +{ + // Unsupported so far. +} + +- (void)setSelected:(BOOL)_selected animated:(BOOL)animated +{ + self.selected = _selected; +} + +- (NSString *)viewPrototypeName +{ + return @"AnnotationOverlay"; +} + +- (NSDictionary *)options +{ + NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:[super options]]; + + if (self.imageUrl) + [options setObject:self.imageUrl forKey:@"imageUrl"]; + + if (latlngCenter) + [options setObject:latlngCenter forKey:@"position"]; + + if ([self.annotation title]) + [options setObject:[self.annotation title] forKey:@"title"]; + + [options setObject:[NSNumber numberWithBool:draggable] forKey:@"draggable"]; + //NSLog(@"options = %@", options); + + return [[options copy] autorelease]; +} + +- (void)draw:(WebScriptObject *)overlayScriptObject +{ + + [latlngCenter release]; + NSString *script = [NSString stringWithFormat:@"new google.maps.LatLng(%f, %f);", self.annotation.coordinate.latitude, self.annotation.coordinate.longitude]; + latlngCenter = (WebScriptObject *)[overlayScriptObject evaluateWebScript:script]; + [latlngCenter retain]; + + [super draw:overlayScriptObject]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKCircle.h b/External Source/MacMapKit/Source/Framework/Classes/MKCircle.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKCircle.h rename to External Source/MacMapKit/Source/Framework/Classes/MKCircle.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKCircle.m b/External Source/MacMapKit/Source/Framework/Classes/MKCircle.m new file mode 100644 index 000000000..cfc81c512 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKCircle.m @@ -0,0 +1,50 @@ +// +// MKCircle.m +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKCircle.h" + +@interface MKCircle (Private) + +- (id)initWithCenterCoordinate:(CLLocationCoordinate2D)aCoord radius:(CLLocationDistance)aRadius; + +@end + + +@implementation MKCircle + +@synthesize coordinate, radius; + ++ (MKCircle *)circleWithCenterCoordinate:(CLLocationCoordinate2D)aCoord radius:(CLLocationDistance)aRadius +{ + return [[[self alloc] initWithCenterCoordinate:aCoord radius:aRadius] autorelease]; +} + + +- (MKCoordinateRegion)region +{ + MKCoordinateRegion theRegion; + theRegion.center = [self coordinate]; + CGFloat latitudeDelta = [self radius] / (111 * 1000); // 111km per degree latitude + theRegion.span.latitudeDelta = latitudeDelta; + theRegion.span.longitudeDelta = latitudeDelta; // assume we're at the equator, it'll make our lives easier, and chances are we're dealing with small circles + return theRegion; +} + +#pragma mark Private + +- (id)initWithCenterCoordinate:(CLLocationCoordinate2D)aCoord radius:(CLLocationDistance)aRadius +{ + if (self = [super init]) + { + coordinate = aCoord; + radius = aRadius; + } + return self; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKCircleView.h b/External Source/MacMapKit/Source/Framework/Classes/MKCircleView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKCircleView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKCircleView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKCircleView.m b/External Source/MacMapKit/Source/Framework/Classes/MKCircleView.m new file mode 100644 index 000000000..e5607be68 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKCircleView.m @@ -0,0 +1,61 @@ +// +// MKCircleView.m +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKCircleView.h" +#import + +@implementation MKCircleView + + +- (id)initWithCircle:(MKCircle *)aCircle +{ + if (self = [super initWithOverlay:aCircle]) + { + } + return self; +} + +- (void)dealloc +{ + [latlngCenter release]; + [super dealloc]; +} + +- (MKCircle *)circle +{ + return [super overlay]; +} + + +- (NSString *)viewPrototypeName +{ + return @"google.maps.Circle"; +} + +- (NSDictionary *)options +{ + NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:[super options]]; + + [options setObject:[NSNumber numberWithFloat:[self circle].radius] forKey:@"radius"]; + + if (latlngCenter) + [options setObject:latlngCenter forKey:@"center"]; + + return [[options copy] autorelease]; +} + +- (void)draw:(WebScriptObject *)overlayScriptObject +{ + [latlngCenter release]; + NSString *script = [NSString stringWithFormat:@"new google.maps.LatLng(%f, %f);", self.circle.coordinate.latitude, self.circle.coordinate.longitude]; + latlngCenter = (WebScriptObject *)[overlayScriptObject evaluateWebScript:script]; + [latlngCenter retain]; + [super draw:overlayScriptObject]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKGeocoder.h b/External Source/MacMapKit/Source/Framework/Classes/MKGeocoder.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKGeocoder.h rename to External Source/MacMapKit/Source/Framework/Classes/MKGeocoder.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKGeocoder.m b/External Source/MacMapKit/Source/Framework/Classes/MKGeocoder.m new file mode 100644 index 000000000..a5ad1ac88 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKGeocoder.m @@ -0,0 +1,249 @@ +// +// MKGeocoder.m +// MapKit +// +// Created by Rick Fillion on 11-01-02. +// Copyright 2011 Centrix.ca. All rights reserved. +// + +/* + Note: Read comments at the top of MKReverseGeocoder, as they apply here too. + */ + +#import "MKGeocoder.h" +#import "JSON.h" +#import "MKPlacemark+Private.h" + +@interface MKGeocoder (WebViewIntegration) + +- (void)didSucceedWithResult:(NSString *)jsonEncodedGeocoderResult; +- (void)didFailWithError:(NSString *)status; +- (void)didReachQueryLimit; + +@end + + +@interface MKGeocoder (Private) + +- (void)createWebView; +- (void)destroyWebView; +- (void)_start; + +@end + + +@implementation MKGeocoder + +@synthesize delegate; +@synthesize address; +@synthesize coordinate; +@synthesize querying; + ++ (NSString *) webScriptNameForSelector:(SEL)sel +{ + NSString *name = nil; + + if (sel == @selector(didSucceedWithResult:)) + { + name = @"didSucceedWithResult"; + } + + if (sel == @selector(didFailWithError:)) + { + name = @"didFailWithError"; + } + + if (sel == @selector(didReachQueryLimit)) + { + name = @"didReachQueryLimit"; + } + + + return name; +} + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(didSucceedWithResult:)) + { + return NO; + } + + if (aSelector == @selector(didFailWithError:)) + { + return NO; + } + + if (aSelector == @selector(didReachQueryLimit)) + { + return NO; + } + + return YES; +} + + +- (id)initWithAddress:(NSString *)anAddress +{ + if (self = [super init]) + { + [self createWebView]; + address = [anAddress retain]; + hasOriginatingCoordinate = NO; + } + return self; +} + +- (id)initWithAddress:(NSString *)anAddress nearCoordinate:(CLLocationCoordinate2D)aCoordinate +{ + if (self = [super init]) + { + [self createWebView]; + address = [anAddress retain]; + hasOriginatingCoordinate = YES; + originatingCoordinate = aCoordinate; + } + return self; +} + + +- (void)dealloc +{ + [address release]; + [self destroyWebView]; + [super dealloc]; +} + + +- (void)start +{ + if (querying) + return; + querying = YES; + if (webViewLoaded) + [self _start]; +} + +- (void)cancel +{ + if (!querying) + return; + querying = NO; +} + +#pragma mark WebViewIntegration + +- (void)didSucceedWithResult:(NSString *)jsonEncodedGeocoderResult; +{ + //NSLog(@"didSucceedWithResult: %@", jsonEncodedGeocoderResult); + if (!querying) + return; + + id result = [jsonEncodedGeocoderResult JSONValue]; + MKPlacemark *aPlacemark = [[MKPlacemark alloc] initWithGoogleGeocoderResult: result]; + coordinate = aPlacemark.coordinate; + [aPlacemark release]; + + if (delegate && [delegate respondsToSelector:@selector(geocoder:didFindCoordinate:)]) + { + [delegate geocoder:self didFindCoordinate:self.coordinate]; + } + + querying = NO; +} + + + +- (void)didFailWithError:(NSString *)domain +{ + //NSLog(@"didFailWithErorr: %@", domain); + if (!querying) + return; + + NSError *error = [NSError errorWithDomain:domain code:0 userInfo:nil]; + // TODO create error + + if (delegate && [delegate respondsToSelector:@selector(geocoder:didFailWithError:)]) + { + [delegate geocoder:self didFailWithError:error]; + } + querying = NO; +} + +- (void)didReachQueryLimit +{ + // Retry again in half a second + if (self.querying) + { + [self performSelector:@selector(_start) withObject:nil afterDelay:0.5]; + } +} + +#pragma mark WebFrameLoadDelegate + +- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowScriptObject forFrame:(WebFrame *)frame +{ + //NSLog(@"didClearWindowObjet"); + [windowScriptObject setValue:self forKey:@"MKGeocoder"]; +} + + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + //NSLog(@"didFinishLoad:"); + [[webView windowScriptObject] setValue:self forKey:@"MKGeocoder"]; + webViewLoaded = YES; + if (self.querying && [sender mainFrame] == frame) + { + [self _start]; + } +} + +#pragma mark Private + +- (void)createWebView +{ + // TODO : make this suck less. + NSBundle *frameworkBundle = [NSBundle bundleForClass:[MKGeocoder class]]; + NSString *indexPath = [frameworkBundle pathForResource:@"MapKit" ofType:@"html"]; + webView = [[WebView alloc] initWithFrame:NSZeroRect frameName:nil groupName:nil]; + [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:indexPath]]]; + [[webView windowScriptObject] setValue:self forKey:@"MKGeocoder"]; + [webView setFrameLoadDelegate:self]; +} + +- (void)destroyWebView +{ + [webView close]; + [webView release]; +} + +- (void)_start +{ + //NSLog(@"start"); + NSArray *args = nil; + if (hasOriginatingCoordinate) + args = [NSArray arrayWithObjects: + self.address, + [NSNumber numberWithDouble:originatingCoordinate.latitude], + [NSNumber numberWithDouble:originatingCoordinate.longitude], + nil]; + else { + args = [NSArray arrayWithObject: self.address]; + } + + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + //NSLog(@"got webscriptobject"); + id val = [webScriptObject callWebScriptMethod:@"geocode" withArguments:args]; + //NSLog(@"val = %@", val); + if (!val) + { + // something went wrong, call the failure delegate + //NSLog(@"MKReverseGeocoder tried to start but the script wasn't ready, rescheduling"); + [self performSelector:@selector(_start) withObject:nil afterDelay:0.1]; + } +} + + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKGeometry.h b/External Source/MacMapKit/Source/Framework/Classes/MKGeometry.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKGeometry.h rename to External Source/MacMapKit/Source/Framework/Classes/MKGeometry.h diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKMapView+Additions.h b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Additions.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKMapView+Additions.h rename to External Source/MacMapKit/Source/Framework/Classes/MKMapView+Additions.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Additions.m b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Additions.m new file mode 100644 index 000000000..2e7ab2e0a --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Additions.m @@ -0,0 +1,49 @@ +// +// MKMapView+Additions.m +// MapKit +// +// Created by Rick Fillion on 7/24/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKMapView+Additions.h" + + +@implementation MKMapView (Additions) + +- (void)addJavascriptTag:(NSString *)urlString +{ + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSURL *url = [NSURL URLWithString:urlString]; + NSArray *args = [NSArray arrayWithObject:[url filePathURL]]; + [webScriptObject callWebScriptMethod:@"addJavascriptTag" withArguments:args]; +} + +- (void)addStylesheetTag:(NSString *)urlString +{ + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSArray *args = [NSArray arrayWithObject:urlString]; + [webScriptObject callWebScriptMethod:@"addStylesheetTag" withArguments:args]; +} + +- (void)showAddress:(NSString *)address +{ + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSArray *args = [NSArray arrayWithObject:address]; + [webScriptObject callWebScriptMethod:@"showAddress" withArguments:args]; +} + +#pragma mark NSControl + +- (void)takeStringValueFrom:(id)sender +{ + if (![sender respondsToSelector:@selector(stringValue)]) + { + NSLog(@"sender must respond to -stringValue"); + return; + } + NSString *stringValue = [sender stringValue]; + [self showAddress:stringValue]; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+DelegateWrappers.h b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+DelegateWrappers.h new file mode 100644 index 000000000..a2ae312d7 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+DelegateWrappers.h @@ -0,0 +1,46 @@ +// +// MKMapView+DelegateWrappers.h +// MapKit +// +// Created by Rick Fillion on 7/22/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import + +@interface MKMapView (DelegateWrappers) + +// Map Position Changes +- (void)delegateRegionWillChangeAnimated:(BOOL)animated; +- (void)delegateRegionDidChangeAnimated:(BOOL)animated; + +// Loading the Map Data +- (void)delegateWillStartLoadingMap; +- (void)delegateDidFinishLoadingMap; +- (void)delegateDidFailLoadingMapWithError:(NSError *)error; + +// Tracking the User Location +- (void)delegateDidUpdateUserLocation; +- (void)delegateDidFailToLocateUserWithError:(NSError *)error; +- (void)delegateWillStartLocatingUser; +- (void)delegateDidStopLocatingUser; + +// Managing Annotation Views +- (void)delegateDidAddAnnotationViews:(NSArray *)annotationViews; + +// Dragging an Annotation View +- (void)delegateAnnotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState; + +// Selecting Annotation Views +- (void)delegateDidSelectAnnotationView:(MKAnnotationView *)view; +- (void)delegateDidDeselectAnnotationView:(MKAnnotationView *)view; + +// Managing Overlay Views +- (void)delegateDidAddOverlayViews:(NSArray *)overlayViews; + +// MacMapKit additions +- (void)delegateUserDidClickAndHoldAtCoordinate:(CLLocationCoordinate2D)coordinate; +- (NSArray *)delegateContextMenuItemsForAnnotationView:(MKAnnotationView *)view; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+DelegateWrappers.m b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+DelegateWrappers.m new file mode 100644 index 000000000..46162d8cd --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+DelegateWrappers.m @@ -0,0 +1,149 @@ +// +// MKMapView+DelegateWrappers.m +// MapKit +// +// Created by Rick Fillion on 7/22/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKMapView+DelegateWrappers.h" + + +@implementation MKMapView (DelegateWrappers) + +- (void)delegateRegionWillChangeAnimated:(BOOL)animated +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)]) + { + [delegate mapView:self regionWillChangeAnimated:animated]; + } +} + +- (void)delegateRegionDidChangeAnimated:(BOOL)animated +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)]) + { + [delegate mapView:self regionDidChangeAnimated:animated]; + } +} + +- (void)delegateDidUpdateUserLocation +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:didUpdateUserLocation:)]) + { + [delegate mapView:self didUpdateUserLocation:userLocation]; + } +} + +- (void)delegateDidFailToLocateUserWithError:(NSError *)error +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:didFailToLocateUserWithError:)]) + { + [delegate mapView:self didFailToLocateUserWithError:error]; + } +} + +- (void)delegateWillStartLocatingUser +{ + if (delegate && [delegate respondsToSelector:@selector(mapViewWillStartLocatingUser:)]) + { + [delegate mapViewWillStartLocatingUser:self]; + } +} + +- (void)delegateDidStopLocatingUser +{ + if (delegate && [delegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]) + { + [delegate mapViewDidStopLocatingUser:self]; + } +} + +- (void)delegateDidAddOverlayViews:(NSArray *)someOverlayViews +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:didAddOverlayViews:)]) + { + [delegate mapView:self didAddOverlayViews:someOverlayViews]; + } +} + +- (void)delegateDidAddAnnotationViews:(NSArray *)someAnnotationViews +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:didAddAnnotationViews:)]) + { + [delegate mapView:self didAddAnnotationViews:someAnnotationViews]; + } +} + +- (void)delegateDidSelectAnnotationView:(MKAnnotationView *)view +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:didSelectAnnotationView:)]) + { + [delegate mapView:self didSelectAnnotationView:view]; + } +} + +- (void)delegateDidDeselectAnnotationView:(MKAnnotationView *)view +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:didDeselectAnnotationView:)]) + { + [delegate mapView:self didDeselectAnnotationView:view]; + } +} + +- (void)delegateAnnotationView:(MKAnnotationView *)annotationView + didChangeDragState:(MKAnnotationViewDragState)newState + fromOldState:(MKAnnotationViewDragState)oldState +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:annotationView:didChangeDragState:fromOldState:)]) + { + [delegate mapView:self annotationView:annotationView didChangeDragState:newState fromOldState:oldState]; + } +} + +- (void)delegateWillStartLoadingMap +{ + if (delegate && [delegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)]) + { + [delegate mapViewWillStartLoadingMap:self]; + } +} + +- (void)delegateDidFinishLoadingMap; +{ + if (delegate && [delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) + { + [delegate mapViewDidFinishLoadingMap:self]; + } +} + +- (void)delegateDidFailLoadingMapWithError:(NSError *)error +{ + if (delegate && [delegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)]) + { + [delegate mapViewDidFailLoadingMap:self withError:error]; + } +} + +// MacMapKit additions +- (void)delegateUserDidClickAndHoldAtCoordinate:(CLLocationCoordinate2D)coordinate; +{ + if (delegate && [delegate respondsToSelector:@selector(mapView:userDidClickAndHoldAtCoordinate:)]) + { + [delegate mapView:self userDidClickAndHoldAtCoordinate:coordinate]; + } + +} + +- (NSArray *)delegateContextMenuItemsForAnnotationView:(MKAnnotationView *)view +{ + NSArray *items = [NSArray array]; + if (delegate && [delegate respondsToSelector:@selector(mapView:contextMenuItemsForAnnotationView:)]) + { + items = [delegate mapView:self contextMenuItemsForAnnotationView:view]; + } + return items; +} + + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Private.h b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Private.h new file mode 100644 index 000000000..c74a4f9ad --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Private.h @@ -0,0 +1,17 @@ +// +// MKMapView+Private.h +// MapKit +// +// Created by Rick Fillion on 11-06-28. +// Copyright 2011 Centrix.ca. All rights reserved. +// + +#import +#import "MKMapView.h" + +@interface MKMapView (Private) + +- (void)customInit; +- (void)loadMapKitHtml; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Private.m b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Private.m new file mode 100644 index 000000000..815d18915 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+Private.m @@ -0,0 +1,55 @@ +// +// MKMapView+Private.m +// MapKit +// +// Created by Rick Fillion on 11-06-28. +// Copyright 2011 Centrix.ca. All rights reserved. +// + +#import "MKMapView+Private.h" +#import "MKWebView.h" +#import "MKUserLocation.h" + +@implementation MKMapView (Private) + +- (void)customInit +{ + // Initialization code here. + if (!webView) + { + webView = [[MKWebView alloc] initWithFrame:[self bounds]]; + } + + [webView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [webView setFrameLoadDelegate:self]; + [webView setUIDelegate:self]; + [webView setMaintainsBackForwardList:NO]; + + // Create the overlay data structures + overlays = [[NSMutableArray array] retain]; + overlayViews = [[NSMapTable mapTableWithStrongToStrongObjects] retain]; + overlayScriptObjects = [[NSMapTable mapTableWithStrongToStrongObjects] retain]; + + // Create the annotation data structures + annotations = [[NSMutableArray array] retain]; + selectedAnnotations = [[NSMutableArray array] retain]; + annotationViews = [[NSMapTable mapTableWithStrongToStrongObjects] retain]; + annotationScriptObjects = [[NSMapTable mapTableWithStrongToStrongObjects] retain]; + + [self loadMapKitHtml]; + + // Create a user location + userLocation = [[MKUserLocation alloc] init]; +} + +- (void)loadMapKitHtml +{ + // TODO : make this suck less. + NSBundle *frameworkBundle = [NSBundle bundleForClass:[MKMapView class]]; + NSString *indexPath = [frameworkBundle pathForResource:@"MapKit" ofType:@"html"]; + [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:indexPath]]]; + [[[webView mainFrame] frameView] setAllowsScrolling:NO]; + [self addSubview:webView]; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+WebViewIntegration.h b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+WebViewIntegration.h new file mode 100644 index 000000000..e577ce83b --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+WebViewIntegration.h @@ -0,0 +1,29 @@ +// +// MKMapView+WebViewIntegration.h +// MapKit +// +// Created by Rick Fillion on 7/22/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import + +@interface MKMapView (WebViewIntegration) + +- (void)setUserLocationMarkerVisible:(BOOL)visible; +- (void)updateUserLocationMarkerWithLocaton:(CLLocation *)location; +- (void)updateOverlayZIndexes; +- (void)updateAnnotationZIndexes; +- (void)annotationScriptObjectSelected:(WebScriptObject *)annotationScriptObject; +- (void)annotationScriptObjectDragStart:(WebScriptObject *)annotationScriptObject; +- (void)annotationScriptObjectDrag:(WebScriptObject *)annotationScriptObject; +- (void)annotationScriptObjectDragEnd:(WebScriptObject *)annotationScriptObject; +- (void)annotationScriptObjectRightClick:(WebScriptObject *)annotationScriptObject; +- (void)webviewReportingRegionChange; +- (void)webviewReportingLoadFailure; +- (void)webviewReportingClick:(NSString *)jsonEncodedLatLng; +- (void)webviewReportingReloadGmaps; +- (CLLocationCoordinate2D)coordinateForAnnotationScriptObject:(WebScriptObject *)annotationScriptObject; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView+WebViewIntegration.m b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+WebViewIntegration.m new file mode 100644 index 000000000..4564494e0 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView+WebViewIntegration.m @@ -0,0 +1,393 @@ +// +// MKMapView+WebViewIntegration.m +// MapKit +// +// Created by Rick Fillion on 7/22/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKMapView+WebViewIntegration.h" +#import "MKMapView+DelegateWrappers.h" +#import "JSON.h" +#import "MKWebView.h" +#import "MKMapView+Private.h" + +// MKAnnotation has a readonly coordinate property, but draggable annotations +// need the ability to set them. +@protocol MKDraggableAnnotation + +// Center latitude and longitude of the annotion view. +@property (nonatomic, assign) CLLocationCoordinate2D coordinate; + +@end + + + +@implementation MKMapView (WebViewIntegration) + ++ (NSString *) webScriptNameForSelector:(SEL)sel +{ + NSString *name = nil; + + if (sel == @selector(annotationScriptObjectSelected:)) + { + name = @"annotationScriptObjectSelected"; + } + + if (sel == @selector(webviewReportingRegionChange)) + { + name = @"webviewReportingRegionChange"; + } + + if (sel == @selector(webviewReportingLoadFailure)) + { + name = @"webviewReportingLoadFailure"; + } + + if (sel == @selector(webviewReportingClick:)) + { + name = @"webviewReportingClick"; + } + + if (sel == @selector(webviewReportingReloadGmaps)) + { + name = @"webviewReportingReloadGmaps"; + } + + if (sel == @selector(annotationScriptObjectDragStart:)) + { + name = @"annotationScriptObjectDragStart"; + } + + if (sel == @selector(annotationScriptObjectDrag:)) + { + name = @"annotationScriptObjectDrag"; + } + + if (sel == @selector(annotationScriptObjectDragEnd:)) + { + name = @"annotationScriptObjectDragEnd"; + } + + if (sel == @selector(annotationScriptObjectRightClick:)) + { + name = @"annotationScriptObjectRightClick"; + } + + return name; +} + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(annotationScriptObjectSelected:)) + { + return NO; + } + + if (aSelector == @selector(webviewReportingRegionChange)) + { + return NO; + } + + if (aSelector == @selector(webviewReportingLoadFailure)) + { + return NO; + } + + if (aSelector == @selector(webviewReportingClick:)) + { + return NO; + } + + if (aSelector == @selector(webviewReportingReloadGmaps)) + { + return NO; + } + + if (aSelector == @selector(annotationScriptObjectDragStart:)) + { + return NO; + } + + if (aSelector == @selector(annotationScriptObjectDrag:)) + { + return NO; + } + + if (aSelector == @selector(annotationScriptObjectDragEnd:)) + { + return NO; + } + + if (aSelector == @selector(annotationScriptObjectRightClick:)) + { + return NO; + } + + return YES; +} + + +- (void)setUserLocationMarkerVisible:(BOOL)visible +{ + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithBool:visible], + nil]; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + [webScriptObject callWebScriptMethod:@"setUserLocationVisible" withArguments:args]; + //NSLog(@"calling setUserLocationVisible with %@", args); +} + +- (void)updateUserLocationMarkerWithLocaton:(CLLocation *)location +{ + WebScriptObject *webScriptObject = [webView windowScriptObject]; + + CLLocationAccuracy accuracy = MAX(location.horizontalAccuracy, location.verticalAccuracy); + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithDouble: accuracy], + nil]; + [webScriptObject callWebScriptMethod:@"setUserLocationRadius" withArguments:args]; + //NSLog(@"calling setUserLocationRadius with %@", args); + args = [NSArray arrayWithObjects: + [NSNumber numberWithDouble:location.coordinate.latitude], + [NSNumber numberWithDouble:location.coordinate.longitude], + nil]; + [webScriptObject callWebScriptMethod:@"setUserLocationLatitudeLongitude" withArguments:args]; + //NSLog(@"caling setUserLocationLatitudeLongitude with %@", args); +} + +- (void)updateOverlayZIndexes +{ + //NSLog(@"updating overlay z indexes of :%@", overlays); + NSUInteger zIndex = 4000; // some arbitrary starting value + WebScriptObject *webScriptObject = [webView windowScriptObject]; + for (id overlay in overlays) + { + WebScriptObject *overlayScriptObject = (WebScriptObject *)[overlayScriptObjects objectForKey: overlay]; + if (overlayScriptObject) + { + NSArray *args = [NSArray arrayWithObjects: overlayScriptObject, @"zIndex", [NSNumber numberWithInteger:zIndex], nil]; + [webScriptObject callWebScriptMethod:@"setOverlayOption" withArguments:args]; + } + zIndex++; + } +} + +- (void)updateAnnotationZIndexes +{ + NSUInteger zIndex = 6000; // some arbitrary starting value + WebScriptObject *webScriptObject = [webView windowScriptObject]; + + NSArray *sortedAnnotations = [annotations sortedArrayUsingComparator: ^(id ann1, id ann2) { + if (ann1.coordinate.latitude < ann2.coordinate.latitude) { + return (NSComparisonResult)NSOrderedDescending; + } + + if (ann1.coordinate.latitude > ann2.coordinate.latitude) { + return (NSComparisonResult)NSOrderedAscending; + } + return (NSComparisonResult)NSOrderedSame; + }]; + + for (id annotation in sortedAnnotations) + { + WebScriptObject *overlayScriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + if (overlayScriptObject) + { + NSArray *args = [NSArray arrayWithObjects: overlayScriptObject, @"zIndex", [NSNumber numberWithInteger:zIndex], nil]; + [webScriptObject callWebScriptMethod:@"setOverlayOption" withArguments:args]; + } + zIndex++; + } +} + +- (void)annotationScriptObjectSelected:(WebScriptObject *)annotationScriptObject +{ + // Deselect everything that was selected + [self setSelectedAnnotations:[NSArray array]]; + + for (id annotation in annotations) + { + WebScriptObject *scriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + if ([scriptObject isEqual:annotationScriptObject]) + { + [self selectAnnotation:annotation animated:NO]; + } + } +} + +- (void)annotationScriptObjectDragStart:(WebScriptObject *)annotationScriptObject +{ + //NSLog(@"annotationScriptObjectDragStart:"); + for (id annotation in annotations) + { + WebScriptObject *scriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + if ([scriptObject isEqual:annotationScriptObject]) + { + // it has to be an annotation that actually supports moving. + if ([annotation respondsToSelector:@selector(setCoordinate:)]) + { + MKAnnotationView *view = (MKAnnotationView *)[annotationViews objectForKey: annotation]; + view.dragState = MKAnnotationViewDragStateStarting; + [self delegateAnnotationView:view didChangeDragState:MKAnnotationViewDragStateStarting fromOldState:MKAnnotationViewDragStateNone]; + } + } + } +} + +- (void)annotationScriptObjectDrag:(WebScriptObject *)annotationScriptObject +{ + //NSLog(@"annotationScriptObjectDrag:"); + for (id annotation in annotations) + { + WebScriptObject *scriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + if ([scriptObject isEqual:annotationScriptObject]) + { + // it has to be an annotation that actually supports moving. + if ([annotation respondsToSelector:@selector(setCoordinate:)]) + { + CLLocationCoordinate2D newCoordinate = [self coordinateForAnnotationScriptObject:annotationScriptObject]; + [(id )annotation setCoordinate:newCoordinate]; + MKAnnotationView *view = (MKAnnotationView *)[annotationViews objectForKey: annotation]; + if (view.dragState != MKAnnotationViewDragStateDragging) + { + view.dragState = MKAnnotationViewDragStateNone; + [self delegateAnnotationView:view didChangeDragState:MKAnnotationViewDragStateDragging fromOldState:MKAnnotationViewDragStateStarting]; + } + } + } + } +} + +- (void)annotationScriptObjectDragEnd:(WebScriptObject *)annotationScriptObject +{ + //NSLog(@"annotationScriptObjectDragEnd"); + for (id annotation in annotations) + { + WebScriptObject *scriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + if ([scriptObject isEqual:annotationScriptObject]) + { + // it has to be an annotation that actually supports moving. + if ([annotation respondsToSelector:@selector(setCoordinate:)]) + { + CLLocationCoordinate2D newCoordinate = [self coordinateForAnnotationScriptObject:annotationScriptObject]; + [(id )annotation setCoordinate:newCoordinate]; + MKAnnotationView *view = (MKAnnotationView *)[annotationViews objectForKey: annotation]; + view.dragState = MKAnnotationViewDragStateNone; + [self delegateAnnotationView:view didChangeDragState:MKAnnotationViewDragStateNone fromOldState:MKAnnotationViewDragStateDragging]; + } + } + } +} + +- (void)webviewReportingRegionChange +{ + [self delegateRegionDidChangeAnimated:NO]; + [self willChangeValueForKey:@"centerCoordinate"]; + [self didChangeValueForKey:@"centerCoordinate"]; + [self willChangeValueForKey:@"region"]; + [self didChangeValueForKey:@"region"]; +} + +- (void)webviewReportingLoadFailure +{ + NSError *error = [NSError errorWithDomain:@"ca.centrix.MapKit" code:0 userInfo:nil]; + [self delegateDidFailLoadingMapWithError:error]; +} + +- (void)webviewReportingClick:(NSString *)jsonEncodedLatLng +{ + // Deselect all annoations + NSArray * currentlySelectedAnnotations = [self selectedAnnotations]; + for (id annotation in currentlySelectedAnnotations) + { + [self deselectAnnotation:annotation animated:YES]; + } + + // Give the delegate the opportunity to do something + // if the clicked and held for more than 0.5 secs. + NSTimeInterval timeSinceMouseDown = [[NSDate date] timeIntervalSinceDate:[webView lastHitTestDate]]; + if (timeSinceMouseDown > 0.5) + { + NSDictionary *latlong = [jsonEncodedLatLng JSONValue]; + NSNumber *latitude = [latlong objectForKey:@"latitude"]; + NSNumber *longitude = [latlong objectForKey:@"longitude"]; + CLLocationCoordinate2D coordinate; + coordinate.latitude = [latitude doubleValue]; + coordinate.longitude = [longitude doubleValue]; + [self delegateUserDidClickAndHoldAtCoordinate:coordinate]; + } +} + +- (void)webviewReportingReloadGmaps +{ + [self loadMapKitHtml]; +} + +- (void)annotationScriptObjectRightClick:(WebScriptObject *)annotationScriptObject +{ + //NSLog(@"annotationScriptObjectRightClick"); + + // Find the actual MKAnnotationView + MKAnnotationView *annotationView = nil; + for (id annotation in annotations) + { + WebScriptObject *scriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + if ([scriptObject isEqual:annotationScriptObject]) + { + annotationView = (MKAnnotationView *)[annotationViews objectForKey: annotation]; + } + } + + // If not found, bail. + if (!annotationView) + return; + + + // Create a corresponding NSEvent object so that we can popup a context menu + NSPoint pointOnScreen = [NSEvent mouseLocation]; + NSPoint pointInBase = [[self window] convertScreenToBase: pointOnScreen]; + + NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseUp + location:pointInBase + modifierFlags:[NSEvent modifierFlags] + timestamp:0 + windowNumber:[[self window] windowNumber] + context:[NSGraphicsContext currentContext] + eventNumber:0 + clickCount:1 + pressure:1.0]; + + // Create the menu and display it if it has anything. + NSMenu *menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; + NSArray *items = [self delegateContextMenuItemsForAnnotationView:annotationView]; + if ([items count] > 0) + { + for (NSMenuItem *item in items) + { + [menu addItem:item]; + } + [NSMenu popUpContextMenu:menu withEvent:event forView:self]; + } +} + +- (CLLocationCoordinate2D)coordinateForAnnotationScriptObject:(WebScriptObject *)annotationScriptObject +{ + CLLocationCoordinate2D coord; + coord.latitude = 0.0; + coord.longitude = 0.0; + WebScriptObject *windowScriptObject = [webView windowScriptObject]; + + NSString *json = [windowScriptObject callWebScriptMethod:@"coordinateForAnnotation" withArguments:[NSArray arrayWithObject:annotationScriptObject]]; + NSDictionary *latlong = [json JSONValue]; + NSNumber *latitude = [latlong objectForKey:@"latitude"]; + NSNumber *longitude = [latlong objectForKey:@"longitude"]; + + coord.latitude = [latitude doubleValue]; + coord.longitude = [longitude doubleValue]; + + return coord; +} + + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKMapView.h b/External Source/MacMapKit/Source/Framework/Classes/MKMapView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKMapView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKMapView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMapView.m b/External Source/MacMapKit/Source/Framework/Classes/MKMapView.m new file mode 100644 index 000000000..c3afc01a7 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMapView.m @@ -0,0 +1,675 @@ +// +// MKMapView.m +// MapKit +// +// Created by Rick Fillion on 7/11/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKMapView.h" +#import "MKMapView+Private.h" +#import "JSON.h" +#import +#import "MKUserLocation+Private.h" +#import +#import +#import +#import +#import +#import +#import "MKMapView+DelegateWrappers.h" +#import "MKMapView+WebViewIntegration.h" +#import "MKWebView.h" + + +@implementation MKMapView + +@synthesize delegate, mapType, userLocation, showsUserLocation; + + +- (id)initWithFrame:(NSRect)frame { + if (self = [super initWithFrame:frame]) + { + [self customInit]; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)decoder +{ + if (self = [super initWithCoder:decoder]) + { + [self customInit]; + [self setMapType:[decoder decodeIntegerForKey:@"mapType"]]; + [self setShowsUserLocation:[decoder decodeBoolForKey:@"showsUserLocation"]]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)encoder +{ + [super encodeWithCoder:encoder]; + //[encoder encodeObject:webView forKey:@"webView"]; + [encoder encodeInteger:[self mapType] forKey:@"mapType"]; + [encoder encodeBool:[self showsUserLocation] forKey:@"showsUserLocation"]; +} + +- (void)dealloc +{ + [webView close]; + [webView setFrameLoadDelegate:nil]; + delegate = nil; + [webView removeFromSuperview]; + [webView autorelease]; + [locationManager stopUpdatingLocation]; + [locationManager release]; + [userLocation release]; + [overlays release]; + [overlayViews release]; + [overlayScriptObjects release]; + [annotations release]; + [selectedAnnotations release]; + [annotationViews release]; + [annotationScriptObjects release]; + [super dealloc]; +} + +- (void)setFrame:(NSRect)frameRect +{ + [self delegateRegionWillChangeAnimated:NO]; + [super setFrame:frameRect]; + [self willChangeValueForKey:@"region"]; + [self didChangeValueForKey:@"region"]; + [self willChangeValueForKey:@"centerCoordinate"]; + [self didChangeValueForKey:@"centerCoordinate"]; + [self delegateRegionDidChangeAnimated:NO]; +} + +- (void)setMapType:(MKMapType)type +{ + mapType = type; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSArray *args = [NSArray arrayWithObject:[NSNumber numberWithInt:mapType]]; + [webScriptObject callWebScriptMethod:@"setMapType" withArguments:args]; +} + +- (CLLocationCoordinate2D)centerCoordinate +{ + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSNumber *latitude = nil; + NSNumber *longitude = nil; + NSString *json = [webScriptObject evaluateWebScript:@"getCenterCoordinate()"]; + if ([json isKindOfClass:[NSString class]]) + { + NSDictionary *latlong = [json JSONValue]; + latitude = [latlong objectForKey:@"latitude"]; + longitude = [latlong objectForKey:@"longitude"]; + } + + CLLocationCoordinate2D centerCoordinate; + centerCoordinate.latitude = [latitude doubleValue]; + centerCoordinate.longitude = [longitude doubleValue]; + return centerCoordinate; +} + +- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate +{ + [self setCenterCoordinate:coordinate animated: NO]; +} + +- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated +{ + [self willChangeValueForKey:@"region"]; + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithDouble:coordinate.latitude], + [NSNumber numberWithDouble:coordinate.longitude], + [NSNumber numberWithBool:animated], + nil]; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + [webScriptObject callWebScriptMethod:@"setCenterCoordinateAnimated" withArguments:args]; + [self didChangeValueForKey:@"region"]; + hasSetCenterCoordinate = YES; +} + + +- (MKCoordinateRegion)region +{ + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSString *json = [webScriptObject evaluateWebScript:@"getRegion()"]; + NSDictionary *regionDict = [json JSONValue]; + + NSNumber *centerLatitude = [regionDict valueForKeyPath:@"center.latitude"]; + NSNumber *centerLongitude = [regionDict valueForKeyPath:@"center.longitude"]; + NSNumber *latitudeDelta = [regionDict objectForKey:@"latitudeDelta"]; + NSNumber *longitudeDelta = [regionDict objectForKey:@"longitudeDelta"]; + + MKCoordinateRegion region; + region.center.longitude = [centerLongitude doubleValue]; + region.center.latitude = [centerLatitude doubleValue]; + region.span.latitudeDelta = [latitudeDelta doubleValue]; + region.span.longitudeDelta = [longitudeDelta doubleValue]; + return region; +} + +- (void)setRegion:(MKCoordinateRegion)region +{ + [self setRegion:region animated: NO]; +} + +- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated +{ + [self delegateRegionWillChangeAnimated:animated]; + [self willChangeValueForKey:@"centerCoordinate"]; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithDouble:region.center.latitude], + [NSNumber numberWithDouble:region.center.longitude], + [NSNumber numberWithDouble:region.span.latitudeDelta], + [NSNumber numberWithDouble:region.span.longitudeDelta], + [NSNumber numberWithBool:animated], + nil]; + [webScriptObject callWebScriptMethod:@"setRegionAnimated" withArguments:args]; + [self didChangeValueForKey:@"centerCoordinate"]; + [self delegateRegionDidChangeAnimated:animated]; +} + +- (void)setShowsUserLocation:(BOOL)show +{ + BOOL oldValue = showsUserLocation; + showsUserLocation = show; + + if (oldValue == NO && showsUserLocation == YES) + { + [self delegateWillStartLocatingUser]; + // To be sure we get all of the delegate calls from CoreLocation, we have to recreate the manager. + // Unfortunately if you just call stop/start, it'll never resend the kCLErrorDenied error. + locationManager = [[CLLocationManager alloc] init]; + locationManager.delegate = self; + locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; + } + + if (showsUserLocation) + { + [userLocation _setUpdating:YES]; + [locationManager startUpdatingLocation]; + } + else + { + [self setUserLocationMarkerVisible: NO]; + [userLocation _setUpdating:NO]; + [locationManager stopUpdatingLocation]; + [locationManager release]; + locationManager = nil; + [userLocation _setLocation:nil]; + } + + if (oldValue == YES && showsUserLocation == NO) + { + [self delegateDidStopLocatingUser]; + } +} + +- (BOOL)isUserLocationVisible +{ + if (!self.showsUserLocation || !userLocation.location) + return NO; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSNumber *visible = [webScriptObject callWebScriptMethod:@"isUserLocationVisible" withArguments:[NSArray array]]; + return [visible boolValue]; +} + +#pragma mark Overlays + +- (NSArray *)overlays +{ + return [[overlays copy] autorelease]; +} + +- (void)addOverlay:(id < MKOverlay >)overlay +{ + [self insertOverlay:overlay atIndex:[overlays count]]; +} + +- (void)addOverlays:(NSArray *)someOverlays +{ + for (idoverlay in someOverlays) + { + [self addOverlay: overlay]; + } +} + +- (void)exchangeOverlayAtIndex:(NSUInteger)index1 withOverlayAtIndex:(NSUInteger)index2 +{ + if (index1 >= [overlays count] || index2 >= [overlays count]) + { + NSLog(@"exchangeOverlayAtIndex: either index1 or index2 is above the bounds of the overlays array."); + return; + } + + id < MKOverlay > overlay1 = [[overlays objectAtIndex: index1] retain]; + id < MKOverlay > overlay2 = [[overlays objectAtIndex: index2] retain]; + [overlays replaceObjectAtIndex:index2 withObject:overlay1]; + [overlays replaceObjectAtIndex:index1 withObject:overlay2]; + [overlay1 release]; + [overlay2 release]; + [self updateOverlayZIndexes]; +} + +- (void)insertOverlay:(id < MKOverlay >)overlay aboveOverlay:(id < MKOverlay >)sibling +{ + if (![overlays containsObject:sibling]) + return; + + NSUInteger indexOfSibling = [overlays indexOfObject:sibling]; + [self insertOverlay:overlay atIndex: indexOfSibling+1]; +} + +- (void)insertOverlay:(id < MKOverlay >)overlay atIndex:(NSUInteger)index +{ + // check if maybe we already have this one. + if ([overlays containsObject:overlay]) + return; + + // Make sure we have a valid index. + if (index > [overlays count]) + index = [overlays count]; + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + if ([webScriptObject isKindOfClass:[WebUndefined class]]) + { + NSLog(@"MapKit view isn't ready to add overlay: %@", overlay); + return; + } + + MKOverlayView *overlayView = nil; + if ([self.delegate respondsToSelector:@selector(mapView:viewForOverlay:)]) + overlayView = [self.delegate mapView:self viewForOverlay:overlay]; + if (!overlayView) + { + // TODO: Handle the case where we have no view + NSLog(@"Wasn't able to create a MKOverlayView for overlay: %@", overlay); + return; + } + + WebScriptObject *overlayScriptObject = [overlayView overlayScriptObjectFromMapScriptObject:webScriptObject]; + if (![overlayScriptObject isKindOfClass:[WebScriptObject class]]) + { + NSLog(@"Error creating internal representation of overlay view for overlay: %@", overlay); + return; + } + + [overlays insertObject:overlay atIndex:index]; + [overlayViews setObject:overlayView forKey:overlay]; + [overlayScriptObjects setObject:overlayScriptObject forKey:overlay]; + + NSArray *args = [NSArray arrayWithObject:overlayScriptObject]; + [webScriptObject callWebScriptMethod:@"addOverlay" withArguments:args]; + [overlayView draw:overlayScriptObject]; + + [self updateOverlayZIndexes]; + + // TODO: refactor how this works so that we can send one batch call + // when they called addOverlays: + [self delegateDidAddOverlayViews:[NSArray arrayWithObject:overlayView]]; +} + +- (void)insertOverlay:(id < MKOverlay >)overlay belowOverlay:(id < MKOverlay >)sibling +{ + if (![overlays containsObject:sibling]) + return; + + NSUInteger indexOfSibling = [overlays indexOfObject:sibling]; + [self insertOverlay:overlay atIndex: indexOfSibling]; +} + +- (void)removeOverlay:(id < MKOverlay >)overlay +{ + if (![overlays containsObject:overlay]) + return; + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + WebScriptObject *overlayScriptObject = (WebScriptObject *)[overlayScriptObjects objectForKey: overlay]; + NSArray *args = [NSArray arrayWithObject:overlayScriptObject]; + [webScriptObject callWebScriptMethod:@"removeOverlay" withArguments:args]; + + [overlayViews removeObjectForKey:overlay]; + [overlayScriptObjects removeObjectForKey:overlay]; + + [overlays removeObject:overlay]; + [self updateOverlayZIndexes]; +} + +- (void)removeOverlays:(NSArray *)someOverlays +{ + for (idoverlay in someOverlays) + { + [self removeOverlay: overlay]; + } +} + +- (MKOverlayView *)viewForOverlay:(id < MKOverlay >)overlay +{ + if (![overlays containsObject:overlay]) + return nil; + return (MKOverlayView *)[overlayViews objectForKey: overlay]; +} + +#pragma mark Annotations + +- (NSArray *)annotations +{ + return [[annotations copy] autorelease]; +} + +- (void)addAnnotation:(id < MKAnnotation >)annotation +{ + // check if maybe we already have this one. + if ([annotations containsObject:annotation]) + return; + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + if ([webScriptObject isKindOfClass:[WebUndefined class]]) + { + NSLog(@"MapKit view isn't ready to add annotation: %@", annotation); + return; + } + + MKAnnotationView *annotationView = nil; + if ([self.delegate respondsToSelector:@selector(mapView:viewForAnnotation:)]) + annotationView = [self.delegate mapView:self viewForAnnotation:annotation]; + if (!annotationView) + { + // TODO: Handle the case where we have no view + NSLog(@"Wasn't able to create a MKAnnotationView for annotation: %@", annotation); + return; + } + + WebScriptObject *annotationScriptObject = [annotationView overlayScriptObjectFromMapScriptObject:webScriptObject]; + if (![annotationScriptObject isKindOfClass:[WebScriptObject class]]) + { + NSLog(@"Error creating internal representation of annotation view for annotation: %@", annotation); + return; + } + + [annotations addObject:annotation]; + [annotationViews setObject:annotationView forKey:annotation]; + [annotationScriptObjects setObject:annotationScriptObject forKey:annotation]; + + NSArray *args = [NSArray arrayWithObject:annotationScriptObject]; + [webScriptObject callWebScriptMethod:@"addAnnotation" withArguments:args]; + [annotationView draw:annotationScriptObject]; + + [self updateAnnotationZIndexes]; + + // TODO: refactor how this works so that we can send one batch call + // when they called addAnnotations: + [self delegateDidAddAnnotationViews:[NSArray arrayWithObject:annotationView]]; +} + +- (void)addAnnotations:(NSArray *)someAnnotations +{ + for (idannotation in someAnnotations) + { + [self addAnnotation: annotation]; + } +} + +- (void)removeAnnotation:(id < MKAnnotation >)annotation +{ + if (![annotations containsObject:annotation]) + return; + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + WebScriptObject *annotationScriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + NSArray *args = [NSArray arrayWithObject:annotationScriptObject]; + [webScriptObject callWebScriptMethod:@"removeAnnotation" withArguments:args]; + + [annotationViews removeObjectForKey: annotation]; + [annotationScriptObjects removeObjectForKey: annotation]; + + [annotations removeObject:annotation]; +} + +- (void)removeAnnotations:(NSArray *)someAnnotations +{ + for (idannotation in someAnnotations) + { + [self removeAnnotation: annotation]; + } +} + +- (MKAnnotationView *)viewForAnnotation:(id < MKAnnotation >)annotation +{ + if (![annotations containsObject:annotation]) + return nil; + return (MKAnnotationView *)[annotationViews objectForKey: annotation]; +} + +- (MKAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier +{ + // Unsupported for now. + return nil; +} + +- (void)selectAnnotation:(id < MKAnnotation >)annotation animated:(BOOL)animated +{ + if ([selectedAnnotations containsObject:annotation]) + return; + + MKAnnotationView *annotationView = (id)[annotationViews objectForKey: annotation]; + [selectedAnnotations addObject:annotation]; + [self delegateDidSelectAnnotationView:annotationView]; + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + WebScriptObject *annotationScriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + + if (annotation.title && annotationView.canShowCallout) + { + NSArray *args = [NSArray arrayWithObjects:annotationScriptObject, annotation.title, nil]; + [webScriptObject callWebScriptMethod:@"setAnnotationCalloutText" withArguments:args]; + args = [NSArray arrayWithObjects:annotationScriptObject, [NSNumber numberWithBool:NO], nil]; + [webScriptObject callWebScriptMethod:@"setAnnotationCalloutHidden" withArguments:args]; + } + +} + +- (void)deselectAnnotation:(id < MKAnnotation >)annotation animated:(BOOL)animated +{ +// TODO : animate this if called for. + if (![selectedAnnotations containsObject:annotation]) + return; + + MKAnnotationView *annotationView = (id)[annotationViews objectForKey: annotation]; + [selectedAnnotations removeObject:annotation]; + [self delegateDidDeselectAnnotationView:annotationView]; + + WebScriptObject *webScriptObject = [webView windowScriptObject]; + WebScriptObject *annotationScriptObject = (WebScriptObject *)[annotationScriptObjects objectForKey: annotation]; + + NSArray *args = [NSArray arrayWithObjects:annotationScriptObject, [NSNumber numberWithBool:YES], nil]; + [webScriptObject callWebScriptMethod:@"setAnnotationCalloutHidden" withArguments:args]; +} + +- (NSArray *)selectedAnnotations +{ + return [[selectedAnnotations copy] autorelease]; +} + +- (void)setSelectedAnnotations:(NSArray *)someAnnotations +{ + // Deselect whatever was selected + NSArray *oldSelectedAnnotations = [self selectedAnnotations]; + for (id annotation in oldSelectedAnnotations) + { + [self deselectAnnotation:annotation animated:NO]; + } + NSMutableArray *newSelectedAnnotations = [NSMutableArray arrayWithArray: [[someAnnotations copy] autorelease]]; + [selectedAnnotations release]; + selectedAnnotations = [newSelectedAnnotations retain]; + + // If it's manually set and there's more than one, you only select the first according to the docs. + if ([selectedAnnotations count] > 0) + [self selectAnnotation:[selectedAnnotations objectAtIndex:0] animated:NO]; +} + +#pragma mark Converting Map Coordinates + +- (NSPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(NSView *)view +{ + NSPoint point = {0,0}; + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithDouble:coordinate.latitude], + [NSNumber numberWithDouble:coordinate.longitude], + nil]; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + NSString *json = [webScriptObject callWebScriptMethod:@"convertCoordinate" withArguments:args]; + NSNumber *x = nil; + NSNumber *y = nil; + if ([json isKindOfClass:[NSString class]]) + { + NSDictionary *xy = [json JSONValue]; + x = [xy objectForKey:@"x"]; + y = [xy objectForKey:@"y"]; + } + + point.x = [x integerValue]; + point.y = [y integerValue]; + + point = [webView convertPoint:point toView:view]; + + return point; +} + +- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(NSView *)view +{ +// TODO: Implement + NSLog(@"-[MKMapView convertPoint: toCoordinateFromView:] not implemented yet"); + CLLocationCoordinate2D coordinate; + + return coordinate; +} + +- (MKCoordinateRegion)convertRect:(CGRect)rect toRegionFromView:(NSView *)view +{ +// TODO: Implement + NSLog(@"-[MKMapView convertRect: toRegionFromView:] not implemented yet"); + MKCoordinateRegion region; + + return region; +} + +- (NSRect)convertRegion:(MKCoordinateRegion)region toRectToView:(NSView *)view +{ +// TODO: Implement + NSLog(@"-[MKMapView convertRegion: toRectToView:] not implemented yet"); + return NSZeroRect; +} + +#pragma mark Faked Properties + +- (BOOL)isScrollEnabled +{ + return YES; +} + +- (void)setScrollEnabled:(BOOL)scrollEnabled +{ + if (!scrollEnabled) + NSLog(@"setting scrollEnabled to NO on MKMapView not supported."); +} + +- (BOOL)isZoomEnabled +{ + return YES; +} + +- (void)setZoomEnabled:(BOOL)zoomEnabled +{ + if (!zoomEnabled) + NSLog(@"setting zoomEnabled to NO on MKMapView not supported"); +} + + + +#pragma mark CoreLocationManagerDelegate + +- (void) locationManager: (CLLocationManager *)manager + didUpdateToLocation: (CLLocation *)newLocation + fromLocation: (CLLocation *)oldLocation +{ + if (!hasSetCenterCoordinate) + [self setCenterCoordinate:newLocation.coordinate]; + [userLocation _setLocation:newLocation]; + [self updateUserLocationMarkerWithLocaton:newLocation]; + [self setUserLocationMarkerVisible:YES]; + [self delegateDidUpdateUserLocation]; +} + +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error +{ + [self delegateDidFailToLocateUserWithError:error]; + [self setUserLocationMarkerVisible:NO]; + + if ([error code] == kCLErrorDenied) + { + [self setShowsUserLocation:NO]; + } +} + +#pragma mark WebFrameLoadDelegate + +- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowScriptObject forFrame:(WebFrame *)frame +{ + [windowScriptObject setValue:windowScriptObject forKey:@"WindowScriptObject"]; + [windowScriptObject setValue:self forKey:@"MKMapView"]; +} + +- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame +{ + if ([frame isEqual:[webView mainFrame]]) + [self delegateWillStartLoadingMap]; +} + +- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame +{ + if ([frame isEqual:[webView mainFrame]]) + [self delegateDidFailLoadingMapWithError:error]; +} + +- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame +{ + if ([frame isEqual:[webView mainFrame]]) + [self delegateDidFailLoadingMapWithError:error]; +} + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + // CoreLocation can sometimes trigger before the page has even finished loading. + if (self.showsUserLocation && userLocation.location) + { + [self locationManager: locationManager didUpdateToLocation: userLocation.location fromLocation:nil]; + } + + if ([frame isEqual:[webView mainFrame]]) + { + // In case we have to resume state from NSCoding + [self setMapType:[self mapType]]; + [self setShowsUserLocation:[self showsUserLocation]]; + + [self performSelector:@selector(delegateDidFinishLoadingMap) withObject:nil afterDelay:0.5]; + } +} + +#pragma mark WebUIDelegate + +- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems +{ + return [NSArray array]; +} + +- (NSUInteger)webView:(WebView *)sender dragDestinationActionMaskForDraggingInfo:(id )draggingInfo +{ + return WebDragDestinationActionNone; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKMultiPoint.h b/External Source/MacMapKit/Source/Framework/Classes/MKMultiPoint.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKMultiPoint.h rename to External Source/MacMapKit/Source/Framework/Classes/MKMultiPoint.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKMultiPoint.m b/External Source/MacMapKit/Source/Framework/Classes/MKMultiPoint.m new file mode 100644 index 000000000..d95a584ff --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKMultiPoint.m @@ -0,0 +1,26 @@ +// +// MKMultiPoint.m +// MapKit +// +// Created by Rick Fillion on 7/15/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKMultiPoint.h" + + +@implementation MKMultiPoint + +@synthesize coordinates; +@synthesize coordinateCount; + + +- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range +{ + for (int i = range.location; i < range.location+range.length; i++) + { + coords[i] = coordinates[i]; + } +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKOverlay.h b/External Source/MacMapKit/Source/Framework/Classes/MKOverlay.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKOverlay.h rename to External Source/MacMapKit/Source/Framework/Classes/MKOverlay.h diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKOverlayPathView.h b/External Source/MacMapKit/Source/Framework/Classes/MKOverlayPathView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKOverlayPathView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKOverlayPathView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKOverlayPathView.m b/External Source/MacMapKit/Source/Framework/Classes/MKOverlayPathView.m new file mode 100644 index 000000000..e2f03a784 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKOverlayPathView.m @@ -0,0 +1,56 @@ +// +// MKOverlayPathView.m +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKOverlayPathView.h" +#import "NSColor+Additions.h" + +@implementation MKOverlayPathView + +@synthesize fillColor, strokeColor, lineWidth; + +- (id)initWithOverlay:(id )anOverlay +{ + if (self = [super initWithOverlay:anOverlay]) + { + self.fillColor = [[NSColor redColor] colorWithAlphaComponent: 0.3]; + self.strokeColor = [NSColor redColor]; + self.lineWidth = 1.0; + } + return self; +} + +- (void)dealloc +{ + [fillColor release]; + [strokeColor release]; + [super dealloc]; +} + +- (NSDictionary *)options +{ + NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:[super options]]; + + [options setObject:[NSNumber numberWithFloat:lineWidth] forKey:@"strokeWeight"]; + [options setObject:[NSNumber numberWithBool:NO] forKey:@"clickable"]; + + if (fillColor) + { + [options setObject:[fillColor hexString] forKey:@"fillColor"]; + [options setObject:[NSNumber numberWithFloat:[fillColor alphaComponent]] forKey:@"fillOpacity"]; + } + if (strokeColor) + { + [options setObject:[strokeColor hexString] forKey:@"strokeColor"]; + [options setObject:[NSNumber numberWithFloat:[strokeColor alphaComponent]] forKey:@"strokeOpacity"]; + + } + + return [[options copy] autorelease]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKOverlayView.h b/External Source/MacMapKit/Source/Framework/Classes/MKOverlayView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKOverlayView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKOverlayView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKOverlayView.m b/External Source/MacMapKit/Source/Framework/Classes/MKOverlayView.m new file mode 100644 index 000000000..385781c46 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKOverlayView.m @@ -0,0 +1,33 @@ +// +// MKOverlayView.m +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKOverlayView.h" + +@implementation MKOverlayView + +@synthesize overlay; + +- (id)initWithOverlay:(id )anOverlay +{ + if (self = [super init]) + { + overlay = [anOverlay retain]; + } + return self; +} + + +- (void)dealloc +{ + [overlay release]; + [super dealloc]; +} + + + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPinAnnotationView.h b/External Source/MacMapKit/Source/Framework/Classes/MKPinAnnotationView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPinAnnotationView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPinAnnotationView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPinAnnotationView.m b/External Source/MacMapKit/Source/Framework/Classes/MKPinAnnotationView.m new file mode 100644 index 000000000..a59547eae --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPinAnnotationView.m @@ -0,0 +1,49 @@ +// +// MKPinAnnotationView.m +// MapKit +// +// Created by Rick Fillion on 7/18/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPinAnnotationView.h" + + +@implementation MKPinAnnotationView + +@synthesize pinColor; +@synthesize animatesDrop; + +- (id)initWithAnnotation:(id )anAnnotation reuseIdentifier:(NSString *)aReuseIdentifier +{ + if (self = [super initWithAnnotation:anAnnotation reuseIdentifier:aReuseIdentifier]) + { + self.canShowCallout = YES; + } + return self; +} + +- (NSString *)imageUrl +{ + NSBundle *bundle = [NSBundle bundleForClass:[MKPinAnnotationView class]]; + NSString *filename = nil; + switch (pinColor) { + case MKPinAnnotationColorRed: + filename = @"MKPinAnnotationColorRed"; + break; + case MKPinAnnotationColorGreen: + filename = @"MKPinAnnotationColorGreen"; + break; + case MKPinAnnotationColorPurple: + filename = @"MKPinAnnotationColorPurple"; + break; + default: + filename = @"MKPinAnnotationColorRed"; + break; + } + NSString *path = [bundle pathForResource:filename ofType:@"png"]; + NSURL *url = [NSURL fileURLWithPath:path]; + return [url absoluteString]; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark+Private.h b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark+Private.h new file mode 100644 index 000000000..0df7fee64 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark+Private.h @@ -0,0 +1,16 @@ +// +// MKPlacemark+Private.h +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import + +@interface MKPlacemark (Private) + +-(id)initWithGoogleGeocoderResult:(NSDictionary *)result; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark+Private.m b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark+Private.m new file mode 100644 index 000000000..540d2335e --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark+Private.m @@ -0,0 +1,87 @@ +// +// MKPlacemark+Private.m +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPlacemark+Private.h" + +@interface MKPlacemark (ReallyPrivate) + +- (CLLocationCoordinate2D)_coordinateFromGoogleGeocoderResult:(NSDictionary *)result; + +@end + + +@implementation MKPlacemark (Private) + +- (id)initWithGoogleGeocoderResult:(NSDictionary *)result +{ + if (self = [super init]) + { + coordinate = [self _coordinateFromGoogleGeocoderResult:result]; + NSArray *components = [result objectForKey:@"address_components"]; + if (components) + { + for (NSDictionary *component in components) + { + NSString *longValue = [component objectForKey:@"long_name"]; + NSString *shortValue = [component objectForKey:@"short_name"]; + NSArray *types = [component objectForKey:@"types"]; + for (NSString *type in types) + { + if ([type isEqualToString:@"street_number"]) + { + thoroughfare = [longValue retain]; + } + if ([type isEqualToString:@"route"]) + { + NSString *newThoroughfare = [thoroughfare stringByAppendingFormat:@" %@", longValue]; + [thoroughfare release]; + thoroughfare = [newThoroughfare retain]; + } + if ([type isEqualToString:@"locality"]) + { + locality = [longValue retain]; + } + if ([type isEqualToString:@"administrative_area_level_2"]) + { + subAdministrativeArea = [longValue retain]; + } + if ([type isEqualToString:@"administrative_area_level_1"]) + { + administrativeArea = [shortValue retain]; + } + if ([type isEqualToString:@"country"]) + { + country = [longValue retain]; + countryCode = [shortValue retain]; + } + } + } + } + + } + return self; +} + +#pragma mark - +#pragma mark Really Private + +- (CLLocationCoordinate2D)_coordinateFromGoogleGeocoderResult:(NSDictionary *)result +{ + NSDictionary *location = [result valueForKeyPath:@"geometry.location"]; + NSArray *orderedKeys = [[location allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSString *latitudeKey = [orderedKeys objectAtIndex:0]; + NSString *longitudeKey = [orderedKeys objectAtIndex:1]; + NSNumber *latitude = [location objectForKey:latitudeKey]; + NSNumber *longitude = [location objectForKey:longitudeKey]; + CLLocationCoordinate2D aCoordinate; + aCoordinate.latitude = [latitude doubleValue]; + aCoordinate.longitude = [longitude doubleValue]; + return aCoordinate; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPlacemark.h b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPlacemark.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPlacemark.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark.m b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark.m new file mode 100644 index 000000000..021d65671 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPlacemark.m @@ -0,0 +1,60 @@ +// +// MKPlacemark.m +// MapKit +// +// Created by Rick Fillion on 7/24/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPlacemark.h" + + +@implementation MKPlacemark + +@synthesize coordinate; +@synthesize addressDictionary; +@synthesize thoroughfare; +@synthesize subThoroughfare; +@synthesize locality; +@synthesize subLocality; +@synthesize administrativeArea; +@synthesize subAdministrativeArea; +@synthesize postalCode; +@synthesize country; +@synthesize countryCode; + +- (id)initWithCoordinate:(CLLocationCoordinate2D)aCoordinate + addressDictionary:(NSDictionary *)anAddressDictionary +{ + if (self = [super init]) + { + coordinate = aCoordinate; + addressDictionary = [anAddressDictionary retain]; + } + return self; +} + +- (void)dealloc +{ + [addressDictionary release]; + [thoroughfare release]; + [subThoroughfare release]; + [locality release]; + [subLocality release]; + [administrativeArea release]; + [subAdministrativeArea release]; + [postalCode release]; + [country release]; + [countryCode release]; + [super dealloc]; +} + +- (NSString *)description +{ + NSString *superDescription = [super description]; + return [superDescription stringByAppendingFormat: + @" (%f, %f) {thoroughfare: %@,\n subThoroughfare: %@,\n locality: %@,\n subLocality: %@,\n administrativeArea: %@,\n subAdministrativeArea: %@,\n postalCode: %@,\n country: %@,\n countryCode: %@\n}", + coordinate.latitude, coordinate.longitude, thoroughfare, subThoroughfare, locality, subLocality, administrativeArea, subAdministrativeArea, postalCode, country, countryCode]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPointAnnotation.h b/External Source/MacMapKit/Source/Framework/Classes/MKPointAnnotation.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPointAnnotation.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPointAnnotation.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPointAnnotation.m b/External Source/MacMapKit/Source/Framework/Classes/MKPointAnnotation.m new file mode 100644 index 000000000..050a6be51 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPointAnnotation.m @@ -0,0 +1,22 @@ +// +// MKPointAnnotation.m +// MapKit +// +// Created by Rick Fillion on 7/18/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPointAnnotation.h" + + +@implementation MKPointAnnotation + +@synthesize coordinate; + +- (NSString *)description +{ + NSString *superDescription = [super description]; + return [superDescription stringByAppendingFormat:@" <%f, %f> %@ - %@", self.coordinate.latitude, self.coordinate.longitude, self.title, self.subtitle]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPolygon.h b/External Source/MacMapKit/Source/Framework/Classes/MKPolygon.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPolygon.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPolygon.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPolygon.m b/External Source/MacMapKit/Source/Framework/Classes/MKPolygon.m new file mode 100644 index 000000000..35c9bc110 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPolygon.m @@ -0,0 +1,69 @@ +// +// MKPolygon.m +// MapKit +// +// Created by Rick Fillion on 7/15/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPolygon.h" + +@interface MKPolygon (Private) + +- (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; +- (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray *)interiorPolygons; + +@end + +@implementation MKPolygon + +@synthesize interiorPolygons; + ++ (MKPolygon *)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count +{ + return [[[self alloc] initWithCoordinates:coords count:count] autorelease]; +} + ++ (MKPolygon *)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray *)interiorPolygons; +{ + return [[[self alloc] initWithCoordinates:coords count:count interiorPolygons:interiorPolygons] autorelease]; +} + +- (CLLocationCoordinate2D) coordinate +{ + return [super coordinate]; +} + +- (void)dealloc +{ + free(coordinates); + [interiorPolygons release]; + [super dealloc]; +} + +#pragma mark Private + +- (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count +{ + if (self = [super init]) + { + coordinates = malloc(sizeof(CLLocationCoordinate2D) * count); + for (int i = 0; i < count; i++) + { + coordinates[i] = coords[i]; + } + coordinateCount = count; + } + return self; +} + +- (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray *)theInteriorPolygons +{ + if (self = [self initWithCoordinates:coords count:count]) + { + interiorPolygons = [theInteriorPolygons retain]; + } + return self; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPolygonView.h b/External Source/MacMapKit/Source/Framework/Classes/MKPolygonView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPolygonView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPolygonView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPolygonView.m b/External Source/MacMapKit/Source/Framework/Classes/MKPolygonView.m new file mode 100644 index 000000000..60852f0c3 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPolygonView.m @@ -0,0 +1,107 @@ +// +// MKPolygonView.m +// MapKit +// +// Created by Rick Fillion on 7/15/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPolygonView.h" +#import + +@interface MKPolygonView (Private) + +- (NSArray *)pathForPolygon:(MKPolygon *)aPolygon webScriptObject:(WebScriptObject *)webScriptObject; + +@end + + +@implementation MKPolygonView + + +- (id)initWithPolygon:(MKPolygon *)polygon; +{ + if (self = [super initWithOverlay:polygon]) + { + } + return self; +} + +- (void)dealloc +{ + [path release]; + [super dealloc]; +} + +- (MKPolygon *)polygon +{ + return [super overlay]; +} + +- (NSString *)viewPrototypeName +{ + return @"google.maps.Polygon"; +} + +- (NSDictionary *)options +{ + NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:[super options]]; + + if (path) + { + if (!interiorPaths) + { + [options setObject:path forKey:@"path"]; + } + else { + NSMutableArray *allPaths = [NSMutableArray arrayWithObject:path]; + [allPaths addObjectsFromArray:interiorPaths]; + [options setObject:allPaths forKey:@"paths"]; + } + + } + + return [[options copy] autorelease]; +} + +- (void)draw:(WebScriptObject *)overlayScriptObject +{ + if (!path) + { + path = [self pathForPolygon:[self polygon] webScriptObject:overlayScriptObject]; + [path retain]; + if ([self polygon].interiorPolygons) + { + NSMutableArray *interiorPolygonPaths = [NSMutableArray array]; + for (MKPolygon *aPolygon in [self polygon].interiorPolygons) + { + NSArray *interiorPath = [self pathForPolygon:aPolygon webScriptObject:overlayScriptObject]; + [interiorPolygonPaths addObject:interiorPath]; + } + interiorPaths = [[[interiorPolygonPaths copy] autorelease] retain]; + } + } + + [super draw:overlayScriptObject]; +} + +#pragma mark Private + +- (NSArray *)pathForPolygon:(MKPolygon *)aPolygon webScriptObject:(WebScriptObject *)webScriptObject +{ + CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * aPolygon.coordinateCount); + NSRange range = NSMakeRange(0, aPolygon.coordinateCount); + [aPolygon getCoordinates:coordinates range:range]; + NSMutableArray *newPath = [NSMutableArray array]; + + for (int i = 0; i< aPolygon.coordinateCount; i++) + { + CLLocationCoordinate2D coordinate = coordinates[i]; + NSString *script = [NSString stringWithFormat:@"new google.maps.LatLng(%f, %f);", coordinate.latitude, coordinate.longitude]; + WebScriptObject *latlng = (WebScriptObject *)[webScriptObject evaluateWebScript:script]; + [newPath addObject:latlng]; + } + return [[newPath copy] autorelease]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPolyline.h b/External Source/MacMapKit/Source/Framework/Classes/MKPolyline.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPolyline.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPolyline.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPolyline.m b/External Source/MacMapKit/Source/Framework/Classes/MKPolyline.m new file mode 100644 index 000000000..b3a385f89 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPolyline.m @@ -0,0 +1,52 @@ +// +// MKPolyline.m +// MapKit +// +// Created by Rick Fillion on 7/15/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPolyline.h" + +@interface MKPolyline (Private) + +- (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; + +@end + + +@implementation MKPolyline + ++ (MKPolyline *)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count +{ + return [[[MKPolyline alloc] initWithCoordinates:coords count:count] autorelease]; +} + +- (CLLocationCoordinate2D) coordinate +{ + return [super coordinate]; +} + +- (void)dealloc +{ + free(coordinates); + [super dealloc]; +} + +#pragma mark Private + +- (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count +{ + if (self = [super init]) + { + coordinates = malloc(sizeof(CLLocationCoordinate2D) * count); + for (int i = 0; i < count; i++) + { + coordinates[i] = coords[i]; + } + coordinateCount = count; + } + return self; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKPolylineView.h b/External Source/MacMapKit/Source/Framework/Classes/MKPolylineView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKPolylineView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKPolylineView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKPolylineView.m b/External Source/MacMapKit/Source/Framework/Classes/MKPolylineView.m new file mode 100644 index 000000000..cab435685 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKPolylineView.m @@ -0,0 +1,71 @@ +// +// MKPolylineView.m +// MapKit +// +// Created by Rick Fillion on 7/15/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKPolylineView.h" +#import + +@implementation MKPolylineView + +- (id)initWithPolyline:(MKPolyline *)polyline; +{ + if (self = [super initWithOverlay:polyline]) + { + self.fillColor = [NSColor clearColor]; + } + return self; +} + +- (void)dealloc +{ + [path release]; + [super dealloc]; +} + +- (MKPolyline *)polyline +{ + return [super overlay]; +} + +- (NSString *)viewPrototypeName +{ + return @"google.maps.Polyline"; +} + +- (NSDictionary *)options +{ + NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:[super options]]; + + if (path) + [options setObject:path forKey:@"path"]; + + return [[options copy] autorelease]; +} + +- (void)draw:(WebScriptObject *)overlayScriptObject +{ + if (!path) + { + CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * [self polyline].coordinateCount); + NSRange range = NSMakeRange(0, [self polyline].coordinateCount); + [[self polyline] getCoordinates:coordinates range:range]; + NSMutableArray *newPath = [NSMutableArray array]; + + for (int i = 0; i< [self polyline].coordinateCount; i++) + { + CLLocationCoordinate2D coordinate = coordinates[i]; + NSString *script = [NSString stringWithFormat:@"new google.maps.LatLng(%f, %f);", coordinate.latitude, coordinate.longitude]; + WebScriptObject *latlng = (WebScriptObject *)[overlayScriptObject evaluateWebScript:script]; + [newPath addObject:latlng]; + } + path = [[[newPath copy] autorelease] retain]; + } + + [super draw:overlayScriptObject]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKReverseGeocoder.h b/External Source/MacMapKit/Source/Framework/Classes/MKReverseGeocoder.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKReverseGeocoder.h rename to External Source/MacMapKit/Source/Framework/Classes/MKReverseGeocoder.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKReverseGeocoder.m b/External Source/MacMapKit/Source/Framework/Classes/MKReverseGeocoder.m new file mode 100644 index 000000000..5b7a72ae2 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKReverseGeocoder.m @@ -0,0 +1,233 @@ +// +// MKReverseGeocoder.m +// MapKit +// +// Created by Rick Fillion on 7/24/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +/* + Note: I'm not particularly proud of this class. It was mostly coded at 1am with a "fuck, just get it working" attitude. + Things that could use some fixing by someone who wants to use it seriously: + - Every MKReverseGeocoder loads up a WebView instance. Just to get access to javascript. Change it to load one for everyone. + - There's this weird issue where the window.MKReverseGeocoder object isn't ready when I want it. That's why there's the rescheduling. + */ + +#import "MKReverseGeocoder.h" +#import "JSON.h" +#import "MKPlacemark+Private.h" + + +@interface MKReverseGeocoder (WebViewIntegration) + +- (void)didSucceedWithAddress:(id)address; +- (void)didFailWithError:(NSString *)status; +- (void)didReachQueryLimit; + +@end + + +@interface MKReverseGeocoder (Private) + +- (void)createWebView; +- (void)destroyWebView; +- (void)_start; + +@end + + +@implementation MKReverseGeocoder + +@synthesize delegate; +@synthesize coordinate; +@synthesize placemark; +@synthesize querying; + ++ (NSString *) webScriptNameForSelector:(SEL)sel +{ + NSString *name = nil; + + if (sel == @selector(didSucceedWithAddress:)) + { + name = @"didSucceedWithAddress"; + } + + if (sel == @selector(didFailWithError:)) + { + name = @"didFailWithError"; + } + + if (sel == @selector(didReachQueryLimit)) + { + name = @"didReachQueryLimit"; + } + + + return name; +} + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(didSucceedWithAddress:)) + { + return NO; + } + + if (aSelector == @selector(didFailWithError:)) + { + return NO; + } + + if (aSelector == @selector(didReachQueryLimit)) + { + return NO; + } + + return YES; +} + + + +- (id)initWithCoordinate:(CLLocationCoordinate2D)aCoordinate +{ + if (self = [super init]) + { + [self createWebView]; + coordinate = aCoordinate; + } + return self; +} + +- (void)dealloc +{ + [placemark release]; + [self destroyWebView]; + [super dealloc]; +} + + +- (void)start +{ + if (querying) + return; + querying = YES; + if (webViewLoaded) + { + [self _start]; + } +} + +- (void)cancel +{ + if (!querying) + return; + querying = NO; +} + +#pragma mark WebViewIntegration + +- (void)didSucceedWithAddress:(NSString *)jsonAddress +{ + //NSLog(@"didSucceedWithAddress: %@", jsonAddress); + if (!querying) + return; + + id result = [jsonAddress JSONValue]; + MKPlacemark *aPlacemark = [[[MKPlacemark alloc] initWithGoogleGeocoderResult: result] autorelease]; + placemark = [aPlacemark retain]; + + if (delegate && [delegate respondsToSelector:@selector(reverseGeocoder:didFindPlacemark:)]) + { + [delegate reverseGeocoder:self didFindPlacemark:self.placemark]; + } + querying = NO; +} + +- (void)didFailWithError:(NSString *)domain +{ + //NSLog(@"didFailWithErorr: %@", domain); + if (!querying) + return; + + NSError *error = [NSError errorWithDomain:domain code:0 userInfo:nil]; + // TODO create error + + if (delegate && [delegate respondsToSelector:@selector(reverseGeocoder:didFailWithError:)]) + { + [delegate reverseGeocoder:self didFailWithError:error]; + } + querying = NO; +} + +- (void)didReachQueryLimit +{ + // Retry again in half a second + if (self.querying) + { + [self performSelector:@selector(_start) withObject:nil afterDelay:0.5]; + } +} + +#pragma mark WebFrameLoadDelegate + +- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowScriptObject forFrame:(WebFrame *)frame +{ + //NSLog(@"didClearWindowObjet"); + [windowScriptObject setValue:self forKey:@"MKReverseGeocoder"]; +} + + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + //NSLog(@"didFinishLoad:"); + [[webView windowScriptObject] setValue:self forKey:@"MKReverseGeocoder"]; + webViewLoaded = YES; + if (self.querying && [sender mainFrame] == frame) + { + [self _start]; + } +} + + +#pragma mark Private + +- (void)createWebView +{ + // create it + // TODO : make this suck less. + NSBundle *frameworkBundle = [NSBundle bundleForClass:[MKReverseGeocoder class]]; + NSString *indexPath = [frameworkBundle pathForResource:@"MapKit" ofType:@"html"]; + webView = [[WebView alloc] initWithFrame:NSZeroRect frameName:nil groupName:nil]; + [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:indexPath]]]; + [[webView windowScriptObject] setValue:self forKey:@"MKReverseGeocoder"]; + [webView setFrameLoadDelegate:self]; +} + +- (void)destroyWebView +{ + [webView close]; + [webView release]; +} + +- (void)_start +{ + //NSLog(@"start"); + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithDouble:coordinate.latitude], + [NSNumber numberWithDouble:coordinate.longitude], + self, + nil]; + WebScriptObject *webScriptObject = [webView windowScriptObject]; + //NSLog(@"got webscriptobject"); + id val = [webScriptObject callWebScriptMethod:@"reverseGeocode" withArguments:args]; + //NSLog(@"val = %@", val); + if (!val) + { + // something went wrong, call the failure delegate + //NSLog(@"MKReverseGeocoder tried to start but the script wasn't ready, rescheduling"); + [self performSelector:@selector(_start) withObject:nil afterDelay:0.1]; + } +} + + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKShape.h b/External Source/MacMapKit/Source/Framework/Classes/MKShape.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKShape.h rename to External Source/MacMapKit/Source/Framework/Classes/MKShape.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKShape.m b/External Source/MacMapKit/Source/Framework/Classes/MKShape.m new file mode 100644 index 000000000..adf59eeeb --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKShape.m @@ -0,0 +1,31 @@ +// +// MKShape.m +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKShape.h" + + +@implementation MKShape + +@synthesize title, subtitle; + +- (CLLocationCoordinate2D)coordinate +{ + CLLocationCoordinate2D coord; + coord.longitude = 0.0; + coord.latitude = 0.0; + return coord; +} + +- (void)dealloc +{ + [title release]; + [subtitle release]; + [super dealloc]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKTypes.h b/External Source/MacMapKit/Source/Framework/Classes/MKTypes.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKTypes.h rename to External Source/MacMapKit/Source/Framework/Classes/MKTypes.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation+Private.h b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation+Private.h new file mode 100644 index 000000000..4c9cd7f9a --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation+Private.h @@ -0,0 +1,19 @@ +// +// MKUserLocation+Private.h +// MapKit +// +// Created by Rick Fillion on 7/11/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import + +@class CLLocation; + +@interface MKUserLocation (Private) + +- (void)_setLocation:(CLLocation *)aLocation; +- (void)_setUpdating:(BOOL)value; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation+Private.m b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation+Private.m new file mode 100644 index 000000000..6c5e3e3a9 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation+Private.m @@ -0,0 +1,30 @@ +// +// MKUserLocation+Private.m +// MapKit +// +// Created by Rick Fillion on 7/11/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKUserLocation+Private.h" + + +@implementation MKUserLocation (Private) + +- (void)_setLocation:(CLLocation *)aLocation +{ + [self willChangeValueForKey:@"location"]; + [aLocation retain]; + [location release]; + location = aLocation; + [self didChangeValueForKey:@"location"]; +} + +- (void)_setUpdating:(BOOL)value +{ + [self willChangeValueForKey:@"isUpdating"]; + updating = value; + [self didChangeValueForKey:@"isUpdating"]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKUserLocation.h b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKUserLocation.h rename to External Source/MacMapKit/Source/Framework/Classes/MKUserLocation.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation.m b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation.m new file mode 100644 index 000000000..cc13f4da1 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKUserLocation.m @@ -0,0 +1,29 @@ +// +// MKUserLocation.m +// MapKit +// +// Created by Rick Fillion on 7/11/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKUserLocation.h" + + +@implementation MKUserLocation + +@synthesize updating, location, title, subtitle; + +- (void)dealloc +{ + [location release]; + [title release]; + [subtitle release]; + [super dealloc]; +} + +- (CLLocationCoordinate2D) coordinate +{ + return [location coordinate]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MKView.h b/External Source/MacMapKit/Source/Framework/Classes/MKView.h similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Headers/MKView.h rename to External Source/MacMapKit/Source/Framework/Classes/MKView.h diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKView.m b/External Source/MacMapKit/Source/Framework/Classes/MKView.m new file mode 100644 index 000000000..ffdaa8a09 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKView.m @@ -0,0 +1,46 @@ +// +// MKView.m +// MapKit +// +// Created by Rick Fillion on 7/19/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKView.h" + + +@implementation MKView + +- (NSString *)viewPrototypeName +{ + return @"MVCObject"; +} + +- (NSDictionary *)options +{ + return [NSDictionary dictionary]; +} + +- (void)draw:(WebScriptObject *)overlayScriptObject +{ + WebScriptObject *windowScriptObject = (WebScriptObject *)[overlayScriptObject evaluateWebScript:@"window"]; + NSDictionary *theOptions = [self options]; + + for (NSString *key in [theOptions allKeys]) + { + id value = [theOptions objectForKey:key]; + [windowScriptObject callWebScriptMethod:@"setOverlayOption" withArguments:[NSArray arrayWithObjects:overlayScriptObject, key, value, nil]]; + //NSLog(@"return value from setOption(%@) = %@",key, val); + } +} + +- (WebScriptObject *)overlayScriptObjectFromMapScriptObject:(WebScriptObject *)mapScriptObject +{ + NSString *script = [NSString stringWithFormat:@"new %@()", [self viewPrototypeName]]; + WebScriptObject *object = (WebScriptObject *)[mapScriptObject evaluateWebScript:script]; + return object; +} + + + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKWebView.h b/External Source/MacMapKit/Source/Framework/Classes/MKWebView.h new file mode 100644 index 000000000..1a7f846d7 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKWebView.h @@ -0,0 +1,19 @@ +// +// MKWebView.h +// MapKit +// +// Created by Rick Fillion on 10-12-12. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import + +@interface MKWebView : WebView +{ + NSDate *lastHitTestDate; +} + +@property (nonatomic, readonly) NSDate *lastHitTestDate; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/MKWebView.m b/External Source/MacMapKit/Source/Framework/Classes/MKWebView.m new file mode 100644 index 000000000..c30b44d2f --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/MKWebView.m @@ -0,0 +1,30 @@ +// +// MKWebView.m +// MapKit +// +// Created by Rick Fillion on 10-12-12. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKWebView.h" + + +@implementation MKWebView + +@synthesize lastHitTestDate; + +- (void)dealloc +{ + [lastHitTestDate release]; + [super dealloc]; +} + +- (NSView *)hitTest:(NSPoint)aPoint +{ + //NSLog(@"hitTest: %@", NSStringFromPoint(aPoint)); + [lastHitTestDate release]; + lastHitTestDate = [[NSDate date] retain]; + return [super hitTest:aPoint]; +} + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Headers/MapKit.h b/External Source/MacMapKit/Source/Framework/Classes/MapKit.h similarity index 96% rename from Frameworks/MapKit.framework/Versions/A/Headers/MapKit.h rename to External Source/MacMapKit/Source/Framework/Classes/MapKit.h index 1c39c591c..6eddeae89 100644 --- a/Frameworks/MapKit.framework/Versions/A/Headers/MapKit.h +++ b/External Source/MacMapKit/Source/Framework/Classes/MapKit.h @@ -29,5 +29,4 @@ #import #import #import -#import - +#import \ No newline at end of file diff --git a/External Source/MacMapKit/Source/Framework/Classes/NSColor+Additions.h b/External Source/MacMapKit/Source/Framework/Classes/NSColor+Additions.h new file mode 100644 index 000000000..944dc4a05 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/NSColor+Additions.h @@ -0,0 +1,16 @@ +// +// NSColor+Additions.h +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import + + +@interface NSColor (Additions) + +- (NSString *)hexString; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/NSColor+Additions.m b/External Source/MacMapKit/Source/Framework/Classes/NSColor+Additions.m new file mode 100644 index 000000000..ae60af28d --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/NSColor+Additions.m @@ -0,0 +1,43 @@ +// +// NSColor+Additions.m +// MapKit +// +// Created by Rick Fillion on 7/12/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "NSColor+Additions.h" + + +@implementation NSColor (Additions) + +-(NSString *)hexString +{ + CGFloat redFloatValue, greenFloatValue, blueFloatValue; + int redIntValue, greenIntValue, blueIntValue; + NSString *redHexValue, *greenHexValue, *blueHexValue; + + //Convert the NSColor to the RGB color space before we can access its components + NSColor *convertedColor=[self colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + + if(convertedColor) + { + // Get the red, green, and blue components of the color + [convertedColor getRed:&redFloatValue green:&greenFloatValue blue:&blueFloatValue alpha:NULL]; + + // Convert the components to numbers (unsigned decimal integer) between 0 and 255 + redIntValue=redFloatValue*255.99999f; + greenIntValue=greenFloatValue*255.99999f; + blueIntValue=blueFloatValue*255.99999f; + + // Convert the numbers to hex strings + redHexValue=[NSString stringWithFormat:@"%02x", redIntValue]; + greenHexValue=[NSString stringWithFormat:@"%02x", greenIntValue]; + blueHexValue=[NSString stringWithFormat:@"%02x", blueIntValue]; + + // Concatenate the red, green, and blue components' hex strings together with a "#" + return [NSString stringWithFormat:@"#%@%@%@", redHexValue, greenHexValue, blueHexValue]; + } + return nil; +} +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/JSON.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/JSON.h new file mode 100644 index 000000000..1e58c9ad9 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/JSON.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @mainpage A strict JSON parser and generator for Objective-C + + JSON (JavaScript Object Notation) is a lightweight data-interchange + format. This framework provides two apis for parsing and generating + JSON. One standard object-based and a higher level api consisting of + categories added to existing Objective-C classes. + + Learn more on the http://code.google.com/p/json-framework project site. + + This framework does its best to be as strict as possible, both in what it + accepts and what it generates. For example, it does not support trailing commas + in arrays or objects. Nor does it support embedded comments, or + anything else not in the JSON specification. This is considered a feature. + +*/ + +#import "SBJSON.h" +#import "NSObject+SBJSON.h" +#import "NSString+SBJSON.h" + diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.h new file mode 100644 index 000000000..6469e27db --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define JSONFragment MKJSONFragment +#define JSONRepresentation MKJSONRepresentation + +#import + + +/** + @brief Adds JSON generation to Foundation classes + + This is a category on NSObject that adds methods for returning JSON representations + of standard objects to the objects themselves. This means you can call the + -JSONRepresentation method on an NSArray object and it'll do what you want. + */ +@interface NSObject (NSObject_SBJSON) + +/** + @brief Returns a string containing the receiver encoded as a JSON fragment. + + This method is added as a category on NSObject but is only actually + supported for the following objects: + @li NSDictionary + @li NSArray + @li NSString + @li NSNumber (also used for booleans) + @li NSNull + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (NSString *)JSONFragment; + +/** + @brief Returns a string containing the receiver encoded in JSON. + + This method is added as a category on NSObject but is only actually + supported for the following objects: + @li NSDictionary + @li NSArray + */ +- (NSString *)JSONRepresentation; + +@end + diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.m b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.m new file mode 100644 index 000000000..20b084b64 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.m @@ -0,0 +1,53 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NSObject+SBJSON.h" +#import "SBJsonWriter.h" + +@implementation NSObject (NSObject_SBJSON) + +- (NSString *)JSONFragment { + SBJsonWriter *jsonWriter = [SBJsonWriter new]; + NSString *json = [jsonWriter stringWithFragment:self]; + if (!json) + NSLog(@"-JSONFragment failed. Error trace is: %@", [jsonWriter errorTrace]); + [jsonWriter release]; + return json; +} + +- (NSString *)JSONRepresentation { + SBJsonWriter *jsonWriter = [SBJsonWriter new]; + NSString *json = [jsonWriter stringWithObject:self]; + if (!json) + NSLog(@"-JSONRepresentation failed. Error trace is: %@", [jsonWriter errorTrace]); + [jsonWriter release]; + return json; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSString+SBJSON.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSString+SBJSON.h new file mode 100644 index 000000000..37b9041b3 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSString+SBJSON.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define JSONFragmentValue MKJSONFragmentValue +#define JSONValue MKJSONValue + +#import + +/** + @brief Adds JSON parsing methods to NSString + +This is a category on NSString that adds methods for parsing the target string. +*/ +@interface NSString (NSString_SBJSON) + + +/** + @brief Returns the object represented in the receiver, or nil on error. + + Returns a a scalar object represented by the string's JSON fragment representation. + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (id)JSONFragmentValue; + +/** + @brief Returns the NSDictionary or NSArray represented by the current string's JSON representation. + + Returns the dictionary or array represented in the receiver, or nil on error. + + Returns the NSDictionary or NSArray represented by the current string's JSON representation. + */ +- (id)JSONValue; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSString+SBJSON.m b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSString+SBJSON.m new file mode 100644 index 000000000..41a5a85bb --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/NSString+SBJSON.m @@ -0,0 +1,55 @@ +/* + Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NSString+SBJSON.h" +#import "SBJsonParser.h" + +@implementation NSString (NSString_SBJSON) + +- (id)JSONFragmentValue +{ + SBJsonParser *jsonParser = [SBJsonParser new]; + id repr = [jsonParser fragmentWithString:self]; + if (!repr) + NSLog(@"-JSONFragmentValue failed. Error trace is: %@", [jsonParser errorTrace]); + [jsonParser release]; + return repr; +} + +- (id)JSONValue +{ + SBJsonParser *jsonParser = [SBJsonParser new]; + id repr = [jsonParser objectWithString:self]; + if (!repr) + NSLog(@"-JSONValue failed. Error trace is: %@", [jsonParser errorTrace]); + [jsonParser release]; + return repr; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJSON.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJSON.h new file mode 100644 index 000000000..8dde6b593 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJSON.h @@ -0,0 +1,77 @@ +/* + Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SBJSON MKSBJSON + +#import +#import "SBJsonParser.h" +#import "SBJsonWriter.h" + +/** + @brief Facade for SBJsonWriter/SBJsonParser. + + Requests are forwarded to instances of SBJsonWriter and SBJsonParser. + */ +@interface SBJSON : SBJsonBase { + +@private + SBJsonParser *jsonParser; + SBJsonWriter *jsonWriter; +} + + +/// Return the fragment represented by the given string +- (id)fragmentWithString:(NSString*)jsonrep + error:(NSError**)error; + +/// Return the object represented by the given string +- (id)objectWithString:(NSString*)jsonrep + error:(NSError**)error; + +/// Parse the string and return the represented object (or scalar) +- (id)objectWithString:(id)value + allowScalar:(BOOL)x + error:(NSError**)error; + + +/// Return JSON representation of an array or dictionary +- (NSString*)stringWithObject:(id)value + error:(NSError**)error; + +/// Return JSON representation of any legal JSON value +- (NSString*)stringWithFragment:(id)value + error:(NSError**)error; + +/// Return JSON representation (or fragment) for the given object +- (NSString*)stringWithObject:(id)value + allowScalar:(BOOL)x + error:(NSError**)error; + + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJSON.m b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJSON.m new file mode 100644 index 000000000..2a30f1a7d --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJSON.m @@ -0,0 +1,212 @@ +/* + Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJSON.h" + +@implementation SBJSON + +- (id)init { + self = [super init]; + if (self) { + jsonWriter = [SBJsonWriter new]; + jsonParser = [SBJsonParser new]; + [self setMaxDepth:512]; + + } + return self; +} + +- (void)dealloc { + [jsonWriter release]; + [jsonParser release]; + [super dealloc]; +} + +#pragma mark Writer + + +- (NSString *)stringWithObject:(id)obj { + NSString *repr = [jsonWriter stringWithObject:obj]; + if (repr) + return repr; + + [errorTrace release]; + errorTrace = [[jsonWriter errorTrace] mutableCopy]; + return nil; +} + +/** + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + @param allowScalar wether to return json fragments for scalar objects + @param error used to return an error by reference (pass NULL if this is not desired) + +@deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (NSString*)stringWithObject:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error { + + NSString *json = allowScalar ? [jsonWriter stringWithFragment:value] : [jsonWriter stringWithObject:value]; + if (json) + return json; + + [errorTrace release]; + errorTrace = [[jsonWriter errorTrace] mutableCopy]; + + if (error) + *error = [errorTrace lastObject]; + return nil; +} + +/** + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + @param error used to return an error by reference (pass NULL if this is not desired) + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (NSString*)stringWithFragment:(id)value error:(NSError**)error { + return [self stringWithObject:value + allowScalar:YES + error:error]; +} + +/** + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error. + + @param value a NSDictionary or NSArray instance + @param error used to return an error by reference (pass NULL if this is not desired) + */ +- (NSString*)stringWithObject:(id)value error:(NSError**)error { + return [self stringWithObject:value + allowScalar:NO + error:error]; +} + +#pragma mark Parsing + +- (id)objectWithString:(NSString *)repr { + id obj = [jsonParser objectWithString:repr]; + if (obj) + return obj; + + [errorTrace release]; + errorTrace = [[jsonParser errorTrace] mutableCopy]; + + return nil; +} + +/** + Returns the object represented by the passed-in string or nil on error. The returned object can be + a string, number, boolean, null, array or dictionary. + + @param value the json string to parse + @param allowScalar whether to return objects for JSON fragments + @param error used to return an error by reference (pass NULL if this is not desired) + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (id)objectWithString:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error { + + id obj = allowScalar ? [jsonParser fragmentWithString:value] : [jsonParser objectWithString:value]; + if (obj) + return obj; + + [errorTrace release]; + errorTrace = [[jsonParser errorTrace] mutableCopy]; + + if (error) + *error = [errorTrace lastObject]; + return nil; +} + +/** + Returns the object represented by the passed-in string or nil on error. The returned object can be + a string, number, boolean, null, array or dictionary. + + @param repr the json string to parse + @param error used to return an error by reference (pass NULL if this is not desired) + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (id)fragmentWithString:(NSString*)repr error:(NSError**)error { + return [self objectWithString:repr + allowScalar:YES + error:error]; +} + +/** + Returns the object represented by the passed-in string or nil on error. The returned object + will be either a dictionary or an array. + + @param repr the json string to parse + @param error used to return an error by reference (pass NULL if this is not desired) + */ +- (id)objectWithString:(NSString*)repr error:(NSError**)error { + return [self objectWithString:repr + allowScalar:NO + error:error]; +} + + + +#pragma mark Properties - parsing + +- (NSUInteger)maxDepth { + return jsonParser.maxDepth; +} + +- (void)setMaxDepth:(NSUInteger)d { + jsonWriter.maxDepth = jsonParser.maxDepth = d; +} + + +#pragma mark Properties - writing + +- (BOOL)humanReadable { + return jsonWriter.humanReadable; +} + +- (void)setHumanReadable:(BOOL)x { + jsonWriter.humanReadable = x; +} + +- (BOOL)sortKeys { + return jsonWriter.sortKeys; +} + +- (void)setSortKeys:(BOOL)x { + jsonWriter.sortKeys = x; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonBase.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonBase.h new file mode 100644 index 000000000..0c50c2dc7 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonBase.h @@ -0,0 +1,88 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SBJsonBase MKSBJsonBase + +#import + +extern NSString * SBJSONErrorDomain; + + +enum { + EUNSUPPORTED = 1, + EPARSENUM, + EPARSE, + EFRAGMENT, + ECTRL, + EUNICODE, + EDEPTH, + EESCAPE, + ETRAILCOMMA, + ETRAILGARBAGE, + EEOF, + EINPUT +}; + +/** + @brief Common base class for parsing & writing. + + This class contains the common error-handling code and option between the parser/writer. + */ +@interface SBJsonBase : NSObject { + NSMutableArray *errorTrace; + +@protected + NSUInteger depth, maxDepth; +} + +/** + @brief The maximum recursing depth. + + Defaults to 512. If the input is nested deeper than this the input will be deemed to be + malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can + turn off this security feature by setting the maxDepth value to 0. + */ +@property NSUInteger maxDepth; + +/** + @brief Return an error trace, or nil if there was no errors. + + Note that this method returns the trace of the last method that failed. + You need to check the return value of the call you're making to figure out + if the call actually failed, before you know call this method. + */ + @property(copy,readonly) NSArray* errorTrace; + +/// @internal for use in subclasses to add errors to the stack trace +- (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str; + +/// @internal for use in subclasess to clear the error before a new parsing attempt +- (void)clearErrorTrace; + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonBase.m b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonBase.m new file mode 100644 index 000000000..6684325d1 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonBase.m @@ -0,0 +1,78 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonBase.h" +NSString * SBJSONErrorDomain = @"org.brautaset.JSON.ErrorDomain"; + + +@implementation SBJsonBase + +@synthesize errorTrace; +@synthesize maxDepth; + +- (id)init { + self = [super init]; + if (self) + self.maxDepth = 512; + return self; +} + +- (void)dealloc { + [errorTrace release]; + [super dealloc]; +} + +- (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str { + NSDictionary *userInfo; + if (!errorTrace) { + errorTrace = [NSMutableArray new]; + userInfo = [NSDictionary dictionaryWithObject:str forKey:NSLocalizedDescriptionKey]; + + } else { + userInfo = [NSDictionary dictionaryWithObjectsAndKeys: + str, NSLocalizedDescriptionKey, + [errorTrace lastObject], NSUnderlyingErrorKey, + nil]; + } + + NSError *error = [NSError errorWithDomain:SBJSONErrorDomain code:code userInfo:userInfo]; + + [self willChangeValueForKey:@"errorTrace"]; + [errorTrace addObject:error]; + [self didChangeValueForKey:@"errorTrace"]; +} + +- (void)clearErrorTrace { + [self willChangeValueForKey:@"errorTrace"]; + [errorTrace release]; + errorTrace = nil; + [self didChangeValueForKey:@"errorTrace"]; +} + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonParser.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonParser.h new file mode 100644 index 000000000..441e24869 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonParser.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SBJsonParser MKSBJsonParser + +#import +#import "SBJsonBase.h" + +/** + @brief Options for the parser class. + + This exists so the SBJSON facade can implement the options in the parser without having to re-declare them. + */ +@protocol SBJsonParser + +/** + @brief Return the object represented by the given string. + + Returns the object represented by the passed-in string or nil on error. The returned object can be + a string, number, boolean, null, array or dictionary. + + @param repr the json string to parse + */ +- (id)objectWithString:(NSString *)repr; + +@end + + +/** + @brief The JSON parser class. + + JSON is mapped to Objective-C types in the following way: + + @li Null -> NSNull + @li String -> NSMutableString + @li Array -> NSMutableArray + @li Object -> NSMutableDictionary + @li Boolean -> NSNumber (initialised with -initWithBool:) + @li Number -> NSDecimalNumber + + Since Objective-C doesn't have a dedicated class for boolean values, these turns into NSNumber + instances. These are initialised with the -initWithBool: method, and + round-trip back to JSON properly. (They won't silently suddenly become 0 or 1; they'll be + represented as 'true' and 'false' again.) + + JSON numbers turn into NSDecimalNumber instances, + as we can thus avoid any loss of precision. (JSON allows ridiculously large numbers.) + + */ +@interface SBJsonParser : SBJsonBase { + +@private + const char *c; +} + +@end + +// don't use - exists for backwards compatibility with 2.1.x only. Will be removed in 2.3. +@interface SBJsonParser (Private) +- (id)fragmentWithString:(id)repr; +@end + + diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonParser.m b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonParser.m new file mode 100644 index 000000000..eda051a83 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonParser.m @@ -0,0 +1,475 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonParser.h" + +@interface SBJsonParser () + +- (BOOL)scanValue:(NSObject **)o; + +- (BOOL)scanRestOfArray:(NSMutableArray **)o; +- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o; +- (BOOL)scanRestOfNull:(NSNull **)o; +- (BOOL)scanRestOfFalse:(NSNumber **)o; +- (BOOL)scanRestOfTrue:(NSNumber **)o; +- (BOOL)scanRestOfString:(NSMutableString **)o; + +// Cannot manage without looking at the first digit +- (BOOL)scanNumber:(NSNumber **)o; + +- (BOOL)scanHexQuad:(unichar *)x; +- (BOOL)scanUnicodeChar:(unichar *)x; + +- (BOOL)scanIsAtEnd; + +@end + +#define skipWhitespace(c) while (isspace(*c)) c++ +#define skipDigits(c) while (isdigit(*c)) c++ + + +@implementation SBJsonParser + +static char ctrl[0x22]; + + ++ (void)initialize { + ctrl[0] = '\"'; + ctrl[1] = '\\'; + for (int i = 1; i < 0x20; i++) + ctrl[i+1] = i; + ctrl[0x21] = 0; +} + +/** + @deprecated This exists in order to provide fragment support in older APIs in one more version. + It should be removed in the next major version. + */ +- (id)fragmentWithString:(id)repr { + [self clearErrorTrace]; + + if (!repr) { + [self addErrorWithCode:EINPUT description:@"Input was 'nil'"]; + return nil; + } + + depth = 0; + c = [repr UTF8String]; + + id o; + if (![self scanValue:&o]) { + return nil; + } + + // We found some valid JSON. But did it also contain something else? + if (![self scanIsAtEnd]) { + [self addErrorWithCode:ETRAILGARBAGE description:@"Garbage after JSON"]; + return nil; + } + + NSAssert1(o, @"Should have a valid object from %@", repr); + return o; +} + +- (id)objectWithString:(NSString *)repr { + + id o = [self fragmentWithString:repr]; + if (!o) + return nil; + + // Check that the object we've found is a valid JSON container. + if (![o isKindOfClass:[NSDictionary class]] && ![o isKindOfClass:[NSArray class]]) { + [self addErrorWithCode:EFRAGMENT description:@"Valid fragment, but not JSON"]; + return nil; + } + + return o; +} + +/* + In contrast to the public methods, it is an error to omit the error parameter here. + */ +- (BOOL)scanValue:(NSObject **)o +{ + skipWhitespace(c); + + switch (*c++) { + case '{': + return [self scanRestOfDictionary:(NSMutableDictionary **)o]; + break; + case '[': + return [self scanRestOfArray:(NSMutableArray **)o]; + break; + case '"': + return [self scanRestOfString:(NSMutableString **)o]; + break; + case 'f': + return [self scanRestOfFalse:(NSNumber **)o]; + break; + case 't': + return [self scanRestOfTrue:(NSNumber **)o]; + break; + case 'n': + return [self scanRestOfNull:(NSNull **)o]; + break; + case '-': + case '0'...'9': + c--; // cannot verify number correctly without the first character + return [self scanNumber:(NSNumber **)o]; + break; + case '+': + [self addErrorWithCode:EPARSENUM description: @"Leading + disallowed in number"]; + return NO; + break; + case 0x0: + [self addErrorWithCode:EEOF description:@"Unexpected end of string"]; + return NO; + break; + default: + [self addErrorWithCode:EPARSE description: @"Unrecognised leading character"]; + return NO; + break; + } + + NSAssert(0, @"Should never get here"); + return NO; +} + +- (BOOL)scanRestOfTrue:(NSNumber **)o +{ + if (!strncmp(c, "rue", 3)) { + c += 3; + *o = [NSNumber numberWithBool:YES]; + return YES; + } + [self addErrorWithCode:EPARSE description:@"Expected 'true'"]; + return NO; +} + +- (BOOL)scanRestOfFalse:(NSNumber **)o +{ + if (!strncmp(c, "alse", 4)) { + c += 4; + *o = [NSNumber numberWithBool:NO]; + return YES; + } + [self addErrorWithCode:EPARSE description: @"Expected 'false'"]; + return NO; +} + +- (BOOL)scanRestOfNull:(NSNull **)o { + if (!strncmp(c, "ull", 3)) { + c += 3; + *o = [NSNull null]; + return YES; + } + [self addErrorWithCode:EPARSE description: @"Expected 'null'"]; + return NO; +} + +- (BOOL)scanRestOfArray:(NSMutableArray **)o { + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + + *o = [NSMutableArray arrayWithCapacity:8]; + + for (; *c ;) { + id v; + + skipWhitespace(c); + if (*c == ']' && c++) { + depth--; + return YES; + } + + if (![self scanValue:&v]) { + [self addErrorWithCode:EPARSE description:@"Expected value while parsing array"]; + return NO; + } + + [*o addObject:v]; + + skipWhitespace(c); + if (*c == ',' && c++) { + skipWhitespace(c); + if (*c == ']') { + [self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in array"]; + return NO; + } + } + } + + [self addErrorWithCode:EEOF description: @"End of input while parsing array"]; + return NO; +} + +- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o +{ + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + + *o = [NSMutableDictionary dictionaryWithCapacity:7]; + + for (; *c ;) { + id k, v; + + skipWhitespace(c); + if (*c == '}' && c++) { + depth--; + return YES; + } + + if (!(*c == '\"' && c++ && [self scanRestOfString:&k])) { + [self addErrorWithCode:EPARSE description: @"Object key string expected"]; + return NO; + } + + skipWhitespace(c); + if (*c != ':') { + [self addErrorWithCode:EPARSE description: @"Expected ':' separating key and value"]; + return NO; + } + + c++; + if (![self scanValue:&v]) { + NSString *string = [NSString stringWithFormat:@"Object value expected for key: %@", k]; + [self addErrorWithCode:EPARSE description: string]; + return NO; + } + + [*o setObject:v forKey:k]; + + skipWhitespace(c); + if (*c == ',' && c++) { + skipWhitespace(c); + if (*c == '}') { + [self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in object"]; + return NO; + } + } + } + + [self addErrorWithCode:EEOF description: @"End of input while parsing object"]; + return NO; +} + +- (BOOL)scanRestOfString:(NSMutableString **)o +{ + *o = [NSMutableString stringWithCapacity:16]; + do { + // First see if there's a portion we can grab in one go. + // Doing this caused a massive speedup on the long string. + size_t len = strcspn(c, ctrl); + if (len) { + // check for + id t = [[NSString alloc] initWithBytesNoCopy:(char*)c + length:len + encoding:NSUTF8StringEncoding + freeWhenDone:NO]; + if (t) { + [*o appendString:t]; + [t release]; + c += len; + } + } + + if (*c == '"') { + c++; + return YES; + + } else if (*c == '\\') { + unichar uc = *++c; + switch (uc) { + case '\\': + case '/': + case '"': + break; + + case 'b': uc = '\b'; break; + case 'n': uc = '\n'; break; + case 'r': uc = '\r'; break; + case 't': uc = '\t'; break; + case 'f': uc = '\f'; break; + + case 'u': + c++; + if (![self scanUnicodeChar:&uc]) { + [self addErrorWithCode:EUNICODE description: @"Broken unicode character"]; + return NO; + } + c--; // hack. + break; + default: + [self addErrorWithCode:EESCAPE description: [NSString stringWithFormat:@"Illegal escape sequence '0x%x'", uc]]; + return NO; + break; + } + CFStringAppendCharacters((CFMutableStringRef)*o, &uc, 1); + c++; + + } else if (*c < 0x20) { + [self addErrorWithCode:ECTRL description: [NSString stringWithFormat:@"Unescaped control character '0x%x'", *c]]; + return NO; + + } else { + NSLog(@"should not be able to get here"); + } + } while (*c); + + [self addErrorWithCode:EEOF description:@"Unexpected EOF while parsing string"]; + return NO; +} + +- (BOOL)scanUnicodeChar:(unichar *)x +{ + unichar hi, lo; + + if (![self scanHexQuad:&hi]) { + [self addErrorWithCode:EUNICODE description: @"Missing hex quad"]; + return NO; + } + + if (hi >= 0xd800) { // high surrogate char? + if (hi < 0xdc00) { // yes - expect a low char + + if (!(*c == '\\' && ++c && *c == 'u' && ++c && [self scanHexQuad:&lo])) { + [self addErrorWithCode:EUNICODE description: @"Missing low character in surrogate pair"]; + return NO; + } + + if (lo < 0xdc00 || lo >= 0xdfff) { + [self addErrorWithCode:EUNICODE description:@"Invalid low surrogate char"]; + return NO; + } + + hi = (hi - 0xd800) * 0x400 + (lo - 0xdc00) + 0x10000; + + } else if (hi < 0xe000) { + [self addErrorWithCode:EUNICODE description:@"Invalid high character in surrogate pair"]; + return NO; + } + } + + *x = hi; + return YES; +} + +- (BOOL)scanHexQuad:(unichar *)x +{ + *x = 0; + for (int i = 0; i < 4; i++) { + unichar uc = *c; + c++; + int d = (uc >= '0' && uc <= '9') + ? uc - '0' : (uc >= 'a' && uc <= 'f') + ? (uc - 'a' + 10) : (uc >= 'A' && uc <= 'F') + ? (uc - 'A' + 10) : -1; + if (d == -1) { + [self addErrorWithCode:EUNICODE description:@"Missing hex digit in quad"]; + return NO; + } + *x *= 16; + *x += d; + } + return YES; +} + +- (BOOL)scanNumber:(NSNumber **)o +{ + const char *ns = c; + + // The logic to test for validity of the number formatting is relicensed + // from JSON::XS with permission from its author Marc Lehmann. + // (Available at the CPAN: http://search.cpan.org/dist/JSON-XS/ .) + + if ('-' == *c) + c++; + + if ('0' == *c && c++) { + if (isdigit(*c)) { + [self addErrorWithCode:EPARSENUM description: @"Leading 0 disallowed in number"]; + return NO; + } + + } else if (!isdigit(*c) && c != ns) { + [self addErrorWithCode:EPARSENUM description: @"No digits after initial minus"]; + return NO; + + } else { + skipDigits(c); + } + + // Fractional part + if ('.' == *c && c++) { + + if (!isdigit(*c)) { + [self addErrorWithCode:EPARSENUM description: @"No digits after decimal point"]; + return NO; + } + skipDigits(c); + } + + // Exponential part + if ('e' == *c || 'E' == *c) { + c++; + + if ('-' == *c || '+' == *c) + c++; + + if (!isdigit(*c)) { + [self addErrorWithCode:EPARSENUM description: @"No digits after exponent"]; + return NO; + } + skipDigits(c); + } + + id str = [[NSString alloc] initWithBytesNoCopy:(char*)ns + length:c - ns + encoding:NSUTF8StringEncoding + freeWhenDone:NO]; + [str autorelease]; + if (str && (*o = [NSDecimalNumber decimalNumberWithString:str])) + return YES; + + [self addErrorWithCode:EPARSENUM description: @"Failed creating decimal instance"]; + return NO; +} + +- (BOOL)scanIsAtEnd +{ + skipWhitespace(c); + return !*c; +} + + +@end diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonWriter.h b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonWriter.h new file mode 100644 index 000000000..bd2a79b21 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonWriter.h @@ -0,0 +1,131 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SBJsonWriter MKSBJsonWriter + +#import +#import "SBJsonBase.h" + +/** + @brief Options for the writer class. + + This exists so the SBJSON facade can implement the options in the writer without having to re-declare them. + */ +@protocol SBJsonWriter + +/** + @brief Whether we are generating human-readable (multiline) JSON. + + Set whether or not to generate human-readable JSON. The default is NO, which produces + JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable + JSON with linebreaks after each array value and dictionary key/value pair, indented two + spaces per nesting level. + */ +@property BOOL humanReadable; + +/** + @brief Whether or not to sort the dictionary keys in the output. + + If this is set to YES, the dictionary keys in the JSON output will be in sorted order. + (This is useful if you need to compare two structures, for example.) The default is NO. + */ +@property BOOL sortKeys; + +/** + @brief Return JSON representation (or fragment) for the given object. + + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + + */ +- (NSString*)stringWithObject:(id)value; + +@end + + +/** + @brief The JSON writer class. + + Objective-C types are mapped to JSON types in the following way: + + @li NSNull -> Null + @li NSString -> String + @li NSArray -> Array + @li NSDictionary -> Object + @li NSNumber (-initWithBool:) -> Boolean + @li NSNumber -> Number + + In JSON the keys of an object must be strings. NSDictionary keys need + not be, but attempting to convert an NSDictionary with non-string keys + into JSON will throw an exception. + + NSNumber instances created with the +initWithBool: method are + converted into the JSON boolean "true" and "false" values, and vice + versa. Any other NSNumber instances are converted to a JSON number the + way you would expect. + + */ +@interface SBJsonWriter : SBJsonBase { + +@private + BOOL sortKeys, humanReadable; +} + +@end + +// don't use - exists for backwards compatibility. Will be removed in 2.3. +@interface SBJsonWriter (Private) +- (NSString*)stringWithFragment:(id)value; +@end + +/** + @brief Allows generation of JSON for otherwise unsupported classes. + + If you have a custom class that you want to create a JSON representation for you can implement + this method in your class. It should return a representation of your object defined + in terms of objects that can be translated into JSON. For example, a Person + object might implement it like this: + + @code + - (id)jsonProxyObject { + return [NSDictionary dictionaryWithObjectsAndKeys: + name, @"name", + phone, @"phone", + email, @"email", + nil]; + } + @endcode + + */ +@interface NSObject (SBProxyForJson) +- (id)proxyForJson; +@end + diff --git a/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonWriter.m b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonWriter.m new file mode 100644 index 000000000..0f3290410 --- /dev/null +++ b/External Source/MacMapKit/Source/Framework/Classes/Third Party/SBJSON/SBJsonWriter.m @@ -0,0 +1,237 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonWriter.h" + +@interface SBJsonWriter () + +- (BOOL)appendValue:(id)fragment into:(NSMutableString*)json; +- (BOOL)appendArray:(NSArray*)fragment into:(NSMutableString*)json; +- (BOOL)appendDictionary:(NSDictionary*)fragment into:(NSMutableString*)json; +- (BOOL)appendString:(NSString*)fragment into:(NSMutableString*)json; + +- (NSString*)indent; + +@end + +@implementation SBJsonWriter + +static NSMutableCharacterSet *kEscapeChars; + ++ (void)initialize { + kEscapeChars = [[NSMutableCharacterSet characterSetWithRange: NSMakeRange(0,32)] retain]; + [kEscapeChars addCharactersInString: @"\"\\"]; +} + + +@synthesize sortKeys; +@synthesize humanReadable; + +/** + @deprecated This exists in order to provide fragment support in older APIs in one more version. + It should be removed in the next major version. + */ +- (NSString*)stringWithFragment:(id)value { + [self clearErrorTrace]; + depth = 0; + NSMutableString *json = [NSMutableString stringWithCapacity:128]; + + if ([self appendValue:value into:json]) + return json; + + return nil; +} + + +- (NSString*)stringWithObject:(id)value { + + if ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]) { + return [self stringWithFragment:value]; + } + + if ([value respondsToSelector:@selector(proxyForJson)]) { + NSString *tmp = [self stringWithObject:[value proxyForJson]]; + if (tmp) + return tmp; + } + + + [self clearErrorTrace]; + [self addErrorWithCode:EFRAGMENT description:@"Not valid type for JSON"]; + return nil; +} + + +- (NSString*)indent { + return [@"\n" stringByPaddingToLength:1 + 2 * depth withString:@" " startingAtIndex:0]; +} + +- (BOOL)appendValue:(id)fragment into:(NSMutableString*)json { + if ([fragment isKindOfClass:[NSDictionary class]]) { + if (![self appendDictionary:fragment into:json]) + return NO; + + } else if ([fragment isKindOfClass:[NSArray class]]) { + if (![self appendArray:fragment into:json]) + return NO; + + } else if ([fragment isKindOfClass:[NSString class]]) { + if (![self appendString:fragment into:json]) + return NO; + + } else if ([fragment isKindOfClass:[NSNumber class]]) { + if ('c' == *[fragment objCType]) + [json appendString:[fragment boolValue] ? @"true" : @"false"]; + else + [json appendString:[fragment stringValue]]; + + } else if ([fragment isKindOfClass:[NSNull class]]) { + [json appendString:@"null"]; + } else if ([fragment respondsToSelector:@selector(proxyForJson)]) { + [self appendValue:[fragment proxyForJson] into:json]; + + } else { + [self addErrorWithCode:EUNSUPPORTED description:[NSString stringWithFormat:@"JSON serialisation not supported for %@", [fragment class]]]; + return NO; + } + return YES; +} + +- (BOOL)appendArray:(NSArray*)fragment into:(NSMutableString*)json { + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + [json appendString:@"["]; + + BOOL addComma = NO; + for (id value in fragment) { + if (addComma) + [json appendString:@","]; + else + addComma = YES; + + if ([self humanReadable]) + [json appendString:[self indent]]; + + if (![self appendValue:value into:json]) { + return NO; + } + } + + depth--; + if ([self humanReadable] && [fragment count]) + [json appendString:[self indent]]; + [json appendString:@"]"]; + return YES; +} + +- (BOOL)appendDictionary:(NSDictionary*)fragment into:(NSMutableString*)json { + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + [json appendString:@"{"]; + + NSString *colon = [self humanReadable] ? @" : " : @":"; + BOOL addComma = NO; + NSArray *keys = [fragment allKeys]; + if (self.sortKeys) + keys = [keys sortedArrayUsingSelector:@selector(compare:)]; + + for (id value in keys) { + if (addComma) + [json appendString:@","]; + else + addComma = YES; + + if ([self humanReadable]) + [json appendString:[self indent]]; + + if (![value isKindOfClass:[NSString class]]) { + [self addErrorWithCode:EUNSUPPORTED description: @"JSON object key must be string"]; + return NO; + } + + if (![self appendString:value into:json]) + return NO; + + [json appendString:colon]; + if (![self appendValue:[fragment objectForKey:value] into:json]) { + [self addErrorWithCode:EUNSUPPORTED description:[NSString stringWithFormat:@"Unsupported value for key %@ in object", value]]; + return NO; + } + } + + depth--; + if ([self humanReadable] && [fragment count]) + [json appendString:[self indent]]; + [json appendString:@"}"]; + return YES; +} + +- (BOOL)appendString:(NSString*)fragment into:(NSMutableString*)json { + + [json appendString:@"\""]; + + NSRange esc = [fragment rangeOfCharacterFromSet:kEscapeChars]; + if ( !esc.length ) { + // No special chars -- can just add the raw string: + [json appendString:fragment]; + + } else { + NSUInteger length = [fragment length]; + for (NSUInteger i = 0; i < length; i++) { + unichar uc = [fragment characterAtIndex:i]; + switch (uc) { + case '"': [json appendString:@"\\\""]; break; + case '\\': [json appendString:@"\\\\"]; break; + case '\t': [json appendString:@"\\t"]; break; + case '\n': [json appendString:@"\\n"]; break; + case '\r': [json appendString:@"\\r"]; break; + case '\b': [json appendString:@"\\b"]; break; + case '\f': [json appendString:@"\\f"]; break; + default: + if (uc < 0x20) { + [json appendFormat:@"\\u%04x", uc]; + } else { + CFStringAppendCharacters((CFMutableStringRef)json, &uc, 1); + } + break; + + } + } + } + + [json appendString:@"\""]; + return YES; +} + + +@end diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/Animations.css b/External Source/MacMapKit/Source/Framework/Resources/Animations.css similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/Animations.css rename to External Source/MacMapKit/Source/Framework/Resources/Animations.css diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/License.rtf b/External Source/MacMapKit/Source/Framework/Resources/License.rtf similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/License.rtf rename to External Source/MacMapKit/Source/Framework/Resources/License.rtf diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/MKPinAnnotationColorGreen.png b/External Source/MacMapKit/Source/Framework/Resources/MKPinAnnotationColorGreen.png similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/MKPinAnnotationColorGreen.png rename to External Source/MacMapKit/Source/Framework/Resources/MKPinAnnotationColorGreen.png diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/MKPinAnnotationColorPurple.png b/External Source/MacMapKit/Source/Framework/Resources/MKPinAnnotationColorPurple.png similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/MKPinAnnotationColorPurple.png rename to External Source/MacMapKit/Source/Framework/Resources/MKPinAnnotationColorPurple.png diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/MKPinAnnotationColorRed.png b/External Source/MacMapKit/Source/Framework/Resources/MKPinAnnotationColorRed.png similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/MKPinAnnotationColorRed.png rename to External Source/MacMapKit/Source/Framework/Resources/MKPinAnnotationColorRed.png diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/Info.plist b/External Source/MacMapKit/Source/Framework/Resources/MapKit-Info.plist similarity index 56% rename from Frameworks/MapKit.framework/Versions/A/Resources/Info.plist rename to External Source/MacMapKit/Source/Framework/Resources/MapKit-Info.plist index 26f632cd6..0bfcebfde 100644 --- a/Frameworks/MapKit.framework/Versions/A/Resources/Info.plist +++ b/External Source/MacMapKit/Source/Framework/Resources/MapKit-Info.plist @@ -2,14 +2,12 @@ - BuildMachineOSBuild - 11D50 CFBundleDevelopmentRegion English CFBundleExecutable - MapKit + ${EXECUTABLE_NAME} CFBundleIdentifier - ca.centrix.MapKit + ca.centrix.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType @@ -20,19 +18,5 @@ CTRX CFBundleVersion 0.8 - DTCompiler - - DTPlatformBuild - 4E109 - DTPlatformVersion - GM - DTSDKBuild - 10K549 - DTSDKName - macosx10.6 - DTXcode - 0430 - DTXcodeBuild - 4E109 diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/MapKit.html b/External Source/MacMapKit/Source/Framework/Resources/MapKit.html similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/MapKit.html rename to External Source/MacMapKit/Source/Framework/Resources/MapKit.html diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/MarkerTest.png b/External Source/MacMapKit/Source/Framework/Resources/MarkerTest.png similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/MarkerTest.png rename to External Source/MacMapKit/Source/Framework/Resources/MarkerTest.png diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/Release Notes.rtf b/External Source/MacMapKit/Source/Framework/Resources/Release Notes.rtf similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/Release Notes.rtf rename to External Source/MacMapKit/Source/Framework/Resources/Release Notes.rtf diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/Stylesheet.css b/External Source/MacMapKit/Source/Framework/Resources/Stylesheet.css similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/Stylesheet.css rename to External Source/MacMapKit/Source/Framework/Resources/Stylesheet.css diff --git a/Frameworks/MapKit.framework/Versions/A/Resources/TransparentPixel.png b/External Source/MacMapKit/Source/Framework/Resources/TransparentPixel.png similarity index 100% rename from Frameworks/MapKit.framework/Versions/A/Resources/TransparentPixel.png rename to External Source/MacMapKit/Source/Framework/Resources/TransparentPixel.png diff --git a/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapView+MapKitPlugin.m b/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapView+MapKitPlugin.m new file mode 100644 index 000000000..6f9659883 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapView+MapKitPlugin.m @@ -0,0 +1,29 @@ +// +// MKMapViewIntegration.m +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import +#import +#import "MKMapViewAttributeInspector.h" + +@implementation MKMapView ( MapKitPlugin ) + +- (void)ibPopulateKeyPaths:(NSMutableDictionary *)keyPaths { + [super ibPopulateKeyPaths:keyPaths]; + + // Remove the comments and replace "MyFirstProperty" and "MySecondProperty" + // in the following line with a list of your view's KVC-compliant properties. + //[[keyPaths objectForKey:IBAttributeKeyPaths] addObjectsFromArray:[NSArray arrayWithObjects:/* @"MyFirstProperty", @"MySecondProperty",*/ nil]]; + [[keyPaths objectForKey:IBAttributeKeyPaths] addObjectsFromArray:[NSArray arrayWithObjects:@"mapType", @"showsUserLocation", nil]]; +} + +- (void)ibPopulateAttributeInspectorClasses:(NSMutableArray *)classes { + [super ibPopulateAttributeInspectorClasses:classes]; + [classes addObject:[MKMapViewAttributeInspector class]]; +} + +@end diff --git a/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapViewAttributeInspector.h b/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapViewAttributeInspector.h new file mode 100644 index 000000000..da940b820 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapViewAttributeInspector.h @@ -0,0 +1,16 @@ +// +// MapKitPluginInspector.h +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import + + +@interface MKMapViewAttributeInspector : IBInspector { + IBOutlet NSPopUpButton *mapTypePopUpButton; +} + +@end diff --git a/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapViewAttributeInspector.m b/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapViewAttributeInspector.m new file mode 100644 index 000000000..585734cd7 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Classes/MKMapViewAttributeInspector.m @@ -0,0 +1,33 @@ +// +// MapKitPluginInspector.m +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MKMapViewAttributeInspector.h" + + +@implementation MKMapViewAttributeInspector + +- (NSString *)viewNibName { + return @"MKMapViewAttributeInspector"; +} + +- (NSString *)label +{ + return @"Map View"; +} + +- (void)awakeFromNib +{ + +} + +- (void)refresh { + // Synchronize your inspector's content view with the currently selected objects. + [super refresh]; +} + +@end diff --git a/External Source/MacMapKit/Source/IBPlugin/Classes/MapKitPlugin.h b/External Source/MacMapKit/Source/IBPlugin/Classes/MapKitPlugin.h new file mode 100644 index 000000000..37ea666ed --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Classes/MapKitPlugin.h @@ -0,0 +1,16 @@ +// +// MapKitPlugin.h +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import + + +@interface MapKitPlugin : IBPlugin { + +} + +@end \ No newline at end of file diff --git a/External Source/MacMapKit/Source/IBPlugin/Classes/MapKitPlugin.m b/External Source/MacMapKit/Source/IBPlugin/Classes/MapKitPlugin.m new file mode 100644 index 000000000..ac2b35cf6 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Classes/MapKitPlugin.m @@ -0,0 +1,27 @@ +// +// MapKitPlugin.m +// MapKit +// +// Created by Rick Fillion on 7/26/10. +// Copyright 2010 Centrix.ca. All rights reserved. +// + +#import "MapKitPlugin.h" + + +@implementation MapKitPlugin + +- (NSArray *)libraryNibNames { + return [NSArray arrayWithObject:@"MapKitPluginLibrary"]; +} + +- (NSArray *)requiredFrameworks { + return [NSArray arrayWithObjects:[NSBundle bundleWithIdentifier:@"ca.centrix.MapKitFramework"], nil]; +} + +- (NSString *)label +{ + return @"Map Kit"; +} + +@end diff --git a/External Source/MacMapKit/Source/IBPlugin/MKMapView.classdescription b/External Source/MacMapKit/Source/IBPlugin/MKMapView.classdescription new file mode 100644 index 000000000..a76b7e571 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/MKMapView.classdescription @@ -0,0 +1,10 @@ +{ + Actions = { + "takeStringValueFrom:" = id; + }; + Outlets = { + delegate = id; + }; + ClassName = MKMapView; + SuperClass = NSView; +} \ No newline at end of file diff --git a/External Source/MacMapKit/Source/IBPlugin/Resources/MKMapViewAttributeInspector.xib b/External Source/MacMapKit/Source/IBPlugin/Resources/MKMapViewAttributeInspector.xib new file mode 100644 index 000000000..ad04e8c4d --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Resources/MKMapViewAttributeInspector.xib @@ -0,0 +1,1076 @@ + + + + 1060 + 10F569 + 823 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 823 + + + YES + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + MKMapViewAttributeInspector + + + FirstResponder + + + NSApplication + + + + 256 + + YES + + + 268 + {{81, 8}, {132, 18}} + + YES + + 67239424 + 131072 + Shows User Location + + LucidaGrande + 11 + 3100 + + + 1211912703 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{81, 36}, {186, 22}} + + YES + + -2076049856 + 133120 + + + 109199615 + 1 + + LucidaGrande + 11 + 16 + + + + 400 + 75 + + + Hybrid + + 1048576 + 2147483647 + 1 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + _popUpItemAction: + 2 + + + YES + + OtherViews + + YES + + + Map + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Satellite + + 1048576 + 2147483647 + + + _popUpItemAction: + 1 + + + + + + + 2 + 3 + YES + YES + 1 + + + + + 268 + {{8, 10}, {70, 14}} + + YES + + 67239488 + 4326400 + Behavior + + LucidaGrande-Bold + 11 + 16 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2ODY1AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 268 + {{8, 40}, {70, 14}} + + YES + + 67239488 + 4326400 + Map Type + + + + + + + + {272, 65} + NSView + NSResponder + + + + + YES + + + inspectorView + + + + 70 + + + + mapTypePopUpButton + + + + 71 + + + + value: inspectedObjectsController.selection.showsUserLocation + + + + + + value: inspectedObjectsController.selection.showsUserLocation + value + inspectedObjectsController.selection.showsUserLocation + 2 + + + 72 + + + + selectedTag: inspectedObjectsController.selection.mapType + + + + + + selectedTag: inspectedObjectsController.selection.mapType + selectedTag + inspectedObjectsController.selection.mapType + 2 + + + 73 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 57 + + + YES + + + + + + + Inspector View + + + 58 + + + YES + + + + + + 59 + + + YES + + + + + + 60 + + + YES + + + + + + 61 + + + YES + + + + + + 62 + + + + + 63 + + + YES + + + + + + 64 + + + YES + + + + + + + + 65 + + + + + 66 + + + + + 67 + + + + + 68 + + + + + 69 + + + + + + + YES + + YES + -3.IBPluginDependency + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 58.IBPluginDependency + 58.ImportedFromIB2 + 59.IBPluginDependency + 59.ImportedFromIB2 + 60.IBPluginDependency + 60.ImportedFromIB2 + 61.IBPluginDependency + 61.ImportedFromIB2 + 62.IBPluginDependency + 62.ImportedFromIB2 + 63.IBPluginDependency + 63.ImportedFromIB2 + 64.IBPluginDependency + 64.ImportedFromIB2 + 65.IBPluginDependency + 65.ImportedFromIB2 + 66.IBPluginDependency + 66.ImportedFromIB2 + 67.IBPluginDependency + 67.ImportedFromIB2 + 68.IBPluginDependency + 68.ImportedFromIB2 + 69.IBPluginDependency + 69.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + {{21, 896}, {272, 65}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 73 + + + + YES + + MKMapViewAttributeInspector + IBInspector + + mapTypePopUpButton + NSPopUpButton + + + mapTypePopUpButton + + mapTypePopUpButton + NSPopUpButton + + + + IBProjectSource + IBPlugin/Classes/MKMapViewAttributeInspector.h + + + + NSObject + + IBProjectSource + Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.h + + + + NSObject + + IBProjectSource + Framework/Classes/Third Party/SBJSON/SBJsonWriter.h + + + + + YES + + IBInspector + NSObject + + inspectorView + NSView + + + inspectorView + + inspectorView + NSView + + + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBInspector.h + + + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMenuItemCell + NSButtonCell + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItemCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBObjectIntegration.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebDownload.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebEditingDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebFrameLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebJavaPlugIn.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPlugin.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPluginContainer.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPolicyDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebResourceLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebScriptObject.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebUIDelegate.h + + + + NSPopUpButton + NSButton + + IBFrameworkSource + AppKit.framework/Headers/NSPopUpButton.h + + + + NSPopUpButtonCell + NSMenuItemCell + + IBFrameworkSource + AppKit.framework/Headers/NSPopUpButtonCell.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSView + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBViewIntegration.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../../MapKit.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + NSSwitch + + + YES + {9, 8} + {7, 2} + {15, 15} + + + + diff --git a/External Source/MacMapKit/Source/IBPlugin/Resources/MapKitPlugin-Info.plist b/External Source/MacMapKit/Source/IBPlugin/Resources/MapKitPlugin-Info.plist new file mode 100644 index 000000000..8a457ac64 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Resources/MapKitPlugin-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleName + MapKitPlugin + NSPrincipalClass + MapKitPlugin + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ca.centrix.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/External Source/MacMapKit/Source/IBPlugin/Resources/MapKitPluginLibrary.xib b/External Source/MacMapKit/Source/IBPlugin/Resources/MapKitPluginLibrary.xib new file mode 100644 index 000000000..a5d92d125 --- /dev/null +++ b/External Source/MacMapKit/Source/IBPlugin/Resources/MapKitPluginLibrary.xib @@ -0,0 +1,962 @@ + + + + 1060 + 10F569 + 823 + 1038.29 + 461.00 + + YES + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.IBSDKPlugin + + + YES + 823 + 823 + + + + YES + + + + YES + com.apple.InterfaceBuilder.IBSDKPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSObject + + + FirstResponder + + + NSApplication + + + + 268 + + YES + + + 268 + {{113, 45}, {296, 184}} + + MKMapView + + + + 268 + + YES + + + 268 + + YES + + YES + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + NSFilenamesPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT TIFF v4.0 pasteboard type + + + {{15, 15}, {48, 48}} + + YES + + 130560 + 33554432 + + NSImage + MapView + + 0 + 0 + 0 + NO + + YES + + + {{20, 154}, {80, 80}} + + Map View + + 0905A182-5F9E-4A5F-8D00-FC98EC369088 + + Allows users to create an editable map + + + + + + + + 0 + NO + + + + 268 + {{20, 242}, {117, 17}} + + YES + + 67239488 + 272630784 + Template + + LucidaGrande + 13 + 1044 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2ODY1AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 12 + {{20, 240}, {224, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + 3 + 2 + 0 + NO + + + {442, 279} + + NSView + + + + + YES + + + representedObject + + + + 45 + + + + draggedView + + + + 46 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 7 + + + YES + + + + + + + Library Objects + + + 18 + + + YES + + + + + + 32 + + + + + 33 + + + YES + + + + + + 34 + + + + + 41 + + + YES + + + + + + 42 + + + + + 44 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 18.IBPluginDependency + 18.notes + 18.showNotes + 32.IBPluginDependency + 33.IBPluginDependency + 34.IBPluginDependency + 41.IBPluginDependency + 42.IBPluginDependency + 44.IBPluginDependency + 44.ImportedFromIB2 + 7.IBEditorWindowLastContentRect + 7.IBPluginDependency + 7.IBUserGuides + 7.WindowOrigin + 7.editorWindowContentRectSynchronizationRect + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.IBSDKPlugin + + SWYgeW91IHdvdWxkIGxpa2UgeW91ciB2aWV3IHRvIGFuaW1hdGUgZnJvbSBhIHNtYWxsLCBpY29uaWMg +cmVwcmVzZW50YXRpb24sIHRvIGEgZmluYWwgcmVwcmVzZW50YXRpb24sIGNvbm5lY3QgdGhpcyB2aWV3 +J3MgJ2RyYWdnZWRWaWV3JyBvdXRsZXQgYnkgY29udHJvbCBjbGlja2luZyBvbiBpdC4KCklmIHRoZSBv +YmplY3QgeW91IHdvdWxkIGxpa2UgZGVwb3NpdGVkIGFmdGVyIHRoZSBkcmFnLCBpcyBzb21ldGhpbmcg +b3RoZXIgdGhhbiB0aGlzIHZpZXcncyBzdWJ2aWV3LCBvciBkcmFnZ2VkVmlldywgdGhlbiB5b3Ugc2hv +dWxkIGNvbm5lY3QgdGhlIHJlcHJlc2VudGVkT2JqZWN0IG91dGxldCBvZiB0aGlzIHZpZXcgdG8gYW4g +b2JqZWN0IHRvIGRlcG9zaXQuA + + YES + + + YES + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{430, 318}, {442, 279}} + com.apple.InterfaceBuilder.CocoaPlugin + + YES + + {332, 343} + {{403, 401}, {264, 327}} + + + + YES + + + YES + + + + + YES + + + YES + + + + 46 + + + + YES + + MKMapView + + takeStringValueFrom: + id + + + takeStringValueFrom: + + takeStringValueFrom: + id + + + + IBProjectSource + Framework/Classes/MKMapView+Additions.h + + + + MKMapView + + IBProjectSource + Framework/Classes/MKMapView+DelegateWrappers.h + + + + MKMapView + + IBProjectSource + Framework/Classes/MKMapView+WebViewIntegration.h + + + + MKMapView + NSView + + delegate + id + + + delegate + + delegate + id + + + + IBProjectSource + Framework/Classes/MKMapView.h + + + + NSObject + + IBProjectSource + Framework/Classes/Third Party/SBJSON/NSObject+SBJSON.h + + + + NSObject + + IBProjectSource + Framework/Classes/Third Party/SBJSON/SBJsonWriter.h + + + + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBox + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSBox.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSImageCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSImageCell.h + + + + NSImageView + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSImageView.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBObjectIntegration.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebDownload.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebEditingDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebFrameLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebJavaPlugIn.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPlugin.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPluginContainer.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPolicyDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebResourceLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebScriptObject.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebUIDelegate.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSView + + IBFrameworkSource + InterfaceBuilderKit.framework/Headers/IBViewIntegration.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../../MapKit.xcodeproj + 3 + + MapView + {48, 48} + + + diff --git a/External Source/MacMapKit/Source/IBPlugin/Resources/MapView.png b/External Source/MacMapKit/Source/IBPlugin/Resources/MapView.png new file mode 100644 index 000000000..b0fdf96d8 Binary files /dev/null and b/External Source/MacMapKit/Source/IBPlugin/Resources/MapView.png differ diff --git a/External Source/MacMapKit/Source/MapKit.xcodeproj/project.pbxproj b/External Source/MacMapKit/Source/MapKit.xcodeproj/project.pbxproj new file mode 100644 index 000000000..163924288 --- /dev/null +++ b/External Source/MacMapKit/Source/MapKit.xcodeproj/project.pbxproj @@ -0,0 +1,1109 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5F199EE8120257FB0083FE72 /* MapKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF17D11F13F690077E84F /* MapKit.framework */; }; + 5F19A03E1208F6DE0083FE72 /* MKMapView+MapKitPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F19A03D1208F6DE0083FE72 /* MKMapView+MapKitPlugin.m */; }; + 5F19A0491208F9260083FE72 /* License.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 5F19A0471208F9260083FE72 /* License.rtf */; }; + 5F19A04A1208F9260083FE72 /* Release Notes.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 5F19A0481208F9260083FE72 /* Release Notes.rtf */; }; + 5F39D6FE12B5AB50001B32CD /* MKWebView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F39D6FC12B5AB50001B32CD /* MKWebView.h */; }; + 5F39D6FF12B5AB50001B32CD /* MKWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F39D6FD12B5AB50001B32CD /* MKWebView.m */; }; + 5F585A5D12110FE7005F437E /* TransparentPixel.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F585A5C12110FE6005F437E /* TransparentPixel.png */; }; + 5F585AAF121231B6005F437E /* Animations.css in Resources */ = {isa = PBXBuildFile; fileRef = 5F585AAD121231B6005F437E /* Animations.css */; }; + 5F585AB0121231B6005F437E /* Stylesheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 5F585AAE121231B6005F437E /* Stylesheet.css */; }; + 5F6EF13C11F13B170077E84F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF13B11F13B170077E84F /* Cocoa.framework */; }; + 5F6EF14411F13B4B0077E84F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5F6EF14311F13B4B0077E84F /* MainMenu.xib */; }; + 5F6EF15011F13BCB0077E84F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F6EF14F11F13BCB0077E84F /* main.m */; }; + 5F6EF16B11F13CB70077E84F /* DemoAppApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F6EF16A11F13CB70077E84F /* DemoAppApplicationDelegate.m */; }; + 5F6EF18211F13F710077E84F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF13B11F13B170077E84F /* Cocoa.framework */; }; + 5F6EF18A11F13FDC0077E84F /* MapKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF17D11F13F690077E84F /* MapKit.framework */; }; + 5F76C78911F4EDE000713BBA /* MKView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F76C78711F4EDE000713BBA /* MKView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F76C78A11F4EDE000713BBA /* MKView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F76C78811F4EDE000713BBA /* MKView.m */; }; + 5F76C82111F4F85E00713BBA /* MarkerTest.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F76C82011F4F85E00713BBA /* MarkerTest.png */; }; + 5F76C83A11F4FC8F00713BBA /* MarkerTest.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F76C82011F4F85E00713BBA /* MarkerTest.png */; }; + 5F76C88011F52BFC00713BBA /* MKPinAnnotationColorRed.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F76C87F11F52BFC00713BBA /* MKPinAnnotationColorRed.png */; }; + 5F76C89A11F52DFA00713BBA /* MKPinAnnotationColorGreen.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F76C89811F52DFA00713BBA /* MKPinAnnotationColorGreen.png */; }; + 5F76C89B11F52DFA00713BBA /* MKPinAnnotationColorPurple.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F76C89911F52DFA00713BBA /* MKPinAnnotationColorPurple.png */; }; + 5F84F0F711F21A4F008D3A32 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FBAF80711F14955004753A9 /* CoreLocation.framework */; }; + 5F84F10A11F21B88008D3A32 /* MapKit.html in Resources */ = {isa = PBXBuildFile; fileRef = 5F84F10911F21B88008D3A32 /* MapKit.html */; }; + 5F84F20511F3E956008D3A32 /* MKPointAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F84F20311F3E956008D3A32 /* MKPointAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F84F20611F3E956008D3A32 /* MKPointAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F84F20411F3E956008D3A32 /* MKPointAnnotation.m */; }; + 5F84F23A11F3ED6E008D3A32 /* MKAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F84F23811F3ED6E008D3A32 /* MKAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F84F23B11F3ED6E008D3A32 /* MKAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F84F23911F3ED6E008D3A32 /* MKAnnotationView.m */; }; + 5F84F25711F3F173008D3A32 /* MKPinAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F84F25511F3F173008D3A32 /* MKPinAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F84F25811F3F173008D3A32 /* MKPinAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F84F25611F3F173008D3A32 /* MKPinAnnotationView.m */; }; + 5F87D82F131C825B00634ACD /* MapViewAdditions.css in Resources */ = {isa = PBXBuildFile; fileRef = 5F87D82E131C825B00634ACD /* MapViewAdditions.css */; }; + 5F96B22513BAB9F4000A1E4A /* MKMapView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F96B22313BAB9F4000A1E4A /* MKMapView+Private.h */; }; + 5F96B22613BAB9F4000A1E4A /* MKMapView+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F96B22413BAB9F4000A1E4A /* MKMapView+Private.m */; }; + 5F9CE3DA12D15F98006354EF /* MKGeocoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F9CE3D812D15F98006354EF /* MKGeocoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F9CE3DB12D15F98006354EF /* MKGeocoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F9CE3D912D15F98006354EF /* MKGeocoder.m */; }; + 5FB7406F11F8C77C00AB2079 /* MKMapView+DelegateWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB7406D11F8C77C00AB2079 /* MKMapView+DelegateWrappers.h */; }; + 5FB7407011F8C77C00AB2079 /* MKMapView+DelegateWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7406E11F8C77C00AB2079 /* MKMapView+DelegateWrappers.m */; }; + 5FB7407711F8C81800AB2079 /* MKMapView+WebViewIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB7407511F8C81800AB2079 /* MKMapView+WebViewIntegration.h */; }; + 5FB7407811F8C81800AB2079 /* MKMapView+WebViewIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7407611F8C81800AB2079 /* MKMapView+WebViewIntegration.m */; }; + 5FB740FF11FB4BD200AB2079 /* MKMapView+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB740FD11FB4BD200AB2079 /* MKMapView+Additions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FB7410011FB4BD200AB2079 /* MKMapView+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB740FE11FB4BD200AB2079 /* MKMapView+Additions.m */; }; + 5FB7411B11FB50B800AB2079 /* MKPlacemark.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB7411911FB50B800AB2079 /* MKPlacemark.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FB7411C11FB50B800AB2079 /* MKPlacemark.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7411A11FB50B800AB2079 /* MKPlacemark.m */; }; + 5FB7413411FB52AF00AB2079 /* MKReverseGeocoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB7413211FB52AF00AB2079 /* MKReverseGeocoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FB7413511FB52AF00AB2079 /* MKReverseGeocoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7413311FB52AF00AB2079 /* MKReverseGeocoder.m */; }; + 5FB7417311FD53B500AB2079 /* MKPlacemark+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB7417111FD53B500AB2079 /* MKPlacemark+Private.h */; }; + 5FB7417411FD53B500AB2079 /* MKPlacemark+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7417211FD53B500AB2079 /* MKPlacemark+Private.m */; }; + 5FB7436711FE6F0500AB2079 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF13B11F13B170077E84F /* Cocoa.framework */; }; + 5FB7436811FE6F1300AB2079 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF17D11F13F690077E84F /* MapKit.framework */; }; + 5FB7437211FE6F4C00AB2079 /* InterfaceBuilderKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FB7437111FE6F4C00AB2079 /* InterfaceBuilderKit.framework */; }; + 5FB7437E11FE700600AB2079 /* MKMapView.classdescription in Resources */ = {isa = PBXBuildFile; fileRef = 5FB7437D11FE700600AB2079 /* MKMapView.classdescription */; }; + 5FB7438411FE705E00AB2079 /* MapKitPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7438311FE705E00AB2079 /* MapKitPlugin.m */; }; + 5FB7438811FE70AC00AB2079 /* MKMapViewAttributeInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FB7438711FE70AC00AB2079 /* MKMapViewAttributeInspector.m */; }; + 5FB743B411FE74B100AB2079 /* MapView.png in Resources */ = {isa = PBXBuildFile; fileRef = 5FB743B311FE74B100AB2079 /* MapView.png */; }; + 5FBAF77511F14518004753A9 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F6EF17D11F13F690077E84F /* MapKit.framework */; }; + 5FBAF7A711F147EF004753A9 /* NSColor+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7A511F147EF004753A9 /* NSColor+Additions.h */; }; + 5FBAF7A811F147EF004753A9 /* NSColor+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7A611F147EF004753A9 /* NSColor+Additions.m */; }; + 5FBAF7B811F1482E004753A9 /* JSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7AB11F1482E004753A9 /* JSON.h */; }; + 5FBAF7B911F1482E004753A9 /* NSObject+SBJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7AC11F1482E004753A9 /* NSObject+SBJSON.h */; }; + 5FBAF7BA11F1482E004753A9 /* NSObject+SBJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7AD11F1482E004753A9 /* NSObject+SBJSON.m */; }; + 5FBAF7BB11F1482E004753A9 /* NSString+SBJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7AE11F1482E004753A9 /* NSString+SBJSON.h */; }; + 5FBAF7BC11F1482E004753A9 /* NSString+SBJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7AF11F1482E004753A9 /* NSString+SBJSON.m */; }; + 5FBAF7BD11F1482E004753A9 /* SBJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7B011F1482E004753A9 /* SBJSON.h */; }; + 5FBAF7BE11F1482E004753A9 /* SBJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7B111F1482E004753A9 /* SBJSON.m */; }; + 5FBAF7BF11F1482E004753A9 /* SBJsonBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7B211F1482E004753A9 /* SBJsonBase.h */; }; + 5FBAF7C011F1482E004753A9 /* SBJsonBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7B311F1482E004753A9 /* SBJsonBase.m */; }; + 5FBAF7C111F1482E004753A9 /* SBJsonParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7B411F1482E004753A9 /* SBJsonParser.h */; }; + 5FBAF7C211F1482E004753A9 /* SBJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7B511F1482E004753A9 /* SBJsonParser.m */; }; + 5FBAF7C311F1482E004753A9 /* SBJsonWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7B611F1482E004753A9 /* SBJsonWriter.h */; }; + 5FBAF7C411F1482E004753A9 /* SBJsonWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7B711F1482E004753A9 /* SBJsonWriter.m */; }; + 5FBAF7CF11F1486D004753A9 /* MKMapView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7C511F1486D004753A9 /* MKMapView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7D011F1486D004753A9 /* MKMapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7C611F1486D004753A9 /* MKMapView.m */; }; + 5FBAF7D111F1486D004753A9 /* MKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7C711F1486D004753A9 /* MKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7D211F1486D004753A9 /* MKGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7C811F1486D004753A9 /* MKGeometry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7D311F1486D004753A9 /* MapKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7C911F1486D004753A9 /* MapKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7D411F1486D004753A9 /* MKUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7CA11F1486D004753A9 /* MKUserLocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7D511F1486D004753A9 /* MKUserLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7CB11F1486D004753A9 /* MKUserLocation.m */; }; + 5FBAF7D611F1486D004753A9 /* MKUserLocation+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7CC11F1486D004753A9 /* MKUserLocation+Private.h */; settings = {ATTRIBUTES = (); }; }; + 5FBAF7D711F1486D004753A9 /* MKUserLocation+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7CD11F1486D004753A9 /* MKUserLocation+Private.m */; }; + 5FBAF7D811F1486D004753A9 /* MKAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7CE11F1486D004753A9 /* MKAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7E511F14889004753A9 /* MKShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7DA11F14889004753A9 /* MKShape.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7E611F14889004753A9 /* MKShape.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7DB11F14889004753A9 /* MKShape.m */; }; + 5FBAF7E711F14889004753A9 /* MKCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7DC11F14889004753A9 /* MKCircle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7E811F14889004753A9 /* MKCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7DD11F14889004753A9 /* MKCircle.m */; }; + 5FBAF7E911F14889004753A9 /* MKOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7DE11F14889004753A9 /* MKOverlay.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7EA11F14889004753A9 /* MKMultiPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7DF11F14889004753A9 /* MKMultiPoint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7EB11F14889004753A9 /* MKMultiPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7E011F14889004753A9 /* MKMultiPoint.m */; }; + 5FBAF7EC11F14889004753A9 /* MKPolyline.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7E111F14889004753A9 /* MKPolyline.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7ED11F14889004753A9 /* MKPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7E211F14889004753A9 /* MKPolyline.m */; }; + 5FBAF7EE11F14889004753A9 /* MKPolygon.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7E311F14889004753A9 /* MKPolygon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7EF11F14889004753A9 /* MKPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7E411F14889004753A9 /* MKPolygon.m */; }; + 5FBAF7FB11F148A5004753A9 /* MKOverlayView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7F111F148A5004753A9 /* MKOverlayView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7FC11F148A5004753A9 /* MKOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7F211F148A5004753A9 /* MKOverlayView.m */; }; + 5FBAF7FD11F148A5004753A9 /* MKOverlayPathView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7F311F148A5004753A9 /* MKOverlayPathView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF7FE11F148A5004753A9 /* MKOverlayPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7F411F148A5004753A9 /* MKOverlayPathView.m */; }; + 5FBAF7FF11F148A5004753A9 /* MKCircleView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7F511F148A5004753A9 /* MKCircleView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF80011F148A5004753A9 /* MKCircleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7F611F148A5004753A9 /* MKCircleView.m */; }; + 5FBAF80111F148A5004753A9 /* MKPolylineView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7F711F148A5004753A9 /* MKPolylineView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF80211F148A5004753A9 /* MKPolylineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7F811F148A5004753A9 /* MKPolylineView.m */; }; + 5FBAF80311F148A5004753A9 /* MKPolygonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FBAF7F911F148A5004753A9 /* MKPolygonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5FBAF80411F148A5004753A9 /* MKPolygonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAF7FA11F148A5004753A9 /* MKPolygonView.m */; }; + 5FBAF80811F14955004753A9 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FBAF80711F14955004753A9 /* CoreLocation.framework */; }; + 5FBAF80C11F14964004753A9 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FBAF80B11F14964004753A9 /* WebKit.framework */; }; + 5FE8314812A60AF600728ECE /* MapKitPluginLibrary.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5FE8314712A60AF600728ECE /* MapKitPluginLibrary.xib */; }; + 5FE8314C12A60BFF00728ECE /* MKMapViewAttributeInspector.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5FE8314B12A60BFF00728ECE /* MKMapViewAttributeInspector.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 5F6EF19111F140360077E84F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5F6EF17C11F13F690077E84F; + remoteInfo = MapKit; + }; + 5FB7436511FE6ED200AB2079 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5F6EF17C11F13F690077E84F; + remoteInfo = MapKit; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 5F199F08120258020083FE72 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 5F199EE8120257FB0083FE72 /* MapKit.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 5F6EF17011F13EFC0077E84F /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 5F6EF18A11F13FDC0077E84F /* MapKit.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 5F19A03D1208F6DE0083FE72 /* MKMapView+MapKitPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKMapView+MapKitPlugin.m"; sourceTree = ""; }; + 5F19A0471208F9260083FE72 /* License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = License.rtf; sourceTree = ""; }; + 5F19A0481208F9260083FE72 /* Release Notes.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Release Notes.rtf"; sourceTree = ""; }; + 5F39D6FC12B5AB50001B32CD /* MKWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKWebView.h; sourceTree = ""; }; + 5F39D6FD12B5AB50001B32CD /* MKWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKWebView.m; sourceTree = ""; }; + 5F585A5C12110FE6005F437E /* TransparentPixel.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TransparentPixel.png; path = ../Framework/Resources/TransparentPixel.png; sourceTree = ""; }; + 5F585AAD121231B6005F437E /* Animations.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = Animations.css; sourceTree = ""; }; + 5F585AAE121231B6005F437E /* Stylesheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = Stylesheet.css; sourceTree = ""; }; + 5F6EF13511F13B0D0077E84F /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 5F6EF13B11F13B170077E84F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 5F6EF14311F13B4B0077E84F /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + 5F6EF14C11F13B8A0077E84F /* DemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DemoApp-Info.plist"; sourceTree = ""; }; + 5F6EF14F11F13BCB0077E84F /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 5F6EF15211F13BE70077E84F /* DemoApp_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoApp_Prefix.pch; sourceTree = ""; }; + 5F6EF16911F13CB70077E84F /* DemoAppApplicationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoAppApplicationDelegate.h; sourceTree = ""; }; + 5F6EF16A11F13CB70077E84F /* DemoAppApplicationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoAppApplicationDelegate.m; sourceTree = ""; }; + 5F6EF17D11F13F690077E84F /* MapKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MapKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5F6EF18711F13FA40077E84F /* MapKit-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MapKit-Info.plist"; sourceTree = ""; }; + 5F76C78711F4EDE000713BBA /* MKView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKView.h; sourceTree = ""; }; + 5F76C78811F4EDE000713BBA /* MKView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKView.m; sourceTree = ""; }; + 5F76C82011F4F85E00713BBA /* MarkerTest.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MarkerTest.png; sourceTree = ""; }; + 5F76C87F11F52BFC00713BBA /* MKPinAnnotationColorRed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MKPinAnnotationColorRed.png; sourceTree = ""; }; + 5F76C89811F52DFA00713BBA /* MKPinAnnotationColorGreen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MKPinAnnotationColorGreen.png; sourceTree = ""; }; + 5F76C89911F52DFA00713BBA /* MKPinAnnotationColorPurple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MKPinAnnotationColorPurple.png; sourceTree = ""; }; + 5F84F10911F21B88008D3A32 /* MapKit.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = MapKit.html; sourceTree = ""; }; + 5F84F20311F3E956008D3A32 /* MKPointAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPointAnnotation.h; sourceTree = ""; }; + 5F84F20411F3E956008D3A32 /* MKPointAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPointAnnotation.m; sourceTree = ""; }; + 5F84F23811F3ED6E008D3A32 /* MKAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKAnnotationView.h; sourceTree = ""; }; + 5F84F23911F3ED6E008D3A32 /* MKAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKAnnotationView.m; sourceTree = ""; }; + 5F84F25511F3F173008D3A32 /* MKPinAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPinAnnotationView.h; sourceTree = ""; }; + 5F84F25611F3F173008D3A32 /* MKPinAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPinAnnotationView.m; sourceTree = ""; }; + 5F87D82E131C825B00634ACD /* MapViewAdditions.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = MapViewAdditions.css; sourceTree = ""; }; + 5F96B22313BAB9F4000A1E4A /* MKMapView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKMapView+Private.h"; sourceTree = ""; }; + 5F96B22413BAB9F4000A1E4A /* MKMapView+Private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKMapView+Private.m"; sourceTree = ""; }; + 5F9CE3D812D15F98006354EF /* MKGeocoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKGeocoder.h; sourceTree = ""; }; + 5F9CE3D912D15F98006354EF /* MKGeocoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKGeocoder.m; sourceTree = ""; }; + 5FB7406D11F8C77C00AB2079 /* MKMapView+DelegateWrappers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKMapView+DelegateWrappers.h"; sourceTree = ""; }; + 5FB7406E11F8C77C00AB2079 /* MKMapView+DelegateWrappers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKMapView+DelegateWrappers.m"; sourceTree = ""; }; + 5FB7407511F8C81800AB2079 /* MKMapView+WebViewIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKMapView+WebViewIntegration.h"; sourceTree = ""; }; + 5FB7407611F8C81800AB2079 /* MKMapView+WebViewIntegration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKMapView+WebViewIntegration.m"; sourceTree = ""; }; + 5FB740FD11FB4BD200AB2079 /* MKMapView+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKMapView+Additions.h"; sourceTree = ""; }; + 5FB740FE11FB4BD200AB2079 /* MKMapView+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKMapView+Additions.m"; sourceTree = ""; }; + 5FB7411911FB50B800AB2079 /* MKPlacemark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPlacemark.h; sourceTree = ""; }; + 5FB7411A11FB50B800AB2079 /* MKPlacemark.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPlacemark.m; sourceTree = ""; }; + 5FB7413211FB52AF00AB2079 /* MKReverseGeocoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKReverseGeocoder.h; sourceTree = ""; }; + 5FB7413311FB52AF00AB2079 /* MKReverseGeocoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKReverseGeocoder.m; sourceTree = ""; }; + 5FB7417111FD53B500AB2079 /* MKPlacemark+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKPlacemark+Private.h"; sourceTree = ""; }; + 5FB7417211FD53B500AB2079 /* MKPlacemark+Private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKPlacemark+Private.m"; sourceTree = ""; }; + 5FB7435711FE6E4A00AB2079 /* MapKit.ibplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MapKit.ibplugin; sourceTree = BUILT_PRODUCTS_DIR; }; + 5FB7437111FE6F4C00AB2079 /* InterfaceBuilderKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InterfaceBuilderKit.framework; path = Library/Frameworks/InterfaceBuilderKit.framework; sourceTree = DEVELOPER_DIR; }; + 5FB7437D11FE700600AB2079 /* MKMapView.classdescription */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.ibClassDescription; path = MKMapView.classdescription; sourceTree = ""; }; + 5FB7438211FE705E00AB2079 /* MapKitPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapKitPlugin.h; sourceTree = ""; }; + 5FB7438311FE705E00AB2079 /* MapKitPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapKitPlugin.m; sourceTree = ""; }; + 5FB7438611FE70AC00AB2079 /* MKMapViewAttributeInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKMapViewAttributeInspector.h; sourceTree = ""; }; + 5FB7438711FE70AC00AB2079 /* MKMapViewAttributeInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKMapViewAttributeInspector.m; sourceTree = ""; }; + 5FB7439511FE727100AB2079 /* MapKitPlugin-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MapKitPlugin-Info.plist"; sourceTree = ""; }; + 5FB743B311FE74B100AB2079 /* MapView.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MapView.png; sourceTree = ""; }; + 5FBAF7A511F147EF004753A9 /* NSColor+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSColor+Additions.h"; sourceTree = ""; }; + 5FBAF7A611F147EF004753A9 /* NSColor+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSColor+Additions.m"; sourceTree = ""; }; + 5FBAF7AB11F1482E004753A9 /* JSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSON.h; sourceTree = ""; }; + 5FBAF7AC11F1482E004753A9 /* NSObject+SBJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SBJSON.h"; sourceTree = ""; }; + 5FBAF7AD11F1482E004753A9 /* NSObject+SBJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SBJSON.m"; sourceTree = ""; }; + 5FBAF7AE11F1482E004753A9 /* NSString+SBJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SBJSON.h"; sourceTree = ""; }; + 5FBAF7AF11F1482E004753A9 /* NSString+SBJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+SBJSON.m"; sourceTree = ""; }; + 5FBAF7B011F1482E004753A9 /* SBJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJSON.h; sourceTree = ""; }; + 5FBAF7B111F1482E004753A9 /* SBJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJSON.m; sourceTree = ""; }; + 5FBAF7B211F1482E004753A9 /* SBJsonBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonBase.h; sourceTree = ""; }; + 5FBAF7B311F1482E004753A9 /* SBJsonBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonBase.m; sourceTree = ""; }; + 5FBAF7B411F1482E004753A9 /* SBJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonParser.h; sourceTree = ""; }; + 5FBAF7B511F1482E004753A9 /* SBJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonParser.m; sourceTree = ""; }; + 5FBAF7B611F1482E004753A9 /* SBJsonWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonWriter.h; sourceTree = ""; }; + 5FBAF7B711F1482E004753A9 /* SBJsonWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonWriter.m; sourceTree = ""; }; + 5FBAF7C511F1486D004753A9 /* MKMapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKMapView.h; sourceTree = ""; }; + 5FBAF7C611F1486D004753A9 /* MKMapView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKMapView.m; sourceTree = ""; }; + 5FBAF7C711F1486D004753A9 /* MKTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKTypes.h; sourceTree = ""; }; + 5FBAF7C811F1486D004753A9 /* MKGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKGeometry.h; sourceTree = ""; }; + 5FBAF7C911F1486D004753A9 /* MapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapKit.h; sourceTree = ""; }; + 5FBAF7CA11F1486D004753A9 /* MKUserLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKUserLocation.h; sourceTree = ""; }; + 5FBAF7CB11F1486D004753A9 /* MKUserLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKUserLocation.m; sourceTree = ""; }; + 5FBAF7CC11F1486D004753A9 /* MKUserLocation+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKUserLocation+Private.h"; sourceTree = ""; }; + 5FBAF7CD11F1486D004753A9 /* MKUserLocation+Private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKUserLocation+Private.m"; sourceTree = ""; }; + 5FBAF7CE11F1486D004753A9 /* MKAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKAnnotation.h; sourceTree = ""; }; + 5FBAF7DA11F14889004753A9 /* MKShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKShape.h; sourceTree = ""; }; + 5FBAF7DB11F14889004753A9 /* MKShape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKShape.m; sourceTree = ""; }; + 5FBAF7DC11F14889004753A9 /* MKCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKCircle.h; sourceTree = ""; }; + 5FBAF7DD11F14889004753A9 /* MKCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKCircle.m; sourceTree = ""; }; + 5FBAF7DE11F14889004753A9 /* MKOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKOverlay.h; sourceTree = ""; }; + 5FBAF7DF11F14889004753A9 /* MKMultiPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKMultiPoint.h; sourceTree = ""; }; + 5FBAF7E011F14889004753A9 /* MKMultiPoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKMultiPoint.m; sourceTree = ""; }; + 5FBAF7E111F14889004753A9 /* MKPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPolyline.h; sourceTree = ""; }; + 5FBAF7E211F14889004753A9 /* MKPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPolyline.m; sourceTree = ""; }; + 5FBAF7E311F14889004753A9 /* MKPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPolygon.h; sourceTree = ""; }; + 5FBAF7E411F14889004753A9 /* MKPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPolygon.m; sourceTree = ""; }; + 5FBAF7F111F148A5004753A9 /* MKOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKOverlayView.h; sourceTree = ""; }; + 5FBAF7F211F148A5004753A9 /* MKOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKOverlayView.m; sourceTree = ""; }; + 5FBAF7F311F148A5004753A9 /* MKOverlayPathView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKOverlayPathView.h; sourceTree = ""; }; + 5FBAF7F411F148A5004753A9 /* MKOverlayPathView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKOverlayPathView.m; sourceTree = ""; }; + 5FBAF7F511F148A5004753A9 /* MKCircleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKCircleView.h; sourceTree = ""; }; + 5FBAF7F611F148A5004753A9 /* MKCircleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKCircleView.m; sourceTree = ""; }; + 5FBAF7F711F148A5004753A9 /* MKPolylineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPolylineView.h; sourceTree = ""; }; + 5FBAF7F811F148A5004753A9 /* MKPolylineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPolylineView.m; sourceTree = ""; }; + 5FBAF7F911F148A5004753A9 /* MKPolygonView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKPolygonView.h; sourceTree = ""; }; + 5FBAF7FA11F148A5004753A9 /* MKPolygonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKPolygonView.m; sourceTree = ""; }; + 5FBAF80711F14955004753A9 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + 5FBAF80B11F14964004753A9 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 5FE8314712A60AF600728ECE /* MapKitPluginLibrary.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MapKitPluginLibrary.xib; sourceTree = ""; }; + 5FE8314B12A60BFF00728ECE /* MKMapViewAttributeInspector.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MKMapViewAttributeInspector.xib; sourceTree = ""; }; + D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5F6EF13311F13B0D0077E84F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5F84F0F711F21A4F008D3A32 /* CoreLocation.framework in Frameworks */, + 5FBAF77511F14518004753A9 /* MapKit.framework in Frameworks */, + 5F6EF13C11F13B170077E84F /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5F6EF17B11F13F690077E84F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5F6EF18211F13F710077E84F /* Cocoa.framework in Frameworks */, + 5FBAF80811F14955004753A9 /* CoreLocation.framework in Frameworks */, + 5FBAF80C11F14964004753A9 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FB7435511FE6E4A00AB2079 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5FB7436711FE6F0500AB2079 /* Cocoa.framework in Frameworks */, + 5FB7436811FE6F1300AB2079 /* MapKit.framework in Frameworks */, + 5FB7437211FE6F4C00AB2079 /* InterfaceBuilderKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 5F6EF13511F13B0D0077E84F /* DemoApp.app */, + 5F6EF17D11F13F690077E84F /* MapKit.framework */, + 5FB7435711FE6E4A00AB2079 /* MapKit.ibplugin */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* MapKit */ = { + isa = PBXGroup; + children = ( + 5F6EF12411F13A9E0077E84F /* DemoApp */, + 5F6EF12311F13A920077E84F /* Framework */, + 5FB7434111FE6D5C00AB2079 /* IBPlugin */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = MapKit; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 5F585AAD121231B6005F437E /* Animations.css */, + 5F585AAE121231B6005F437E /* Stylesheet.css */, + 5F19A0471208F9260083FE72 /* License.rtf */, + 5F19A0481208F9260083FE72 /* Release Notes.rtf */, + 5F76C89811F52DFA00713BBA /* MKPinAnnotationColorGreen.png */, + 5F76C89911F52DFA00713BBA /* MKPinAnnotationColorPurple.png */, + 5F76C87F11F52BFC00713BBA /* MKPinAnnotationColorRed.png */, + 5F76C82011F4F85E00713BBA /* MarkerTest.png */, + 5F84F10911F21B88008D3A32 /* MapKit.html */, + 5F6EF18711F13FA40077E84F /* MapKit-Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* Classes */ = { + isa = PBXGroup; + children = ( + 5FB7411611FB507900AB2079 /* Geocoding */, + 5F84F20B11F3E9C1008D3A32 /* Annotations And Overlays */, + 5FBAF7A411F147DC004753A9 /* Categories */, + 5FBAF7A911F147FF004753A9 /* Third Party */, + 5FBAF7C511F1486D004753A9 /* MKMapView.h */, + 5FBAF7C611F1486D004753A9 /* MKMapView.m */, + 5F96B22313BAB9F4000A1E4A /* MKMapView+Private.h */, + 5F96B22413BAB9F4000A1E4A /* MKMapView+Private.m */, + 5FB740FD11FB4BD200AB2079 /* MKMapView+Additions.h */, + 5FB740FE11FB4BD200AB2079 /* MKMapView+Additions.m */, + 5FB7406D11F8C77C00AB2079 /* MKMapView+DelegateWrappers.h */, + 5FB7406E11F8C77C00AB2079 /* MKMapView+DelegateWrappers.m */, + 5FB7407511F8C81800AB2079 /* MKMapView+WebViewIntegration.h */, + 5FB7407611F8C81800AB2079 /* MKMapView+WebViewIntegration.m */, + 5FBAF7C711F1486D004753A9 /* MKTypes.h */, + 5FBAF7C811F1486D004753A9 /* MKGeometry.h */, + 5FBAF7C911F1486D004753A9 /* MapKit.h */, + 5FBAF7CA11F1486D004753A9 /* MKUserLocation.h */, + 5FBAF7CB11F1486D004753A9 /* MKUserLocation.m */, + 5FBAF7CC11F1486D004753A9 /* MKUserLocation+Private.h */, + 5FBAF7CD11F1486D004753A9 /* MKUserLocation+Private.m */, + 5F39D6FC12B5AB50001B32CD /* MKWebView.h */, + 5F39D6FD12B5AB50001B32CD /* MKWebView.m */, + ); + path = Classes; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 5FB7437111FE6F4C00AB2079 /* InterfaceBuilderKit.framework */, + 5FBAF80B11F14964004753A9 /* WebKit.framework */, + 5FBAF80711F14955004753A9 /* CoreLocation.framework */, + 5F6EF13B11F13B170077E84F /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + D2F7E79907B2D74100F64583 /* CoreData.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 5F6EF12311F13A920077E84F /* Framework */ = { + isa = PBXGroup; + children = ( + 08FB77AEFE84172EC02AAC07 /* Classes */, + 089C1665FE841158C02AAC07 /* Resources */, + ); + path = Framework; + sourceTree = ""; + }; + 5F6EF12411F13A9E0077E84F /* DemoApp */ = { + isa = PBXGroup; + children = ( + 5F6EF14E11F13BB40077E84F /* Other Sources */, + 5F6EF14611F13B5A0077E84F /* Resources */, + 5F6EF14511F13B520077E84F /* Classes */, + ); + path = DemoApp; + sourceTree = ""; + }; + 5F6EF14511F13B520077E84F /* Classes */ = { + isa = PBXGroup; + children = ( + 5F6EF16911F13CB70077E84F /* DemoAppApplicationDelegate.h */, + 5F6EF16A11F13CB70077E84F /* DemoAppApplicationDelegate.m */, + ); + path = Classes; + sourceTree = ""; + }; + 5F6EF14611F13B5A0077E84F /* Resources */ = { + isa = PBXGroup; + children = ( + 5F87D82E131C825B00634ACD /* MapViewAdditions.css */, + 5F6EF14C11F13B8A0077E84F /* DemoApp-Info.plist */, + 5F6EF14311F13B4B0077E84F /* MainMenu.xib */, + 5F585A5C12110FE6005F437E /* TransparentPixel.png */, + ); + name = Resources; + sourceTree = ""; + }; + 5F6EF14E11F13BB40077E84F /* Other Sources */ = { + isa = PBXGroup; + children = ( + 5F6EF14F11F13BCB0077E84F /* main.m */, + 5F6EF15211F13BE70077E84F /* DemoApp_Prefix.pch */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 5F84F20211F3E930008D3A32 /* Annotations */ = { + isa = PBXGroup; + children = ( + 5F84F23C11F3EDB8008D3A32 /* Views */, + 5F84F20311F3E956008D3A32 /* MKPointAnnotation.h */, + 5F84F20411F3E956008D3A32 /* MKPointAnnotation.m */, + ); + name = Annotations; + sourceTree = ""; + }; + 5F84F20B11F3E9C1008D3A32 /* Annotations And Overlays */ = { + isa = PBXGroup; + children = ( + 5F76C78711F4EDE000713BBA /* MKView.h */, + 5F76C78811F4EDE000713BBA /* MKView.m */, + 5FBAF7DE11F14889004753A9 /* MKOverlay.h */, + 5FBAF7CE11F1486D004753A9 /* MKAnnotation.h */, + 5FBAF7DA11F14889004753A9 /* MKShape.h */, + 5FBAF7DB11F14889004753A9 /* MKShape.m */, + 5FBAF7D911F1487C004753A9 /* Overlays */, + 5F84F20211F3E930008D3A32 /* Annotations */, + ); + name = "Annotations And Overlays"; + sourceTree = ""; + }; + 5F84F23C11F3EDB8008D3A32 /* Views */ = { + isa = PBXGroup; + children = ( + 5F84F23811F3ED6E008D3A32 /* MKAnnotationView.h */, + 5F84F23911F3ED6E008D3A32 /* MKAnnotationView.m */, + 5F84F25511F3F173008D3A32 /* MKPinAnnotationView.h */, + 5F84F25611F3F173008D3A32 /* MKPinAnnotationView.m */, + ); + name = Views; + sourceTree = ""; + }; + 5FB7411611FB507900AB2079 /* Geocoding */ = { + isa = PBXGroup; + children = ( + 5FB7411911FB50B800AB2079 /* MKPlacemark.h */, + 5FB7411A11FB50B800AB2079 /* MKPlacemark.m */, + 5FB7417111FD53B500AB2079 /* MKPlacemark+Private.h */, + 5FB7417211FD53B500AB2079 /* MKPlacemark+Private.m */, + 5FB7413211FB52AF00AB2079 /* MKReverseGeocoder.h */, + 5FB7413311FB52AF00AB2079 /* MKReverseGeocoder.m */, + 5F9CE3D812D15F98006354EF /* MKGeocoder.h */, + 5F9CE3D912D15F98006354EF /* MKGeocoder.m */, + ); + name = Geocoding; + sourceTree = ""; + }; + 5FB7434111FE6D5C00AB2079 /* IBPlugin */ = { + isa = PBXGroup; + children = ( + 5FB7434511FE6D9F00AB2079 /* Resources */, + 5FB7434411FE6D9900AB2079 /* Other Sources */, + 5FB7434311FE6D9400AB2079 /* Classes */, + 5FB7434211FE6D8E00AB2079 /* Class Descriptions */, + ); + path = IBPlugin; + sourceTree = ""; + }; + 5FB7434211FE6D8E00AB2079 /* Class Descriptions */ = { + isa = PBXGroup; + children = ( + 5FB7437D11FE700600AB2079 /* MKMapView.classdescription */, + ); + name = "Class Descriptions"; + sourceTree = ""; + }; + 5FB7434311FE6D9400AB2079 /* Classes */ = { + isa = PBXGroup; + children = ( + 5F19A03D1208F6DE0083FE72 /* MKMapView+MapKitPlugin.m */, + 5FB7438211FE705E00AB2079 /* MapKitPlugin.h */, + 5FB7438311FE705E00AB2079 /* MapKitPlugin.m */, + 5FB7438611FE70AC00AB2079 /* MKMapViewAttributeInspector.h */, + 5FB7438711FE70AC00AB2079 /* MKMapViewAttributeInspector.m */, + ); + path = Classes; + sourceTree = ""; + }; + 5FB7434411FE6D9900AB2079 /* Other Sources */ = { + isa = PBXGroup; + children = ( + ); + name = "Other Sources"; + sourceTree = ""; + }; + 5FB7434511FE6D9F00AB2079 /* Resources */ = { + isa = PBXGroup; + children = ( + 5FE8314712A60AF600728ECE /* MapKitPluginLibrary.xib */, + 5FE8314B12A60BFF00728ECE /* MKMapViewAttributeInspector.xib */, + 5FB743B311FE74B100AB2079 /* MapView.png */, + 5FB7439511FE727100AB2079 /* MapKitPlugin-Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + 5FBAF7A411F147DC004753A9 /* Categories */ = { + isa = PBXGroup; + children = ( + 5FBAF7A511F147EF004753A9 /* NSColor+Additions.h */, + 5FBAF7A611F147EF004753A9 /* NSColor+Additions.m */, + ); + name = Categories; + sourceTree = ""; + }; + 5FBAF7A911F147FF004753A9 /* Third Party */ = { + isa = PBXGroup; + children = ( + 5FBAF7AA11F14806004753A9 /* SBJSON */, + ); + path = "Third Party"; + sourceTree = ""; + }; + 5FBAF7AA11F14806004753A9 /* SBJSON */ = { + isa = PBXGroup; + children = ( + 5FBAF7AB11F1482E004753A9 /* JSON.h */, + 5FBAF7AC11F1482E004753A9 /* NSObject+SBJSON.h */, + 5FBAF7AD11F1482E004753A9 /* NSObject+SBJSON.m */, + 5FBAF7AE11F1482E004753A9 /* NSString+SBJSON.h */, + 5FBAF7AF11F1482E004753A9 /* NSString+SBJSON.m */, + 5FBAF7B011F1482E004753A9 /* SBJSON.h */, + 5FBAF7B111F1482E004753A9 /* SBJSON.m */, + 5FBAF7B211F1482E004753A9 /* SBJsonBase.h */, + 5FBAF7B311F1482E004753A9 /* SBJsonBase.m */, + 5FBAF7B411F1482E004753A9 /* SBJsonParser.h */, + 5FBAF7B511F1482E004753A9 /* SBJsonParser.m */, + 5FBAF7B611F1482E004753A9 /* SBJsonWriter.h */, + 5FBAF7B711F1482E004753A9 /* SBJsonWriter.m */, + ); + path = SBJSON; + sourceTree = ""; + }; + 5FBAF7D911F1487C004753A9 /* Overlays */ = { + isa = PBXGroup; + children = ( + 5FBAF7F011F1488F004753A9 /* Views */, + 5FBAF7DC11F14889004753A9 /* MKCircle.h */, + 5FBAF7DD11F14889004753A9 /* MKCircle.m */, + 5FBAF7DF11F14889004753A9 /* MKMultiPoint.h */, + 5FBAF7E011F14889004753A9 /* MKMultiPoint.m */, + 5FBAF7E111F14889004753A9 /* MKPolyline.h */, + 5FBAF7E211F14889004753A9 /* MKPolyline.m */, + 5FBAF7E311F14889004753A9 /* MKPolygon.h */, + 5FBAF7E411F14889004753A9 /* MKPolygon.m */, + ); + name = Overlays; + sourceTree = ""; + }; + 5FBAF7F011F1488F004753A9 /* Views */ = { + isa = PBXGroup; + children = ( + 5FBAF7F111F148A5004753A9 /* MKOverlayView.h */, + 5FBAF7F211F148A5004753A9 /* MKOverlayView.m */, + 5FBAF7F311F148A5004753A9 /* MKOverlayPathView.h */, + 5FBAF7F411F148A5004753A9 /* MKOverlayPathView.m */, + 5FBAF7F511F148A5004753A9 /* MKCircleView.h */, + 5FBAF7F611F148A5004753A9 /* MKCircleView.m */, + 5FBAF7F711F148A5004753A9 /* MKPolylineView.h */, + 5FBAF7F811F148A5004753A9 /* MKPolylineView.m */, + 5FBAF7F911F148A5004753A9 /* MKPolygonView.h */, + 5FBAF7FA11F148A5004753A9 /* MKPolygonView.m */, + ); + name = Views; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 5F6EF17811F13F690077E84F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 5FBAF7A711F147EF004753A9 /* NSColor+Additions.h in Headers */, + 5FBAF7B811F1482E004753A9 /* JSON.h in Headers */, + 5FBAF7B911F1482E004753A9 /* NSObject+SBJSON.h in Headers */, + 5FBAF7BB11F1482E004753A9 /* NSString+SBJSON.h in Headers */, + 5FBAF7BD11F1482E004753A9 /* SBJSON.h in Headers */, + 5FBAF7BF11F1482E004753A9 /* SBJsonBase.h in Headers */, + 5FBAF7C111F1482E004753A9 /* SBJsonParser.h in Headers */, + 5FBAF7C311F1482E004753A9 /* SBJsonWriter.h in Headers */, + 5FBAF7CF11F1486D004753A9 /* MKMapView.h in Headers */, + 5FBAF7D111F1486D004753A9 /* MKTypes.h in Headers */, + 5FBAF7D211F1486D004753A9 /* MKGeometry.h in Headers */, + 5FBAF7D311F1486D004753A9 /* MapKit.h in Headers */, + 5FBAF7D411F1486D004753A9 /* MKUserLocation.h in Headers */, + 5FBAF7D611F1486D004753A9 /* MKUserLocation+Private.h in Headers */, + 5FBAF7D811F1486D004753A9 /* MKAnnotation.h in Headers */, + 5FBAF7E511F14889004753A9 /* MKShape.h in Headers */, + 5FBAF7E711F14889004753A9 /* MKCircle.h in Headers */, + 5FBAF7E911F14889004753A9 /* MKOverlay.h in Headers */, + 5FBAF7EA11F14889004753A9 /* MKMultiPoint.h in Headers */, + 5FBAF7EC11F14889004753A9 /* MKPolyline.h in Headers */, + 5FBAF7EE11F14889004753A9 /* MKPolygon.h in Headers */, + 5FBAF7FB11F148A5004753A9 /* MKOverlayView.h in Headers */, + 5FBAF7FD11F148A5004753A9 /* MKOverlayPathView.h in Headers */, + 5FBAF7FF11F148A5004753A9 /* MKCircleView.h in Headers */, + 5FBAF80111F148A5004753A9 /* MKPolylineView.h in Headers */, + 5FBAF80311F148A5004753A9 /* MKPolygonView.h in Headers */, + 5F84F20511F3E956008D3A32 /* MKPointAnnotation.h in Headers */, + 5F84F23A11F3ED6E008D3A32 /* MKAnnotationView.h in Headers */, + 5F84F25711F3F173008D3A32 /* MKPinAnnotationView.h in Headers */, + 5F76C78911F4EDE000713BBA /* MKView.h in Headers */, + 5FB7406F11F8C77C00AB2079 /* MKMapView+DelegateWrappers.h in Headers */, + 5FB7407711F8C81800AB2079 /* MKMapView+WebViewIntegration.h in Headers */, + 5FB740FF11FB4BD200AB2079 /* MKMapView+Additions.h in Headers */, + 5FB7411B11FB50B800AB2079 /* MKPlacemark.h in Headers */, + 5FB7413411FB52AF00AB2079 /* MKReverseGeocoder.h in Headers */, + 5FB7417311FD53B500AB2079 /* MKPlacemark+Private.h in Headers */, + 5F39D6FE12B5AB50001B32CD /* MKWebView.h in Headers */, + 5F9CE3DA12D15F98006354EF /* MKGeocoder.h in Headers */, + 5F96B22513BAB9F4000A1E4A /* MKMapView+Private.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 5F6EF13411F13B0D0077E84F /* DemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5F6EF13A11F13B0D0077E84F /* Build configuration list for PBXNativeTarget "DemoApp" */; + buildPhases = ( + 5F6EF13111F13B0D0077E84F /* Resources */, + 5F6EF13211F13B0D0077E84F /* Sources */, + 5F6EF17011F13EFC0077E84F /* Copy Frameworks */, + 5F6EF13311F13B0D0077E84F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 5F6EF19211F140360077E84F /* PBXTargetDependency */, + ); + name = DemoApp; + productName = DemoApp; + productReference = 5F6EF13511F13B0D0077E84F /* DemoApp.app */; + productType = "com.apple.product-type.application"; + }; + 5F6EF17C11F13F690077E84F /* MapKitFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5F6EF18111F13F690077E84F /* Build configuration list for PBXNativeTarget "MapKitFramework" */; + buildPhases = ( + 5F6EF17811F13F690077E84F /* Headers */, + 5F6EF17911F13F690077E84F /* Resources */, + 5F6EF17A11F13F690077E84F /* Sources */, + 5F6EF17B11F13F690077E84F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MapKitFramework; + productName = MapKit; + productReference = 5F6EF17D11F13F690077E84F /* MapKit.framework */; + productType = "com.apple.product-type.framework"; + }; + 5FB7435611FE6E4A00AB2079 /* MapKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5FB7435D11FE6E4A00AB2079 /* Build configuration list for PBXNativeTarget "MapKit" */; + buildPhases = ( + 5FB7435311FE6E4A00AB2079 /* Resources */, + 5FB7435411FE6E4A00AB2079 /* Sources */, + 5FB7435511FE6E4A00AB2079 /* Frameworks */, + 5F199F08120258020083FE72 /* Copy Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 5FB7436611FE6ED200AB2079 /* PBXTargetDependency */, + ); + name = MapKit; + productName = MapKitPlugin; + productReference = 5FB7435711FE6E4A00AB2079 /* MapKit.ibplugin */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "MapKit" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 0867D691FE84028FC02AAC07 /* MapKit */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5F6EF13411F13B0D0077E84F /* DemoApp */, + 5F6EF17C11F13F690077E84F /* MapKitFramework */, + 5FB7435611FE6E4A00AB2079 /* MapKit */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5F6EF13111F13B0D0077E84F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5F76C83A11F4FC8F00713BBA /* MarkerTest.png in Resources */, + 5F6EF14411F13B4B0077E84F /* MainMenu.xib in Resources */, + 5F87D82F131C825B00634ACD /* MapViewAdditions.css in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5F6EF17911F13F690077E84F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5F84F10A11F21B88008D3A32 /* MapKit.html in Resources */, + 5F76C82111F4F85E00713BBA /* MarkerTest.png in Resources */, + 5F76C88011F52BFC00713BBA /* MKPinAnnotationColorRed.png in Resources */, + 5F76C89A11F52DFA00713BBA /* MKPinAnnotationColorGreen.png in Resources */, + 5F76C89B11F52DFA00713BBA /* MKPinAnnotationColorPurple.png in Resources */, + 5F19A0491208F9260083FE72 /* License.rtf in Resources */, + 5F19A04A1208F9260083FE72 /* Release Notes.rtf in Resources */, + 5F585A5D12110FE7005F437E /* TransparentPixel.png in Resources */, + 5F585AAF121231B6005F437E /* Animations.css in Resources */, + 5F585AB0121231B6005F437E /* Stylesheet.css in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FB7435311FE6E4A00AB2079 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5FB7437E11FE700600AB2079 /* MKMapView.classdescription in Resources */, + 5FB743B411FE74B100AB2079 /* MapView.png in Resources */, + 5FE8314812A60AF600728ECE /* MapKitPluginLibrary.xib in Resources */, + 5FE8314C12A60BFF00728ECE /* MKMapViewAttributeInspector.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5F6EF13211F13B0D0077E84F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5F6EF15011F13BCB0077E84F /* main.m in Sources */, + 5F6EF16B11F13CB70077E84F /* DemoAppApplicationDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5F6EF17A11F13F690077E84F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5FBAF7A811F147EF004753A9 /* NSColor+Additions.m in Sources */, + 5FBAF7BA11F1482E004753A9 /* NSObject+SBJSON.m in Sources */, + 5FBAF7BC11F1482E004753A9 /* NSString+SBJSON.m in Sources */, + 5FBAF7BE11F1482E004753A9 /* SBJSON.m in Sources */, + 5FBAF7C011F1482E004753A9 /* SBJsonBase.m in Sources */, + 5FBAF7C211F1482E004753A9 /* SBJsonParser.m in Sources */, + 5FBAF7C411F1482E004753A9 /* SBJsonWriter.m in Sources */, + 5FBAF7D011F1486D004753A9 /* MKMapView.m in Sources */, + 5FBAF7D511F1486D004753A9 /* MKUserLocation.m in Sources */, + 5FBAF7D711F1486D004753A9 /* MKUserLocation+Private.m in Sources */, + 5FBAF7E611F14889004753A9 /* MKShape.m in Sources */, + 5FBAF7E811F14889004753A9 /* MKCircle.m in Sources */, + 5FBAF7EB11F14889004753A9 /* MKMultiPoint.m in Sources */, + 5FBAF7ED11F14889004753A9 /* MKPolyline.m in Sources */, + 5FBAF7EF11F14889004753A9 /* MKPolygon.m in Sources */, + 5FBAF7FC11F148A5004753A9 /* MKOverlayView.m in Sources */, + 5FBAF7FE11F148A5004753A9 /* MKOverlayPathView.m in Sources */, + 5FBAF80011F148A5004753A9 /* MKCircleView.m in Sources */, + 5FBAF80211F148A5004753A9 /* MKPolylineView.m in Sources */, + 5FBAF80411F148A5004753A9 /* MKPolygonView.m in Sources */, + 5F84F20611F3E956008D3A32 /* MKPointAnnotation.m in Sources */, + 5F84F23B11F3ED6E008D3A32 /* MKAnnotationView.m in Sources */, + 5F84F25811F3F173008D3A32 /* MKPinAnnotationView.m in Sources */, + 5F76C78A11F4EDE000713BBA /* MKView.m in Sources */, + 5FB7407011F8C77C00AB2079 /* MKMapView+DelegateWrappers.m in Sources */, + 5FB7407811F8C81800AB2079 /* MKMapView+WebViewIntegration.m in Sources */, + 5FB7410011FB4BD200AB2079 /* MKMapView+Additions.m in Sources */, + 5FB7411C11FB50B800AB2079 /* MKPlacemark.m in Sources */, + 5FB7413511FB52AF00AB2079 /* MKReverseGeocoder.m in Sources */, + 5FB7417411FD53B500AB2079 /* MKPlacemark+Private.m in Sources */, + 5F39D6FF12B5AB50001B32CD /* MKWebView.m in Sources */, + 5F9CE3DB12D15F98006354EF /* MKGeocoder.m in Sources */, + 5F96B22613BAB9F4000A1E4A /* MKMapView+Private.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FB7435411FE6E4A00AB2079 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5FB7438411FE705E00AB2079 /* MapKitPlugin.m in Sources */, + 5FB7438811FE70AC00AB2079 /* MKMapViewAttributeInspector.m in Sources */, + 5F19A03E1208F6DE0083FE72 /* MKMapView+MapKitPlugin.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5F6EF19211F140360077E84F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5F6EF17C11F13F690077E84F /* MapKitFramework */; + targetProxy = 5F6EF19111F140360077E84F /* PBXContainerItemProxy */; + }; + 5FB7436611FE6ED200AB2079 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5F6EF17C11F13F690077E84F /* MapKitFramework */; + targetProxy = 5FB7436511FE6ED200AB2079 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SDKROOT = macosx10.6; + }; + name = Release; + }; + 5F6EF13811F13B0D0077E84F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = DemoApp/DemoApp_Prefix.pch; + INFOPLIST_FILE = "DemoApp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = DemoApp; + }; + name = Debug; + }; + 5F6EF13911F13B0D0077E84F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = DemoApp/DemoApp_Prefix.pch; + INFOPLIST_FILE = "DemoApp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = DemoApp; + ZERO_LINK = NO; + }; + name = Release; + }; + 5F6EF17F11F13F690077E84F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + ); + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_GC = supported; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "Framework/Resources/MapKit-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = MapKit; + }; + name = Debug; + }; + 5F6EF18011F13F690077E84F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + ); + FRAMEWORK_VERSION = A; + GCC_ENABLE_OBJC_GC = supported; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "Framework/Resources/MapKit-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = MapKit; + ZERO_LINK = NO; + }; + name = Release; + }; + 5FB7435B11FE6E4A00AB2079 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_FRAMEWORKS_DIR)\"", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(DEVELOPER_DIR)/Library/Frameworks\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "IBPlugin/Resources/MapKitPlugin-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Bundles"; + LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = MapKit; + WRAPPER_EXTENSION = ibplugin; + }; + name = Debug; + }; + 5FB7435C11FE6E4A00AB2079 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_FRAMEWORKS_DIR)\"", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(DEVELOPER_DIR)/Library/Frameworks\""; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "IBPlugin/Resources/MapKitPlugin-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Bundles"; + LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = MapKit; + WRAPPER_EXTENSION = ibplugin; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "MapKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5F6EF13A11F13B0D0077E84F /* Build configuration list for PBXNativeTarget "DemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5F6EF13811F13B0D0077E84F /* Debug */, + 5F6EF13911F13B0D0077E84F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5F6EF18111F13F690077E84F /* Build configuration list for PBXNativeTarget "MapKitFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5F6EF17F11F13F690077E84F /* Debug */, + 5F6EF18011F13F690077E84F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5FB7435D11FE6E4A00AB2079 /* Build configuration list for PBXNativeTarget "MapKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5FB7435B11FE6E4A00AB2079 /* Debug */, + 5FB7435C11FE6E4A00AB2079 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/External Source/NSLogger/.gitignore b/External Source/NSLogger/.gitignore new file mode 100644 index 000000000..ffc090e53 --- /dev/null +++ b/External Source/NSLogger/.gitignore @@ -0,0 +1,9 @@ +# OS X +.DS_Store + +# Xcode +build/ +*.pbxuser +*.perspectivev3 +*.mode1v3 +*.mode2v3 diff --git a/External Source/NSLogger/CONTRIBUTORS b/External Source/NSLogger/CONTRIBUTORS new file mode 100644 index 000000000..fd51fdc2a --- /dev/null +++ b/External Source/NSLogger/CONTRIBUTORS @@ -0,0 +1,7 @@ +Florent Pillet (https://github.com/fpillet) - NSLogger design, architecture, coding + +Guillaume Cerquant (https://github.com/gcerquant) - Fixes and improvements to the Desktop Viewer code +Arne Harren (https://github.com/aharren) - LibComponentLogging-NSLogger backend, improvements +Peter Steinberger (https://github.com/steipete) - NSLogger-CocoaLumberjack backend +Louis Harboe (http://graphicpeel.com) - Designed the `Console' icon (public domain), used with permission +Dirk Holtwick (https://github.com/holtwick) - Found & prepared Louis Harbroe's icon for use in NSLogger diff --git a/External Source/NSLogger/Client Logger/Android/README.markdown b/External Source/NSLogger/Client Logger/Android/README.markdown new file mode 100644 index 000000000..3e4b8b60a --- /dev/null +++ b/External Source/NSLogger/Client Logger/Android/README.markdown @@ -0,0 +1,51 @@ +### Android client code for NSLogger + +This code works (I use it every day) but is not completely packaged in a way easy to access for newcomers. In particular, you'll need to get JMmDNS for Bonjour support. See instructions below. + +I have not completed a proper Ant build file yet, so you'll have to do things more or less manually. + +## Integrating in your project + +Here is how to use NSLogger on Android: + +- Add the contents of src to your project (sorry I have not made a jar yet). +- Add lib/jmdns.jar to your project + +- The classes Debug and DroidLogger are not part of NSLogger itself, but are the ones I use in my app + to use NSLogger and have logs that can stay in the code but are totally removed in production + + For that matter, Debug.D is a boolean that you set to false when making a production build. + Since it's a 'static final', the compiler will completely remove the logging code when used in + conjunction with a test for Debug.D (see below) + +- You'll need to setup the logger once, preferrably in your activity or in a service, this way: + +```java + // Use direct TCP/IP connection for now, as it will connect 100% of the time + // (Bonjour not 100% reliable to find the desktop logger yet) + if (Debug.D) { + Debug.enableDebug(getApplication(), true); + Debug.L.setRemoteHost("192.168.0.2", 50007, true); // change to your mac's IP address, set a fixed TCP port in the Prefs in desktop NSLogger + Debug.L.LOG_MARK("ViewerActivity startup"); + } +``` + +- To log, use one of the convenience methods in droidLogger. i.e.: + +```java + if (Debug.D) + Debug.L.LOG_APP(0, "Steve Jobs Lives!"); +``` + +- DroidLogger's convenience methods support variable arguments, same as String.format. Take advantage of this. + +- I have not tested image logging yet. + +- Make sure you set the appropriate permissions for NSLogger to work. We need to access the internet, but also to enable Multicast on Wifi for Bonjour to work (when it does, sigh). Mainly, permissions should include: + +```xml + + + + +``` diff --git a/External Source/NSLogger/Client Logger/Android/client-code/lib/jmdns.jar b/External Source/NSLogger/Client Logger/Android/client-code/lib/jmdns.jar new file mode 100644 index 000000000..a07921e77 Binary files /dev/null and b/External Source/NSLogger/Client Logger/Android/client-code/lib/jmdns.jar differ diff --git a/External Source/NSLogger/Client Logger/Android/client-code/src/com/NSLogger/NSLoggerClient.java b/External Source/NSLogger/Client Logger/Android/client-code/src/com/NSLogger/NSLoggerClient.java new file mode 100644 index 000000000..6b5883fb9 --- /dev/null +++ b/External Source/NSLogger/Client Logger/Android/client-code/src/com/NSLogger/NSLoggerClient.java @@ -0,0 +1,1416 @@ +/* + * NSLoggerClient.java + * + * Android version 1.0b4 2012-02-18 + * + * Android port of the NSLogger client code + * https://github.com/fpillet/NSLogger + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2011-2012 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +package com.NSLogger; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.net.SSLCertificateSocketFactory; +import android.net.wifi.WifiManager; +import android.os.*; +import android.os.Process; +import android.provider.Settings.Secure; +import android.util.Log; + +import javax.jmdns.JmDNS; +import javax.jmdns.ServiceEvent; +import javax.jmdns.ServiceInfo; +import javax.jmdns.ServiceListener; +import javax.net.ssl.HandshakeCompletedEvent; +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.LogRecord; + +/** + * NSLoggerClient maintain one connection to the remote NSLogger desktop viewer (or log to a log file) + * You can use multiple NSLoggerClient instances if you need to, this will open multiple windows + * in the desktop viewer. + * + * Your application's AndroidManifest.xml needs to make use of the following permission: + * + * + * + * In addition, if you are going to use NSLoggerClient with Bonjour to automatically locate the desktop viewer + * (this is the default), make sure your application's AndroidManifest.xml uses the following permissions: + * + * + * + */ +public class NSLoggerClient +{ + // DEBUG MODE. Only set to true when debugging NSLogger itself, to output logs to (sigh) logcat + // this generates a quite verbose log of what's happening internally in NSLogger. + private final boolean DEBUG_LOGGER = false; + + // Options + static final int + OPT_FLUSH_EACH_MESSAGE = 1, // If set, NSLogger waits for each message to be sent to the desktop viewer (this includes connecting to the viewer) + OPT_BROWSE_BONJOUR = 2, + OPT_USE_SSL = 4; + + // A global lock that we use to tell the OS that we need to use multicasting + // when we need to use Bonjour. Each NSLogger instance willing to use Bonjour + // will acquire() the lock when needed. Lock is created on-demand the first + private static WifiManager.MulticastLock multicastLock; + + // Instance variables + Context currentContext; + int options; + String bufferFile; // buffer file to write to. We use this when not connected if OPT_BUFFER_UNTIL_CONNECTION, and when no remote host defined and no OPT_LOG_TO_CONSOLE + String bonjourServiceName; // when browsing for Bonjour services, the bonjour service name to use. If not customized by the user, we will use the first service found + String bonjourServiceType; // the service type to use. If not customized by the user, we will use either the SSL or non-SSL service type + String remoteHost; // the remote host we're talking to + int remotePort; // the remote port + InetAddress remoteAddress; // or use a full-fledged InetAddress + final AtomicInteger nextSequenceNumber = new AtomicInteger(0); // the unique message-sequence number we use to differentiate and order message on the viewer side + + LoggingWorker loggingThread; + Handler loggingThreadHandler; + + // Message types for communicating with the logger thread + protected static final int + MSG_TRY_CONNECT = 1, + MSG_CONNECT_COMPLETE = 2, + MSG_ADDLOG = 3, + MSG_ADDLOGRECORD = 4, + MSG_OPTCHANGE = 5, + MSG_QUIT = 10; + + // The charset we use for transmitting strings + protected static Charset stringsCharset = Charset.forName("utf-8"); + + /** + * Create a new NSLoggerClient instance. Multiple instances will create multiple log windows on + * the desktop viewer, or you can have instances that log to a file and others that + * log to the desktop viewer. Typically, you will use only one instance. + * Default options are to lookup for a desktop viewer on Bonjour, and use SSL + * @param ctx the current context, which is used to extract and send information about the client application + */ + public NSLoggerClient(Context ctx) + { + if (DEBUG_LOGGER) + Log.i("NSLogger", "NSLoggerClient created"); + currentContext = ctx.getApplicationContext(); + + // create the multicast lock (for Bonjour) if needed, otherwise the WiFi adapter + // doesn't process multicast packets when needed. We will acquire the lock ONLY + // while looking for a Bonjour service to connect to, and will release it as soon + // as we acquire an actual connection to the service. + if (multicastLock == null) + { + synchronized (this.getClass()) + { + if (multicastLock == null) + { + WifiManager wifi = (WifiManager)ctx.getSystemService(Context.WIFI_SERVICE); + multicastLock = wifi.createMulticastLock("NSLoggerBonjourLock"); + multicastLock.setReferenceCounted(true); + } + } + } + + options = (OPT_BROWSE_BONJOUR | OPT_USE_SSL); + } + + /** + * Enables of disable messages flushing. When enabled, NSLogger will wait for each + * message to have been sent to the desktop viewer. This includes waiting for connection + * if we are not currently connected to the desktop viewer + * @param flushEachMessage set to true to enable flushing + */ + public final synchronized void setMessageFlushing(boolean flushEachMessage) + { + if (flushEachMessage) + options |= OPT_FLUSH_EACH_MESSAGE; + else + options &= ~OPT_FLUSH_EACH_MESSAGE; + } + + /** + * Setup NSLogger to write logs to a buffer file. Calling this method automatically + * shuts down any current connection to the desktop viewer and switches to writing + * to a file instead + * @param filePath an absolute path to the buffer file + */ + public final synchronized void setBufferFile(String filePath) + { + if (loggingThreadHandler != null) + { + Properties opts = new Properties(); + opts.setProperty("filename", filePath); + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_OPTCHANGE, opts)); + } + else + { + if (filePath == null) + throw new NullPointerException("buffer file path is null"); + bufferFile = filePath; + } + } + + /** + * Setup NSLogger for Bonjour browsing with specific parameters. By default, the + * service name and service type are null. You can elect to connect to a specific + * service type (although it is not recommended to customize this -- this is useful + * only if you have customized the desktop side of NSLogger) and if you specify a + * service name (the machine name), you can direct logs to a specific machine on + * your network in the case there are multiple instances of the NSLogger viewer + * running there. + * @param serviceType a type of service, or null (NSLogger uses "_nslogger-ssl._tcp" for secure connections, + * and "_nslogger._tcp" for insecure connections) + * @param serviceName the name of the service to look for, or null. In the desktop viewer, + * you can give a specific name for an instance of NSLogger. + * Passing the same name here guarantees that your logger will only connect to this instance. + * @param useSSL set to true to use the secure transport to desktop viewer + */ + public final synchronized void setupBonjour(String serviceType, String serviceName, boolean useSSL) + { + if (loggingThreadHandler != null) + { + Properties opts = new Properties(); + opts.setProperty("bonjourService", serviceName); + opts.setProperty("bonjourType", serviceType); + opts.setProperty("useSSL", useSSL ? "1" : "0"); + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_OPTCHANGE, opts)); + } + else + { + bonjourServiceName = serviceName; + bonjourServiceType = serviceType; + if (useSSL) + options |= OPT_USE_SSL; + else + options &= ~OPT_USE_SSL; + } + } + + /** + * Set the remote host and port to connect to. Setting these to valid values + * (non-null hostname, non-zero port) automatically invalidates Bonjour browsing, + * and NSLogger will only try to connect. If you pass null hostname and/or zero + * port value, NSLogger will automatically revert to using Bonjour. + * @param hostname non-null hostname, or null to cancel and use Bonjour + * @param port non-zero port, or zero to cancel and use Bonjour + * @param useSSL set to true to select SSL transport to desktop viewer + */ + public final synchronized void setRemoteHost(String hostname, int port, boolean useSSL) + { + if (DEBUG_LOGGER) + Log.i("NSLogger", String.format("setRemoteHost host=%s port=%d useSSL=%b", hostname, port, useSSL)); + + if (loggingThreadHandler != null) + { + Properties opts = new Properties(); + opts.setProperty("remoteHost", hostname); + opts.setProperty("remotePort", Integer.toString(port)); + opts.setProperty("useSSL", useSSL ? "1" : "0"); + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_OPTCHANGE, opts)); + } + else + { + remoteHost = hostname; + remotePort = port; + if (useSSL) + options |= OPT_USE_SSL; + else + options &= ~OPT_USE_SSL; + } + } + + private void startLoggingThreadIfNeeded() + { + try + { + boolean waiting = false; + if (loggingThread == null) + { + synchronized (this) + { + if (loggingThread == null) + { + loggingThread = new LoggingWorker(); + loggingThread.readyWaiters.add(Thread.currentThread()); + loggingThread.start(); + waiting = true; + } + } + } + while (!loggingThread.ready.get()) + { + if (!waiting) + { + loggingThread.readyWaiters.add(Thread.currentThread()); + waiting = true; + } + LockSupport.parkUntil(this, System.currentTimeMillis() + 100); + if (Thread.interrupted()) + Thread.currentThread().interrupt(); + } + } + catch (Exception e) + { + Log.e("NSLogger", "Exception catched in startLoggingThreadIfNeeded: " + e.toString()); + } + } + + /** + * Log a message with full information (if provided) + * @param filename the filename (or class name), or null + * @param method the method that emitted the message, or null + * @param tag a tag attributed to the message, or empty string or null + * @param level a level >= 0 + * @param message the message to send + */ + public final void log(String filename, int lineNumber, String method, String tag, int level, String message) + { + startLoggingThreadIfNeeded(); + if (loggingThreadHandler == null) + return; + + final LogMessage lm = new LogMessage(LogMessage.LOGMSG_TYPE_LOG, nextSequenceNumber.getAndIncrement()); + lm.addInt16(level, LogMessage.PART_KEY_LEVEL); + if (filename != null) + { + lm.addString(filename, LogMessage.PART_KEY_FILENAME); + if (lineNumber != 0) + lm.addInt32(lineNumber, LogMessage.PART_KEY_LINENUMBER); + } + if (method != null) + lm.addString(method, LogMessage.PART_KEY_FUNCTIONNAME); + if (tag != null && !tag.isEmpty()) + lm.addString(tag, LogMessage.PART_KEY_TAG); + lm.addString(message, LogMessage.PART_KEY_MESSAGE); + + final boolean needsFlush = ((options & OPT_FLUSH_EACH_MESSAGE) != 0); + if (needsFlush) + lm.prepareForFlush(); + + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_ADDLOG, lm)); + + if (needsFlush) + lm.waitFlush(); + } + + /** + * Log a message, attributing a tag and level to the message + * @param tag a tag attributed to the message, or empty string or null + * @param level a level >= 0 + * @param message the message to send + */ + public final void log(String tag, int level, String message) + { + log(null, 0, null, tag, level, message); + } + + /** + * Log a message with no tag and default level (0) + * @param message the message to send + */ + public final void log(String message) + { + log(null, 0, message); + } + + /** + * Log a message that you built yourself + * @param message + */ + public final void log(LogMessage message) + { + startLoggingThreadIfNeeded(); + if (loggingThreadHandler != null) + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_ADDLOG, message)); + } + + /** + * Log a block of data + * @param filename the filename (or class name), or null + * @param method the method that emitted the message, or null + * @param lineNumber the line number in the source code file where this method was called + * @param tag a tag attributed to the message, or empty string or null + * @param level a level >= 0 + * @param data a block of data + */ + public final void logData(String filename, int lineNumber, String method, String tag, int level, byte[] data) + { + startLoggingThreadIfNeeded(); + if (loggingThreadHandler == null) + return; + + final LogMessage lm = new LogMessage(LogMessage.LOGMSG_TYPE_LOG, nextSequenceNumber.getAndIncrement()); + lm.addInt16(level, LogMessage.PART_KEY_LEVEL); + if (filename != null) + { + lm.addString(filename, LogMessage.PART_KEY_FILENAME); + if (lineNumber != 0) + lm.addInt32(lineNumber, LogMessage.PART_KEY_LINENUMBER); + } + if (method != null) + lm.addString(method, LogMessage.PART_KEY_FUNCTIONNAME); + if (tag != null && tag.length() != 0) + lm.addString(tag, LogMessage.PART_KEY_TAG); + lm.addBinaryData(data, LogMessage.PART_KEY_MESSAGE); + + final boolean needsFlush = ((options & OPT_FLUSH_EACH_MESSAGE) != 0); + if (needsFlush) + lm.prepareForFlush(); + + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_ADDLOG, lm)); + + if (needsFlush) + lm.waitFlush(); + } + + /** + * Log an image + * + * @param filename the filename (or class name), or null + * @param method the method that emitted the message, or null + * @param lineNumber the line number in the source code file where this method was called + * @param tag a tag attributed to the message, or empty string or null + * @param level a level >= 0 + * @param data raw image data. Most image file formats are automatically decoded and recognized + * by the desktop viewer + */ + public final void logImage(String filename, int lineNumber, String method, String tag, int level, byte[] data) + { + startLoggingThreadIfNeeded(); + if (loggingThreadHandler == null) + return; + + final LogMessage lm = new LogMessage(LogMessage.LOGMSG_TYPE_LOG, nextSequenceNumber.getAndIncrement()); + lm.addInt16(level, LogMessage.PART_KEY_LEVEL); + if (filename != null) + { + lm.addString(filename, LogMessage.PART_KEY_FILENAME); + if (lineNumber != 0) + lm.addInt32(lineNumber, LogMessage.PART_KEY_LINENUMBER); + } + if (method != null) + lm.addString(method, LogMessage.PART_KEY_FUNCTIONNAME); + if (tag != null && tag.length() != 0) + lm.addString(tag, LogMessage.PART_KEY_TAG); + lm.addImageData(data, LogMessage.PART_KEY_MESSAGE); + + final boolean needsFlush = ((options & OPT_FLUSH_EACH_MESSAGE) != 0); + if (needsFlush) + lm.prepareForFlush(); + + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_ADDLOG, lm)); + + if (needsFlush) + lm.waitFlush(); + } + + /** + * Log a mark to the desktop viewer. Marks are important points that you can jump to directly + * in the desktop viewer. Message is optional, if null or empty it will be replaced with the + * current date / time + * @param message optional message + */ + public final void logMark(String message) + { + startLoggingThreadIfNeeded(); + if (loggingThreadHandler == null) + return; + + final LogMessage lm = new LogMessage(LogMessage.LOGMSG_TYPE_MARK, nextSequenceNumber.getAndIncrement()); + lm.addInt16(0, LogMessage.PART_KEY_LEVEL); + if (message != null && message.length() != 0) + lm.addString(message, LogMessage.PART_KEY_MESSAGE); + else + lm.addString(new Date().toString(), LogMessage.PART_KEY_MESSAGE); + + final boolean needsFlush = ((options & OPT_FLUSH_EACH_MESSAGE) != 0); + if (needsFlush) + lm.prepareForFlush(); + + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_ADDLOG, lm)); + + if (needsFlush) + lm.waitFlush(); + } + + /** + * A class that encapsulates a log message and can produce a binary representation + * to send to the desktop NSLogger viewer. Methods are provided to gradually build + * the various parts of the messsage. Once building is complete, a call to the + * getBytes() method returns a full-fledged binary message to send to the desktop + * viewer. + */ + public final class LogMessage + { + // Constants for the "part key" field + static final int + PART_KEY_MESSAGE_TYPE = 0, // defines the type of message (see LOGMSG_TYPE_*) + PART_KEY_TIMESTAMP_S = 1, // "seconds" component of timestamp + PART_KEY_TIMESTAMP_MS = 2, // milliseconds component of timestamp (optional, mutually exclusive with PART_KEY_TIMESTAMP_US) + PART_KEY_TIMESTAMP_US = 3, // microseconds component of timestamp (optional, mutually exclusive with PART_KEY_TIMESTAMP_MS) + PART_KEY_THREAD_ID = 4, + PART_KEY_TAG = 5, + PART_KEY_LEVEL = 6, + PART_KEY_MESSAGE = 7, + PART_KEY_IMAGE_WIDTH = 8, // messages containing an image should also contain a part with the image size + PART_KEY_IMAGE_HEIGHT = 9, // (this is mainly for the desktop viewer to compute the cell size without having to immediately decode the image) + PART_KEY_MESSAGE_SEQ = 10, // the sequential number of this message which indicates the order in which messages are generated + PART_KEY_FILENAME = 11, // when logging, message can contain a file name + PART_KEY_LINENUMBER = 12, // as well as a line number + PART_KEY_FUNCTIONNAME = 13; // and a function or method name + + // Constants for parts in LOGMSG_TYPE_CLIENTINFO + static final int + PART_KEY_CLIENT_NAME = 20, + PART_KEY_CLIENT_VERSION = 21, + PART_KEY_OS_NAME = 22, + PART_KEY_OS_VERSION = 23, + PART_KEY_CLIENT_MODEL = 24, // For iPhone, device model (i.e 'iPhone', 'iPad', etc) + PART_KEY_UNIQUEID = 25; // for remote device identification, part of LOGMSG_TYPE_CLIENTINFO + + // Area starting at which you may define your own constants + static final int + PART_KEY_USER_DEFINED = 100; + + // Constants for the "partType" field + static final int + PART_TYPE_STRING = 0, // Strings are stored as UTF-8 data + PART_TYPE_BINARY = 1, // A block of binary data + PART_TYPE_INT16 = 2, + PART_TYPE_INT32 = 3, + PART_TYPE_INT64 = 4, + PART_TYPE_IMAGE = 5; // An image, stored in PNG format + + // Data values for the PART_KEY_MESSAGE_TYPE parts + static final int + LOGMSG_TYPE_LOG = 0, // A standard log message + LOGMSG_TYPE_BLOCKSTART = 1, // The start of a "block" (a group of log entries) + LOGMSG_TYPE_BLOCKEND = 2, // The end of the last started "block" + LOGMSG_TYPE_CLIENTINFO = 3, // Information about the client app + LOGMSG_TYPE_DISCONNECT = 4, // Pseudo-message on the desktop side to identify client disconnects + LOGMSG_TYPE_MARK = 5; // Pseudo-message that defines a "mark" that users can place in the log flow + + // Instance variables + private byte[] data; + private int dataUsed; + private final int sequenceNumber; + private short numParts; + + // Flushing support + private ReentrantLock doneLock; + private Condition doneCondition; + + /** + * Create a new binary log record from an existing LogRecord instance + * @param record the LogRecord instance we want to send + * @param seq the message's sequence number + */ + public LogMessage(LogRecord record, int seq) + { + sequenceNumber = seq; + String msg = record.getMessage(); + data = new byte[msg.length() + 64]; // gross approximation + dataUsed = 6; + addTimestamp(record.getMillis()); + addInt32(LOGMSG_TYPE_LOG, PART_KEY_MESSAGE_TYPE); + addInt32(sequenceNumber, PART_KEY_MESSAGE_SEQ); + addString(Long.toString(record.getThreadID()), PART_KEY_THREAD_ID); + addInt16(record.getLevel().intValue(), PART_KEY_LEVEL); + addString(record.getSourceClassName() + "." + record.getSourceMethodName(), PART_KEY_FUNCTIONNAME); + addString(record.getMessage(), PART_KEY_MESSAGE); + } + + /** + * Prepare an empty log message that can be filled + * @param messageType the message type (i.e. LOGMSG_TYPE_LOG) + * @param seq the message's sequence number + */ + public LogMessage(int messageType, int seq) + { + sequenceNumber = seq; + data = new byte[256]; + dataUsed = 6; + addInt32(messageType, PART_KEY_MESSAGE_TYPE); + addInt32(sequenceNumber, PART_KEY_MESSAGE_SEQ); + addTimestamp(0); + addThreadID(Thread.currentThread().getId()); + } + + /** + * Obtain this message's sequence number (should be a unique number that orders messages sent) + * @return the sequence number + */ + public int getSequenceNumber() + { + return sequenceNumber; + } + + /** + * Internally used to indicate that the client thread will wait for this + * message to have been sent before continuing + */ + protected void prepareForFlush() + { + doneLock = new ReentrantLock(); + doneCondition = doneLock.newCondition(); + doneLock.lock(); + } + + /** + * Internally used by the client thread to wait for the logging thread + * to have successfully sent the message. Thread is blocked in the + * meantime. + */ + protected void waitFlush() + { + try { + if (DEBUG_LOGGER) + Log.v("NSLogger", String.format("waiting for flush of message %d", sequenceNumber)); + doneCondition.await(); + } catch (InterruptedException e) { + // nothing here + } finally { + doneLock.unlock(); + } + } + + /** + * Internally used by the logging thread to mark this message as "flushed" + * (sent to the desktop viewer or written to the log file) + */ + protected void markFlushed() + { + if (doneLock != null) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", String.format("marking message %d as flushed", sequenceNumber)); + doneLock.lock(); + doneCondition.signal(); + doneLock.unlock(); + } + } + + /** + * Return the generated binary message + * + * @return bytes to send to desktop NSLogger + */ + byte[] getBytes() + { + int size = dataUsed - 4; + data[0] = (byte) (size >> 24); + data[1] = (byte) (size >> 16); + data[2] = (byte) (size >> 8); + data[3] = (byte) size; + data[4] = (byte) (numParts >> 8); + data[5] = (byte) numParts; + + if (dataUsed == data.length) + return data; + + byte[] b = new byte[dataUsed]; + System.arraycopy(data, 0, b, 0, dataUsed); + data = null; + return b; + } + + void addTimestamp(long ts) + { + if (ts == 0) + ts = System.currentTimeMillis(); + addInt64(ts / 1000, PART_KEY_TIMESTAMP_S); + addInt16((int) (ts % 1000), PART_KEY_TIMESTAMP_MS); + } + + void addThreadID(long threadID) + { + String s = null; + // If the thread is part if our thread group, we can extract its + // name. Otherwise, just use a thread number + Thread t = Thread.currentThread(); + if (t.getId() == threadID) + s = t.getName(); + else + { + Thread array[] = new Thread[Thread.activeCount()]; + Thread.enumerate(array); + for (Thread th : array) + { + if (th.getId() == threadID) + { + s = t.getName(); + break; + } + } + } + if (s == null || s.isEmpty()) + s = Long.toString(threadID); + addString(s, PART_KEY_THREAD_ID); + } + + private void grow(int nBytes) + { + final int n = data.length; + if (n >= dataUsed + nBytes) + return; + + byte b[] = new byte[Math.max(n + n / 2, dataUsed + nBytes + 64)]; + System.arraycopy(data, 0, b, 0, dataUsed); + data = b; + } + + public void addInt16(int value, int key) + { + grow(4); + int n = dataUsed; + data[n++] = (byte)key; + data[n++] = (byte)PART_TYPE_INT16; + data[n++] = (byte)(value >> 8); + data[n++] = (byte)value; + dataUsed = n; + numParts++; + } + + public void addInt32(int value, int key) + { + grow(6); + int n = dataUsed; + data[n++] = (byte)key; + data[n++] = (byte)PART_TYPE_INT32; + data[n++] = (byte)(value >> 24); + data[n++] = (byte)(value >> 16); + data[n++] = (byte)(value >> 8); + data[n++] = (byte)value; + dataUsed = n; + numParts++; + } + + public void addInt64(long value, int key) + { + grow(10); + int n = dataUsed; + data[n++] = (byte)key; + data[n++] = (byte)PART_TYPE_INT64; + data[n++] = (byte)(value >> 56); + data[n++] = (byte)(value >> 48); + data[n++] = (byte)(value >> 40); + data[n++] = (byte)(value >> 32); + data[n++] = (byte)(value >> 24); + data[n++] = (byte)(value >> 16); + data[n++] = (byte)(value >> 8); + data[n++] = (byte)value; + dataUsed = n; + numParts++; + } + + public void addBytes(int key, int type, byte[] bytes) + { + final int l = bytes.length; + grow(l + 6); + int n = dataUsed; + data[n++] = (byte)key; + data[n++] = (byte)type; + data[n++] = (byte)(l >> 24); + data[n++] = (byte)(l >> 16); + data[n++] = (byte)(l >> 8); + data[n++] = (byte)l; + System.arraycopy(bytes, 0, data, n, l); + dataUsed = n + l; + numParts++; + } + + public void addString(String s, int key) + { + byte[] sb = s.getBytes(stringsCharset); + addBytes(key, PART_TYPE_STRING, sb); + } + + public void addBinaryData(byte[] d, int key) + { + addBytes(key, PART_TYPE_BINARY, d); + } + + public void addImageData(byte[] img, int key) + { + addBytes(key, PART_TYPE_IMAGE, img); + } + } + + /** + * The class encapsulating the actual worker thread for NSLogger + */ + private class LoggingWorker extends Thread implements ServiceListener, HandshakeCompletedListener, JmDNS.Delegate + { + ArrayList logs = new ArrayList(64); + + boolean connecting; // a connection attempt is already in progress + boolean reconnectionScheduled; // a reconnection message has been scheduled + boolean clientInfoAdded; // info about us has been queued (reset after each disconnect) + + Socket remoteSocket; // the remote socket we're talking to + int socketSendBufferSize; // the size of the socket's send buffer + boolean connected; // only set to true when the connect complete message has been received + + OutputStream writeStream; // the write stream we use to write to either socket or file + InputStream readStream; // when flushing file contents, temporarily hold a readStream + byte[] incompleteSend; // if last message could not be sent in one batch, the full message here + int incompleteSendOffset; // and the offset from which to continue sending here + + JmDNS bonjourBrowser; // Bonjour browser instance while trying to find a viewer on the network + String bonjourListeningType; + + // Startup locking mechanism + final AtomicBoolean ready = new AtomicBoolean(false); + final Queue readyWaiters = new ConcurrentLinkedQueue(); + + /** + * Our private class which handles messages sent from other threads + */ + private class InternalMsgHandler extends Handler + { + public void handleMessage(Message msg) + { + switch (msg.what) + { + case MSG_ADDLOG: + if (DEBUG_LOGGER) + Log.v("NSLogger", String.format("add log %d to the queue", ((LogMessage)msg.obj).getSequenceNumber())); + logs.add((LogMessage) msg.obj); + if (connected) + processLogQueue(); + break; + + case MSG_ADDLOGRECORD: + if (DEBUG_LOGGER) + Log.v("NSLogger", "add LogRecord to the queue"); + logs.add(new LogMessage((LogRecord) msg.obj, nextSequenceNumber.getAndIncrement())); + if (connected) + processLogQueue(); + break; + + case MSG_OPTCHANGE: + if (DEBUG_LOGGER) + Log.v("NSLogger", "options change message received"); + changeOptions((Properties)msg.obj); + break; + + case MSG_CONNECT_COMPLETE: + if (DEBUG_LOGGER) + Log.v("NSLogger", "connect complete message received"); + connecting = false; + connected = true; + processLogQueue(); + break; + + case MSG_TRY_CONNECT: + if (DEBUG_LOGGER) + Log.v("NSLogger", String.format("try connect message received, remote socket is %s, writeStream is %s, connecting=%d", remoteSocket==null?"null":"not null", writeStream==null?"null":"not null", connecting ? 1 : 0)); + reconnectionScheduled = false; + if (remoteSocket == null && writeStream == null) + { + if (!connecting && remoteHost != null && remotePort != 0) + connectToRemote(); + } + break; + + case MSG_QUIT: + Looper.myLooper().quit(); + break; + } + } + } + + LoggingWorker() + { + // We want NSLogger to leave as much CPU as possible for the app to run + // TODO: when flushing is turned ON, change priority to normal + super("NSLogger"); + setPriority(Process.THREAD_PRIORITY_LESS_FAVORABLE); + } + + @Override + public void run() + { + // create the buffer file if needed + try + { + if (DEBUG_LOGGER) + Log.i("NSLogger", "Logging thread starting up"); + + // Prepare to receive messages + Looper.prepare(); + loggingThreadHandler = new InternalMsgHandler(); + + // We are ready to run. Unpark the waiting threads now + // (there may be multiple thread trying to start logging at the same time) + ready.set(true); + while (!readyWaiters.isEmpty()) + LockSupport.unpark(readyWaiters.poll()); + + // Initial setup according to current parameters + if (bufferFile != null) + createBufferWriteStream(); + else if (remoteHost != null && remotePort != 0) + connectToRemote(); + else if ((options & OPT_BROWSE_BONJOUR) != 0) + setupBonjour(); + + if (DEBUG_LOGGER) + Log.i("NSLogger", "Logging thread looper starting"); + + // Process messages + Looper.loop(); + + if (DEBUG_LOGGER) + Log.i("NSLogger", "Logging thread looper ended"); + + // Once loop exists, reset the variable (in case of problem we'll recreate a thread) + closeBonjour(); + loggingThread = null; + loggingThreadHandler = null; + } + catch (Exception e) + { + if (DEBUG_LOGGER) + Log.e("NSLogger", "Exception catched in LoggingWorker.run(): " + e.toString()); + + // In case an exception was caused before run, make sure waiters are unblocked + ready.set(true); + while (!readyWaiters.isEmpty()) + LockSupport.unpark(readyWaiters.peek()); + } + } + + void changeOptions(Properties newOptions) + { + // We received an options change message. If options were actually change, + // we will interrupt the current logging stream, switch options and the + // next message sent will trigger a reconnect with the new options + if (newOptions.containsKey("filename")) + { + String filename = newOptions.getProperty("filename"); + if (bufferFile == null || !bufferFile.equalsIgnoreCase(filename)) + { + if (bufferFile == null) + disconnectFromRemote(); + else if (writeStream != null) + closeBufferWriteStream(); + bufferFile = filename; + createBufferWriteStream(); + } + } + else + { + boolean change = (bufferFile != null); + String host = ""; + int port = 0, newFlags = 0; + if (newOptions.getProperty("useSSL", "0").equals("1")) + newFlags = OPT_USE_SSL; + if (newOptions.containsKey("bonjourService")) + newFlags = OPT_BROWSE_BONJOUR; + else + { + host = newOptions.getProperty("remoteHost"); + port = Integer.parseInt(newOptions.getProperty("remotePort", "0")); + if (!change && (options & OPT_BROWSE_BONJOUR) == 0) + { + // Check if changing host or port + change = (remoteHost == null || remoteHost.equalsIgnoreCase(host) || remotePort != port); + } + } + if (newFlags != options || change) + { + if (DEBUG_LOGGER) + Log.i("NSLogger", "Options changed, closing/restarting"); + + if (bufferFile != null) + closeBufferWriteStream(); + else + disconnectFromRemote(); + options = newFlags; + if ((newFlags & OPT_BROWSE_BONJOUR) == 0) + { + remoteHost = host; + remotePort = port; + connectToRemote(); + } + else + setupBonjour(); + } + } + } + + void processLogQueue() + { + if (logs.isEmpty()) + return; + + if (!clientInfoAdded) + pushClientInfoToFrontOfQueue(); + + if (writeStream == null) + { + if (bufferFile != null) + createBufferWriteStream(); + else if (!(connecting || reconnectionScheduled || (options & OPT_BROWSE_BONJOUR) != 0) && + remoteHost != null && remotePort != 0) + connectToRemote(); + return; + } + + if (remoteSocket == null) + { + flushQueueToBufferStream(); + } + else if (!remoteSocket.isConnected()) + { + disconnectFromRemote(); + tryReconnecting(); + } + else if (connected) + { + int written = 0, remaining = socketSendBufferSize; + try + { + if (incompleteSend != null) + { + int n = Math.min(remaining, incompleteSend.length - incompleteSendOffset); + writeStream.write(incompleteSend, incompleteSendOffset, n); + written += n; + incompleteSendOffset += n; + remaining -= n; + if (incompleteSendOffset == incompleteSend.length) + { + incompleteSend = null; + incompleteSendOffset = 0; + } + } + if (DEBUG_LOGGER) + { + if (!logs.isEmpty()) + Log.v("NSLogger", String.format("processLogQueue: %d bytes available on socket, %d queued messages", remaining, logs.size())); + } + while (remaining > 0 && !logs.isEmpty()) + { + LogMessage log = logs.get(0); + byte[] msg = log.getBytes(); + int length = msg.length; + if (length > socketSendBufferSize) + { + incompleteSend = msg; + writeStream.write(msg, 0, socketSendBufferSize); + incompleteSendOffset = socketSendBufferSize; + } + else + { + // TODO: take the socketSendBufferSize into account + writeStream.write(msg); + } + log.markFlushed(); + logs.remove(0); + } + } + catch (IOException e) + { + if (DEBUG_LOGGER) + Log.d("NSLogger", "processLogQueue(): remote socket disconnected - exception: " + e.toString()); + disconnectFromRemote(); + tryReconnecting(); + } + } + } + + void connectToRemote() + { + // Connect to the remote logging host + if (writeStream != null) + throw new NullPointerException("internal error: writeStream should be null"); + if (remoteSocket != null) + throw new NullPointerException("internal error: remoteSocket should be null"); + + try + { + closeBonjour(); + + if (DEBUG_LOGGER) + Log.d("NSLogger", String.format("connecting to %s:%d", remoteHost, remotePort)); + + remoteSocket = new Socket(remoteHost, remotePort); + if ((options & OPT_USE_SSL) != 0) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "activating SSL connection"); + + SSLSocketFactory sf = SSLCertificateSocketFactory.getInsecure(5000, null); + remoteSocket = sf.createSocket(remoteSocket, remoteHost, remotePort, true); + if (remoteSocket != null) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", String.format("starting SSL handshake with %s:%d", remoteSocket.getInetAddress().toString(), remoteSocket.getPort())); + + SSLSocket socket = (SSLSocket) remoteSocket; + socket.setUseClientMode(true); + socket.addHandshakeCompletedListener(this); + socket.startHandshake(); + } + } + else + { + // non-SSL sockets are immediately ready for use + socketSendBufferSize = remoteSocket.getSendBufferSize(); + writeStream = remoteSocket.getOutputStream(); + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_CONNECT_COMPLETE)); + } + } + catch (UnknownHostException e) + { + Log.e("NSLogger", String.format("can't connect to %s:%d (unknown host)", remoteHost, remotePort)); + disconnectFromRemote(); + } + catch (Exception e) + { + Log.e("NSLogger", String.format("exception while trying to connect to %s:%d: %s", remoteHost, remotePort, e.toString())); + disconnectFromRemote(); + tryReconnecting(); + } + } + + void disconnectFromRemote() + { + connected = false; + if (remoteSocket != null) + { + try + { + if (DEBUG_LOGGER) + Log.d("NSLogger", "disconnectFromRemote()"); + + if (remoteSocket instanceof SSLSocket) + { + SSLSocket socket = (SSLSocket) remoteSocket; + socket.removeHandshakeCompletedListener(this); + } + if (writeStream != null) + writeStream.close(); + remoteSocket.close(); + } + catch (Exception e) + { + Log.e("NSLogger", "Exception catched in disconnectFromRemote: " + e.toString()); + } + finally + { + writeStream = null; + remoteSocket = null; + socketSendBufferSize = 0; + connecting = false; + clientInfoAdded = false; + } + } + } + + void tryReconnecting() + { + if (reconnectionScheduled) + return; + + if (DEBUG_LOGGER) + Log.d("NSLogger", "tryReconnecting"); + + if ((options & OPT_BROWSE_BONJOUR) != 0) + { + if (bonjourBrowser == null) + setupBonjour(); + } + else + { + reconnectionScheduled = true; + loggingThreadHandler.sendMessageDelayed(loggingThreadHandler.obtainMessage(MSG_TRY_CONNECT), 2000); + } + } + + public void handshakeCompleted(HandshakeCompletedEvent handshakeCompletedEvent) + { + try + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "SSL handshake completed"); + + socketSendBufferSize = remoteSocket.getSendBufferSize(); + writeStream = remoteSocket.getOutputStream(); + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_CONNECT_COMPLETE)); + } + catch (Exception e) + { + Log.e("NSLogger", "Exception cached in handshakeCompleted: " + e.toString()); + disconnectFromRemote(); + tryReconnecting(); + } + } + + void pushClientInfoToFrontOfQueue() + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "Pushing client info to front of queue"); + + LogMessage lm = new LogMessage(LogMessage.LOGMSG_TYPE_CLIENTINFO, nextSequenceNumber.getAndIncrement()); + lm.addString(Build.MANUFACTURER + " " + Build.MODEL, LogMessage.PART_KEY_CLIENT_MODEL); + lm.addString("Android", LogMessage.PART_KEY_OS_NAME); + lm.addString(Build.VERSION.RELEASE, LogMessage.PART_KEY_OS_VERSION); + lm.addString(Secure.getString(currentContext.getContentResolver(), Secure.ANDROID_ID), LogMessage.PART_KEY_UNIQUEID); + ApplicationInfo ai = currentContext.getApplicationInfo(); + String appName = ai.packageName; + if (appName == null) + { + appName = ai.processName; + if (appName == null) + { + appName = ai.taskAffinity; + if (appName == null) + appName = ai.toString(); + } + } + lm.addString(appName, LogMessage.PART_KEY_CLIENT_NAME); + logs.add(0, lm); + clientInfoAdded = true; + } + + void createBufferWriteStream() + { + // Create the write stream that writes to a log file, + // and if needed flush the current logs to the log file + if (bufferFile == null || bufferFile.isEmpty()) + return; + + try + { + if (DEBUG_LOGGER) + Log.d("NSLogger", String.format("Creating file buffer stream to %s", bufferFile)); + + writeStream = new BufferedOutputStream(new FileOutputStream(bufferFile, true)); + flushQueueToBufferStream(); + } + catch (Exception e) + { + Log.e("NSLogger", "Exception catched while trying to create file stream: " + e.toString()); + bufferFile = null; + } + } + + void closeBufferWriteStream() + { + if (DEBUG_LOGGER) + Log.d("NSLogger", "Closing file buffer stream"); + + try + { + writeStream.flush(); + writeStream.close(); + } + catch (Exception e) + { + Log.e("NSLogger", "Exception catched in closeBufferWriteStream: " + e.toString()); + } + writeStream = null; + } + + /** + * Write outstanding messages to the buffer file (streams don't detect disconnection + * until the next write, where we could lose one or more messages) + */ + void flushQueueToBufferStream() + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "flushQueueToBufferStream"); + + incompleteSendOffset = 0; + + if (incompleteSend != null) + { + try + { + writeStream.write(incompleteSend, + incompleteSendOffset, + incompleteSend.length - incompleteSendOffset); + incompleteSend = null; + incompleteSendOffset = 0; + } + catch (IOException e) + { + Log.e("NSLogger", "Exception catched while trying to write to file stream: " + e.toString()); + } + } + try + { + while (!logs.isEmpty()) + { + LogMessage log = logs.get(0); + byte[] message = log.getBytes(); + if (message == null) + break; + writeStream.write(message); + log.markFlushed(); + logs.remove(0); + } + } + catch (IOException e) + { + Log.e("NSLogger", "Exception catched in flushQueueToBufferStream: " + e.toString()); + } + } + + void setupBonjour() + { + if ((options & OPT_BROWSE_BONJOUR) != 0) + { + if (bonjourBrowser == null) + { + try + { + if (DEBUG_LOGGER) + Log.d("NSLogger", "setupBonjour(): creating JmDNS instance"); + + // acquire the wifi multicasting lock, so that the WiFi interface + // starts processing multicast packets. This uses more battery, + // but Bonjour can't work without it + multicastLock.acquire(); + + bonjourBrowser = JmDNS.create(); + bonjourBrowser.setDelegate(this); + bonjourListeningType = bonjourServiceType; + if (bonjourListeningType == null || bonjourListeningType.isEmpty()) + bonjourListeningType = ((options & OPT_USE_SSL) != 0) ? "_nslogger-ssl._tcp.local." : "_nslogger._tcp.local."; + bonjourBrowser.addServiceListener(bonjourListeningType, this); + } + catch (Exception e) + { + Log.e("NSLogger", "Exception catched in setupBonjour(): " + e.toString()); + bonjourListeningType = null; + } + } + } + else + { + closeBonjour(); + } + } + + void closeBonjour() + { + try + { + if (bonjourBrowser != null) + { + if (DEBUG_LOGGER) + Log.d("NSLogger", "closeBonjour()"); + + if (bonjourListeningType != null) + { + bonjourBrowser.removeServiceListener(bonjourListeningType, this); + bonjourListeningType = null; + } + bonjourBrowser.unregisterAllServices(); + bonjourBrowser.setDelegate(null); + bonjourBrowser = null; + + // release the wifi multicasting lock for this instance + // when count drops to 0, wifi stops processing multicasting + // packets so as to save battery + multicastLock.release(); + } + } + catch (Exception e) + { + Log.e("NSLogger", "Exception catched in closeBonjour(): " + e.toString()); + } + } + + public void serviceAdded(ServiceEvent event) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "Bonjour service found: " + event.getType() + " " + event.getName()); + + bonjourBrowser.requestServiceInfo(event.getType(), event.getName(), false, 1); + } + + public void serviceRemoved(ServiceEvent event) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "Bonjour service removed: " + event.toString()); + } + + public void serviceResolved(ServiceEvent event) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "Bonjour service resolved: " + event.toString()); + + if (remoteSocket == null) + { + if (DEBUG_LOGGER) + Log.v("NSLogger", "-> retrieving service info"); + + ServiceInfo info = event.getInfo(); + InetAddress[] addrs = info.getInetAddresses(); + if (addrs.length > 0) + { + remoteHost = addrs[0].getHostAddress(); + remotePort = info.getPort(); + + if (DEBUG_LOGGER) + Log.v("NSLogger", String.format("-> will try to connect to Bonjour service %s:%d", remoteHost, remotePort)); + + loggingThreadHandler.sendMessage(loggingThreadHandler.obtainMessage(MSG_TRY_CONNECT)); + } + } + } + + public void cannotRecoverFromIOError(JmDNS dns, Collection infos) + { + if (DEBUG_LOGGER) + Log.e("NSLogger", "JmDNS can't record from IOError: infos=" + infos.toString()); + } + } +} diff --git a/External Source/NSLogger/Client Logger/Android/example/com/example/Debug.java b/External Source/NSLogger/Client Logger/Android/example/com/example/Debug.java new file mode 100644 index 000000000..3cc9a5046 --- /dev/null +++ b/External Source/NSLogger/Client Logger/Android/example/com/example/Debug.java @@ -0,0 +1,24 @@ +package com.example; + +import android.content.Context; + +public class Debug +{ + public static final boolean D = true; // set to false to disable debug + public static DroidLogger L = null; + + public static void assert_(boolean condition) + { + if (D && !condition) + throw new AssertionError("assertion failed"); + } + + public static void enableDebug(Context ctx, boolean flushEachMessage) + { + if (L == null) + { + L = new DroidLogger(ctx); + L.setMessageFlushing(flushEachMessage); + } + } +} diff --git a/External Source/NSLogger/Client Logger/Android/example/com/example/DroidLogger.java b/External Source/NSLogger/Client Logger/Android/example/com/example/DroidLogger.java new file mode 100644 index 000000000..2f3349081 --- /dev/null +++ b/External Source/NSLogger/Client Logger/Android/example/com/example/DroidLogger.java @@ -0,0 +1,108 @@ +package com.example; + +import android.content.Context; +import com.NSLogger.NSLoggerClient; + +import java.util.Formatter; + +public final class DroidLogger extends NSLoggerClient +{ + public DroidLogger(Context ctx) + { + super(ctx); + } + + private void taggedLog(final int level, final String tag, final String message) + { + final StackTraceElement[] st = Thread.currentThread().getStackTrace(); + if (st != null && st.length > 4) + { + // log with originating source code info + final StackTraceElement e = st[4]; + log(e.getFileName(), e.getLineNumber(), e.getClassName() + "." + e.getMethodName() + "()", tag, level, message); + } + else + { + // couldn't obtain stack trace? log without source code info + log(tag, level, message); + } + } + + public void LOG_MARK(String mark) + { + logMark(mark); + } + + public void LOG_EXCEPTION(Exception exc) + { + final StackTraceElement[] st = exc.getStackTrace(); + if (st != null && st.length != 0) + { + // a stack trace was attached to exception, report the most recent callsite in file/line/function + // information, and append the full stack trace to the message + StringBuilder sb = new StringBuilder(256); + sb.append("Exception: "); + sb.append(exc.toString()); + sb.append("\n\nStack trace:\n"); + for (int i=0, n=st.length; i < n; i++) + { + final StackTraceElement e = st[i]; + sb.append(e.getFileName()); + if (e.getLineNumber() < 0) + sb.append(" (native)"); + else + { + sb.append(":"); + sb.append(Integer.toString(e.getLineNumber())); + } + sb.append(" "); + sb.append(e.getClassName()); + sb.append("."); + sb.append(e.getMethodName()); + sb.append("\n"); + } + final StackTraceElement e = st[0]; + log(e.getFileName(), e.getLineNumber(), e.getClassName() + "." + e.getMethodName() + "()", "exception", 0, sb.toString()); + } + else + { + // no stack trace attached to exception (should not happen) + taggedLog(0, "exception", exc.toString()); + } + } + + public void LOG_APP(int level, String format, Object ... args) + { + taggedLog(level, "app", new Formatter().format(format, args).toString()); + } + + public void LOG_DYNAMIC_IMAGES(int level, String format, Object ... args) + { + taggedLog(level, "images", new Formatter().format(format, args).toString()); + } + + public void LOG_WEBVIEW(int level, String format, Object ... args) + { + taggedLog(level, "webview", new Formatter().format(format, args).toString()); + } + + public void LOG_CACHE(int level, String format, Object ... args) + { + taggedLog(level, "cache", new Formatter().format(format, args).toString()); + } + + public void LOG_NETWORK(int level, String format, Object ... args) + { + taggedLog(level, "network", new Formatter().format(format, args).toString()); + } + + public void LOG_SERVICE(int level, String format, Object ... args) + { + taggedLog(level, "service", new Formatter().format(format, args).toString()); + } + + public void LOG_UI(int level, String format, Object ... args) + { + taggedLog(level, "ui", new Formatter().format(format, args).toString()); + } +} diff --git a/External Source/NSLogger/Client Logger/iOS/LoggerClient.h b/External Source/NSLogger/Client Logger/iOS/LoggerClient.h new file mode 100644 index 000000000..7509c0b08 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/LoggerClient.h @@ -0,0 +1,231 @@ +/* + * LoggerClient.h + * + * version 1.0 2011-10-30 + * + * Part of NSLogger (client side) + * https://github.com/fpillet/NSLogger + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#import +#import +#import +#import +#import +#if !TARGET_OS_IPHONE +#import +#endif + +// This define is here so that user application can test whether NSLogger Client is +// being included in the project, and potentially configure their macros accordingly +#define NSLOGGER_WAS_HERE 1 + +// Set this to 0 if you absolutely NOT want any access to Cocoa (Objective-C, NS* calls) +// We need a couple ones to reliably obtain the thread number and device information +// Note that since we need NSAutoreleasePool when using Cocoa in the logger's worker thread, +// we need to put Cocoa in multithreading mode. Also, ALLOW_COCOA_USE allows the client code +// to use NSLog()-style message formatting (less verbose than CFShow()-style) through the +// use of -[NSString stringWithFormat:arguments:] +#define ALLOW_COCOA_USE 1 + +/* ----------------------------------------------------------------- + * Logger option flags & default options + * ----------------------------------------------------------------- + */ +enum { + kLoggerOption_LogToConsole = 0x01, + kLoggerOption_BufferLogsUntilConnection = 0x02, + kLoggerOption_BrowseBonjour = 0x04, + kLoggerOption_BrowseOnlyLocalDomain = 0x08, + kLoggerOption_UseSSL = 0x10 +}; + +#define LOGGER_DEFAULT_OPTIONS (kLoggerOption_BufferLogsUntilConnection | \ + kLoggerOption_BrowseBonjour | \ + kLoggerOption_BrowseOnlyLocalDomain | \ + kLoggerOption_UseSSL) + +/* ----------------------------------------------------------------- + * Structure defining a Logger + * ----------------------------------------------------------------- + */ +typedef struct +{ + CFStringRef bufferFile; // If non-NULL, all buffering is done to the specified file instead of in-memory + CFStringRef host; // Viewer host to connect to (instead of using Bonjour) + UInt32 port; // port on the viewer host + + CFMutableArrayRef bonjourServiceBrowsers; // Active service browsers + CFMutableArrayRef bonjourServices; // Services being tried + CFNetServiceBrowserRef bonjourDomainBrowser; // Domain browser + + CFMutableArrayRef logQueue; // Message queue + pthread_mutex_t logQueueMutex; + pthread_cond_t logQueueEmpty; + + pthread_t workerThread; // The worker thread responsible for Bonjour resolution, connection and logs transmission + CFRunLoopSourceRef messagePushedSource; // A message source that fires on the worker thread when messages are available for send + CFRunLoopSourceRef bufferFileChangedSource; // A message source that fires on the worker thread when the buffer file configuration changes + + CFWriteStreamRef logStream; // The connected stream we're writing to + CFWriteStreamRef bufferWriteStream; // If bufferFile not NULL and we're not connected, points to a stream for writing log data + CFReadStreamRef bufferReadStream; // If bufferFile not NULL, points to a read stream that will be emptied prior to sending the rest of in-memory messages + + SCNetworkReachabilityRef reachability; // The reachability object we use to determine when the target host becomes reachable + CFRunLoopTimerRef checkHostTimer; // A timer to regularly check connection to the defined host, along with reachability for added reliability + + uint8_t *sendBuffer; // data waiting to be sent + NSUInteger sendBufferSize; + NSUInteger sendBufferUsed; // number of bytes of the send buffer currently in use + NSUInteger sendBufferOffset; // offset in sendBuffer to start sending at + + int32_t messageSeq; // sequential message number (added to each message sent) + + // settings + uint32_t options; // Flags, see enum above + CFStringRef bonjourServiceType; // leave NULL to use the default + CFStringRef bonjourServiceName; // leave NULL to use the first one available + + // internal state + BOOL connected; // Set to YES once the write stream declares the connection open + volatile BOOL quit; // Set to YES to terminate the logger worker thread's runloop + BOOL incompleteSendOfFirstItem; // set to YES if we are sending the first item in the queue and it's bigger than what the buffer can hold +} Logger; + + +/* ----------------------------------------------------------------- + * LOGGING FUNCTIONS + * ----------------------------------------------------------------- + */ + +#ifdef __cplusplus +extern "C" { +#endif + +// Functions to set and get the default logger +extern void LoggerSetDefaultLogger(Logger *aLogger); +extern Logger *LoggerGetDefaultLogger(void); + +// Initialize a new logger, set as default logger if this is the first one +// Options default to: +// - logging to console = NO +// - buffer until connection = YES +// - browse Bonjour = YES +// - browse only locally on Bonjour = YES +extern Logger* LoggerInit(void); + +// Set logger options if you don't want the default options (see above) +extern void LoggerSetOptions(Logger *logger, uint32_t options); + +// Set Bonjour logging names, so you can force the logger to use a specific service type +// or direct logs to the machine on your network which publishes a specific name +extern void LoggerSetupBonjour(Logger *logger, CFStringRef bonjourServiceType, CFStringRef bonjourServiceName); + +// Directly set the viewer host (hostname or IP address) and port we want to connect to. If set, LoggerStart() will +// try to connect there first before trying Bonjour +extern void LoggerSetViewerHost(Logger *logger, CFStringRef hostName, UInt32 port); + + +// Configure the logger to use a local file for buffering, instead of memory. +// - If you initially set a buffer file after logging started but while a logger connection +// has not been acquired, the contents of the log queue will be written to the buffer file +// the next time a logging function is called, or when LoggerStop() is called. +// - If you want to change the buffering file after logging started, you should first +// call LoggerStop() the call LoggerSetBufferFile(). Note that all logs stored in the previous +// buffer file WON'T be transferred to the new file in this case. +extern void LoggerSetBufferFile(Logger *logger, CFStringRef absolutePath); + +// Activate the logger, try connecting +extern void LoggerStart(Logger *logger); + +//extern void LoggerConnectToHost(CFDataRef address, int port); + +// Deactivate and free the logger. +extern void LoggerStop(Logger *logger); + +// Pause the current thread until all messages from the logger have been transmitted +// this is useful to use before an assert() aborts your program. If waitForConnection is YES, +// LoggerFlush() will block even if the client is not currently connected to the desktop +// viewer. You should be using NO most of the time, but in some cases it can be useful. +extern void LoggerFlush(Logger *logger, BOOL waitForConnection); + +/* Logging functions. Each function exists in four versions: + * + * - one without a Logger instance (uses default logger) and without filename/line/function (no F suffix) + * - one without a Logger instance but with filename/line/function (F suffix) + * - one with a Logger instance (use a specific Logger) and without filename/line/function (no F suffix) + * - one with a Logger instance (use a specific Logger) and with filename/line/function (F suffix) + * + * The exception being the single LogMessageCompat() function which is designed to be a drop-in replacement for NSLog() + * + */ + +// Log a message, calling format compatible with NSLog +extern void LogMessageCompat(NSString *format, ...); + +// Log a message. domain can be nil if default domain. +extern void LogMessage(NSString *domain, int level, NSString *format, ...); +extern void LogMessageF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, ...); +extern void LogMessageTo(Logger *logger, NSString *domain, int level, NSString *format, ...); +extern void LogMessageToF(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, ...); + +// Log a message. domain can be nil if default domain (versions with va_list format args instead of ...) +extern void LogMessage_va(NSString *domain, int level, NSString *format, va_list args); +extern void LogMessageF_va(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, va_list args); +extern void LogMessageTo_va(Logger *logger, NSString *domain, int level, NSString *format, va_list args); +extern void LogMessageToF_va(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, va_list args); + +// Send binary data to remote logger +extern void LogData(NSString *domain, int level, NSData *data); +extern void LogDataF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSData *data); +extern void LogDataTo(Logger *logger, NSString *domain, int level, NSData *data); +extern void LogDataToF(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSData *data); + +// Send image data to remote logger +extern void LogImageData(NSString *domain, int level, int width, int height, NSData *data); +extern void LogImageDataF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, int width, int height, NSData *data); +extern void LogImageDataTo(Logger *logger, NSString *domain, int level, int width, int height, NSData *data); +extern void LogImageDataToF(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, int width, int height, NSData *data); + +// Mark the start of a block. This allows the remote logger to group blocks together +extern void LogStartBlock(NSString *format, ...); +extern void LogStartBlockTo(Logger *logger, NSString *format, ...); + +// Mark the end of a block +extern void LogEndBlock(void); +extern void LogEndBlockTo(Logger *logger); + +// Log a marker (text can be null) +extern void LogMarker(NSString *text); +extern void LogMarkerTo(Logger *logger, NSString *text); + +#ifdef __cplusplus +}; +#endif diff --git a/External Source/NSLogger/Client Logger/iOS/LoggerClient.m b/External Source/NSLogger/Client Logger/iOS/LoggerClient.m new file mode 100644 index 000000000..79f174d46 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/LoggerClient.m @@ -0,0 +1,2300 @@ +/* + * LoggerClient.m + * + * version 1.0.1 2011-12-03 + * + * Main implementation of the NSLogger client side code + * Part of NSLogger (client side) + * https://github.com/fpillet/NSLogger + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#if !TARGET_OS_IPHONE + #import + #import + #import +#elif ALLOW_COCOA_USE + #import +#endif +#import + +#import "LoggerClient.h" +#import "LoggerCommon.h" + +/* -------------------------------------------------------------------------------- + * IMPLEMENTATION NOTES: + * + * The logger runs in a separate thread. It is written + * in straight C for maximum compatibility with all runtime environments + * (does not use the Objective-C runtime, only uses unix and CoreFoundation + * calls, except for get the thread name and device information, but these + * can be disabled by setting ALLOW_COCOA_USE to 0). + * + * It is suitable for use in both Cocoa and low-level code. It does not activate + * Cocoa multi-threading (no call to [NSThread detachNewThread...]). You can start + * logging very early (as soon as your code starts running), logs will be + * buffered and sent to the log viewer as soon as a connection is acquired. + * This makes the logger suitable for use in conditions where you usually + * don't have a connection to a remote machine yet (early wakeup, network + * down, etc). + * + * When you call one of the public logging functions, the logger is designed + * to return to your application as fast as possible. It enqueues logs to + * send for processing by its own thread, while your application keeps running. + * + * The logger does buffer logs while not connected to a desktop + * logger. It uses Bonjour to find a logger on the local network, and can + * optionally connect to a remote logger identified by an IP address / port + * or a Host Name / port. + * + * The logger can optionally output its log to the console, like NSLog(). + * + * The logger can optionally buffer its logs to a file for which you specify the + * full path. Upon connection to the desktop viewer, the file contents are + * transmitted to the viewer prior to sending new logs. When the whole file + * content has been transmitted, it is emptied. + * + * Multiple loggers can coexist at the same time. You can perfectly use a + * logger for your debug traces, and another that connects remotely to help + * diagnostic issues while the application runs on your user's device. + * + * Using the logger's flexible packet format, you can customize logging by + * creating your own log types, and customize the desktop viewer to display + * runtime information panels for your application. + * -------------------------------------------------------------------------------- + */ + +/* Logger internal debug flags */ +// Set to 0 to disable internal debug completely +// Set to 1 to activate console logs when running the logger itself +// Set to 2 to see every logging call issued by the app, too +#define LOGGER_DEBUG 0 +#ifdef NSLog + #undef NSLog +#endif + +// Internal debugging stuff for the logger itself +#if LOGGER_DEBUG + #define LOGGERDBG LoggerDbg + #if LOGGER_DEBUG > 1 + #define LOGGERDBG2 LoggerDbg + #else + #define LOGGERDBG2(format, ...) do{}while(0) + #endif + // Internal logging function prototype + static void LoggerDbg(CFStringRef format, ...); +#else + #define LOGGERDBG(format, ...) do{}while(0) + #define LOGGERDBG2(format, ...) do{}while(0) +#endif + +// small set of macros for proper ARC/non-ARC compilation support +// with added cruft to support non-clang compilers +#undef LOGGER_ARC_MACROS_DEFINED +#if defined(__has_feature) + #if __has_feature(objc_arc) + #define CAST_TO_CFSTRING __bridge CFStringRef + #define CAST_TO_CFDATA __bridge CFDataRef + #define RELEASE(obj) do{}while(0) + #define AUTORELEASE_POOL_BEGIN @autoreleasepool{ + #define AUTORELEASE_POOL_END } + #define LOGGER_ARC_MACROS_DEFINED + #endif +#endif +#if !defined(LOGGER_ARC_MACROS_DEFINED) + #define CAST_TO_CFSTRING CFStringRef + #define CAST_TO_CFDATA CFDataRef + #define RELEASE(obj) [obj release] + #define AUTORELEASE_POOL_BEGIN NSAutoreleasePool *__pool=[[NSAutoreleasePool alloc] init]; + #define AUTORELEASE_POOL_END [__pool drain]; +#endif +#undef LOGGER_ARC_MACROS_DEFINED + +/* Local prototypes */ +static void* LoggerWorkerThread(Logger *logger); +static void LoggerWriteMoreData(Logger *logger); +static void LoggerPushMessageToQueue(Logger *logger, CFDataRef message); + +// Bonjour management +static void LoggerStartBonjourBrowsing(Logger *logger); +static void LoggerStopBonjourBrowsing(Logger *logger); +static BOOL LoggerBrowseBonjourForServices(Logger *logger, CFStringRef domainName); +static void LoggerServiceBrowserCallBack(CFNetServiceBrowserRef browser, CFOptionFlags flags, CFTypeRef domainOrService, CFStreamError* error, void *info); + +// Reachability and reconnect timer +static void LoggerStartReachabilityChecking(Logger *logger); +static void LoggerStopReachabilityChecking(Logger *logger); +static void LoggerReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info); +static void LoggerTimedReconnectCallback(CFRunLoopTimerRef timer, void *info); + +// Connection & stream management +static void LoggerTryConnect(Logger *logger); +static void LoggerWriteStreamCallback(CFWriteStreamRef ws, CFStreamEventType event, void* info); + +// File buffering +static void LoggerCreateBufferWriteStream(Logger *logger); +static void LoggerCreateBufferReadStream(Logger *logger); +static void LoggerEmptyBufferFile(Logger *logger); +static void LoggerFileBufferingOptionsChanged(Logger *logger); +static void LoggerFlushQueueToBufferStream(Logger *logger, BOOL firstEntryIsClientInfo); + +// Encoding functions +static void LoggerPushClientInfoToFrontOfQueue(Logger *logger); +static void LoggerMessageAddTimestampAndThreadID(CFMutableDataRef encoder); + +static CFMutableDataRef LoggerMessageCreate(); +static void LoggerMessageUpdateDataHeader(CFMutableDataRef data); + +static void LoggerMessageAddInt32(CFMutableDataRef data, int32_t anInt, int key); +#if __LP64__ +static void LoggerMessageAddInt64(CFMutableDataRef data, int64_t anInt, int key); +#endif +static void LoggerMessageAddString(CFMutableDataRef data, CFStringRef aString, int key); +static void LoggerMessageAddData(CFMutableDataRef data, CFDataRef theData, int key, int partType); +static uint32_t LoggerMessageGetSeq(CFDataRef message); + +/* Static objects */ +static Logger* volatile sDefaultLogger = NULL; +static pthread_mutex_t sDefaultLoggerMutex = PTHREAD_MUTEX_INITIALIZER; + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Default logger +// ----------------------------------------------------------------------------- +void LoggerSetDefaultLogger(Logger *defaultLogger) +{ + pthread_mutex_lock(&sDefaultLoggerMutex); + sDefaultLogger = defaultLogger; + pthread_mutex_unlock(&sDefaultLoggerMutex); +} + +Logger *LoggerGetDefaultLogger(void) +{ + if (sDefaultLogger == NULL) + { + pthread_mutex_lock(&sDefaultLoggerMutex); + Logger *logger = LoggerInit(); + if (sDefaultLogger == NULL) + { + sDefaultLogger = logger; + logger = NULL; + } + pthread_mutex_unlock(&sDefaultLoggerMutex); + if (logger != NULL) + LoggerStop(logger); + } + return sDefaultLogger; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Initialization and setup +// ----------------------------------------------------------------------------- +Logger *LoggerInit(void) +{ + LOGGERDBG(CFSTR("LoggerInit defaultLogger=%p"), sDefaultLogger); + + Logger *logger = (Logger *)malloc(sizeof(Logger)); + bzero(logger, sizeof(Logger)); + + logger->logQueue = CFArrayCreateMutable(NULL, 32, &kCFTypeArrayCallBacks); + pthread_mutex_init(&logger->logQueueMutex, NULL); + pthread_cond_init(&logger->logQueueEmpty, NULL); + + logger->bonjourServiceBrowsers = CFArrayCreateMutable(NULL, 4, &kCFTypeArrayCallBacks); + logger->bonjourServices = CFArrayCreateMutable(NULL, 4, &kCFTypeArrayCallBacks); + + // for now we don't grow the send buffer, just use one page of memory which should be enouh + // (bigger messages will be sent separately) + logger->sendBuffer = (uint8_t *)malloc(4096); + logger->sendBufferSize = 4096; + + logger->options = LOGGER_DEFAULT_OPTIONS; + + logger->quit = NO; + + // Set this logger as the default logger is none exist already + if (!pthread_mutex_trylock(&sDefaultLoggerMutex)) + { + if (sDefaultLogger == NULL) + sDefaultLogger = logger; + pthread_mutex_unlock(&sDefaultLoggerMutex); + } + + return logger; +} + +void LoggerSetOptions(Logger *logger, uint32_t options) +{ + LOGGERDBG(CFSTR("LoggerSetOptions options=0x%08lx"), options); + + if (logger == NULL) + logger = LoggerGetDefaultLogger(); + if (logger != NULL) + logger->options = options; +} + +void LoggerSetupBonjour(Logger *logger, CFStringRef bonjourServiceType, CFStringRef bonjourServiceName) +{ + LOGGERDBG(CFSTR("LoggerSetupBonjour serviceType=%@ serviceName=%@"), bonjourServiceType, bonjourServiceName); + + if (logger == NULL) + logger = LoggerGetDefaultLogger(); + if (logger != NULL) + { + if (bonjourServiceType != NULL) + CFRetain(bonjourServiceType); + if (bonjourServiceName != NULL) + CFRetain(bonjourServiceName); + if (logger->bonjourServiceType != NULL) + CFRelease(logger->bonjourServiceType); + if (logger->bonjourServiceName != NULL) + CFRelease(logger->bonjourServiceName); + logger->bonjourServiceType = bonjourServiceType; + logger->bonjourServiceName = bonjourServiceName; + } +} + +void LoggerSetViewerHost(Logger *logger, CFStringRef hostName, UInt32 port) +{ + if (logger == NULL) + logger = LoggerGetDefaultLogger(); + if (logger == NULL) + return; + + if (logger->host != NULL) + { + CFRelease(logger->host); + logger->host = NULL; + } + if (hostName != NULL) + { + logger->host = CFStringCreateCopy(NULL, hostName); + logger->port = port; + } +} + +void LoggerSetBufferFile(Logger *logger, CFStringRef absolutePath) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + if (logger == NULL) + return; + } + + BOOL change = ((logger->bufferFile != NULL && absolutePath == NULL) || + (logger->bufferFile == NULL && absolutePath != NULL) || + (logger->bufferFile != NULL && absolutePath != NULL && CFStringCompare(logger->bufferFile, absolutePath, 0) != kCFCompareEqualTo)); + if (change) + { + if (logger->bufferFile != NULL) + { + CFRelease(logger->bufferFile); + logger->bufferFile = NULL; + } + if (absolutePath != NULL) + logger->bufferFile = CFStringCreateCopy(NULL, absolutePath); + if (logger->bufferFileChangedSource != NULL) + CFRunLoopSourceSignal(logger->bufferFileChangedSource); + } +} + +void LoggerStart(Logger *logger) +{ + // will do nothing if logger is already started + if (logger == NULL) + logger = LoggerGetDefaultLogger(); + + if (logger->workerThread == NULL) + { + // Start the work thread which performs the Bonjour search, + // connects to the logging service and forwards the logs + LOGGERDBG(CFSTR("LoggerStart logger=%p"), logger); + pthread_create(&logger->workerThread, NULL, (void *(*)(void *))&LoggerWorkerThread, logger); + } +} + +void LoggerStop(Logger *logger) +{ + LOGGERDBG(CFSTR("LoggerStop")); + + pthread_mutex_lock(&sDefaultLoggerMutex); + if (logger == NULL || logger == sDefaultLogger) + { + logger = sDefaultLogger; + sDefaultLogger = NULL; + } + pthread_mutex_unlock(&sDefaultLoggerMutex); + + if (logger != NULL) + { + if (logger->workerThread != NULL) + { + logger->quit = YES; + pthread_join(logger->workerThread, NULL); + } + + CFRelease(logger->bonjourServiceBrowsers); + CFRelease(logger->bonjourServices); + free(logger->sendBuffer); + if (logger->host != NULL) + CFRelease(logger->host); + if (logger->bufferFile != NULL) + CFRelease(logger->bufferFile); + if (logger->bonjourServiceType != NULL) + CFRelease(logger->bonjourServiceType); + if (logger->bonjourServiceName != NULL) + CFRelease(logger->bonjourServiceName); + + // to make sure potential errors are catched, set the whole structure + // to a value that will make code crash if it tries using pointers to it. + memset(logger, 0x55, sizeof(Logger)); + + free(logger); + } +} + +void LoggerFlush(Logger *logger, BOOL waitForConnection) +{ + // Special case: if nothing has ever been logged, don't bother + if (logger == NULL && sDefaultLogger == NULL) + return; + if (logger == NULL) + logger = LoggerGetDefaultLogger(); + if (logger != NULL && + pthread_self() != logger->workerThread && + (logger->connected || logger->bufferFile != NULL || waitForConnection)) + { + pthread_mutex_lock(&logger->logQueueMutex); + if (CFArrayGetCount(logger->logQueue) > 0) + pthread_cond_wait(&logger->logQueueEmpty, &logger->logQueueMutex); + pthread_mutex_unlock(&logger->logQueueMutex); + } +} + +#if LOGGER_DEBUG +static void LoggerDbg(CFStringRef format, ...) +{ + // Internal debugging function + // (what do you think, that we use the Logger to debug itself ??) + if (format != NULL) + { + AUTORELEASE_POOL_BEGIN + va_list args; + va_start(args, format); + CFStringRef s = CFStringCreateWithFormatAndArguments(NULL, NULL, (CFStringRef)format, args); + va_end(args); + if (s != NULL) + { + CFShow(s); + CFRelease(s); + } + AUTORELEASE_POOL_END + } +} +#endif + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Main processing +// ----------------------------------------------------------------------------- +static void *LoggerWorkerThread(Logger *logger) +{ + LOGGERDBG(CFSTR("Start LoggerWorkerThread")); + +#if !TARGET_OS_IPHONE + // Register thread with Garbage Collector on Mac OS X if we're running an OS version that has GC + void (*registerThreadWithCollector_fn)(void); + registerThreadWithCollector_fn = (void(*)(void)) dlsym(RTLD_NEXT, "objc_registerThreadWithCollector"); + if (registerThreadWithCollector_fn) + (*registerThreadWithCollector_fn)(); +#endif + + // Create and get the runLoop for this thread + CFRunLoopRef runLoop = CFRunLoopGetCurrent(); + + // Create the run loop source that signals when messages have been added to the runloop + // this will directly trigger a WriteMoreData() call, which will or won't write depending + // on whether we're connected and there's space available in the stream + CFRunLoopSourceContext context; + bzero(&context, sizeof(context)); + context.info = logger; + context.perform = (void *)&LoggerWriteMoreData; + logger->messagePushedSource = CFRunLoopSourceCreate(NULL, 0, &context); + if (logger->messagePushedSource == NULL) + { + // Failing to create the runloop source for pushing messages is a major failure. + // This NSLog is intentional. We WANT console output in this case + NSLog(@"*** NSLogger: Worker thread failed creating runLoop source, switching to console logging."); + logger->options |= kLoggerOption_LogToConsole; + logger->workerThread = NULL; + return NULL; + } + CFRunLoopAddSource(runLoop, logger->messagePushedSource, kCFRunLoopDefaultMode); + + // Create the buffering stream if needed + if (logger->bufferFile != NULL) + LoggerCreateBufferWriteStream(logger); + + // Create the runloop source that lets us know when file buffering options change + context.perform = (void *)&LoggerFileBufferingOptionsChanged; + logger->bufferFileChangedSource = CFRunLoopSourceCreate(NULL, 0, &context); + if (logger->bufferFileChangedSource == NULL) + { + // This failure MUST be logged to console + NSLog(@"*** NSLogger Warning: failed creating a runLoop source for file buffering options change."); + } + else + CFRunLoopAddSource(runLoop, logger->bufferFileChangedSource, kCFRunLoopDefaultMode); + + // Start Bonjour browsing, wait for remote logging service to be found + if (logger->host == NULL && (logger->options & kLoggerOption_BrowseBonjour)) + { + LOGGERDBG(CFSTR("-> logger configured for Bonjour, no direct host set -- trying Bonjour first")); + LoggerStartBonjourBrowsing(logger); + } + else if (logger->host != NULL) + { + LOGGERDBG(CFSTR("-> logger configured with direct host, trying it first")); + LoggerTryConnect(logger); + } + + // Run logging thread until LoggerStop() is called + NSTimeInterval timeout = 0.10; + while (!logger->quit) + { + int result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, true); + if (result == kCFRunLoopRunFinished || result == kCFRunLoopRunStopped) + break; + if (result == kCFRunLoopRunHandledSource) + { + timeout = 0.0; + continue; + } + timeout = fmin(0.10, timeout+0.0005); + + // Make sure we restart connection attempts if we get disconnected + if (!logger->connected && + !CFArrayGetCount(logger->bonjourServices) && + !CFArrayGetCount(logger->bonjourServiceBrowsers) && + !CFArrayGetCount(logger->bonjourServices)) + { + if (logger->options & kLoggerOption_BrowseBonjour) + LoggerStartBonjourBrowsing(logger); + else if (logger->host != NULL && logger->reachability == NULL && logger->checkHostTimer == NULL) + LoggerTryConnect(logger); + } + } + + // Cleanup + if (logger->options & kLoggerOption_BrowseBonjour) + LoggerStopBonjourBrowsing(logger); + LoggerStopReachabilityChecking(logger); + + if (logger->logStream != NULL) + { + CFWriteStreamSetClient(logger->logStream, 0, NULL, NULL); + CFWriteStreamClose(logger->logStream); + CFRelease(logger->logStream); + logger->logStream = NULL; + } + + if (logger->bufferWriteStream == NULL && logger->bufferFile != NULL) + { + // If there are messages in the queue and LoggerStop() was called and + // a buffer file was set just before LoggerStop() was called, flush + // the log queue to the buffer file + pthread_mutex_lock(&logger->logQueueMutex); + CFIndex outstandingMessages = CFArrayGetCount(logger->logQueue); + pthread_mutex_unlock(&logger->logQueueMutex); + if (outstandingMessages) + LoggerCreateBufferWriteStream(logger); + } + + if (logger->bufferWriteStream != NULL) + { + CFWriteStreamClose(logger->bufferWriteStream); + CFRelease(logger->bufferWriteStream); + logger->bufferWriteStream = NULL; + } + + if (logger->messagePushedSource != NULL) + { + CFRunLoopSourceInvalidate(logger->messagePushedSource); + CFRelease(logger->messagePushedSource); + logger->messagePushedSource = NULL; + } + + if (logger->bufferFileChangedSource != NULL) + { + CFRunLoopSourceInvalidate(logger->bufferFileChangedSource); + CFRelease(logger->bufferFileChangedSource); + logger->bufferFileChangedSource = NULL; + } + + // if the client ever tries to log again against us, make sure that logs at least + // go to console + logger->options |= kLoggerOption_LogToConsole; + logger->workerThread = NULL; + return NULL; +} + +static CFStringRef LoggerCreateStringRepresentationFromBinaryData(CFDataRef data) +{ + CFMutableStringRef s = CFStringCreateMutable(NULL, 0); + unsigned int offset = 0; + unsigned int dataLen = (unsigned int)CFDataGetLength(data); + char buffer[1+6+16*3+1+16+1+1+1]; + buffer[0] = '\0'; + const unsigned char *q = (unsigned char *)CFDataGetBytePtr(data); + if (dataLen == 1) + CFStringAppend(s, CFSTR("Raw data, 1 byte:\n")); + else + CFStringAppendFormat(s, NULL, CFSTR("Raw data, %u bytes:\n"), dataLen); + while (dataLen) + { + int i, j, b = sprintf(buffer," %04x: ", offset); + for (i=0; i < 16 && i < (int)dataLen; i++) + sprintf(&buffer[b+3*i], "%02x ", (int)q[i]); + for (j=i; j < 16; j++) + strcat(buffer, " "); + + b = (int)strlen(buffer); + buffer[b++] = '\''; + for (i=0; i < 16 && i < (int)dataLen; i++, q++) + { + if (*q >= 32 && *q < 128) + buffer[b++] = *q; + else + buffer[b++] = ' '; + } + for (j=i; j < 16; j++) + buffer[b++] = ' '; + buffer[b++] = '\''; + buffer[b++] = '\n'; + buffer[b] = 0; + + CFStringRef bufferStr = CFStringCreateWithBytesNoCopy(NULL, (const UInt8 *)buffer, strlen(buffer), kCFStringEncodingISOLatin1, false, kCFAllocatorNull); + CFStringAppend(s, bufferStr); + CFRelease(bufferStr); + + dataLen -= i; + offset += i; + } + return s; +} + +static void LoggerLogToConsole(CFDataRef data) +{ + // Decode and log a message to the console. Doing this from the worker thread + // allow us to serialize logging, which is a benefit that NSLog() doesn't have. + // Only drawback is that we have to decode our own message, but that is a minor hassle. + + struct timeval timestamp; + bzero(×tamp, sizeof(timestamp)); + int type = LOGMSG_TYPE_LOG, contentsType = PART_TYPE_STRING; + int imgWidth=0, imgHeight=0; + CFStringRef message = NULL; + CFStringRef thread = NULL; + + // decode message contents + uint8_t *p = (uint8_t *)CFDataGetBytePtr(data) + 4; + uint16_t partCount; + memcpy(&partCount, p, 2); + partCount = ntohs(partCount); + p += 2; + while (partCount--) + { + uint8_t partKey = *p++; + uint8_t partType = *p++; + uint32_t partSize; + if (partType == PART_TYPE_INT16) + partSize = 2; + else if (partType == PART_TYPE_INT32) + partSize = 4; + else if (partType == PART_TYPE_INT64) + partSize = 8; + else + { + memcpy(&partSize, p, 4); + p += 4; + partSize = ntohl(partSize); + } + CFTypeRef part = NULL; + uint32_t value32 = 0; + uint64_t value64 = 0; + if (partSize > 0) + { + if (partType == PART_TYPE_STRING) + { + // trim whitespace and newline at both ends of the string + uint8_t *q = p; + uint32_t l = partSize; + while (l && (*q == ' ' || *q == '\t' || *q == '\n' || *q == '\r')) + q++, l--; + uint8_t *r = q + l - 1; + while (l && (*r == ' ' || *r == '\t' || *r == '\n' || *r == '\r')) + r--, l--; + part = CFStringCreateWithBytesNoCopy(NULL, q, l, kCFStringEncodingUTF8, false, kCFAllocatorNull); + } + else if (partType == PART_TYPE_BINARY) + { + part = CFDataCreateWithBytesNoCopy(NULL, p, partSize, kCFAllocatorNull); + } + else if (partType == PART_TYPE_IMAGE) + { + // ignore image data, we can't log it to console + } + else if (partType == PART_TYPE_INT16) + { + value32 = ((uint32_t)p[0]) << 8 | (uint32_t)p[1]; + } + else if (partType == PART_TYPE_INT32) + { + memcpy(&value32, p, 4); + value32 = ntohl(value32); + } + else if (partType == PART_TYPE_INT64) + { + memcpy(&value64, p, 8); + value64 = CFSwapInt64BigToHost(value64); + } + p += partSize; + } + switch (partKey) + { + case PART_KEY_MESSAGE_TYPE: + type = (int)value32; + break; + case PART_KEY_TIMESTAMP_S: // timestamp with seconds-level resolution + timestamp.tv_sec = (partType == PART_TYPE_INT64) ? (__darwin_time_t)value64 : (__darwin_time_t)value32; + break; + case PART_KEY_TIMESTAMP_MS: // millisecond part of the timestamp (optional) + timestamp.tv_usec = ((partType == PART_TYPE_INT64) ? (__darwin_suseconds_t)value64 : (__darwin_suseconds_t)value32) * 1000; + break; + case PART_KEY_TIMESTAMP_US: // microsecond part of the timestamp (optional) + timestamp.tv_usec = (partType == PART_TYPE_INT64) ? (__darwin_suseconds_t)value64 : (__darwin_suseconds_t)value32; + break; + case PART_KEY_THREAD_ID: + if (thread == NULL) // useless test, we know what we're doing but clang analyzer doesn't... + { + if (partType == PART_TYPE_INT32) + thread = CFStringCreateWithFormat(NULL, NULL, CFSTR("thread 0x%08x"), value32); + else if (partType == PART_TYPE_INT64) + thread = CFStringCreateWithFormat(NULL, NULL, CFSTR("thread 0x%qx"), value64); + else if (partType == PART_TYPE_STRING && part != NULL) + thread = CFRetain(part); + } + break; + case PART_KEY_MESSAGE: + if (part != NULL) + { + if (partType == PART_TYPE_STRING) + message = CFRetain(part); + else if (partType == PART_TYPE_BINARY) + message = LoggerCreateStringRepresentationFromBinaryData(part); + } + contentsType = partType; + break; + case PART_KEY_IMAGE_WIDTH: + imgWidth = (partType == PART_TYPE_INT32 ? (int)value32 : (int)value64); + break; + case PART_KEY_IMAGE_HEIGHT: + imgHeight = (partType == PART_TYPE_INT32 ? (int)value32 : (int)value64); + break; + default: + break; + } + if (part != NULL) + CFRelease(part); + } + + // Prepare the final representation and log to console + CFMutableStringRef s = CFStringCreateMutable(NULL, 0); + + char buf[32]; + struct tm t; + gmtime_r(×tamp.tv_sec, &t); + strftime(buf, sizeof(buf)-1, "%T", &t); + CFStringRef ts = CFStringCreateWithBytesNoCopy(NULL, (const UInt8 *)buf, strlen(buf), kCFStringEncodingASCII, false, kCFAllocatorNull); + CFStringAppend(s, ts); + CFRelease(ts); + + if (contentsType == PART_TYPE_IMAGE) + message = CFStringCreateWithFormat(NULL, NULL, CFSTR(""), imgWidth, imgHeight); + + char threadNamePadding[20]; + threadNamePadding[0] = 0; + if (thread != NULL && CFStringGetLength(thread) < 16) + { + int n = 16 - (int)CFStringGetLength(thread); + memset(threadNamePadding, ' ', n); + threadNamePadding[n] = 0; + } + CFStringAppendFormat(s, NULL, CFSTR(".%04d %s%@ | %@"), + (int)(timestamp.tv_usec / 1000), + threadNamePadding, (thread == NULL) ? CFSTR("") : thread, + message ? message : CFSTR("")); + + if (thread != NULL) + CFRelease(thread); + if (message) + CFRelease(message); + + if (type == LOGMSG_TYPE_LOG || type == LOGMSG_TYPE_MARK) + CFShow(s); + + CFRelease(s); +} + +static void LoggerWriteMoreData(Logger *logger) +{ + if (!logger->connected) + { + if (logger->options & kLoggerOption_LogToConsole) + { + pthread_mutex_lock(&logger->logQueueMutex); + while (CFArrayGetCount(logger->logQueue)) + { + LoggerLogToConsole((CFDataRef)CFArrayGetValueAtIndex(logger->logQueue, 0)); + CFArrayRemoveValueAtIndex(logger->logQueue, 0); + } + pthread_mutex_unlock(&logger->logQueueMutex); + pthread_cond_broadcast(&logger->logQueueEmpty); + } + else if (logger->bufferWriteStream != NULL) + { + LoggerFlushQueueToBufferStream(logger, NO); + } + else if (!(logger->options & kLoggerOption_BufferLogsUntilConnection)) + { + /* No client connected + * User don't want to log to console + * User don't want to log to file + * and user don't want us to buffer it in memory + * So let's just sack the whole queue + */ + pthread_mutex_lock(&logger->logQueueMutex); + while (CFArrayGetCount(logger->logQueue)) + { + CFArrayRemoveValueAtIndex(logger->logQueue, 0); + } + pthread_mutex_unlock(&logger->logQueueMutex); + pthread_cond_broadcast(&logger->logQueueEmpty); + } + + return; + } + + if (CFWriteStreamCanAcceptBytes(logger->logStream)) + { + // prepare archived data with log queue contents, unblock the queue as soon as possible + CFMutableDataRef sendFirstItem = NULL; + if (logger->sendBufferUsed == 0) + { + // pull more data from the log queue + if (logger->bufferReadStream != NULL) + { + if (!CFReadStreamHasBytesAvailable(logger->bufferReadStream)) + { + CFReadStreamClose(logger->bufferReadStream); + CFRelease(logger->bufferReadStream); + logger->bufferReadStream = NULL; + LoggerEmptyBufferFile(logger); + } + else + { + logger->sendBufferUsed = CFReadStreamRead(logger->bufferReadStream, logger->sendBuffer, logger->sendBufferSize); + } + } + else + { + pthread_mutex_lock(&logger->logQueueMutex); + while (CFArrayGetCount(logger->logQueue)) + { + CFDataRef d = (CFDataRef)CFArrayGetValueAtIndex(logger->logQueue, 0); + CFIndex dsize = CFDataGetLength(d); + if ((logger->sendBufferUsed + dsize) > logger->sendBufferSize) + break; + memcpy(logger->sendBuffer + logger->sendBufferUsed, CFDataGetBytePtr(d), dsize); + logger->sendBufferUsed += dsize; + CFArrayRemoveValueAtIndex(logger->logQueue, 0); + logger->incompleteSendOfFirstItem = NO; + } + pthread_mutex_unlock(&logger->logQueueMutex); + } + if (logger->sendBufferUsed == 0) + { + // are we done yet? + pthread_mutex_lock(&logger->logQueueMutex); + if (CFArrayGetCount(logger->logQueue) == 0) + { + pthread_mutex_unlock(&logger->logQueueMutex); + pthread_cond_broadcast(&logger->logQueueEmpty); + return; + } + + // first item is too big to fit in a single packet, send it separately + sendFirstItem = (CFMutableDataRef)CFArrayGetValueAtIndex(logger->logQueue, 0); + logger->incompleteSendOfFirstItem = YES; + pthread_mutex_unlock(&logger->logQueueMutex); + logger->sendBufferOffset = 0; + } + } + + // send data over the socket. We try hard to be failsafe and if we have to send + // data in fragments, we make sure that in case a disconnect occurs we restart + // sending the whole message(s) + if (logger->sendBufferUsed != 0) + { + CFIndex written = CFWriteStreamWrite(logger->logStream, + logger->sendBuffer + logger->sendBufferOffset, + logger->sendBufferUsed - logger->sendBufferOffset); + if (written < 0) + { + // We'll get an event if the stream closes on error. Don't discard the data, + // it will be sent as soon as a connection is re-acquired. + return; + } + if ((logger->sendBufferOffset + written) < logger->sendBufferUsed) + { + // everything couldn't be sent at once + logger->sendBufferOffset += written; + } + else + { + logger->sendBufferUsed = 0; + logger->sendBufferOffset = 0; + } + } + else if (sendFirstItem) + { + CFIndex length = CFDataGetLength(sendFirstItem) - logger->sendBufferOffset; + CFIndex written = CFWriteStreamWrite(logger->logStream, + CFDataGetBytePtr(sendFirstItem) + logger->sendBufferOffset, + length); + if (written < 0) + { + // We'll get an event if the stream closes on error + return; + } + if (written < length) + { + // The output pipe is full, and the first item has not been sent completely + // We need to reduce the remaining data on the first item so it can be taken + // care of at the next iteration. We take advantage of the fact that each item + // in the queue is actually a mutable data block + // @@@ NOTE: IF WE GET DISCONNECTED WHILE DOING THIS, THINGS WILL GO WRONG + // NEED TO UPDATE THIS LOGIC + CFDataReplaceBytes((CFMutableDataRef)sendFirstItem, CFRangeMake(0, written), NULL, 0); + return; + } + + // we are done sending the first item in the queue, remove it now + pthread_mutex_lock(&logger->logQueueMutex); + CFArrayRemoveValueAtIndex(logger->logQueue, 0); + logger->incompleteSendOfFirstItem = NO; + pthread_mutex_unlock(&logger->logQueueMutex); + logger->sendBufferOffset = 0; + } + + pthread_mutex_lock(&logger->logQueueMutex); + int remainingMsgs = CFArrayGetCount(logger->logQueue); + pthread_mutex_unlock(&logger->logQueueMutex); + if (remainingMsgs == 0) + pthread_cond_broadcast(&logger->logQueueEmpty); + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark File buffering functions +// ----------------------------------------------------------------------------- +static void LoggerCreateBufferWriteStream(Logger *logger) +{ + LOGGERDBG(CFSTR("LoggerCreateBufferWriteStream to file %@"), logger->bufferFile); + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, logger->bufferFile, kCFURLPOSIXPathStyle, false); + if (fileURL != NULL) + { + // Create write stream to file + logger->bufferWriteStream = CFWriteStreamCreateWithFile(NULL, fileURL); + CFRelease(fileURL); + if (logger->bufferWriteStream != NULL) + { + // Set flag to append new data to buffer file + CFWriteStreamSetProperty(logger->bufferWriteStream, kCFStreamPropertyAppendToFile, kCFBooleanTrue); + + // Open the buffer stream for writing + if (!CFWriteStreamOpen(logger->bufferWriteStream)) + { + CFRelease(logger->bufferWriteStream); + logger->bufferWriteStream = NULL; + } + else + { + // Write client info and flush the queue contents to buffer file + LoggerPushClientInfoToFrontOfQueue(logger); + LoggerFlushQueueToBufferStream(logger, YES); + } + } + } + if (logger->bufferWriteStream == NULL) + { + CFShow(CFSTR("NSLogger Warning: failed opening buffer file for writing:")); + CFShow(logger->bufferFile); + } +} + +static void LoggerCreateBufferReadStream(Logger *logger) +{ + LOGGERDBG(CFSTR("LoggerCreateBufferReadStream from file %@"), logger->bufferFile); + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, logger->bufferFile, kCFURLPOSIXPathStyle, false); + if (fileURL != NULL) + { + // Create read stream from file + logger->bufferReadStream = CFReadStreamCreateWithFile(NULL, fileURL); + CFRelease(fileURL); + if (logger->bufferReadStream != NULL) + { + if (!CFReadStreamOpen(logger->bufferReadStream)) + { + CFRelease(logger->bufferReadStream); + logger->bufferReadStream = NULL; + } + } + } +} + +static void LoggerEmptyBufferFile(Logger *logger) +{ + // completely remove the buffer file from storage + LOGGERDBG(CFSTR("LoggerEmptyBufferFile %@"), logger->bufferFile); + if (logger->bufferFile != NULL) + { + CFIndex bufferSize = 1 + CFStringGetLength(logger->bufferFile) * 3; + char *buffer = (char *)malloc(bufferSize); + if (buffer != NULL) + { + if (CFStringGetFileSystemRepresentation(logger->bufferFile, buffer, bufferSize)) + { + // remove file + unlink(buffer); + } + free(buffer); + } + } +} + +static void LoggerFileBufferingOptionsChanged(Logger *logger) +{ + // File buffering options changed: + // - close the current buffer file stream, if any + // - create a new one, if needed + LOGGERDBG(CFSTR("LoggerFileBufferingOptionsChanged bufferFile=%@"), logger->bufferFile); + if (logger->bufferWriteStream != NULL) + { + CFWriteStreamClose(logger->bufferWriteStream); + CFRelease(logger->bufferWriteStream); + logger->bufferWriteStream = NULL; + } + if (logger->bufferFile != NULL) + LoggerCreateBufferWriteStream(logger); +} + +static void LoggerFlushQueueToBufferStream(Logger *logger, BOOL firstEntryIsClientInfo) +{ + LOGGERDBG(CFSTR("LoggerFlushQueueToBufferStream")); + pthread_mutex_lock(&logger->logQueueMutex); + if (logger->incompleteSendOfFirstItem) + { + // drop anything being sent + logger->sendBufferUsed = 0; + logger->sendBufferOffset = 0; + } + logger->incompleteSendOfFirstItem = NO; + + // Write outstanding messages to the buffer file (streams don't detect disconnection + // until the next write, where we could lose one or more messages) + if (!firstEntryIsClientInfo && logger->sendBufferUsed) + CFWriteStreamWrite(logger->bufferWriteStream, logger->sendBuffer + logger->sendBufferOffset, logger->sendBufferUsed - logger->sendBufferOffset); + + int n = 0; + while (CFArrayGetCount(logger->logQueue)) + { + CFDataRef data = CFArrayGetValueAtIndex(logger->logQueue, 0); + CFIndex dataLength = CFDataGetLength(data); + CFIndex written = CFWriteStreamWrite(logger->bufferWriteStream, CFDataGetBytePtr(data), dataLength); + if (written != dataLength) + { + // couldn't write all data to file, maybe storage run out of space? + CFShow(CFSTR("NSLogger Error: failed flushing the whole queue to buffer file:")); + CFShow(logger->bufferFile); + break; + } + CFArrayRemoveValueAtIndex(logger->logQueue, 0); + if (n == 0 && firstEntryIsClientInfo && logger->sendBufferUsed) + { + // try hard: write any outstanding messages to the buffer file, after the client info + CFWriteStreamWrite(logger->bufferWriteStream, logger->sendBuffer + logger->sendBufferOffset, logger->sendBufferUsed - logger->sendBufferOffset); + } + n++; + } + logger->sendBufferUsed = 0; + logger->sendBufferOffset = 0; + pthread_mutex_unlock(&logger->logQueueMutex); +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Bonjour browsing +// ----------------------------------------------------------------------------- +static void LoggerStartBonjourBrowsing(Logger *logger) +{ + LOGGERDBG(CFSTR("LoggerStartBonjourBrowsing")); + + if (logger->options & kLoggerOption_BrowseOnlyLocalDomain) + { + LOGGERDBG(CFSTR("Logger configured to search only the local domain, searching for services on: local.")); + if (!LoggerBrowseBonjourForServices(logger, CFSTR("local.")) && logger->host == NULL) + { + LOGGERDBG(CFSTR("*** Logger: could not browse for services in domain local., no remote host configured: reverting to console logging. ***")); + logger->options |= kLoggerOption_LogToConsole; + } + } + else + { + LOGGERDBG(CFSTR("Logger configured to search all domains, browsing for domains first")); + CFNetServiceClientContext context = {0, (void *)logger, NULL, NULL, NULL}; + CFRunLoopRef runLoop = CFRunLoopGetCurrent(); + logger->bonjourDomainBrowser = CFNetServiceBrowserCreate(NULL, &LoggerServiceBrowserCallBack, &context); + CFNetServiceBrowserScheduleWithRunLoop(logger->bonjourDomainBrowser, runLoop, kCFRunLoopCommonModes); + if (!CFNetServiceBrowserSearchForDomains(logger->bonjourDomainBrowser, false, NULL)) + { + // An error occurred, revert to console logging if there is no remote host + LOGGERDBG(CFSTR("*** Logger: could not browse for domains, reverting to console logging. ***")); + CFNetServiceBrowserUnscheduleFromRunLoop(logger->bonjourDomainBrowser, runLoop, kCFRunLoopCommonModes); + CFRelease(logger->bonjourDomainBrowser); + logger->bonjourDomainBrowser = NULL; + if (logger->host == NULL) + logger->options |= kLoggerOption_LogToConsole; + } + } +} + +static void LoggerStopBonjourBrowsing(Logger *logger) +{ + LOGGERDBG(CFSTR("LoggerStopBonjourBrowsing")); + + // stop browsing for domains + if (logger->bonjourDomainBrowser != NULL) + { + CFNetServiceBrowserStopSearch(logger->bonjourDomainBrowser, NULL); + CFNetServiceBrowserUnscheduleFromRunLoop(logger->bonjourDomainBrowser, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + CFNetServiceBrowserInvalidate(logger->bonjourDomainBrowser); + CFRelease(logger->bonjourDomainBrowser); + logger->bonjourDomainBrowser = NULL; + } + + // stop browsing for services + CFIndex idx; + for (idx = 0; idx < CFArrayGetCount(logger->bonjourServiceBrowsers); idx++) + { + CFNetServiceBrowserRef browser = (CFNetServiceBrowserRef)CFArrayGetValueAtIndex(logger->bonjourServiceBrowsers, idx); + CFNetServiceBrowserStopSearch(browser, NULL); + CFNetServiceBrowserUnscheduleFromRunLoop(browser, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + CFNetServiceBrowserInvalidate(browser); + } + CFArrayRemoveAllValues(logger->bonjourServiceBrowsers); + + // Forget all services + CFArrayRemoveAllValues(logger->bonjourServices); +} + +static BOOL LoggerBrowseBonjourForServices(Logger *logger, CFStringRef domainName) +{ + BOOL result = NO; + CFNetServiceClientContext context = {0, (void *)logger, NULL, NULL, NULL}; + CFRunLoopRef runLoop = CFRunLoopGetCurrent(); + + CFNetServiceBrowserRef browser = CFNetServiceBrowserCreate(NULL, (CFNetServiceBrowserClientCallBack)&LoggerServiceBrowserCallBack, &context); + CFNetServiceBrowserScheduleWithRunLoop(browser, runLoop, kCFRunLoopCommonModes); + CFStreamError error; + + // try to use the user-specfied service type if any, fallback on our + // default service type + CFStringRef serviceType = logger->bonjourServiceType; + if (serviceType == NULL) + { + if (logger->options & kLoggerOption_UseSSL) + serviceType = LOGGER_SERVICE_TYPE_SSL; + else + serviceType = LOGGER_SERVICE_TYPE; + } + if (!CFNetServiceBrowserSearchForServices(browser, domainName, serviceType, &error)) + { + LOGGERDBG(CFSTR("Logger can't start search on domain: %@ (error %d)"), domainName, error.error); + CFNetServiceBrowserUnscheduleFromRunLoop(browser, runLoop, kCFRunLoopCommonModes); + CFNetServiceBrowserInvalidate(browser); + } + else + { + LOGGERDBG(CFSTR("Logger started search for services of type %@ in domain %@"), serviceType, domainName); + CFArrayAppendValue(logger->bonjourServiceBrowsers, browser); + result = YES; + } + CFRelease(browser); + return result; +} + +static void LoggerServiceBrowserCallBack (CFNetServiceBrowserRef browser, + CFOptionFlags flags, + CFTypeRef domainOrService, + CFStreamError* error, + void* info) +{ + LOGGERDBG(CFSTR("LoggerServiceBrowserCallback browser=%@ flags=0x%04x domainOrService=%@ error=%d"), browser, flags, domainOrService, error==NULL ? 0 : error->error); + + Logger *logger = (Logger *)info; + assert(logger != NULL); + + if (flags & kCFNetServiceFlagRemove) + { + if (!(flags & kCFNetServiceFlagIsDomain)) + { + CFNetServiceRef service = (CFNetServiceRef)domainOrService; + CFIndex idx; + for (idx = 0; idx < CFArrayGetCount(logger->bonjourServices); idx++) + { + if (CFArrayGetValueAtIndex(logger->bonjourServices, idx) == service) + { + CFNetServiceUnscheduleFromRunLoop(service, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + CFNetServiceClientContext context = {0, NULL, NULL, NULL, NULL}; + CFNetServiceSetClient(service, NULL, &context); + CFNetServiceCancel(service); + CFArrayRemoveValueAtIndex(logger->bonjourServices, idx); + break; + } + } + } + } + else + { + if (flags & kCFNetServiceFlagIsDomain) + { + // start searching for services in this domain + LoggerBrowseBonjourForServices(logger, (CFStringRef)domainOrService); + } + else + { + // a service has been found + LOGGERDBG(CFSTR("Logger found service: %@"), domainOrService); + CFNetServiceRef service = (CFNetServiceRef)domainOrService; + if (service != NULL) + { + // if the user has specified that Logger shall only connect to the specified + // Bonjour service name, check it now. This makes things easier in a teamwork + // environment where multiple instances of NSLogger viewer may run on the + // same network + if (logger->bonjourServiceName != NULL) + { + LOGGERDBG(CFSTR("-> looking for services of name %@"), logger->bonjourServiceName); + CFStringRef name = CFNetServiceGetName(service); + if (name == NULL || kCFCompareEqualTo != CFStringCompare(name, logger->bonjourServiceName, kCFCompareCaseInsensitive | kCFCompareDiacriticInsensitive)) + { + LOGGERDBG(CFSTR("-> service name %@ does not match requested service name, ignoring."), name, logger->bonjourServiceName); + return; + } + } + CFArrayAppendValue(logger->bonjourServices, service); + LoggerTryConnect(logger); + } + } + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Reachability +// ----------------------------------------------------------------------------- +static void LoggerStartReachabilityChecking(Logger *logger) +{ + if (logger->host != NULL && logger->reachability == NULL) + { + LOGGERDBG(CFSTR("Starting SCNetworkReachability to wait for host %@ to be reachable"), logger->host); + + CFIndex length = CFStringGetLength(logger->host) * 3; + char *buffer = (char *)malloc(length + 1); + CFStringGetBytes(logger->host, CFRangeMake(0, CFStringGetLength(logger->host)), kCFStringEncodingUTF8, '?', false, (UInt8 *)buffer, length, &length); + buffer[length] = 0; + + logger->reachability = SCNetworkReachabilityCreateWithName(NULL, buffer); + + SCNetworkReachabilityContext context = {0, logger, NULL, NULL, NULL}; + SCNetworkReachabilitySetCallback(logger->reachability, &LoggerReachabilityCallBack, &context); + SCNetworkReachabilityScheduleWithRunLoop(logger->reachability, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + + free(buffer); + + // Also start a timer that will try to reconnect every N seconds + if (logger->checkHostTimer == NULL) + { + CFRunLoopTimerContext timerCtx = { + .version = 0, + .info = logger, + .retain = NULL, + .release = NULL, + .copyDescription = NULL + }; + logger->checkHostTimer = CFRunLoopTimerCreate(NULL, + CFAbsoluteTimeGetCurrent() + 5, + 5, // reconnect interval + 0, + 0, + &LoggerTimedReconnectCallback, + &timerCtx); + if (logger->checkHostTimer != NULL) + { + LOGGERDBG(CFSTR("Starting the TimedReconnect timer to regularly retry the connection")); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), logger->checkHostTimer, kCFRunLoopCommonModes); + } + } + } +} + +static void LoggerStopReachabilityChecking(Logger *logger) +{ + if (logger->reachability != NULL) + { + LOGGERDBG(CFSTR("Stopping SCNetworkReachability")); + SCNetworkReachabilityUnscheduleFromRunLoop(logger->reachability, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + CFRelease(logger->reachability); + logger->reachability = NULL; + } + if (logger->checkHostTimer != NULL) + { + CFRunLoopTimerInvalidate(logger->checkHostTimer); + CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), logger->checkHostTimer, kCFRunLoopCommonModes); + CFRelease(logger->checkHostTimer); + logger->checkHostTimer = NULL; + } +} + +static void LoggerReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) +{ + Logger *logger = (Logger *)info; + assert(logger != NULL); + LOGGERDBG(CFSTR("LoggerReachabilityCallBack called with flags=0x%08lx"), flags); + if (flags & kSCNetworkReachabilityFlagsReachable) + { + // target host became reachable. If we have not other open connection, + // try direct connection to the host + if (logger->logStream == NULL && logger->host != NULL) + { + LOGGERDBG(CFSTR("-> host %@ became reachable, trying to connect."), logger->host); + LoggerTryConnect(logger); + } + } +} + +static void LoggerTimedReconnectCallback(CFRunLoopTimerRef timer, void *info) +{ + Logger *logger = (Logger *)info; + assert(logger != NULL); + LOGGERDBG(CFSTR("LoggerTimedReconnectCallback")); + if (logger->logStream == NULL && logger->host != NULL) + { + LOGGERDBG(CFSTR("-> trying to reconnect to host %@"), logger->host); + LoggerTryConnect(logger); + } + else + { + LOGGERDBG(CFSTR("-> timer not needed anymore, removing it form runloop")); + CFRunLoopTimerInvalidate(timer); + CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), logger->checkHostTimer, kCFRunLoopCommonModes); + CFRelease(timer); + logger->checkHostTimer = NULL; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Stream management +// ----------------------------------------------------------------------------- +static BOOL LoggerConfigureAndOpenStream(Logger *logger) +{ + // configure and open stream + LOGGERDBG(CFSTR("LoggerConfigureAndOpenStream configuring and opening log stream")); + CFStreamClientContext context = {0, (void *)logger, NULL, NULL, NULL}; + if (CFWriteStreamSetClient(logger->logStream, + (kCFStreamEventOpenCompleted | + kCFStreamEventCanAcceptBytes | + kCFStreamEventErrorOccurred | + kCFStreamEventEndEncountered), + &LoggerWriteStreamCallback, + &context)) + { + if (logger->options & kLoggerOption_UseSSL) + { + // Configure stream to require a SSL connection + LOGGERDBG(CFSTR("-> configuring SSL")); + const void *SSLKeys[] = { + kCFStreamSSLLevel, + kCFStreamSSLValidatesCertificateChain, + kCFStreamSSLIsServer, + kCFStreamSSLPeerName + }; + const void *SSLValues[] = { + kCFStreamSocketSecurityLevelNegotiatedSSL, + kCFBooleanFalse, // no certificate chain validation (we use a self-signed certificate) + kCFBooleanFalse, // not a server + kCFNull + }; + +#if TARGET_OS_IPHONE + // workaround for TLS in iOS 5 as per TN2287 + // see http://developer.apple.com/library/ios/#technotes/tn2287/_index.html#//apple_ref/doc/uid/DTS40011309 + // if we are running iOS 5 or later, use a special mode that allows the stack to downgrade gracefully + #if ALLOW_COCOA_USE + AUTORELEASE_POOL_BEGIN + NSString *versionString = [[UIDevice currentDevice] systemVersion]; + if ([versionString compare:@"5.0" options:NSNumericSearch] != NSOrderedAscending) + SSLValues[0] = CFSTR("kCFStreamSocketSecurityLevelTLSv1_0SSLv3"); + AUTORELEASE_POOL_END + #else + // we can't find out, assume we _may_ be on iOS 5 but can't be certain + // go for SSLv3 which works without the TLS 1.2 / 1.1 / 1.0 downgrade issue + SSLValues[0] = kCFStreamSocketSecurityLevelSSLv3; + #endif +#endif + + CFDictionaryRef SSLDict = CFDictionaryCreate(NULL, SSLKeys, SSLValues, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFWriteStreamSetProperty(logger->logStream, kCFStreamPropertySSLSettings, SSLDict); + CFRelease(SSLDict); + } + + CFWriteStreamScheduleWithRunLoop(logger->logStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + + if (CFWriteStreamOpen(logger->logStream)) + { + LOGGERDBG(CFSTR("-> stream open attempt, waiting for open completion")); + return YES; + } + + LOGGERDBG(CFSTR("-> stream open failed.")); + + CFWriteStreamSetClient(logger->logStream, kCFStreamEventNone, NULL, NULL); + if (CFWriteStreamGetStatus(logger->logStream) == kCFStreamStatusOpen) + CFWriteStreamClose(logger->logStream); + CFWriteStreamUnscheduleFromRunLoop(logger->logStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + } + else + { + LOGGERDBG(CFSTR("-> stream set client failed.")); + } + CFRelease(logger->logStream); + logger->logStream = NULL; + return NO; +} + +static void LoggerTryConnect(Logger *logger) +{ + // Try connecting to the next address in the sConnectAttempts array + LOGGERDBG(CFSTR("LoggerTryConnect, %d services registered, current stream=%@"), CFArrayGetCount(logger->bonjourServices), logger->logStream); + + // If we already have a connection established or being attempted, stop here + if (logger->logStream != NULL) + { + LOGGERDBG(CFSTR("-> another connection is opened or in progress, giving up for now")); + return; + } + + // If there are discovered Bonjour services, try them now + while (CFArrayGetCount(logger->bonjourServices)) + { + CFNetServiceRef service = (CFNetServiceRef)CFArrayGetValueAtIndex(logger->bonjourServices, 0); + LOGGERDBG(CFSTR("-> Trying to open write stream to service %@"), service); + CFStreamCreatePairWithSocketToNetService(NULL, service, NULL, &logger->logStream); + CFArrayRemoveValueAtIndex(logger->bonjourServices, 0); + if (logger->logStream == NULL) + { + // create pair failed + LOGGERDBG(CFSTR("-> failed.")); + } + else if (LoggerConfigureAndOpenStream(logger)) + { + // open is now in progress + return; + } + } + + // If there is a host to directly connect to, try it now (this will happen before + // Bonjour kicks in, Bonjour being handled as a fallback solution if direct Host + // fails) + if (logger->host != NULL) + { + LOGGERDBG(CFSTR("-> Trying to open direct connection to host %@ port %u"), logger->host, logger->port); + CFStreamCreatePairWithSocketToHost(NULL, logger->host, logger->port, NULL, &logger->logStream); + if (logger->logStream == NULL) + { + // Create stream failed + LOGGERDBG(CFSTR("-> failed.")); + if (logger->logStream != NULL) + { + CFRelease(logger->logStream); + logger->logStream = NULL; + } + } + else if (LoggerConfigureAndOpenStream(logger)) + { + // open is now in progress + return; + } + + // Could not connect to host: start Reachability so we know when target host becomes reachable + // and can try to connect again + LoggerStartReachabilityChecking(logger); + } + + // Finally, if Bonjour is enabled and not started yet, start it now. + if ((logger->options & kLoggerOption_BrowseBonjour) && + (logger->bonjourDomainBrowser == NULL || CFArrayGetCount(logger->bonjourServiceBrowsers) == 0)) + { + LoggerStartBonjourBrowsing(logger); + } +} + +static void LoggerWriteStreamCallback(CFWriteStreamRef ws, CFStreamEventType event, void* info) +{ + Logger *logger = (Logger *)info; + assert(ws == logger->logStream); + switch (event) + { + case kCFStreamEventOpenCompleted: + // A stream open was complete. Cancel all bonjour browsing, + // service resolution and connection attempts, and try to + // write existing buffer contents + LOGGERDBG(CFSTR("Logger CONNECTED")); + logger->connected = YES; + LoggerStopBonjourBrowsing(logger); + LoggerStopReachabilityChecking(logger); + if (logger->bufferWriteStream != NULL) + { + // now that a connection is acquired, we can stop logging to a file + CFWriteStreamClose(logger->bufferWriteStream); + CFRelease(logger->bufferWriteStream); + logger->bufferWriteStream = NULL; + } + if (logger->bufferFile != NULL) + { + // if a buffer file was defined, try to read its contents + LoggerCreateBufferReadStream(logger); + } + LoggerPushClientInfoToFrontOfQueue(logger); + LoggerWriteMoreData(logger); + break; + + case kCFStreamEventCanAcceptBytes: + LoggerWriteMoreData(logger); + break; + + case kCFStreamEventErrorOccurred: { + CFErrorRef error = CFWriteStreamCopyError(ws); + LOGGERDBG(CFSTR("Logger stream error: %@"), error); + CFRelease(error); + // Fall-thru + } + + case kCFStreamEventEndEncountered: + if (logger->connected) + { + LOGGERDBG(CFSTR("Logger DISCONNECTED")); + logger->connected = NO; + } + CFWriteStreamSetClient(logger->logStream, 0, NULL, NULL); + CFWriteStreamUnscheduleFromRunLoop(logger->logStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + CFWriteStreamClose(logger->logStream); + + CFRelease(logger->logStream); + logger->logStream = NULL; + + if (logger->bufferReadStream != NULL) + { + // In the case the connection drops before we have flushed the + // whole contents of the file, we choose to keep it integrally + // and retransmit it when reconnecting to the viewer. The reason + // of this choice is that we may have transmitted only part of + // a message, and this may cause errors on the desktop side. + CFReadStreamClose(logger->bufferReadStream); + CFRelease(logger->bufferReadStream); + logger->bufferReadStream = NULL; + } + if (logger->bufferFile != NULL && logger->bufferWriteStream == NULL) + LoggerCreateBufferWriteStream(logger); + + if (logger->host != NULL && !(logger->options & kLoggerOption_BrowseBonjour)) + LoggerStartReachabilityChecking(logger); + else + LoggerTryConnect(logger); + break; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Internal encoding functions +// ----------------------------------------------------------------------------- +static void LoggerMessageAddTimestamp(CFMutableDataRef encoder) +{ + struct timeval t; + if (gettimeofday(&t, NULL) == 0) + { +#if __LP64__ + LoggerMessageAddInt64(encoder, t.tv_sec, PART_KEY_TIMESTAMP_S); + LoggerMessageAddInt64(encoder, t.tv_usec, PART_KEY_TIMESTAMP_US); +#else + LoggerMessageAddInt32(encoder, t.tv_sec, PART_KEY_TIMESTAMP_S); + LoggerMessageAddInt32(encoder, t.tv_usec, PART_KEY_TIMESTAMP_US); +#endif + } + else + { + time_t ts = time(NULL); +#if __LP64__ + LoggerMessageAddInt64(encoder, ts, PART_KEY_TIMESTAMP_S); +#else + LoggerMessageAddInt32(encoder, ts, PART_KEY_TIMESTAMP_S); +#endif + } +} + +static void LoggerMessageAddTimestampAndThreadID(CFMutableDataRef encoder) +{ + LoggerMessageAddTimestamp(encoder); + + BOOL hasThreadName = NO; +#if ALLOW_COCOA_USE + // Getting the thread number is tedious, to say the least. Since there is + // no direct way to get it, we have to do it sideways. Note that it can be dangerous + // to use any Cocoa call when in a multithreaded application that only uses non-Cocoa threads + // and for which Cocoa's multithreading has not been activated. We test for this case. + if ([NSThread isMultiThreaded] || [NSThread isMainThread]) + { + AUTORELEASE_POOL_BEGIN + NSThread *thread = [NSThread currentThread]; + NSString *name = [thread name]; + if (![name length]) + { + if ([thread isMainThread]) + name = @"Main thread"; + else + { + name = [thread description]; + NSRange range = [name rangeOfString:@"num = "]; + if (range.location != NSNotFound) + { + name = [NSString stringWithFormat:@"Thread %@", + [name substringWithRange:NSMakeRange(range.location + range.length, + [name length] - range.location - range.length - 1)]]; + } + } + } + if (name != nil) + { + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)name, PART_KEY_THREAD_ID); + hasThreadName = YES; + } + AUTORELEASE_POOL_END + } +#endif + if (!hasThreadName) + { +#if __LP64__ + LoggerMessageAddInt64(encoder, (int64_t)pthread_self(), PART_KEY_THREAD_ID); +#else + LoggerMessageAddInt32(encoder, (int32_t)pthread_self(), PART_KEY_THREAD_ID); +#endif + } +} + +static void LoggerMessageUpdateDataHeader(CFMutableDataRef data) +{ + // update the data header with updated part count and size + UInt8 *p = CFDataGetMutableBytePtr(data); + uint32_t size = htonl(CFDataGetLength(data) - 4); + uint16_t partCount = htons(ntohs(*(uint16_t *)(p + 4)) + 1); + memcpy(p, &size, 4); + memcpy(p+4, &partCount, 2); +} + +static CFMutableDataRef LoggerMessageCreate() +{ + CFMutableDataRef data = CFDataCreateMutable(NULL, 0); + CFDataIncreaseLength(data, 6); + UInt8 *p = CFDataGetMutableBytePtr(data); + p[3] = 2; // size 0x00000002 in big endian + return data; +} + +static void LoggerMessageAddInt32(CFMutableDataRef data, int32_t anInt, int key) +{ + uint32_t partData = htonl(anInt); + uint8_t keyAndType[2] = {(uint8_t)key, PART_TYPE_INT32}; + CFDataAppendBytes(data, (const UInt8 *)&keyAndType, 2); + CFDataAppendBytes(data, (const UInt8 *)&partData, 4); + LoggerMessageUpdateDataHeader(data); +} + +#if __LP64__ +static void LoggerMessageAddInt64(CFMutableDataRef data, int64_t anInt, int key) +{ + uint32_t partData[2] = {htonl((uint32_t)(anInt >> 32)), htonl((uint32_t)anInt)}; + uint8_t keyAndType[2] = {(uint8_t)key, PART_TYPE_INT64}; + CFDataAppendBytes(data, (const UInt8 *)&keyAndType, 2); + CFDataAppendBytes(data, (const UInt8 *)&partData, 8); + LoggerMessageUpdateDataHeader(data); +} +#endif + +static void LoggerMessageAddCString(CFMutableDataRef data, const char *aString, int key) +{ + if (aString == NULL || *aString == 0) + return; + + // convert to UTF-8 + int len = (int)strlen(aString); + uint8_t *buf = malloc(2 * len); + if (buf != NULL) + { + int i, n = 0; + for (i = 0; i < len; i++) + { + uint8_t c = (uint8_t)(*aString++); + if (c < 0x80) + buf[n++] = c; + else { + buf[n++] = 0xC0 | (c >> 6); + buf[n++] = (c & 0x6F) | 0x80; + } + } + if (n) + { + uint32_t partSize = htonl(n); + uint8_t keyAndType[2] = {(uint8_t)key, PART_TYPE_STRING}; + CFDataAppendBytes(data, (const UInt8 *)&keyAndType, 2); + CFDataAppendBytes(data, (const UInt8 *)&partSize, 4); + CFDataAppendBytes(data, buf, n); + LoggerMessageUpdateDataHeader(data); + } + free(buf); + } +} + +static void LoggerMessageAddString(CFMutableDataRef data, CFStringRef aString, int key) +{ + if (aString == NULL) + aString = CFSTR(""); + + // All strings are UTF-8 encoded + uint8_t keyAndType[2] = {(uint8_t)key, PART_TYPE_STRING}; + uint32_t partSize = 0; + uint8_t *bytes = NULL; + + CFIndex stringLength = CFStringGetLength(aString); + CFIndex bytesLength = stringLength * 4; + if (stringLength) + { + bytes = (uint8_t *)malloc(stringLength * 4 + 4); + CFStringGetBytes(aString, CFRangeMake(0, stringLength), kCFStringEncodingUTF8, '?', false, bytes, bytesLength, &bytesLength); + partSize = htonl(bytesLength); + } + + CFDataAppendBytes(data, (const UInt8 *)&keyAndType, 2); + CFDataAppendBytes(data, (const UInt8 *)&partSize, 4); + if (partSize) + CFDataAppendBytes(data, bytes, bytesLength); + + if (bytes != NULL) + free(bytes); + LoggerMessageUpdateDataHeader(data); +} + +static void LoggerMessageAddData(CFMutableDataRef data, CFDataRef theData, int key, int partType) +{ + if ( theData != nil ){ + uint8_t keyAndType[2] = {(uint8_t)key, (uint8_t)partType}; + CFIndex dataLength = CFDataGetLength(theData); + uint32_t partSize = htonl(dataLength); + CFDataAppendBytes(data, (const UInt8 *)&keyAndType, 2); + CFDataAppendBytes(data, (const UInt8 *)&partSize, 4); + if (partSize) + CFDataAppendBytes(data, CFDataGetBytePtr(theData), dataLength); + LoggerMessageUpdateDataHeader(data); + } +} + +static uint32_t LoggerMessageGetSeq(CFDataRef message) +{ + // Extract the sequence number from a message. When pushing messages to the queue, + // we use this to guarantee the logging order according to the seq# + uint32_t seq = 0; + uint8_t *p = (uint8_t *)CFDataGetBytePtr(message) + 4; + uint16_t partCount; + memcpy(&partCount, p, 2); + partCount = ntohs(partCount); + p += 2; + while (partCount--) + { + uint8_t partKey = *p++; + uint8_t partType = *p++; + uint32_t partSize; + if (partType == PART_TYPE_INT16) + partSize = 2; + else if (partType == PART_TYPE_INT32) + partSize = 4; + else if (partType == PART_TYPE_INT64) + partSize = 8; + else + { + memcpy(&partSize, p, 4); + p += 4; + partSize = ntohl(partSize); + } + if (partKey == PART_KEY_MESSAGE_SEQ) + { + memcpy(&seq, p, sizeof(uint32_t)); + seq = ntohl(seq); + break; + } + p += partSize; + } + return seq; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Private logging functions +// ----------------------------------------------------------------------------- +static void LoggerPushClientInfoToFrontOfQueue(Logger *logger) +{ + // Extract client information from the main bundle, as well as platform info, + // and assmble it to a message that will be put in front of the queue + // Helps desktop viewer display who's talking to it + // Note that we must be called from the logger work thread, as we don't + // run through the message port to transmit this message to the queue + CFBundleRef bundle = CFBundleGetMainBundle(); + if (bundle == NULL) + return; + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestamp(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_CLIENTINFO, PART_KEY_MESSAGE_TYPE); + + CFStringRef version = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey); + if (version != NULL && CFGetTypeID(version) == CFStringGetTypeID()) + LoggerMessageAddString(encoder, version, PART_KEY_CLIENT_VERSION); + CFStringRef name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleNameKey); + if (name != NULL) + LoggerMessageAddString(encoder, name, PART_KEY_CLIENT_NAME); + +#if TARGET_OS_IPHONE && ALLOW_COCOA_USE + if ([NSThread isMultiThreaded] || [NSThread isMainThread]) + { + AUTORELEASE_POOL_BEGIN + UIDevice *device = [UIDevice currentDevice]; + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)device.uniqueIdentifier, PART_KEY_UNIQUEID); + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)device.systemVersion, PART_KEY_OS_VERSION); + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)device.systemName, PART_KEY_OS_NAME); + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)device.model, PART_KEY_CLIENT_MODEL); + AUTORELEASE_POOL_END + } +#elif TARGET_OS_MAC + SInt32 versionMajor, versionMinor, versionFix; + Gestalt(gestaltSystemVersionMajor, &versionMajor); + Gestalt(gestaltSystemVersionMinor, &versionMinor); + Gestalt(gestaltSystemVersionBugFix, &versionFix); + CFStringRef osVersion = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d.%d.%d"), versionMajor, versionMinor, versionFix); + LoggerMessageAddString(encoder, osVersion, PART_KEY_OS_VERSION); + CFRelease(osVersion); + LoggerMessageAddString(encoder, CFSTR("Mac OS X"), PART_KEY_OS_NAME); + + char buf[64]; + size_t len; + int ncpu = 0; + bzero(buf, sizeof(buf)); + len = sizeof(buf)-1; + sysctlbyname("hw.model", buf, &len, NULL, 0); + len = sizeof(ncpu); + sysctlbyname("hw.ncpu", &ncpu, &len, NULL, 0); + sprintf(buf+strlen(buf), " - %d * ", ncpu); + len = sizeof(buf)-strlen(buf)-1; + sysctlbyname("hw.machine", buf+strlen(buf), &len, NULL, 0); + + CFStringRef s = CFStringCreateWithCString(NULL, buf, kCFStringEncodingASCII); + LoggerMessageAddString(encoder, s, PART_KEY_CLIENT_MODEL); + CFRelease(s); +#endif + pthread_mutex_lock(&logger->logQueueMutex); + CFArrayInsertValueAtIndex(logger->logQueue, logger->incompleteSendOfFirstItem ? 1 : 0, encoder); + pthread_mutex_unlock(&logger->logQueueMutex); + + CFRelease(encoder); + } +} + +static void LoggerPushMessageToQueue(Logger *logger, CFDataRef message) +{ + // Add the message to the log queue and signal the runLoop source that will trigger + // a send on the worker thread. + pthread_mutex_lock(&logger->logQueueMutex); + CFIndex idx = CFArrayGetCount(logger->logQueue); + if (idx) + { + // to prevent out-of-order messages (as much as possible), we try to transmit messages in the + // order their sequence number was generated. Since the seq is generated first-thing, + // we can provide fine-grained ordering that gives a reasonable idea of the order + // the logging calls were made (useful for precise information about multithreading code) + uint32_t lastSeq, seq = LoggerMessageGetSeq(message); + do { + lastSeq = LoggerMessageGetSeq(CFArrayGetValueAtIndex(logger->logQueue, idx-1)); + } while (lastSeq > seq && --idx > 0); + } + if (idx >= 0) + CFArrayInsertValueAtIndex(logger->logQueue, idx, message); + else + CFArrayAppendValue(logger->logQueue, message); + pthread_mutex_unlock(&logger->logQueueMutex); + + if (logger->messagePushedSource != NULL) + { + // One case where the pushed source may be NULL is if the client code + // immediately starts logging without initializing the logger first. + // In this case, the worker thread has not completed startup, so we don't need + // to fire the runLoop source + CFRunLoopSourceSignal(logger->messagePushedSource); + } + else if (logger->workerThread == NULL && (logger->options & kLoggerOption_LogToConsole)) + { + // In this case, a failure creating the message runLoop source forces us + // to always log to console + pthread_mutex_lock(&logger->logQueueMutex); + while (CFArrayGetCount(logger->logQueue)) + { + LoggerLogToConsole(CFArrayGetValueAtIndex(logger->logQueue, 0)); + CFArrayRemoveValueAtIndex(logger->logQueue, 0); + } + pthread_mutex_unlock(&logger->logQueueMutex); + } +} + +static void LogMessageTo_internal(Logger *logger, + const char *filename, + int lineNumber, + const char *functionName, + NSString *domain, + int level, + NSString *format, + va_list args) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + LoggerStart(logger); + } + + int32_t seq = OSAtomicIncrement32Barrier(&logger->messageSeq); + LOGGERDBG2(CFSTR("%ld LogMessage"), seq); + + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestampAndThreadID(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_LOG, PART_KEY_MESSAGE_TYPE); + LoggerMessageAddInt32(encoder, seq, PART_KEY_MESSAGE_SEQ); + if (domain != nil && [domain length]) + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)domain, PART_KEY_TAG); + if (level) + LoggerMessageAddInt32(encoder, level, PART_KEY_LEVEL); + if (filename != NULL) + LoggerMessageAddCString(encoder, filename, PART_KEY_FILENAME); + if (lineNumber) + LoggerMessageAddInt32(encoder, lineNumber, PART_KEY_LINENUMBER); + if (functionName != NULL) + LoggerMessageAddCString(encoder, functionName, PART_KEY_FUNCTIONNAME); + +#if ALLOW_COCOA_USE + // Go though NSString to avoid low-level logging of CF datastructures (i.e. too detailed NSDictionary, etc) + NSString *msgString = [[NSString alloc] initWithFormat:format arguments:args]; + if (msgString != nil) + { + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)msgString, PART_KEY_MESSAGE); + RELEASE(msgString); + } +#else + CFStringRef msgString = CFStringCreateWithFormatAndArguments(NULL, NULL, (CFStringRef)format, args); + if (msgString != NULL) + { + LoggerMessageAddString(encoder, msgString, PART_KEY_MESSAGE); + CFRelease(msgString); + } +#endif + + LoggerPushMessageToQueue(logger, encoder); + CFRelease(encoder); + } + else + { + LOGGERDBG2(CFSTR("-> failed creating encoder")); + } +} + +static void LogImageTo_internal(Logger *logger, + const char *filename, + int lineNumber, + const char *functionName, + NSString *domain, + int level, + int width, + int height, + NSData *data) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + LoggerStart(logger); + } + + int32_t seq = OSAtomicIncrement32Barrier(&logger->messageSeq); + LOGGERDBG2(CFSTR("%ld LogImage"), seq); + + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestampAndThreadID(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_LOG, PART_KEY_MESSAGE_TYPE); + LoggerMessageAddInt32(encoder, seq, PART_KEY_MESSAGE_SEQ); + if (domain != nil && [domain length]) + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)domain, PART_KEY_TAG); + if (level) + LoggerMessageAddInt32(encoder, level, PART_KEY_LEVEL); + if (width && height) + { + LoggerMessageAddInt32(encoder, width, PART_KEY_IMAGE_WIDTH); + LoggerMessageAddInt32(encoder, height, PART_KEY_IMAGE_HEIGHT); + } + if (filename != NULL) + LoggerMessageAddCString(encoder, filename, PART_KEY_FILENAME); + if (lineNumber) + LoggerMessageAddInt32(encoder, lineNumber, PART_KEY_LINENUMBER); + if (functionName != NULL) + LoggerMessageAddCString(encoder, functionName, PART_KEY_FUNCTIONNAME); + LoggerMessageAddData(encoder, (CAST_TO_CFDATA)data, PART_KEY_MESSAGE, PART_TYPE_IMAGE); + + LoggerPushMessageToQueue(logger, encoder); + CFRelease(encoder); + } + else + { + LOGGERDBG2(CFSTR("-> failed creating encoder")); + } +} + +static void LogDataTo_internal(Logger *logger, + const char *filename, + int lineNumber, + const char *functionName, + NSString *domain, + int level, NSData *data) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + LoggerStart(logger); + } + + int32_t seq = OSAtomicIncrement32Barrier(&logger->messageSeq); + LOGGERDBG2(CFSTR("%ld LogData"), seq); + + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestampAndThreadID(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_LOG, PART_KEY_MESSAGE_TYPE); + LoggerMessageAddInt32(encoder, seq, PART_KEY_MESSAGE_SEQ); + if (domain != nil && [domain length]) + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)domain, PART_KEY_TAG); + if (level) + LoggerMessageAddInt32(encoder, level, PART_KEY_LEVEL); + if (filename != NULL) + LoggerMessageAddCString(encoder, filename, PART_KEY_FILENAME); + if (lineNumber) + LoggerMessageAddInt32(encoder, lineNumber, PART_KEY_LINENUMBER); + if (functionName != NULL) + LoggerMessageAddCString(encoder, functionName, PART_KEY_FUNCTIONNAME); + LoggerMessageAddData(encoder, (CAST_TO_CFDATA)data, PART_KEY_MESSAGE, PART_TYPE_BINARY); + + LoggerPushMessageToQueue(logger, encoder); + CFRelease(encoder); + } + else + { + LOGGERDBG2(CFSTR("-> failed creating encoder")); + } +} + +static void LogStartBlockTo_internal(Logger *logger, NSString *format, va_list args) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + LoggerStart(logger); + } + + int32_t seq = OSAtomicIncrement32Barrier(&logger->messageSeq); + LOGGERDBG2(CFSTR("%ld LogStartBlock"), seq); + + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestampAndThreadID(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_BLOCKSTART, PART_KEY_MESSAGE_TYPE); + LoggerMessageAddInt32(encoder, seq, PART_KEY_MESSAGE_SEQ); + + if (format != nil) + { + CFStringRef msgString = CFStringCreateWithFormatAndArguments(NULL, NULL, (CAST_TO_CFSTRING)format, args); + if (msgString != NULL) + { + LoggerMessageAddString(encoder, msgString, PART_KEY_MESSAGE); + CFRelease(msgString); + } + } + + LoggerPushMessageToQueue(logger, encoder); + CFRelease(encoder); + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Public logging functions +// ----------------------------------------------------------------------------- +void LogMessageCompat(NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogMessageTo_internal(NULL, NULL, 0, NULL, nil, 0, format, args); + va_end(args); +} + +void LogMessageTo(Logger *logger, NSString *domain, int level, NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogMessageTo_internal(logger, NULL, 0, NULL, domain, level, format, args); + va_end(args); +} + +void LogMessageToF(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogMessageTo_internal(logger, filename, lineNumber, functionName, domain, level, format, args); + va_end(args); +} + +void LogMessageTo_va(Logger *logger, NSString *domain, int level, NSString *format, va_list args) +{ + LogMessageTo_internal(logger, NULL, 0, NULL, domain, level, format, args); +} + +void LogMessageToF_va(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, va_list args) +{ + LogMessageTo_internal(logger, filename, lineNumber, functionName, domain, level, format, args); +} + +void LogMessage(NSString *domain, int level, NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogMessageTo_internal(NULL, NULL, 0, NULL, domain, level, format, args); + va_end(args); +} + +void LogMessageF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogMessageTo_internal(NULL, filename, lineNumber, functionName, domain, level, format, args); + va_end(args); +} + +void LogMessage_va(NSString *domain, int level, NSString *format, va_list args) +{ + LogMessageTo_internal(NULL, NULL, 0, NULL, domain, level, format, args); +} + +void LogMessageF_va(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *format, va_list args) +{ + LogMessageTo_internal(NULL, filename, lineNumber, functionName, domain, level, format, args); +} + +void LogData(NSString *domain, int level, NSData *data) +{ + LogDataTo_internal(NULL, NULL, 0, NULL, domain, level, data); +} + +void LogDataF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSData *data) +{ + LogDataTo_internal(NULL, filename, lineNumber, functionName, domain, level, data); +} + +void LogDataTo(Logger *logger, NSString *domain, int level, NSData *data) +{ + LogDataTo_internal(logger, NULL, 0, NULL, domain, level, data); +} + +void LogDataToF(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSData *data) +{ + LogDataTo_internal(logger, filename, lineNumber, functionName, domain, level, data); +} + +void LogImageData(NSString *domain, int level, int width, int height, NSData *data) +{ + LogImageTo_internal(NULL, NULL, 0, NULL, domain, level, width, height, data); +} + +void LogImageDataF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, int width, int height, NSData *data) +{ + LogImageTo_internal(NULL, filename, lineNumber, functionName, domain, level, width, height, data); +} + +void LogImageDataTo(Logger *logger, NSString *domain, int level, int width, int height, NSData *data) +{ + LogImageTo_internal(logger, NULL, 0, NULL, domain, level, width, height, data); +} + +void LogImageDataToF(Logger *logger, const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, int width, int height, NSData *data) +{ + LogImageTo_internal(logger, filename, lineNumber, functionName, domain, level, width, height, data); +} + +void LogStartBlock(NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogStartBlockTo_internal(NULL, format, args); + va_end(args); +} + +void LogStartBlockTo(Logger *logger, NSString *format, ...) +{ + va_list args; + va_start(args, format); + LogStartBlockTo_internal(logger, format, args); + va_end(args); +} + +void LogEndBlockTo(Logger *logger) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + LoggerStart(logger); + } + + if (logger->options & kLoggerOption_LogToConsole) + return; + + int32_t seq = OSAtomicIncrement32Barrier(&logger->messageSeq); + LOGGERDBG2(CFSTR("%ld LogEndBlock"), seq); + + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestampAndThreadID(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_BLOCKEND, PART_KEY_MESSAGE_TYPE); + LoggerMessageAddInt32(encoder, seq, PART_KEY_MESSAGE_SEQ); + LoggerPushMessageToQueue(logger, encoder); + CFRelease(encoder); + } + else + { + LOGGERDBG2(CFSTR("-> failed creating encoder")); + } +} + +void LogEndBlock(void) +{ + LogEndBlockTo(NULL); +} + +void LogMarkerTo(Logger *logger, NSString *text) +{ + if (logger == NULL) + { + logger = LoggerGetDefaultLogger(); + LoggerStart(logger); + } + + int32_t seq = OSAtomicIncrement32Barrier(&logger->messageSeq); + LOGGERDBG2(CFSTR("%ld LogMarker"), seq); + + CFMutableDataRef encoder = LoggerMessageCreate(); + if (encoder != NULL) + { + LoggerMessageAddTimestampAndThreadID(encoder); + LoggerMessageAddInt32(encoder, LOGMSG_TYPE_MARK, PART_KEY_MESSAGE_TYPE); + if (text == nil) + { + CFDateFormatterRef df = CFDateFormatterCreate(NULL, NULL, kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); + CFStringRef str = CFDateFormatterCreateStringWithAbsoluteTime(NULL, df, CFAbsoluteTimeGetCurrent()); + CFRelease(df); + LoggerMessageAddString(encoder, str, PART_KEY_MESSAGE); + CFRelease(str); + } + else + { + LoggerMessageAddString(encoder, (CAST_TO_CFSTRING)text, PART_KEY_MESSAGE); + } + LoggerMessageAddInt32(encoder, seq, PART_KEY_MESSAGE_SEQ); + LoggerPushMessageToQueue(logger, encoder); + CFRelease(encoder); + } + else + { + LOGGERDBG2(CFSTR("-> failed creating encoder")); + } +} + +void LogMarker(NSString *text) +{ + LogMarkerTo(NULL, text); +} diff --git a/External Source/NSLogger/Client Logger/iOS/LoggerCommon.h b/External Source/NSLogger/Client Logger/iOS/LoggerCommon.h new file mode 100644 index 000000000..8765067bd --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/LoggerCommon.h @@ -0,0 +1,113 @@ +/* + * LoggerCommon.h + * + * version 1.0 2011-10-30 + * + * Definitions common to NSLogger Viewer and NSLoggerClient + * for the binary messages format + * https://github.com/fpillet/NSLogger + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* NSLogger native binary message format: + * Each message is a dictionary encoded in a compact format. All values are stored + * in network order (big endian). A message is made of several "parts", which are + * typed chunks of data, each with a specific purpose (partKey), data type (partType) + * and data size (partSize). + * + * uint32_t totalSize (total size for the whole message) + * uint16_t partCount (number of parts below) + * [repeat partCount times]: + * uint8_t partKey the part key + * uint8_t partType (string, binary, image, int16, int32, int64) + * uint32_t partSize (only for string, binary and image types, others are implicit) + * .. `partSize' data bytes + * + * Complete message is usually made of: + * - a PART_KEY_MESSAGE_TYPE (mandatory) which contains one of the LOGMSG_TYPE_* values + * - a PART_KEY_TIMESTAMP_S (mandatory) which is the timestamp returned by gettimeofday() (seconds from 01.01.1970 00:00) + * - a PART_KEY_TIMESTAMP_MS (optional) complement of the timestamp seconds, in milliseconds + * - a PART_KEY_TIMESTAMP_US (optional) complement of the timestamp seconds and milliseconds, in microseconds + * - a PART_KEY_THREAD_ID (mandatory) the ID of the user thread that produced the log entry + * - a PART_KEY_TAG (optional) a tag that helps categorizing and filtering logs from your application, and shows up in viewer logs + * - a PART_KEY_LEVEL (optional) a log level that helps filtering logs from your application (see as few or as much detail as you need) + * - a PART_KEY_MESSAGE which is the message text, binary data or image + * - a PART_KEY_MESSAGE_SEQ which is the message sequence number (message# sent by client) + * - a PART_KEY_FILENAME (optional) with the filename from which the log was generated + * - a PART_KEY_LINENUMBER (optional) the linenumber in the filename at which the log was generated + * - a PART_KEY_FUNCTIONNAME (optional) the function / method / selector from which the log was generated + * - if logging an image, PART_KEY_IMAGE_WIDTH and PART_KEY_IMAGE_HEIGHT let the desktop know the image size without having to actually decode it + */ + +// Constants for the "part key" field +#define PART_KEY_MESSAGE_TYPE 0 +#define PART_KEY_TIMESTAMP_S 1 // "seconds" component of timestamp +#define PART_KEY_TIMESTAMP_MS 2 // milliseconds component of timestamp (optional, mutually exclusive with PART_KEY_TIMESTAMP_US) +#define PART_KEY_TIMESTAMP_US 3 // microseconds component of timestamp (optional, mutually exclusive with PART_KEY_TIMESTAMP_MS) +#define PART_KEY_THREAD_ID 4 +#define PART_KEY_TAG 5 +#define PART_KEY_LEVEL 6 +#define PART_KEY_MESSAGE 7 +#define PART_KEY_IMAGE_WIDTH 8 // messages containing an image should also contain a part with the image size +#define PART_KEY_IMAGE_HEIGHT 9 // (this is mainly for the desktop viewer to compute the cell size without having to immediately decode the image) +#define PART_KEY_MESSAGE_SEQ 10 // the sequential number of this message which indicates the order in which messages are generated +#define PART_KEY_FILENAME 11 // when logging, message can contain a file name +#define PART_KEY_LINENUMBER 12 // as well as a line number +#define PART_KEY_FUNCTIONNAME 13 // and a function or method name + +// Constants for parts in LOGMSG_TYPE_CLIENTINFO +#define PART_KEY_CLIENT_NAME 20 +#define PART_KEY_CLIENT_VERSION 21 +#define PART_KEY_OS_NAME 22 +#define PART_KEY_OS_VERSION 23 +#define PART_KEY_CLIENT_MODEL 24 // For iPhone, device model (i.e 'iPhone', 'iPad', etc) +#define PART_KEY_UNIQUEID 25 // for remote device identification, part of LOGMSG_TYPE_CLIENTINFO + +// Area starting at which you may define your own constants +#define PART_KEY_USER_DEFINED 100 + +// Constants for the "partType" field +#define PART_TYPE_STRING 0 // Strings are stored as UTF-8 data +#define PART_TYPE_BINARY 1 // A block of binary data +#define PART_TYPE_INT16 2 +#define PART_TYPE_INT32 3 +#define PART_TYPE_INT64 4 +#define PART_TYPE_IMAGE 5 // An image, stored in PNG format + +// Data values for the PART_KEY_MESSAGE_TYPE parts +#define LOGMSG_TYPE_LOG 0 // A standard log message +#define LOGMSG_TYPE_BLOCKSTART 1 // The start of a "block" (a group of log entries) +#define LOGMSG_TYPE_BLOCKEND 2 // The end of the last started "block" +#define LOGMSG_TYPE_CLIENTINFO 3 // Information about the client app +#define LOGMSG_TYPE_DISCONNECT 4 // Pseudo-message on the desktop side to identify client disconnects +#define LOGMSG_TYPE_MARK 5 // Pseudo-message that defines a "mark" that users can place in the log flow + +// Default Bonjour service identifiers +#define LOGGER_SERVICE_TYPE_SSL CFSTR("_nslogger-ssl._tcp") +#define LOGGER_SERVICE_TYPE CFSTR("_nslogger._tcp") diff --git a/Source/Quincy/en.lproj/InfoPlist.strings b/External Source/NSLogger/Client Logger/iOS/Mac Test App/InfoPlist.strings similarity index 100% rename from Source/Quincy/en.lproj/InfoPlist.strings rename to External Source/NSLogger/Client Logger/iOS/Mac Test App/InfoPlist.strings diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/MainMenu.xib b/External Source/NSLogger/Client Logger/iOS/Mac Test App/MainMenu.xib new file mode 100644 index 000000000..404c19b06 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/MainMenu.xib @@ -0,0 +1,3220 @@ + + + + 1060 + 10F569 + 804 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 804 + + + YES + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + NSLoggerMacClientTest + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + NSLoggerMacClientTest + + YES + + + About NSLoggerMacClientTest + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide NSLoggerMacClientTest + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit NSLoggerMacClientTest + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + NSLoggerMacClientTest Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 7 + 2 + {{335, 476}, {335, 274}} + 1954021376 + NSLoggerMacClientTest + NSWindow + + {3.40282e+38, 3.40282e+38} + + + 256 + + YES + + + 268 + {{19, 19}, {297, 35}} + + + YES + + 67239424 + 134217728 + Start Logging Messages + + LucidaGrande-Bold + 13 + 16 + + + -2033434369 + 160 + + + 400 + 75 + + + + + 268 + {{17, 222}, {100, 17}} + + + YES + + 68288064 + 71304192 + Messages sent: + + LucidaGrande + 13 + 1044 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2ODY1AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 268 + {{17, 197}, {100, 17}} + + + YES + + 68288064 + 71304192 + Images sent: + + + + + + + + + 268 + {{119, 222}, {128, 17}} + + + YES + + 68288064 + 272630784 + + + + + + + + + + 268 + {{119, 197}, {128, 17}} + + + YES + + 68288064 + 272630784 + + + + + + + + + {335, 274} + + + + {{0, 0}, {1920, 1178}} + {3.40282e+38, 3.40282e+38} + + + NSLoggerMacClientTestAppDelegate + + + NSFontManager + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + delegate + + + + 495 + + + + window + + + + 532 + + + + startStopButton + + + + 547 + + + + messagesCountLabel + + + + 548 + + + + imagesCountLabel + + + + 549 + + + + startStopLogging: + + + + 550 + + + + delegate + + + + 551 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + YES + + + + + + 372 + + + YES + + + + + + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 494 + + + + + 537 + + + YES + + + + + + 538 + + + + + 539 + + + YES + + + + + + 540 + + + + + 541 + + + YES + + + + + + 542 + + + + + 543 + + + YES + + + + + + 544 + + + + + 545 + + + YES + + + + + + 546 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 371.IBEditorWindowLastContentRect + 371.IBPluginDependency + 371.IBViewEditorWindowController.showingLayoutRectangles + 371.IBWindowTemplateEditedContentRect + 371.NSWindowTemplate.visibleAtLaunch + 371.editorWindowContentRectSynchronizationRect + 371.windowTemplate.maxSize + 372.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 537.IBPluginDependency + 537.IBViewBoundsToFrameTransform + 538.IBPluginDependency + 539.IBPluginDependency + 539.IBViewBoundsToFrameTransform + 540.IBPluginDependency + 541.IBPluginDependency + 541.IBViewBoundsToFrameTransform + 542.IBPluginDependency + 543.IBPluginDependency + 543.IBViewBoundsToFrameTransform + 544.IBPluginDependency + 545.IBPluginDependency + 545.IBViewBoundsToFrameTransform + 546.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{547, 180}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{599, 763}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{312, 836}, {419, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{451, 594}, {335, 274}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{451, 594}, {335, 274}} + + {{33, 99}, {480, 360}} + {3.40282e+38, 3.40282e+38} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{725, 289}, {246, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBmAAAwpYAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBiAAAw20AAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBsAAAw2gAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABC7gAAw20AAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABC7gAAw20AAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{324, 653}, {296, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{513, 633}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 551 + + + + YES + + NSLoggerMacClientTestAppDelegate + NSObject + + startStopLogging: + id + + + startStopLogging: + + startStopLogging: + id + + + + YES + + YES + imagesCountLabel + messagesCountLabel + startStopButton + window + + + YES + NSTextField + NSTextField + NSButton + NSWindow + + + + YES + + YES + imagesCountLabel + messagesCountLabel + startStopButton + window + + + YES + + imagesCountLabel + NSTextField + + + messagesCountLabel + NSTextField + + + startStopButton + NSButton + + + window + NSWindow + + + + + IBProjectSource + NSLoggerMacClientTestAppDelegate.h + + + + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + + clearRecentDocuments: + id + + + newDocument: + id + + + openDocument: + id + + + saveAllDocuments: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../NSLoggerMacClientTest.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest-Info.plist b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest-Info.plist new file mode 100644 index 000000000..f696cb233 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest-Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest.xcodeproj/project.pbxproj b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest.xcodeproj/project.pbxproj new file mode 100644 index 000000000..6c2c61f73 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest.xcodeproj/project.pbxproj @@ -0,0 +1,289 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 256AC3DA0F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.m */; }; + 3D8B619F126AFE0D00659751 /* LoggerClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8B619E126AFE0D00659751 /* LoggerClient.m */; }; + 3D8B61FB126B029100659751 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58150DA1D0A300B32029 /* MainMenu.xib */; }; + 3D8B61FC126B029B00659751 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165DFE840E0CC02AAC07 /* InfoPlist.strings */; }; + 3DB964DB1274D4B30054F72D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DB964DA1274D4B30054F72D /* SystemConfiguration.framework */; }; + 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 089C165DFE840E0CC02AAC07 /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InfoPlist.strings; sourceTree = ""; }; + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + 1DDD58150DA1D0A300B32029 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + 256AC3D80F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSLoggerMacClientTestAppDelegate.h; sourceTree = ""; }; + 256AC3D90F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSLoggerMacClientTestAppDelegate.m; sourceTree = ""; }; + 256AC3F00F4B6AF500CF3369 /* NSLoggerMacClientTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSLoggerMacClientTest_Prefix.pch; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 3D8B619C126AFE0D00659751 /* LoggerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerCommon.h; path = ../LoggerCommon.h; sourceTree = SOURCE_ROOT; }; + 3D8B619D126AFE0D00659751 /* LoggerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerClient.h; path = ../LoggerClient.h; sourceTree = SOURCE_ROOT; }; + 3D8B619E126AFE0D00659751 /* LoggerClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerClient.m; path = ../LoggerClient.m; sourceTree = SOURCE_ROOT; }; + 3DB964DA1274D4B30054F72D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 8D1107310486CEB800E47090 /* NSLoggerMacClientTest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "NSLoggerMacClientTest-Info.plist"; sourceTree = ""; }; + 8D1107320486CEB800E47090 /* NSLoggerMacClientTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NSLoggerMacClientTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D11072E0486CEB800E47090 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, + 3DB964DB1274D4B30054F72D /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 256AC3D80F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.h */, + 256AC3D90F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.m */, + ); + name = Classes; + sourceTree = ""; + }; + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 29B97324FDCFA39411CA2CEA /* AppKit.framework */, + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, + 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + 3DB964DA1274D4B30054F72D /* SystemConfiguration.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47090 /* NSLoggerMacClientTest.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* NSLoggerMacClientTest */ = { + isa = PBXGroup; + children = ( + 3D8B619B126AFE0D00659751 /* Logger Client */, + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = NSLoggerMacClientTest; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 256AC3F00F4B6AF500CF3369 /* NSLoggerMacClientTest_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 8D1107310486CEB800E47090 /* NSLoggerMacClientTest-Info.plist */, + 089C165DFE840E0CC02AAC07 /* InfoPlist.strings */, + 1DDD58150DA1D0A300B32029 /* MainMenu.xib */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3D8B619B126AFE0D00659751 /* Logger Client */ = { + isa = PBXGroup; + children = ( + 3D8B619C126AFE0D00659751 /* LoggerCommon.h */, + 3D8B619D126AFE0D00659751 /* LoggerClient.h */, + 3D8B619E126AFE0D00659751 /* LoggerClient.m */, + ); + name = "Logger Client"; + path = "../iPhone Test App/Classes"; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D1107260486CEB800E47090 /* NSLoggerMacClientTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "NSLoggerMacClientTest" */; + buildPhases = ( + 8D1107290486CEB800E47090 /* Resources */, + 8D11072C0486CEB800E47090 /* Sources */, + 8D11072E0486CEB800E47090 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NSLoggerMacClientTest; + productInstallPath = "$(HOME)/Applications"; + productName = NSLoggerMacClientTest; + productReference = 8D1107320486CEB800E47090 /* NSLoggerMacClientTest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLoggerMacClientTest" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* NSLoggerMacClientTest */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8D1107260486CEB800E47090 /* NSLoggerMacClientTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47090 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D8B61FC126B029B00659751 /* InfoPlist.strings in Resources */, + 3D8B61FB126B029100659751 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D11072C0486CEB800E47090 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072D0486CEB800E47090 /* main.m in Sources */, + 256AC3DA0F4B6AC300CF3369 /* NSLoggerMacClientTestAppDelegate.m in Sources */, + 3D8B619F126AFE0D00659751 /* LoggerClient.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C01FCF4B08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLoggerMacClientTest_Prefix.pch; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INFOPLIST_FILE = "NSLoggerMacClientTest-Info.plist"; + PRODUCT_NAME = NSLoggerMacClientTest; + }; + name = Debug; + }; + C01FCF4C08A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLoggerMacClientTest_Prefix.pch; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INFOPLIST_FILE = "NSLoggerMacClientTest-Info.plist"; + PRODUCT_NAME = NSLoggerMacClientTest; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "NSLoggerMacClientTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4B08A954540054247B /* Debug */, + C01FCF4C08A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLoggerMacClientTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTestAppDelegate.h b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTestAppDelegate.h new file mode 100644 index 000000000..3d23b9d55 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTestAppDelegate.h @@ -0,0 +1,50 @@ +/* + * NSLoggerMacClientTestAppDelegate.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@interface NSLoggerMacClientTestAppDelegate : NSObject { + NSWindow *window; + + IBOutlet NSTextField *messagesCountLabel; + IBOutlet NSTextField *imagesCountLabel; + IBOutlet NSButton *startStopButton; + + NSTimer *sendTimer; + NSArray *tagsArray; + int counter; + int imagesCounter; +} + +@property (assign) IBOutlet NSWindow *window; + +- (IBAction)startStopLogging:(id)sender; + +@end diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTestAppDelegate.m b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTestAppDelegate.m new file mode 100644 index 000000000..7069d578f --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTestAppDelegate.m @@ -0,0 +1,182 @@ +/* + * NSLoggerMacClientTestAppDelegate.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "NSLoggerMacClientTestAppDelegate.h" +#import "LoggerClient.h" + +#define TEST_BONJOUR_SETUP 0 +#define TEST_CONSOLE_LOGGING 0 +#define TEST_FILE_BUFFERING 0 +#define TEST_DIRECT_CONNECTION 0 +#define LOGGING_HOST CFSTR("127.0.0.1") +#define LOGGING_PORT 50007 + +@implementation NSLoggerMacClientTestAppDelegate + +@synthesize window; + +- (void)awakeFromNib +{ + tagsArray = [[NSArray arrayWithObjects:@"main",@"audio",@"video",@"network",@"database",nil] retain]; + +#if TEST_CONSOLE_LOGGING + LoggerSetOptions(NULL, kLoggerOption_LogToConsole); +#else + #if TEST_FILE_BUFFERING + LoggerSetBufferFile(NULL, CFSTR("/tmp/NSLoggerTempData_MacOSX.rawnsloggerdata")); + #endif + #if TEST_DIRECT_CONNECTION + LoggerSetViewerHost(NULL, LOGGING_HOST, LOGGING_PORT); + #endif +#endif +#if TEST_BONJOUR_SETUP + // test restricting bonjour lookup for a specific machine + LoggerSetupBonjour(NULL, NULL, CFSTR("MyOwnComputerOny")); +#endif +} + +- (void)windowWillClose:(NSNotification *)notification +{ + LoggerStop(NULL); + [NSApp terminate:self]; +} + +- (IBAction)startStopLogging:(id)sender +{ + if (sendTimer == nil) + { + counter = 0; + imagesCounter = 0; + sendTimer = [[NSTimer scheduledTimerWithTimeInterval:0.20f + target:self + selector:@selector(sendTimerFired:) + userInfo:nil + repeats:YES] retain]; + [startStopButton setTitle:@"Stop Sending Logs"]; + } + else + { + [sendTimer invalidate]; + [sendTimer release]; + sendTimer = nil; + [startStopButton setTitle:@"Start Sending Logs"]; + } +} + +- (void)sendTimerFired:(NSTimer *)timer +{ + static int image = 1; + int phase = arc4random() % 10; + if (phase != 1 && phase != 5) + { + NSMutableString *s = [NSMutableString stringWithFormat:@"test log message %d - Random characters follow: ", counter++]; + int nadd = 1 + arc4random() % 150; + for (int i = 0; i < nadd; i++) + [s appendFormat:@"%c", 32 + (arc4random() % 27)]; + int what = (arc4random() % 4); + if (what == 0) + LogMessage([tagsArray objectAtIndex:(arc4random() % [tagsArray count])], arc4random() % 3, s); + else if (what == 1) + { + // log full origin info + LogMessageF(__FILE__, __LINE__, __FUNCTION__, [tagsArray objectAtIndex:(arc4random() % [tagsArray count])], arc4random() % 3, s); + } + else if (what == 2) + { + // just log __FUNCTION__ + LogMessageF(NULL, 0, __FUNCTION__, [tagsArray objectAtIndex:(arc4random() % [tagsArray count])], arc4random() % 3, s); + } + else + { + // just log __FILE__ __LINE__ + LogMessageF(__FILE__, __LINE__, NULL, [tagsArray objectAtIndex:(arc4random() % [tagsArray count])], arc4random() % 3, s); + } + } + else if (phase == 1) + { + unsigned char *buf = (unsigned char *)malloc(1024); + int n = 1 + arc4random() % 1024; + for (int i = 0; i < n; i++) + buf[i] = (unsigned char)arc4random(); + NSData *d = [[NSData alloc] initWithBytesNoCopy:buf length:n]; + LogData(@"main", 1, d); + [d release]; + } + else if (phase == 5) + { + // nearly same code as iPhone example, could certainly be made shorter + imagesCounter++; + NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(100,100)]; + [img lockFocusFlipped:NO]; + CGContextRef ctx = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); + CGFloat r = (CGFloat)(arc4random() % 256) / 255.0f; + CGFloat g = (CGFloat)(arc4random() % 256) / 255.0f; + CGFloat b = (CGFloat)(arc4random() % 256) / 255.0f; + CGColorRef fillColor = CGColorCreateGenericRGB(r, g, b, 1.0f); + CGContextSetFillColorWithColor(ctx, fillColor); + CGColorRelease(fillColor); + CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100)); + CGContextSetTextMatrix(ctx, CGAffineTransformIdentity); + CGContextSelectFont(ctx, "Helvetica", 14.0, kCGEncodingMacRoman); + CGColorRef white = CGColorCreateGenericGray(1.0f, 1.0f); + CGContextSetShadowWithColor(ctx, CGSizeMake(1, 1), 1.0f, white); + CGColorRelease(white); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGColorRef black = CGColorCreateGenericGray(0.0f, 1.0f); + CGContextSetFillColorWithColor(ctx, black); + CGColorRelease(black); + char buf[64]; + sprintf(buf, "Log Image %d", image++); + CGContextShowTextAtPoint(ctx, 0, 50, buf, strlen(buf)); + [img unlockFocus]; + + NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithData:[img TIFFRepresentation]]; + NSData *bitmapData = [bitmapRep representationUsingType:NSPNGFileType properties:nil]; + [bitmapRep release]; + [img release]; + + LogImageData(@"image", 0, 100, 100, bitmapData); + } + if (phase == 0) + { + [NSThread detachNewThreadSelector:@selector(sendLogFromAnotherThread:) + toTarget:self + withObject:[NSNumber numberWithInteger:counter++]]; + } + [messagesCountLabel setStringValue:[NSString stringWithFormat:@"%d", counter]]; + [imagesCountLabel setStringValue:[NSString stringWithFormat:@"%d", imagesCounter]]; +} + +- (void)sendLogFromAnotherThread:(NSNumber *)counterNum +{ + LogMessage(@"transfers", 0, @"message %d from standalone thread", [counterNum integerValue]); +} + +@end diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest_Prefix.pch b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest_Prefix.pch new file mode 100644 index 000000000..470a775d0 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/NSLoggerMacClientTest_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'NSLoggerMacClientTest' target in the 'NSLoggerMacClientTest' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/External Source/NSLogger/Client Logger/iOS/Mac Test App/main.m b/External Source/NSLogger/Client Logger/iOS/Mac Test App/main.m new file mode 100644 index 000000000..160da8101 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/Mac Test App/main.m @@ -0,0 +1,36 @@ +/* + * main.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientAppDelegate.h b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientAppDelegate.h new file mode 100644 index 000000000..5461f056d --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientAppDelegate.h @@ -0,0 +1,44 @@ +/* + * NSLoggerClientAppDelegate.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerClientViewController; + +@interface LoggerClientAppDelegate : NSObject { + UIWindow *window; + LoggerClientViewController *viewController; +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet LoggerClientViewController *viewController; + +@end + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientAppDelegate.m b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientAppDelegate.m new file mode 100644 index 000000000..583872c9d --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientAppDelegate.m @@ -0,0 +1,46 @@ +/* + * NSLoggerClientAppDelegate.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import "LoggerClientAppDelegate.h" +#import "LoggerClientViewController.h" + +@implementation LoggerClientAppDelegate + +@synthesize window; +@synthesize viewController; + +- (void)applicationDidFinishLaunching:(UIApplication *)application +{ + [window addSubview:viewController.view]; + [window makeKeyAndVisible]; +} + +@end diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientViewController.h b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientViewController.h new file mode 100644 index 000000000..befca85c4 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientViewController.h @@ -0,0 +1,55 @@ +/* + * LoggerClientViewController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#import "LoggerClient.h" + +@interface LoggerClientViewController : UIViewController +{ + IBOutlet UIButton *timerButton; + IBOutlet UILabel *messagesSentLabel; + IBOutlet UILabel *imagesSentLabel; + IBOutlet UITextField *viewerHostField; + IBOutlet UITextField *viewerPortField; + IBOutlet UISwitch *browseBonjour; + IBOutlet UISwitch *browseLocalDomainOnly; + + NSTimer *sendTimer; + NSArray *tagsArray; + int counter; + int imagesCounter; +} + +- (IBAction)startStopSendingMessages; +- (IBAction)bonjourSettingChanged; +- (IBAction)browseLocalDomainOnlySettingChanged; + +@end + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientViewController.m b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientViewController.m new file mode 100644 index 000000000..6c260d2dd --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Classes/LoggerClientViewController.m @@ -0,0 +1,220 @@ +/* + * LoggerClientViewController.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerClientViewController.h" + +#define TEST_FILE_BUFFERING 0 + +@implementation LoggerClientViewController + +- (void)awakeFromNib +{ + tagsArray = [NSArray arrayWithObjects:@"main",@"audio",@"video",@"network",@"database",nil]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + viewerHostField.text = [ud stringForKey:@"host"]; + viewerPortField.text = [ud stringForKey:@"port"]; + browseBonjour.on = [ud boolForKey:@"browseBonjour"]; + browseLocalDomainOnly.on = [ud boolForKey:@"localDomain"]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(textFieldDidChange:) + name:UITextFieldTextDidChangeNotification + object:nil]; + +#if TEST_FILE_BUFFERING + NSString *bufferPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"NSLoggerTempData_iOS.rawnsloggerdata"]; + LoggerSetBufferFile(NULL, (CFStringRef)bufferPath); +#endif +} + +- (IBAction)bonjourSettingChanged +{ + browseLocalDomainOnly.enabled = browseBonjour.on; + [[NSUserDefaults standardUserDefaults] setBool:browseBonjour.on forKey:@"browseBonjour"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (IBAction)browseLocalDomainOnlySettingChanged +{ + [[NSUserDefaults standardUserDefaults] setBool:browseLocalDomainOnly.on forKey:@"localDomain"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (IBAction)startStopSendingMessages +{ + if (sendTimer == nil) + { + // Configure the logger + NSString *host = [viewerHostField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + int port = [viewerPortField.text integerValue]; + port = MAX(0, MIN(port, 65535)); + viewerPortField.text = [NSString stringWithFormat:@"%d", port]; + + if ([host length] && port != 0) + LoggerSetViewerHost(NULL, (__bridge CFStringRef)host, (UInt32)port); + else + LoggerSetViewerHost(NULL, NULL, 0); + + LoggerSetOptions(NULL, // configure the default logger + kLoggerOption_BufferLogsUntilConnection | + kLoggerOption_UseSSL | + (browseBonjour.on ? kLoggerOption_BrowseBonjour : 0) | + (browseLocalDomainOnly.on ? kLoggerOption_BrowseOnlyLocalDomain : 0)); + + // Start logging random messages + counter = 0; + imagesCounter = 0; + sendTimer = [NSTimer scheduledTimerWithTimeInterval:0.20f + target:self + selector:@selector(sendTimerFired:) + userInfo:nil + repeats:YES]; + [timerButton setTitle:@"Stop Sending Logs" forState:UIControlStateNormal]; + } + else + { + [sendTimer invalidate]; + sendTimer = nil; + [timerButton setTitle:@"Start Sending Logs" forState:UIControlStateNormal]; + } +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + if (textField == viewerHostField) + [viewerPortField becomeFirstResponder]; + else + [textField resignFirstResponder]; + return NO; +} + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + // we use the numbers & punct keyboard to get the Done key, + // in exchange we need to validate input to exclude non-number chars + if (textField != viewerPortField) + return YES; + NSMutableString *s = [string mutableCopy]; + NSUInteger length = [string length]; + for (NSUInteger i = 0; i < length; i++) + { + unichar c = [string characterAtIndex:i]; + if (c < '0' || c > '9') + { + [s replaceCharactersInRange:NSMakeRange(i, 1) withString:@""]; + length--; + } + } + NSMutableString *ts = [textField.text mutableCopy]; + [ts replaceCharactersInRange:range withString:s]; + textField.text = ts; + return NO; +} + +- (void)textFieldDidChange:(NSNotification *)note +{ + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + [ud setObject:viewerHostField.text forKey:@"host"]; + [ud setObject:viewerPortField.text forKey:@"port"]; + [ud synchronize]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [sendTimer invalidate]; +} + +- (void)sendTimerFired:(NSTimer *)timer +{ + static int image = 1; + int phase = arc4random() % 10; + if (phase != 1 && phase != 5) + { + NSMutableString *s = [NSMutableString stringWithFormat:@"test log message %d - Random characters follow: ", counter++]; + int nadd = 1 + arc4random() % 150; + for (int i = 0; i < nadd; i++) + [s appendFormat:@"%c", 32 + (arc4random() % 27)]; + LogMessage([tagsArray objectAtIndex:(arc4random() % [tagsArray count])], arc4random() % 3, s); + } + else if (phase == 1) + { + unsigned char *buf = (unsigned char *)malloc(1024); + int n = 1 + arc4random() % 1024; + for (int i = 0; i < n; i++) + buf[i] = (unsigned char)arc4random(); + LogData(@"main", 1, [[NSData alloc] initWithBytesNoCopy:buf length:n]); + } + else if (phase == 5) + { + imagesCounter++; + UIGraphicsBeginImageContext(CGSizeMake(100, 100)); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGFloat r = (CGFloat)(arc4random() % 256) / 255.0f; + CGFloat g = (CGFloat)(arc4random() % 256) / 255.0f; + CGFloat b = (CGFloat)(arc4random() % 256) / 255.0f; + UIColor *fillColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f]; + CGContextSetFillColorWithColor(ctx, fillColor.CGColor); + CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100)); + CGContextSetTextMatrix(ctx, CGAffineTransformConcat(CGAffineTransformMakeTranslation(0, 100), CGAffineTransformMakeScale(1.0f, -1.0f))); + CGContextSelectFont(ctx, "Helvetica", 14.0, kCGEncodingMacRoman); + CGContextSetShadowWithColor(ctx, CGSizeMake(1, 1), 1.0f, [UIColor whiteColor].CGColor); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor); + char buf[64]; + sprintf(buf, "Log Image %d", image++); + CGContextShowTextAtPoint(ctx, 0, 50, buf, strlen(buf)); + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); + CGSize sz = img.size; + LogImageData(@"image", 0, sz.width, sz.height, UIImagePNGRepresentation(img)); + UIGraphicsEndImageContext(); + } + if (phase == 0) + { + [NSThread detachNewThreadSelector:@selector(sendLogFromAnotherThread:) + toTarget:self + withObject:[NSNumber numberWithInteger:counter++]]; + } + messagesSentLabel.text = [NSString stringWithFormat:@"%d", counter]; + imagesSentLabel.text = [NSString stringWithFormat:@"%d", imagesCounter]; +} + +- (void)sendLogFromAnotherThread:(NSNumber *)counterNum +{ + LogMessage(@"transfers", 0, @"message %d from standalone thread", [counterNum integerValue]); +} + +@end diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Info.plist b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Info.plist new file mode 100644 index 000000000..1b86cf2ce --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.florentpillet.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/LoggerTestAppViewController.xib b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/LoggerTestAppViewController.xib new file mode 100644 index 000000000..8e136cbaf --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/LoggerTestAppViewController.xib @@ -0,0 +1,1047 @@ + + + + 528 + 10F569 + 804 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 123 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 290 + {{119, 279}, {181, 37}} + + NO + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Bold + 15 + 16 + + 1 + + + Stop Sending Logs + Start Sending Logs + + 1 + MSAxIDEAA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MAA + + + + + 290 + {{68, 84}, {232, 31}} + + NO + YES + IBCocoaTouchFramework + 0 + + 3 + + + 3 + MAA + + 2 + + + + Helvetica + 15 + 16 + + YES + 9 + + 1 + 3 + 4 + IBCocoaTouchFramework + + 3 + + + + 292 + {{20, 87}, {40, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Host: + + + 1 + MCAwIDAAA + + + 3 + MQA + + 1 + 10 + + + + 290 + {{20, 7}, {280, 77}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Enter hostname / IP and port # for desktop viewer, leave empty to use Bonjour only. + + + + 1 + 10 + 0 + + + + 290 + {{68, 123}, {108, 31}} + + NO + YES + IBCocoaTouchFramework + 0 + + 3 + + + 3 + MAA + + + + YES + 9 + + 1 + 2 + 9 + IBCocoaTouchFramework + + 3 + + + + 292 + {{20, 126}, {36, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Port: + + + + 1 + 10 + + + + 292 + {{206, 180}, {94, 27}} + + NO + IBCocoaTouchFramework + 0 + 0 + YES + + + + 292 + {{206, 215}, {94, 27}} + + NO + IBCocoaTouchFramework + 0 + 0 + YES + + + + 292 + {{20, 183}, {178, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Search on Bonjour + + + + 1 + 10 + + + + 292 + {{20, 218}, {178, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Local domain only + + + + 1 + 10 + + + + 266 + + YES + + + 268 + {{20, 20}, {120, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Messages sent: + + + 1 + 10 + 2 + + + + 268 + {{20, 49}, {120, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Images sent: + + + 1 + 10 + 2 + + + + 268 + {{148, 20}, {116, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + 0 + + Helvetica-Bold + 17 + 16 + + + + 1 + 10 + + + + 268 + {{148, 49}, {116, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + 0 + + + + 1 + 10 + + + {{0, 370}, {320, 90}} + + + 3 + MC42NjY2NjY2ODY1AA + + 3 + IBCocoaTouchFramework + + + {320, 460} + + + 3 + MC44OTk5OTk5NzYyAA + + NO + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 7 + + + + timerButton + + + + 9 + + + + startStopSendingMessages + + + 7 + + 10 + + + + messagesSentLabel + + + + 15 + + + + imagesSentLabel + + + + 16 + + + + bonjourSettingChanged + + + 13 + + 28 + + + + viewerHostField + + + + 29 + + + + viewerPortField + + + + 30 + + + + delegate + + + + 33 + + + + delegate + + + + 34 + + + + browseBonjour + + + + 35 + + + + browseLocalDomainOnly + + + + 36 + + + + browseLocalDomainOnlySettingChanged + + + 13 + + 37 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + + + + + + + + + + + + 8 + + + + + 17 + + + + + 18 + + + + + 19 + + + + + 20 + + + + + 21 + + + + + 22 + + + + + 23 + + + + + 24 + + + + + 25 + + + + + 31 + + + YES + + + + + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 14 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 11.IBPluginDependency + 11.IBViewBoundsToFrameTransform + 12.IBPluginDependency + 12.IBViewBoundsToFrameTransform + 13.IBPluginDependency + 13.IBViewBoundsToFrameTransform + 14.IBPluginDependency + 14.IBViewBoundsToFrameTransform + 17.IBPluginDependency + 17.IBViewBoundsToFrameTransform + 18.IBPluginDependency + 18.IBViewBoundsToFrameTransform + 19.IBPluginDependency + 19.IBViewBoundsToFrameTransform + 20.IBPluginDependency + 20.IBViewBoundsToFrameTransform + 21.IBPluginDependency + 21.IBViewBoundsToFrameTransform + 22.IBPluginDependency + 22.IBViewBoundsToFrameTransform + 23.IBPluginDependency + 23.IBViewBoundsToFrameTransform + 24.IBPluginDependency + 24.IBViewBoundsToFrameTransform + 25.IBPluginDependency + 25.IBViewBoundsToFrameTransform + 6.IBEditorWindowLastContentRect + 6.IBPluginDependency + 8.IBPluginDependency + 8.IBViewBoundsToFrameTransform + + + YES + LoggerClientViewController + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABAQAAAw4mAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABAQAAAw5gAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDAwAAw4mAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDAwAAw5gAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUK6AABCqAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUGgAABCrgAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCoAAAwpQAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCugAAwxgAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABBoAAAww4AAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUNOAABDNAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDTgAAw4AAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUGgAABDNwAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABBoAAAw30AAA + + {{34, 620}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABC7gAAw5oAAA + + + + + YES + + + YES + + + + + YES + + + YES + + + + 37 + + + + YES + + LoggerClientViewController + UIViewController + + YES + + YES + bonjourSettingChanged + browseLocalDomainOnlySettingChanged + startStopSendingMessages + + + YES + id + id + id + + + + YES + + YES + bonjourSettingChanged + browseLocalDomainOnlySettingChanged + startStopSendingMessages + + + YES + + bonjourSettingChanged + id + + + browseLocalDomainOnlySettingChanged + id + + + startStopSendingMessages + id + + + + + YES + + YES + browseBonjour + browseLocalDomainOnly + imagesSentLabel + messagesSentLabel + timerButton + viewerHostField + viewerPortField + + + YES + UISwitch + UISwitch + UILabel + UILabel + UIButton + UITextField + UITextField + + + + YES + + YES + browseBonjour + browseLocalDomainOnly + imagesSentLabel + messagesSentLabel + timerButton + viewerHostField + viewerPortField + + + YES + + browseBonjour + UISwitch + + + browseLocalDomainOnly + UISwitch + + + imagesSentLabel + UILabel + + + messagesSentLabel + UILabel + + + timerButton + UIButton + + + viewerHostField + UITextField + + + viewerPortField + UITextField + + + + + IBProjectSource + Classes/LoggerClientViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UISwitch + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UISwitch.h + + + + UITextField + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + NSLoggerTestApp.xcodeproj + 3 + 123 + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/MainWindow.xib b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/MainWindow.xib new file mode 100644 index 000000000..972af1d63 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/MainWindow.xib @@ -0,0 +1,468 @@ + + + + 528 + 10F569 + 788 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 117 + + + YES + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + LoggerTestAppViewController + + + 1 + + IBCocoaTouchFramework + NO + + + + 292 + {320, 480} + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + NSLoggerClient App Delegate + + + -2 + + + + + 10 + + + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + LoggerClientViewController + {{512, 351}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + LoggerClientAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 14 + + + + YES + + LoggerClientAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + LoggerClientViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + LoggerClientViewController + + + window + UIWindow + + + + + IBProjectSource + Classes/LoggerClientAppDelegate.h + + + + LoggerClientViewController + UIViewController + + startStopSendingMessages + id + + + startStopSendingMessages + + startStopSendingMessages + id + + + + timerButton + UIButton + + + timerButton + + timerButton + UIButton + + + + IBProjectSource + Classes/LoggerClientViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + NSLoggerTestApp.xcodeproj + 3 + 117 + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp.xcodeproj/project.pbxproj b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp.xcodeproj/project.pbxproj new file mode 100755 index 000000000..f4e79374e --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp.xcodeproj/project.pbxproj @@ -0,0 +1,289 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1D3623260D0F684500981E51 /* LoggerClientAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* LoggerClientAppDelegate.m */; }; + 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + 2899E5220DE3E06400AC0155 /* LoggerTestAppViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* LoggerTestAppViewController.xib */; }; + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 28D7ACF80DDB3853001CB0EB /* LoggerClientViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* LoggerClientViewController.m */; }; + 3D62642B125223CA00359022 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D62642A125223CA00359022 /* CFNetwork.framework */; }; + 3DA99CB50F10BC160077756A /* LoggerClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DA99CB40F10BC160077756A /* LoggerClient.m */; }; + 3DB964331274C5E60054F72D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DB964321274C5E50054F72D /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D3623240D0F684500981E51 /* LoggerClientAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggerClientAppDelegate.h; sourceTree = ""; }; + 1D3623250D0F684500981E51 /* LoggerClientAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoggerClientAppDelegate.m; sourceTree = ""; }; + 1D6058910D05DD3D006BFB54 /* NSLoggerClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NSLoggerClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 2899E5210DE3E06400AC0155 /* LoggerTestAppViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoggerTestAppViewController.xib; sourceTree = ""; }; + 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; + 28D7ACF60DDB3853001CB0EB /* LoggerClientViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggerClientViewController.h; sourceTree = ""; }; + 28D7ACF70DDB3853001CB0EB /* LoggerClientViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoggerClientViewController.m; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* NSLoggerTestApp_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSLoggerTestApp_Prefix.pch; sourceTree = ""; }; + 3D0187E01255D10C009D8545 /* LoggerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerCommon.h; path = ../LoggerCommon.h; sourceTree = SOURCE_ROOT; }; + 3D62642A125223CA00359022 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 3DA99CB30F10BC160077756A /* LoggerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerClient.h; path = ../../LoggerClient.h; sourceTree = ""; }; + 3DA99CB40F10BC160077756A /* LoggerClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerClient.m; path = ../../LoggerClient.m; sourceTree = ""; }; + 3DB964321274C5E50054F72D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + 3D62642B125223CA00359022 /* CFNetwork.framework in Frameworks */, + 3DB964331274C5E60054F72D /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 1D3623240D0F684500981E51 /* LoggerClientAppDelegate.h */, + 1D3623250D0F684500981E51 /* LoggerClientAppDelegate.m */, + 28D7ACF60DDB3853001CB0EB /* LoggerClientViewController.h */, + 28D7ACF70DDB3853001CB0EB /* LoggerClientViewController.m */, + ); + path = Classes; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* NSLoggerClient.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 3DAAC60112550D7C000ACF7A /* Logger Client */, + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* NSLoggerTestApp_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 2899E5210DE3E06400AC0155 /* LoggerTestAppViewController.xib */, + 28AD733E0D9D9553002E5188 /* MainWindow.xib */, + 8D1107310486CEB800E47090 /* Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + 3D62642A125223CA00359022 /* CFNetwork.framework */, + 3DB964321274C5E50054F72D /* SystemConfiguration.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3DAAC60112550D7C000ACF7A /* Logger Client */ = { + isa = PBXGroup; + children = ( + 3D0187E01255D10C009D8545 /* LoggerCommon.h */, + 3DA99CB30F10BC160077756A /* LoggerClient.h */, + 3DA99CB40F10BC160077756A /* LoggerClient.m */, + ); + name = "Logger Client"; + path = Classes; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* NSLoggerClient TestApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "NSLoggerClient TestApp" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "NSLoggerClient TestApp"; + productName = NSLoggerClient; + productReference = 1D6058910D05DD3D006BFB54 /* NSLoggerClient.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLoggerTestApp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* NSLoggerClient TestApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, + 2899E5220DE3E06400AC0155 /* LoggerTestAppViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 1D3623260D0F684500981E51 /* LoggerClientAppDelegate.m in Sources */, + 28D7ACF80DDB3853001CB0EB /* LoggerClientViewController.m in Sources */, + 3DA99CB50F10BC160077756A /* LoggerClient.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLoggerTestApp_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + PRODUCT_NAME = NSLoggerClient; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLoggerTestApp_Prefix.pch; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + PRODUCT_NAME = NSLoggerClient; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SDKROOT = iphoneos; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "NSLoggerClient TestApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLoggerTestApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..8d3c2596e --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,6 @@ + + + + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp_Prefix.pch b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp_Prefix.pch new file mode 100644 index 000000000..a17209c55 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/NSLoggerTestApp_Prefix.pch @@ -0,0 +1,4 @@ +#ifdef __OBJC__ + #import + #import +#endif diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/main.m b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/main.m new file mode 100644 index 000000000..c9989214f --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App (ARC)/main.m @@ -0,0 +1,15 @@ +// +// main.m +// NSLoggerClient +// +// Created by Florent Pillet on 1/4/09. +// Copyright Florent Pillet 2009. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, nil); + } +} diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientAppDelegate.h b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientAppDelegate.h new file mode 100644 index 000000000..5461f056d --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientAppDelegate.h @@ -0,0 +1,44 @@ +/* + * NSLoggerClientAppDelegate.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerClientViewController; + +@interface LoggerClientAppDelegate : NSObject { + UIWindow *window; + LoggerClientViewController *viewController; +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet LoggerClientViewController *viewController; + +@end + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientAppDelegate.m b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientAppDelegate.m new file mode 100644 index 000000000..4e92abf39 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientAppDelegate.m @@ -0,0 +1,55 @@ +/* + * NSLoggerClientAppDelegate.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import "LoggerClientAppDelegate.h" +#import "LoggerClientViewController.h" + +@implementation LoggerClientAppDelegate + +@synthesize window; +@synthesize viewController; + +- (void)applicationDidFinishLaunching:(UIApplication *)application +{ + [window addSubview:viewController.view]; + [window makeKeyAndVisible]; +} + + +- (void)dealloc +{ + [viewController release]; + [window release]; + [super dealloc]; +} + + +@end diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientViewController.h b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientViewController.h new file mode 100644 index 000000000..befca85c4 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientViewController.h @@ -0,0 +1,55 @@ +/* + * LoggerClientViewController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#import "LoggerClient.h" + +@interface LoggerClientViewController : UIViewController +{ + IBOutlet UIButton *timerButton; + IBOutlet UILabel *messagesSentLabel; + IBOutlet UILabel *imagesSentLabel; + IBOutlet UITextField *viewerHostField; + IBOutlet UITextField *viewerPortField; + IBOutlet UISwitch *browseBonjour; + IBOutlet UISwitch *browseLocalDomainOnly; + + NSTimer *sendTimer; + NSArray *tagsArray; + int counter; + int imagesCounter; +} + +- (IBAction)startStopSendingMessages; +- (IBAction)bonjourSettingChanged; +- (IBAction)browseLocalDomainOnlySettingChanged; + +@end + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientViewController.m b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientViewController.m new file mode 100644 index 000000000..daf9e93fb --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Classes/LoggerClientViewController.m @@ -0,0 +1,228 @@ +/* + * LoggerClientViewController.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerClientViewController.h" + +#define TEST_FILE_BUFFERING 0 + +@implementation LoggerClientViewController + +- (void)awakeFromNib +{ + tagsArray = [[NSArray arrayWithObjects:@"main",@"audio",@"video",@"network",@"database",nil] retain]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + viewerHostField.text = [ud stringForKey:@"host"]; + viewerPortField.text = [ud stringForKey:@"port"]; + browseBonjour.on = [ud boolForKey:@"browseBonjour"]; + browseLocalDomainOnly.on = [ud boolForKey:@"localDomain"]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(textFieldDidChange:) + name:UITextFieldTextDidChangeNotification + object:nil]; + +#if TEST_FILE_BUFFERING + NSString *bufferPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"NSLoggerTempData_iOS.rawnsloggerdata"]; + LoggerSetBufferFile(NULL, (CFStringRef)bufferPath); +#endif +} + +- (IBAction)bonjourSettingChanged +{ + browseLocalDomainOnly.enabled = browseBonjour.on; + [[NSUserDefaults standardUserDefaults] setBool:browseBonjour.on forKey:@"browseBonjour"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (IBAction)browseLocalDomainOnlySettingChanged +{ + [[NSUserDefaults standardUserDefaults] setBool:browseLocalDomainOnly.on forKey:@"localDomain"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (IBAction)startStopSendingMessages +{ + if (sendTimer == nil) + { + // Configure the logger + NSString *host = [viewerHostField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + int port = [viewerPortField.text integerValue]; + port = MAX(0, MIN(port, 65535)); + viewerPortField.text = [NSString stringWithFormat:@"%d", port]; + + if ([host length] && port != 0) + LoggerSetViewerHost(NULL, (CFStringRef)host, (UInt32)port); + else + LoggerSetViewerHost(NULL, NULL, 0); + + LoggerSetOptions(NULL, // configure the default logger + kLoggerOption_BufferLogsUntilConnection | + kLoggerOption_UseSSL | + (browseBonjour.on ? kLoggerOption_BrowseBonjour : 0) | + (browseLocalDomainOnly.on ? kLoggerOption_BrowseOnlyLocalDomain : 0)); + + // Start logging random messages + counter = 0; + imagesCounter = 0; + sendTimer = [[NSTimer scheduledTimerWithTimeInterval:0.20f + target:self + selector:@selector(sendTimerFired:) + userInfo:nil + repeats:YES] retain]; + [timerButton setTitle:@"Stop Sending Logs" forState:UIControlStateNormal]; + } + else + { + [sendTimer invalidate]; + [sendTimer release]; + sendTimer = nil; + [timerButton setTitle:@"Start Sending Logs" forState:UIControlStateNormal]; + } +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + if (textField == viewerHostField) + [viewerPortField becomeFirstResponder]; + else + [textField resignFirstResponder]; + return NO; +} + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + // we use the numbers & punct keyboard to get the Done key, + // in exchange we need to validate input to exclude non-number chars + if (textField != viewerPortField) + return YES; + NSMutableString *s = [string mutableCopy]; + NSUInteger length = [string length]; + for (NSUInteger i = 0; i < length; i++) + { + unichar c = [string characterAtIndex:i]; + if (c < '0' || c > '9') + { + [s replaceCharactersInRange:NSMakeRange(i, 1) withString:@""]; + length--; + } + } + NSMutableString *ts = [textField.text mutableCopy]; + [ts replaceCharactersInRange:range withString:s]; + textField.text = ts; + [ts release]; + [s release]; + return NO; +} + +- (void)textFieldDidChange:(NSNotification *)note +{ + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + [ud setObject:viewerHostField.text forKey:@"host"]; + [ud setObject:viewerPortField.text forKey:@"port"]; + [ud synchronize]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [sendTimer invalidate]; + [sendTimer release]; + [tagsArray release]; + [super dealloc]; +} + +- (void)sendTimerFired:(NSTimer *)timer +{ + static int image = 1; + int phase = arc4random() % 10; + if (phase != 1 && phase != 5) + { + NSMutableString *s = [NSMutableString stringWithFormat:@"test log message %d - Random characters follow: ", counter++]; + int nadd = 1 + arc4random() % 150; + for (int i = 0; i < nadd; i++) + [s appendFormat:@"%c", 32 + (arc4random() % 27)]; + LogMessage([tagsArray objectAtIndex:(arc4random() % [tagsArray count])], arc4random() % 3, s); + } + else if (phase == 1) + { + unsigned char *buf = (unsigned char *)malloc(1024); + int n = 1 + arc4random() % 1024; + for (int i = 0; i < n; i++) + buf[i] = (unsigned char)arc4random(); + NSData *d = [[NSData alloc] initWithBytesNoCopy:buf length:n]; + LogData(@"main", 1, d); + [d release]; + } + else if (phase == 5) + { + imagesCounter++; + UIGraphicsBeginImageContext(CGSizeMake(100, 100)); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGFloat r = (CGFloat)(arc4random() % 256) / 255.0f; + CGFloat g = (CGFloat)(arc4random() % 256) / 255.0f; + CGFloat b = (CGFloat)(arc4random() % 256) / 255.0f; + UIColor *fillColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f]; + CGContextSetFillColorWithColor(ctx, fillColor.CGColor); + CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100)); + CGContextSetTextMatrix(ctx, CGAffineTransformConcat(CGAffineTransformMakeTranslation(0, 100), CGAffineTransformMakeScale(1.0f, -1.0f))); + CGContextSelectFont(ctx, "Helvetica", 14.0, kCGEncodingMacRoman); + CGContextSetShadowWithColor(ctx, CGSizeMake(1, 1), 1.0f, [UIColor whiteColor].CGColor); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor); + char buf[64]; + sprintf(buf, "Log Image %d", image++); + CGContextShowTextAtPoint(ctx, 0, 50, buf, strlen(buf)); + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); + CGSize sz = img.size; + LogImageData(@"image", 0, sz.width, sz.height, UIImagePNGRepresentation(img)); + UIGraphicsEndImageContext(); + } + if (phase == 0) + { + [NSThread detachNewThreadSelector:@selector(sendLogFromAnotherThread:) + toTarget:self + withObject:[NSNumber numberWithInteger:counter++]]; + } + messagesSentLabel.text = [NSString stringWithFormat:@"%d", counter]; + imagesSentLabel.text = [NSString stringWithFormat:@"%d", imagesCounter]; +} + +- (void)sendLogFromAnotherThread:(NSNumber *)counterNum +{ + LogMessage(@"transfers", 0, @"message %d from standalone thread", [counterNum integerValue]); +} + +@end diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Info.plist b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Info.plist new file mode 100644 index 000000000..1b86cf2ce --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.florentpillet.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/LoggerTestAppViewController.xib b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/LoggerTestAppViewController.xib new file mode 100644 index 000000000..8e136cbaf --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/LoggerTestAppViewController.xib @@ -0,0 +1,1047 @@ + + + + 528 + 10F569 + 804 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 123 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 290 + {{119, 279}, {181, 37}} + + NO + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Bold + 15 + 16 + + 1 + + + Stop Sending Logs + Start Sending Logs + + 1 + MSAxIDEAA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MAA + + + + + 290 + {{68, 84}, {232, 31}} + + NO + YES + IBCocoaTouchFramework + 0 + + 3 + + + 3 + MAA + + 2 + + + + Helvetica + 15 + 16 + + YES + 9 + + 1 + 3 + 4 + IBCocoaTouchFramework + + 3 + + + + 292 + {{20, 87}, {40, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Host: + + + 1 + MCAwIDAAA + + + 3 + MQA + + 1 + 10 + + + + 290 + {{20, 7}, {280, 77}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Enter hostname / IP and port # for desktop viewer, leave empty to use Bonjour only. + + + + 1 + 10 + 0 + + + + 290 + {{68, 123}, {108, 31}} + + NO + YES + IBCocoaTouchFramework + 0 + + 3 + + + 3 + MAA + + + + YES + 9 + + 1 + 2 + 9 + IBCocoaTouchFramework + + 3 + + + + 292 + {{20, 126}, {36, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Port: + + + + 1 + 10 + + + + 292 + {{206, 180}, {94, 27}} + + NO + IBCocoaTouchFramework + 0 + 0 + YES + + + + 292 + {{206, 215}, {94, 27}} + + NO + IBCocoaTouchFramework + 0 + 0 + YES + + + + 292 + {{20, 183}, {178, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Search on Bonjour + + + + 1 + 10 + + + + 292 + {{20, 218}, {178, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Local domain only + + + + 1 + 10 + + + + 266 + + YES + + + 268 + {{20, 20}, {120, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Messages sent: + + + 1 + 10 + 2 + + + + 268 + {{20, 49}, {120, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Images sent: + + + 1 + 10 + 2 + + + + 268 + {{148, 20}, {116, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + 0 + + Helvetica-Bold + 17 + 16 + + + + 1 + 10 + + + + 268 + {{148, 49}, {116, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + 0 + + + + 1 + 10 + + + {{0, 370}, {320, 90}} + + + 3 + MC42NjY2NjY2ODY1AA + + 3 + IBCocoaTouchFramework + + + {320, 460} + + + 3 + MC44OTk5OTk5NzYyAA + + NO + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 7 + + + + timerButton + + + + 9 + + + + startStopSendingMessages + + + 7 + + 10 + + + + messagesSentLabel + + + + 15 + + + + imagesSentLabel + + + + 16 + + + + bonjourSettingChanged + + + 13 + + 28 + + + + viewerHostField + + + + 29 + + + + viewerPortField + + + + 30 + + + + delegate + + + + 33 + + + + delegate + + + + 34 + + + + browseBonjour + + + + 35 + + + + browseLocalDomainOnly + + + + 36 + + + + browseLocalDomainOnlySettingChanged + + + 13 + + 37 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + + + + + + + + + + + + 8 + + + + + 17 + + + + + 18 + + + + + 19 + + + + + 20 + + + + + 21 + + + + + 22 + + + + + 23 + + + + + 24 + + + + + 25 + + + + + 31 + + + YES + + + + + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 14 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 11.IBPluginDependency + 11.IBViewBoundsToFrameTransform + 12.IBPluginDependency + 12.IBViewBoundsToFrameTransform + 13.IBPluginDependency + 13.IBViewBoundsToFrameTransform + 14.IBPluginDependency + 14.IBViewBoundsToFrameTransform + 17.IBPluginDependency + 17.IBViewBoundsToFrameTransform + 18.IBPluginDependency + 18.IBViewBoundsToFrameTransform + 19.IBPluginDependency + 19.IBViewBoundsToFrameTransform + 20.IBPluginDependency + 20.IBViewBoundsToFrameTransform + 21.IBPluginDependency + 21.IBViewBoundsToFrameTransform + 22.IBPluginDependency + 22.IBViewBoundsToFrameTransform + 23.IBPluginDependency + 23.IBViewBoundsToFrameTransform + 24.IBPluginDependency + 24.IBViewBoundsToFrameTransform + 25.IBPluginDependency + 25.IBViewBoundsToFrameTransform + 6.IBEditorWindowLastContentRect + 6.IBPluginDependency + 8.IBPluginDependency + 8.IBViewBoundsToFrameTransform + + + YES + LoggerClientViewController + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABAQAAAw4mAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABAQAAAw5gAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDAwAAw4mAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDAwAAw5gAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUK6AABCqAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUGgAABCrgAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCoAAAwpQAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCugAAwxgAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABBoAAAww4AAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUNOAABDNAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDTgAAw4AAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AUGgAABDNwAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABBoAAAw30AAA + + {{34, 620}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABC7gAAw5oAAA + + + + + YES + + + YES + + + + + YES + + + YES + + + + 37 + + + + YES + + LoggerClientViewController + UIViewController + + YES + + YES + bonjourSettingChanged + browseLocalDomainOnlySettingChanged + startStopSendingMessages + + + YES + id + id + id + + + + YES + + YES + bonjourSettingChanged + browseLocalDomainOnlySettingChanged + startStopSendingMessages + + + YES + + bonjourSettingChanged + id + + + browseLocalDomainOnlySettingChanged + id + + + startStopSendingMessages + id + + + + + YES + + YES + browseBonjour + browseLocalDomainOnly + imagesSentLabel + messagesSentLabel + timerButton + viewerHostField + viewerPortField + + + YES + UISwitch + UISwitch + UILabel + UILabel + UIButton + UITextField + UITextField + + + + YES + + YES + browseBonjour + browseLocalDomainOnly + imagesSentLabel + messagesSentLabel + timerButton + viewerHostField + viewerPortField + + + YES + + browseBonjour + UISwitch + + + browseLocalDomainOnly + UISwitch + + + imagesSentLabel + UILabel + + + messagesSentLabel + UILabel + + + timerButton + UIButton + + + viewerHostField + UITextField + + + viewerPortField + UITextField + + + + + IBProjectSource + Classes/LoggerClientViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UISwitch + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UISwitch.h + + + + UITextField + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + NSLoggerTestApp.xcodeproj + 3 + 123 + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/MainWindow.xib b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/MainWindow.xib new file mode 100644 index 000000000..972af1d63 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/MainWindow.xib @@ -0,0 +1,468 @@ + + + + 528 + 10F569 + 788 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 117 + + + YES + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + LoggerTestAppViewController + + + 1 + + IBCocoaTouchFramework + NO + + + + 292 + {320, 480} + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + NSLoggerClient App Delegate + + + -2 + + + + + 10 + + + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + LoggerClientViewController + {{512, 351}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + LoggerClientAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 14 + + + + YES + + LoggerClientAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + LoggerClientViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + LoggerClientViewController + + + window + UIWindow + + + + + IBProjectSource + Classes/LoggerClientAppDelegate.h + + + + LoggerClientViewController + UIViewController + + startStopSendingMessages + id + + + startStopSendingMessages + + startStopSendingMessages + id + + + + timerButton + UIButton + + + timerButton + + timerButton + UIButton + + + + IBProjectSource + Classes/LoggerClientViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + NSLoggerTestApp.xcodeproj + 3 + 117 + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp.xcodeproj/project.pbxproj b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp.xcodeproj/project.pbxproj new file mode 100755 index 000000000..43683a289 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp.xcodeproj/project.pbxproj @@ -0,0 +1,287 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1D3623260D0F684500981E51 /* LoggerClientAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* LoggerClientAppDelegate.m */; }; + 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + 2899E5220DE3E06400AC0155 /* LoggerTestAppViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* LoggerTestAppViewController.xib */; }; + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 28D7ACF80DDB3853001CB0EB /* LoggerClientViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* LoggerClientViewController.m */; }; + 3D62642B125223CA00359022 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D62642A125223CA00359022 /* CFNetwork.framework */; }; + 3DA99CB50F10BC160077756A /* LoggerClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DA99CB40F10BC160077756A /* LoggerClient.m */; }; + 3DB964331274C5E60054F72D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DB964321274C5E50054F72D /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D3623240D0F684500981E51 /* LoggerClientAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggerClientAppDelegate.h; sourceTree = ""; }; + 1D3623250D0F684500981E51 /* LoggerClientAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoggerClientAppDelegate.m; sourceTree = ""; }; + 1D6058910D05DD3D006BFB54 /* NSLoggerClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NSLoggerClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 2899E5210DE3E06400AC0155 /* LoggerTestAppViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoggerTestAppViewController.xib; sourceTree = ""; }; + 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; + 28D7ACF60DDB3853001CB0EB /* LoggerClientViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggerClientViewController.h; sourceTree = ""; }; + 28D7ACF70DDB3853001CB0EB /* LoggerClientViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoggerClientViewController.m; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* NSLoggerTestApp_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSLoggerTestApp_Prefix.pch; sourceTree = ""; }; + 3D0187E01255D10C009D8545 /* LoggerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerCommon.h; path = ../LoggerCommon.h; sourceTree = SOURCE_ROOT; }; + 3D62642A125223CA00359022 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 3DA99CB30F10BC160077756A /* LoggerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerClient.h; path = ../../LoggerClient.h; sourceTree = ""; }; + 3DA99CB40F10BC160077756A /* LoggerClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerClient.m; path = ../../LoggerClient.m; sourceTree = ""; }; + 3DB964321274C5E50054F72D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + 3D62642B125223CA00359022 /* CFNetwork.framework in Frameworks */, + 3DB964331274C5E60054F72D /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 1D3623240D0F684500981E51 /* LoggerClientAppDelegate.h */, + 1D3623250D0F684500981E51 /* LoggerClientAppDelegate.m */, + 28D7ACF60DDB3853001CB0EB /* LoggerClientViewController.h */, + 28D7ACF70DDB3853001CB0EB /* LoggerClientViewController.m */, + ); + path = Classes; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* NSLoggerClient.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 3DAAC60112550D7C000ACF7A /* Logger Client */, + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* NSLoggerTestApp_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 2899E5210DE3E06400AC0155 /* LoggerTestAppViewController.xib */, + 28AD733E0D9D9553002E5188 /* MainWindow.xib */, + 8D1107310486CEB800E47090 /* Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + 3D62642A125223CA00359022 /* CFNetwork.framework */, + 3DB964321274C5E50054F72D /* SystemConfiguration.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3DAAC60112550D7C000ACF7A /* Logger Client */ = { + isa = PBXGroup; + children = ( + 3D0187E01255D10C009D8545 /* LoggerCommon.h */, + 3DA99CB30F10BC160077756A /* LoggerClient.h */, + 3DA99CB40F10BC160077756A /* LoggerClient.m */, + ); + name = "Logger Client"; + path = Classes; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* NSLoggerClient TestApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "NSLoggerClient TestApp" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "NSLoggerClient TestApp"; + productName = NSLoggerClient; + productReference = 1D6058910D05DD3D006BFB54 /* NSLoggerClient.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLoggerTestApp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* NSLoggerClient TestApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, + 2899E5220DE3E06400AC0155 /* LoggerTestAppViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 1D3623260D0F684500981E51 /* LoggerClientAppDelegate.m in Sources */, + 28D7ACF80DDB3853001CB0EB /* LoggerClientViewController.m in Sources */, + 3DA99CB50F10BC160077756A /* LoggerClient.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLoggerTestApp_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_VERSION = ""; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + PRODUCT_NAME = NSLoggerClient; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLoggerTestApp_Prefix.pch; + GCC_VERSION = ""; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + PRODUCT_NAME = NSLoggerClient; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SDKROOT = iphoneos; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "NSLoggerClient TestApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLoggerTestApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..8d3c2596e --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,6 @@ + + + + + diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp_Prefix.pch b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp_Prefix.pch new file mode 100644 index 000000000..a17209c55 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/NSLoggerTestApp_Prefix.pch @@ -0,0 +1,4 @@ +#ifdef __OBJC__ + #import + #import +#endif diff --git a/External Source/NSLogger/Client Logger/iOS/iPhone Test App/main.m b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/main.m new file mode 100644 index 000000000..20cb61532 --- /dev/null +++ b/External Source/NSLogger/Client Logger/iOS/iPhone Test App/main.m @@ -0,0 +1,17 @@ +// +// main.m +// NSLoggerClient +// +// Created by Florent Pillet on 1/4/09. +// Copyright Florent Pillet 2009. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerAppDelegate.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerAppDelegate.h new file mode 100644 index 000000000..06c8efb30 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerAppDelegate.h @@ -0,0 +1,87 @@ +/* + * LoggerAppDelegate.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerConnection, LoggerTransport, LoggerStatusWindowController, LoggerPrefsWindowController; + +@interface LoggerAppDelegate : NSObject +{ + CFArrayRef serverCerts; + BOOL serverCertsLoadAttempted; + NSMutableArray *transports; + NSMutableArray *filterSets; + NSArray *filtersSortDescriptors; + LoggerStatusWindowController *statusController; + LoggerPrefsWindowController *prefsController; +} + +@property (nonatomic, readonly) CFArrayRef serverCerts; +@property (nonatomic, readonly) BOOL serverCertsLoadAttempted; +@property (nonatomic, readonly) NSMutableArray *transports; +@property (nonatomic, readonly) NSMutableArray *filterSets; +@property (nonatomic, retain) NSArray *filtersSortDescriptors; +@property (nonatomic, readonly) LoggerStatusWindowController *statusController; + ++ (NSDictionary *)defaultPreferences; + +- (void)newConnection:(LoggerConnection *)aConnection fromTransport:(LoggerTransport *)aTransport; + +- (NSMutableArray *)defaultFilters; +- (NSNumber *)nextUniqueFilterIdentifier:(NSArray *)filters; +- (void)saveFiltersDefinition; + +- (IBAction)showPreferences:(id)sender; + +- (BOOL)loadEncryptionCertificate:(NSError **)outError; + +@end + +extern NSString * const kPrefKeepMultipleRuns; + +extern NSString * const kPrefPublishesBonjourService; +extern NSString * const kPrefHasDirectTCPIPResponder; +extern NSString * const kPrefDirectTCPIPResponderPort; +extern NSString * const kPrefBonjourServiceName; +extern NSString * const kPrefClientApplicationSettings; + +extern NSString * const kPref_ApplicationFilterSet; + +// Menu item identifiers +#define TOOLS_MENU_ITEM_TAG 1 +#define TOOLS_MENU_ADD_MARK_TAG 1 +#define TOOLS_MENU_ADD_MARK_WITH_TITLE_TAG 2 +#define TOOLS_MENU_INSERT_MARK_TAG 3 +#define TOOLS_MENU_DELETE_MARK_TAG 4 +#define TOOLS_MENU_JUMP_TO_MARK_TAG 5 +#define TOOLS_MENU_HIDE_SHOW_TOOLBAR 7 + +#define VIEW_MENU_ITEM_TAG 2 +#define VIEW_MENU_SWITCH_TO_RUN_TAG 6 diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerAppDelegate.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerAppDelegate.m new file mode 100644 index 000000000..f6935cee3 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerAppDelegate.m @@ -0,0 +1,512 @@ +/* + * LoggerAppDelegate.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#import "LoggerAppDelegate.h" +#import "LoggerNativeTransport.h" +#import "LoggerWindowController.h" +#import "LoggerDocument.h" +#import "LoggerDocumentController.h" +#import "LoggerStatusWindowController.h" +#import "LoggerPrefsWindowController.h" + +NSString * const kPrefKeepMultipleRuns = @"keepMultipleRuns"; + +NSString * const kPrefPublishesBonjourService = @"publishesBonjourService"; +NSString * const kPrefHasDirectTCPIPResponder = @"hasDirectTCPIPResponder"; +NSString * const kPrefDirectTCPIPResponderPort = @"directTCPIPResponderPort"; +NSString * const kPrefBonjourServiceName = @"bonjourServiceName"; +NSString * const kPrefClientApplicationSettings = @"clientApplicationSettings"; + +NSString * const kPref_ApplicationFilterSet = @"appFilterSet"; + +@implementation LoggerAppDelegate +@synthesize transports, filterSets, filtersSortDescriptors, statusController; +@synthesize serverCerts, serverCertsLoadAttempted; + ++ (NSDictionary *)defaultPreferences +{ + static NSDictionary *sDefaultPrefs = nil; + if (sDefaultPrefs == nil) + { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + sDefaultPrefs = [[NSDictionary alloc] initWithObjectsAndKeys: + // [NSNumber numberWithBool:NO], k + [NSNumber numberWithBool:YES], kPrefPublishesBonjourService, + [NSNumber numberWithBool:NO], kPrefHasDirectTCPIPResponder, + [NSNumber numberWithInteger:50000], kPrefDirectTCPIPResponderPort, + @"", kPrefBonjourServiceName, + nil]; + [pool release]; + } + return sDefaultPrefs; +} + ++ (void)load +{ + [[NSUserDefaults standardUserDefaults] registerDefaults:[self defaultPreferences]]; +} + +- (id) init +{ + if ((self = [super init]) != nil) + { + transports = [[NSMutableArray alloc] init]; + + // default filter ordering. The first sort descriptor ensures that the object with + // uid 1 (the "Default Set" filter set or "All Logs" filter) is always on top. Other + // items are ordered by title. + self.filtersSortDescriptors = [NSArray arrayWithObjects: + [NSSortDescriptor sortDescriptorWithKey:@"uid" ascending:YES + comparator: + ^(id uid1, id uid2) + { + if ([uid1 integerValue] == 1) + return (NSComparisonResult)NSOrderedAscending; + if ([uid2 integerValue] == 1) + return (NSComparisonResult)NSOrderedDescending; + return (NSComparisonResult)NSOrderedSame; + }], + [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES], + nil]; + + // resurrect filters before the app nib loads + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSData *filterSetsData = [defaults objectForKey:@"filterSets"]; + if (filterSetsData != nil) + { + filterSets = [[NSKeyedUnarchiver unarchiveObjectWithData:filterSetsData] retain]; + if (![filterSets isKindOfClass:[NSMutableArray class]]) + { + [filterSets release]; + filterSets = nil; + } + } + if (filterSets == nil) + filterSets = [[NSMutableArray alloc] init]; + if (![filterSets count]) + { + NSMutableArray *filters = nil; + + // Try to reload pre-1.0b4 filters (will remove this code soon) + NSData *filterData = [defaults objectForKey:@"filters"]; + if (filterData != nil) + { + filters = [NSKeyedUnarchiver unarchiveObjectWithData:filterData]; + if (![filters isMemberOfClass:[NSMutableArray class]]) + filters = nil; + } + if (filters == nil) + { + // Create a default set + filters = [self defaultFilters]; + } + NSMutableDictionary *defaultSet = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + NSLocalizedString(@"Default Set", @""), @"title", + [NSNumber numberWithInteger:1], @"uid", + filters, @"filters", + nil]; + [filterSets addObject:defaultSet]; + [defaultSet release]; + } + + // fix for issue found by Stefan Neumärker: default filters in versions 1.0b7 were immutable, + // leading to a crash if the user tried to edit them + for (NSDictionary *dict in filterSets) + { + NSMutableArray *filters = [dict objectForKey:@"filters"]; + for (NSUInteger i = 0; i < [filters count]; i++) + { + if (![[filters objectAtIndex:i] isMemberOfClass:[NSMutableDictionary class]]) + { + [filters replaceObjectAtIndex:i + withObject:[[[filters objectAtIndex:i] mutableCopy] autorelease]]; + } + } + } + } + return self; +} + +- (void)dealloc +{ + if (serverCerts != NULL) + CFRelease(serverCerts); + [transports release]; + [super dealloc]; +} + +- (void)saveFiltersDefinition +{ + @try + { + NSData *filterSetsData = [NSKeyedArchiver archivedDataWithRootObject:filterSets]; + if (filterSetsData != nil) + { + [[NSUserDefaults standardUserDefaults] setObject:filterSetsData forKey:@"filterSets"]; + // remove pre-1.0b4 filters + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"filters"]; + } + } + @catch (NSException * e) + { + NSLog(@"Catched exception while trying to archive filters: %@", e); + } +} + +- (void)prefsChangeNotification:(NSNotification *)note +{ + [self performSelector:@selector(startStopTransports) withObject:nil afterDelay:0]; +} + +- (void)startStopTransports +{ + // Start and stop transports as needed + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + for (LoggerTransport *transport in transports) + { + if ([transport isKindOfClass:[LoggerNativeTransport class]]) + { + LoggerNativeTransport *t = (LoggerNativeTransport *)transport; + if (t.publishBonjourService) + { + if ([[ud objectForKey:kPrefPublishesBonjourService] boolValue]) + [t restart]; + else if (t.active) + [t shutdown]; + } + else + { + if ([[ud objectForKey:kPrefHasDirectTCPIPResponder] boolValue]) + [t restart]; + else + [t shutdown]; + } + } + } +} + +- (void)applicationWillFinishLaunching:(NSNotification *)aNotification +{ + // instantiate our controller once to make it the shared document controller + [LoggerDocumentController sharedDocumentController]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + // Listen to prefs change notifications, where we start / stop transports on demand + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(prefsChangeNotification:) + name:kPrefsChangedNotification + object:nil]; + // Prepare the logger status + statusController = [[LoggerStatusWindowController alloc] initWithWindowNibName:@"LoggerStatus"]; + [statusController showWindow:self]; + + /* initialize all supported transports */ + + // unencrypted Bonjour service (for backwards compatibility) + LoggerNativeTransport *t = [[LoggerNativeTransport alloc] init]; + t.publishBonjourService = YES; + t.secure = NO; + [transports addObject:t]; + [t release]; + + // SSL Bonjour service + t = [[LoggerNativeTransport alloc] init]; + t.publishBonjourService = YES; + t.secure = YES; + [transports addObject:t]; + [t release]; + + // Direct TCP/IP service (SSL mandatory) + t = [[LoggerNativeTransport alloc] init]; + t.listenerPort = [[NSUserDefaults standardUserDefaults] integerForKey:kPrefDirectTCPIPResponderPort]; + t.secure = YES; + [transports addObject:t]; + [t release]; + + // start transports + [self performSelector:@selector(startStopTransports) withObject:nil afterDelay:0]; +} + +- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender +{ + return NO; +} + +- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag +{ + return NO; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication +{ + return NO; +} + +- (void)newConnection:(LoggerConnection *)aConnection fromTransport:(LoggerTransport *)aTransport +{ + // we are being called on the main thread (using dispatch_sync() from transport, so take care) + assert([NSThread isMainThread]); + + // Go through all open documents, + // Detect reconnection from a previously disconnected client + NSDocumentController *docController = [NSDocumentController sharedDocumentController]; + for (LoggerDocument *doc in [docController documents]) + { + if (![doc isKindOfClass:[LoggerDocument class]]) + continue; + for (LoggerConnection *c in doc.attachedLogs) + { + if (c != aConnection && [aConnection isNewRunOfClient:c]) + { + // recycle this document window, bring it to front + aConnection.reconnectionCount = ((LoggerConnection *)[doc.attachedLogs lastObject]).reconnectionCount + 1; + [doc addConnection:aConnection]; + return; + } + } + } + + // Instantiate a new window for this connection + LoggerDocument *doc = [[LoggerDocument alloc] initWithConnection:aConnection]; + [docController addDocument:doc]; + [doc makeWindowControllers]; + [doc showWindows]; + [doc release]; +} + +- (NSMutableArray *)defaultFilters +{ + NSMutableArray *filters = [NSMutableArray arrayWithCapacity:4]; + [filters addObject:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInteger:1], @"uid", + NSLocalizedString(@"All logs", @""), @"title", + [NSPredicate predicateWithValue:YES], @"predicate", + nil]]; + [filters addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInteger:2], @"uid", + NSLocalizedString(@"Text messages", @""), @"title", + [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:[NSPredicate predicateWithFormat:@"(messageType == \"text\")"]]], @"predicate", + nil]]; + [filters addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInteger:3], @"uid", + NSLocalizedString(@"Images", @""), @"title", + [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:[NSPredicate predicateWithFormat:@"(messageType == \"img\")"]]], @"predicate", + nil]]; + [filters addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInteger:4], @"uid", + NSLocalizedString(@"Data blocks", @""), @"title", + [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:[NSPredicate predicateWithFormat:@"(messageType == \"data\")"]]], @"predicate", + nil]]; + return filters; +} + +- (NSNumber *)nextUniqueFilterIdentifier:(NSArray *)filters +{ + // since we're using basic NSDictionary to store filters, we add a filter + // identifier number so that no two filters are strictly identical -- makes + // things much easier wih NSArrayController + return [NSNumber numberWithInteger:[[filters valueForKeyPath:@"@max.uid"] integerValue] + 1]; +} + +- (IBAction)showPreferences:(id)sender +{ + if (prefsController == nil) + prefsController = [[LoggerPrefsWindowController alloc] initWithWindowNibName:@"LoggerPrefs"]; + [prefsController showWindow:sender]; +} + +- (void)relaunchApplication +{ + NSString *appToRelaunch = [[NSBundle mainBundle] bundlePath]; + NSString *relaunchToolPath = [[[NSBundle mainBundle] sharedSupportPath] stringByAppendingPathComponent:@"relaunch"]; + [NSTask launchedTaskWithLaunchPath:relaunchToolPath + arguments:[NSArray arrayWithObjects: + appToRelaunch, + [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], + nil]]; + exit(0); +} + +- (BOOL)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recoveryOptionIndex +{ + [self relaunchApplication]; + return NO; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark SSL support +// ----------------------------------------------------------------------------- +- (BOOL)loadEncryptionCertificate:(NSError **)outError +{ + // Load the certificate we need to support encrypted incoming connections via SSL + // + // To this end, we will (once): + // - generate a self-signed certificate and private key + // - import the self-signed certificate and private key into the default keychain + // - retrieve the certificate from the keychain + // - create the required SecIdentityRef for the certificate to be recognized by the CFStream + // - keep this in the running app and use for incoming connections + + if (outError != NULL) + *outError = nil; + + serverCertsLoadAttempted = YES; + + SecKeychainRef keychain; + NSString *failurePoint = NSLocalizedString(@"Can't get the default keychain", @""); + OSStatus status = SecKeychainCopyDefault(&keychain); + for (int pass = 0; pass < 2 && status == noErr && serverCerts == NULL; pass++) + { + // Search through existing identities to find our NSLogger certificate + SecIdentitySearchRef searchRef = NULL; + failurePoint = NSLocalizedString(@"Can't search through default keychain", @""); + status = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_ANY, &searchRef); + if (status == noErr) + { + SecIdentityRef identityRef = NULL; + while (serverCerts == NULL && SecIdentitySearchCopyNext(searchRef, &identityRef) == noErr) + { + SecCertificateRef certRef = NULL; + if (SecIdentityCopyCertificate(identityRef, &certRef) == noErr) + { + CFStringRef commonName = NULL; + if (SecCertificateCopyCommonName(certRef, &commonName) == noErr) + { + if (commonName != NULL && CFStringCompare(commonName, CFSTR("NSLogger SSL"), 0) == kCFCompareEqualTo) + { + // We found our identity + CFTypeRef values[] = { + identityRef, certRef + }; + serverCerts = CFArrayCreate(NULL, values, 2, &kCFTypeArrayCallBacks); + } + if (commonName != NULL) + { + CFRelease(commonName); + } + } + CFRelease(certRef); + } + CFRelease(identityRef); + } + CFRelease(searchRef); + status = noErr; + } + + // Not found: create a cert, import it + if (serverCerts == NULL && status == noErr && pass == 0) + { + // Path to our self-signed certificate + NSString *tempDir = NSTemporaryDirectory(); + NSString *pemFileName = @"NSLoggerCert.pem"; + NSString *pemFilePath = [tempDir stringByAppendingPathComponent:pemFileName]; + NSFileManager *fm = [NSFileManager defaultManager]; + [fm removeItemAtPath:pemFilePath error:nil]; + + // Generate a private certificate + NSArray *args = [NSArray arrayWithObjects: + @"req", + @"-x509", + @"-nodes", + @"-days", @"3650", + @"-config", [[NSBundle mainBundle] pathForResource:@"NSLoggerCertReq" ofType:@"conf"], + @"-newkey", @"rsa:1024", + @"-keyout", pemFileName, + @"-out", pemFileName, + @"-batch", + nil]; + + NSTask *certTask = [[[NSTask alloc] init] autorelease]; + [certTask setLaunchPath:@"/usr/bin/openssl"]; + [certTask setCurrentDirectoryPath:tempDir]; + [certTask setArguments:args]; + [certTask launch]; + do + { + [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]]; + } + while([certTask isRunning]); + + // Load the NSLogger self-signed certificate + NSData *certData = [NSData dataWithContentsOfFile:pemFilePath]; + if (certData == nil) + { + failurePoint = NSLocalizedString(@"Can't load self-signed certificate data", @""); + status = -1; + } + else + { + // Import certificate and private key into our private keychain + SecKeyImportExportParameters kp; + bzero(&kp, sizeof(kp)); + kp.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + SecExternalFormat inputFormat = kSecFormatPEMSequence; + SecExternalItemType itemType = kSecItemTypeAggregate; + failurePoint = NSLocalizedString(@"Failed importing self-signed certificate", @""); + status = SecKeychainItemImport((CFDataRef)certData, + (CFStringRef)pemFileName, + &inputFormat, + &itemType, + 0, // flags are unused + &kp, // import-export parameters + keychain, + NULL); + } + } + } + + if (keychain != NULL) + CFRelease(keychain); + + if (serverCerts == NULL && outError != NULL) + { + if (status == noErr) + failurePoint = NSLocalizedString(@"Failed retrieving our self-signed certificate", @""); + + NSString *errMsg = [NSString stringWithFormat:NSLocalizedString(@"Our private encryption certificate could not be loaded (%@, error code %d)", @""), + failurePoint, status]; + + *outError = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:[NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"NSLogger won't be able to accept SSL connections", @""), NSLocalizedDescriptionKey, + errMsg, NSLocalizedFailureReasonErrorKey, + NSLocalizedString(@"Please contact the application developers", @""), NSLocalizedRecoverySuggestionErrorKey, + nil]]; + } + + return (serverCerts != NULL); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerClientInfoCell.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerClientInfoCell.h new file mode 100644 index 000000000..8ec39fdb8 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerClientInfoCell.h @@ -0,0 +1,37 @@ +/* + * LoggerClientInfoCell.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerMessageCell.h" + +@interface LoggerClientInfoCell : LoggerMessageCell +{ +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerClientInfoCell.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerClientInfoCell.m new file mode 100644 index 000000000..1c07da853 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerClientInfoCell.m @@ -0,0 +1,155 @@ +/* + * LoggerClientInfoCell.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerClientInfoCell.h" +#import "LoggerMessage.h" +#import "LoggerCommon.h" + +@implementation LoggerClientInfoCell + ++ (NSDictionary *)clientInfoAttributes:(BOOL)highlighted +{ + NSMutableDictionary *attrs = [[[[self defaultAttributes] objectForKey:@"text"] mutableCopy] autorelease]; + NSMutableParagraphStyle *style = [[attrs objectForKey:NSParagraphStyleAttributeName] mutableCopy]; + [style setAlignment:NSCenterTextAlignment]; + [attrs setObject:style forKey:NSParagraphStyleAttributeName]; + [style release]; + if (highlighted) + [attrs setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + return attrs; +} + ++ (CGFloat)heightForCellWithMessage:(LoggerMessage *)aMessage maxSize:(NSSize)sz showFunctionNames:(BOOL)showFunctionNames +{ + // return cached cell height if possible + CGFloat minimumHeight = [self minimumHeightForCell]; + NSSize cellSize = aMessage.cachedCellSize; + if (cellSize.width == sz.width) + return cellSize.height; + + cellSize.width = sz.width; + + // new width is larger, but cell already at minimum height, don't recompute + if (cellSize.width > 0 && cellSize.width < sz.width && cellSize.height == minimumHeight) + return minimumHeight; + + sz.width -= 8; + sz.height -= 4; + + NSRect lr = [aMessage.message boundingRectWithSize:sz + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:[self clientInfoAttributes:NO]]; + sz.height = fminf(NSHeight(lr), sz.height); + + // cache and return cell height + cellSize.height = fmaxf(sz.height + 4, minimumHeight); + aMessage.cachedCellSize = cellSize; + return cellSize.height; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + BOOL disconnected = (message.type == LOGMSG_TYPE_DISCONNECT); + BOOL highlighted = [self isHighlighted]; + + // background and separators colors (thank you, Xcode build window) + CGColorRef separatorColor, backgroundColor; + if (disconnected) + { + separatorColor = CGColorCreateGenericRGB(202.0f / 255.0f, + 31.0f / 255.0f, + 27.0f / 255.0f, + 1.0f); + backgroundColor = CGColorCreateGenericRGB(252.0f / 255.0f, + 224.0f / 255.0f, + 224.0f / 255.0f, + 1.0f); + } + else + { + separatorColor = CGColorCreateGenericRGB(28.0f / 255.0f, + 227.0f / 255.0f, + 0.0f, + 1.0f); + backgroundColor = CGColorCreateGenericRGB(224.0f / 255.0f, + 1.0f, + 224.0f / 255.0f, + 1.0f); + } + + // Draw cell background and separators + if (!highlighted) + { + CGContextSetFillColorWithColor(ctx, backgroundColor); + CGContextFillRect(ctx, NSRectToCGRect(cellFrame)); + } + + CGContextSetShouldAntialias(ctx, false); + CGContextSetLineWidth(ctx, 1.0f); + CGContextSetLineCap(ctx, kCGLineCapSquare); + CGContextSetStrokeColorWithColor(ctx, separatorColor); + CGContextBeginPath(ctx); + + // horizontal bottom separator + CGContextMoveToPoint(ctx, NSMinX(cellFrame), floorf(NSMinY(cellFrame))); + CGContextAddLineToPoint(ctx, floorf(NSMaxX(cellFrame)), floorf(NSMinY(cellFrame))); + CGContextMoveToPoint(ctx, NSMinX(cellFrame), floorf(NSMaxY(cellFrame))); + CGContextAddLineToPoint(ctx, NSMaxX(cellFrame), floorf(NSMaxY(cellFrame))); + CGContextStrokePath(ctx); + CGContextSetShouldAntialias(ctx, true); + + CGColorRelease(separatorColor); + CGColorRelease(backgroundColor); + + // If the window is not main, don't change the text color + if (highlighted && ![[controlView window] isMainWindow]) + highlighted = NO; + + // Draw client info + NSRect r = NSMakeRect(NSMinX(cellFrame) + 3, + NSMinY(cellFrame), + NSWidth(cellFrame) - 6, + NSHeight(cellFrame)); + + NSDictionary *attrs = [[self class] clientInfoAttributes:highlighted]; + NSRect lr = [(NSString *)message.message boundingRectWithSize:r.size + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + r.size.height = lr.size.height; + CGFloat offset = floorf((NSHeight(cellFrame) - NSHeight(lr)) / 2.0f); + if (offset > 0) + r.origin.y += offset; + [(NSString *)message.message drawWithRect:r + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerConnection.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerConnection.h new file mode 100644 index 000000000..4dd96cb89 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerConnection.h @@ -0,0 +1,113 @@ +/* + * LoggerConnection.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerConnection, LoggerMessage; + +// ----------------------------------------------------------------------------- +// LoggerConnectionDelegate protocol +// ----------------------------------------------------------------------------- +@protocol LoggerConnectionDelegate +// method that may not be called on main thread +- (void)connection:(LoggerConnection *)theConnection didReceiveMessages:(NSArray *)theMessages range:(NSRange)rangeInMessagesList; +@end + +@interface NSObject (LoggerConnectionDelegateOptional) +// method always called on main thread +- (void)remoteDisconnected:(LoggerConnection *)theConnection; +@end + +// ----------------------------------------------------------------------------- +// NSLoggerConnection class +// ----------------------------------------------------------------------------- +@interface LoggerConnection : NSObject +{ + id delegate; + + // Client info, as transmitted + NSString *clientName; + NSString *clientVersion; + NSString *clientOSName; + NSString *clientOSVersion; + NSString *clientDevice; + NSString *clientUDID; + + NSMutableSet *filenames; // pool of unique file names + NSMutableSet *functionNames; // pool of unique function names + + NSData *clientAddress; // depends on the underlying protocol + + NSMutableArray *messages; + NSMutableArray *parentIndexesStack; // during messages receive, use this to quickly locate parent indexes in groups + dispatch_queue_t messageProcessingQueue; + + int reconnectionCount; // when a reconnection is detected (same client, disconnects then reconnects), the # reconnection for this connection + BOOL connected; + BOOL restoredFromSave; + BOOL attachedToWindow; +} + +@property (retain) id delegate; + +@property (nonatomic, retain) NSString *clientName; +@property (nonatomic, retain) NSString *clientVersion; +@property (nonatomic, retain) NSString *clientOSName; +@property (nonatomic, retain) NSString *clientOSVersion; +@property (nonatomic, retain) NSString *clientDevice; +@property (nonatomic, retain) NSString *clientUDID; + +@property (nonatomic, readonly) NSData *clientAddress; +@property (nonatomic, readonly) NSMutableSet *filenames; +@property (nonatomic, readonly) NSMutableSet *functionNames; + +@property (nonatomic, readonly) NSMutableArray *messages; +@property (nonatomic, assign) int reconnectionCount; +@property (nonatomic, assign) BOOL connected; +@property (nonatomic, readonly) BOOL restoredFromSave; +@property (nonatomic, assign) BOOL attachedToWindow; +@property (nonatomic, readonly) dispatch_queue_t messageProcessingQueue; + +- (id)initWithAddress:(NSData *)anAddress; +- (void)shutdown; + +- (void)messagesReceived:(NSArray *)msgs; +- (void)clientInfoReceived:(LoggerMessage *)message; +- (void)clearMessages; + +- (NSString *)clientAppDescription; +- (NSString *)clientAddressDescription; +- (NSString *)clientDescription; + +- (BOOL)isNewRunOfClient:(LoggerConnection *)aConnection; + +@end + +extern char sConnectionAssociatedObjectKey; diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerConnection.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerConnection.m new file mode 100644 index 000000000..9d90b6d15 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerConnection.m @@ -0,0 +1,406 @@ +/* + * LoggerConnection.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#import +#import "LoggerConnection.h" +#import "LoggerMessage.h" +#import "LoggerCommon.h" +#import "LoggerAppDelegate.h" +#import "LoggerStatusWindowController.h" + +char sConnectionAssociatedObjectKey = 1; + +@implementation LoggerConnection + +@synthesize delegate; +@synthesize messages; +@synthesize reconnectionCount, connected, restoredFromSave, attachedToWindow; +@synthesize clientName, clientVersion, clientOSName, clientOSVersion, clientDevice, clientAddress, clientUDID; +@synthesize messageProcessingQueue; +@synthesize filenames, functionNames; + +- (id)init +{ + if ((self = [super init]) != nil) + { + messageProcessingQueue = dispatch_queue_create("com.florentpillet.nslogger.messageProcessingQueue", NULL); + messages = [[NSMutableArray alloc] initWithCapacity:1024]; + parentIndexesStack = [[NSMutableArray alloc] init]; + filenames = [[NSMutableSet alloc] init]; + functionNames = [[NSMutableSet alloc] init]; + } + return self; +} + +- (id)initWithAddress:(NSData *)anAddress +{ + if ((self = [super init]) != nil) + { + messageProcessingQueue = dispatch_queue_create("com.florentpillet.nslogger.messageProcessingQueue", NULL); + messages = [[NSMutableArray alloc] initWithCapacity:1024]; + parentIndexesStack = [[NSMutableArray alloc] init]; + clientAddress = [anAddress copy]; + filenames = [[NSMutableSet alloc] init]; + functionNames = [[NSMutableSet alloc] init]; + } + return self; +} + +- (void)dealloc +{ + dispatch_release(messageProcessingQueue); + [messages release]; + [parentIndexesStack release]; + [clientName release]; + [clientVersion release]; + [clientOSName release]; + [clientOSVersion release]; + [clientDevice release]; + [clientAddress release]; + [clientUDID release]; + [filenames release]; + [functionNames release]; + [super dealloc]; +} + +- (BOOL)isNewRunOfClient:(LoggerConnection *)aConnection +{ + // Try to detect if a connection is a new run of an older, disconnected session + // (goal is to detect restarts, so as to replace logs in the same window) + assert(restoredFromSave == NO); + + // exclude files loaded from disk + if (aConnection.restoredFromSave) + return NO; + + // as well as still-up connections + if (aConnection.connected) + return NO; + + // check whether client info is the same + BOOL (^isSame)(NSString *, NSString *) = ^(NSString *s1, NSString *s2) + { + if ((s1 == nil) != (s2 == nil)) + return NO; + if (s1 != nil && ![s2 isEqualToString:s1]) + return NO; + return YES; // s1 and d2 either nil or same + }; + + if (!isSame(clientName, aConnection.clientName) || + !isSame(clientVersion, aConnection.clientVersion) || + !isSame(clientOSName, aConnection.clientOSName) || + !isSame(clientOSVersion, aConnection.clientOSVersion) || + !isSame(clientDevice, aConnection.clientDevice)) + { + return NO; + } + + // check whether address is the same, OR hardware ID (if present) is the same. + // hardware ID wins (on desktop, iOS simulator can connect have different + // addresses from run to run if the computer has multiple network interfaces / VMs installed + if (clientUDID != nil && isSame(clientUDID, aConnection.clientUDID)) + return YES; + + if ((clientAddress != nil) != (aConnection.clientAddress != nil)) + return NO; + + if (clientAddress != nil) + { + // compare address blocks sizes (ipv4 vs. ipv6) + NSUInteger addrSize = [clientAddress length]; + if (addrSize != [aConnection.clientAddress length]) + return NO; + + // compare ipv4 or ipv6 address. We don't want to compare the source port, + // because it will change with each connection + if (addrSize == sizeof(struct sockaddr_in)) + { + struct sockaddr_in addra, addrb; + [clientAddress getBytes:&addra]; + [aConnection.clientAddress getBytes:&addrb]; + if (memcmp(&addra.sin_addr, &addrb.sin_addr, sizeof(addra.sin_addr))) + return NO; + } + else if (addrSize == sizeof(struct sockaddr_in6)) + { + struct sockaddr_in6 addr6a, addr6b; + [clientAddress getBytes:&addr6a]; + [aConnection.clientAddress getBytes:&addr6b]; + if (memcmp(&addr6a.sin6_addr, &addr6b.sin6_addr, sizeof(addr6a.sin6_addr))) + return NO; + } + else if (![clientAddress isEqualToData:aConnection.clientAddress]) + return NO; // we only support ipv4 and ipv6, so this should not happen + } + + return YES; +} + +- (void)messagesReceived:(NSArray *)msgs +{ + dispatch_async(messageProcessingQueue, ^{ + /* Code not functional yet + * + NSRange range = NSMakeRange([messages count], [msgs count]); + NSUInteger lastParent = NSNotFound; + if ([parentIndexesStack count]) + lastParent = [[parentIndexesStack lastObject] intValue]; + + for (NSUInteger i = 0, count = [msgs count]; i < count; i++) + { + // update cache for indentation + LoggerMessage *message = [msgs objectAtIndex:i]; + switch (message.type) + { + case LOGMSG_TYPE_BLOCKSTART: + [parentIndexesStack addObject:[NSNumber numberWithInt:range.location+i]]; + lastParent = range.location + i; + break; + + case LOGMSG_TYPE_BLOCKEND: + if ([parentIndexesStack count]) + { + [parentIndexesStack removeLastObject]; + if ([parentIndexesStack count]) + lastParent = [[parentIndexesStack lastObject] intValue]; + else + lastParent = NSNotFound; + } + break; + + default: + if (lastParent != NSNotFound) + { + message.distanceFromParent = range.location + i - lastParent; + message.indent = [parentIndexesStack count]; + } + break; + } + } + * + */ + NSRange range; + @synchronized (messages) + { + range = NSMakeRange([messages count], [msgs count]); + [messages addObjectsFromArray:msgs]; + } + + if (attachedToWindow) + [self.delegate connection:self didReceiveMessages:msgs range:range]; + }); +} + +- (void)clearMessages +{ + // Clear the backlog of messages, only keeping the top (client info) message + // This MUST be called on the messageProcessingQueue + assert(dispatch_get_current_queue() == messageProcessingQueue); + if (![messages count]) + return; + + // Locate the clientInfo message + if (((LoggerMessage *)[messages objectAtIndex:0]).type == LOGMSG_TYPE_CLIENTINFO) + [messages removeObjectsInRange:NSMakeRange(1, [messages count]-1)]; + else + [messages removeAllObjects]; +} + +- (void)clientInfoReceived:(LoggerMessage *)message +{ + // Insert message at first position in the message list. In the unlikely event there is + // an existing ClientInfo message at this position, just replace it. Also, don't fire + // a "didReceiveMessages". The rationale behind this is that if the connection just came in, + // we are not yet attached to a window and when attaching, the window will refresh all messages. + dispatch_async(messageProcessingQueue, ^{ + @synchronized (messages) + { + if ([messages count] == 0 || ((LoggerMessage *)[messages objectAtIndex:0]).type != LOGMSG_TYPE_CLIENTINFO) + [messages insertObject:message atIndex:0]; + } + }); + + // all this stuff occurs on the main thread to avoid touching values + // while the UI reads them + dispatch_async(dispatch_get_main_queue(), ^{ + NSDictionary *parts = message.parts; + id value = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_CLIENT_NAME]]; + if (value != nil) + self.clientName = value; + value = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_CLIENT_VERSION]]; + if (value != nil) + self.clientVersion = value; + value = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_OS_NAME]]; + if (value != nil) + self.clientOSName = value; + value = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_OS_VERSION]]; + if (value != nil) + self.clientOSVersion = value; + value = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_CLIENT_MODEL]]; + if (value != nil) + self.clientDevice = value; + value = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_UNIQUEID]]; + if (value != nil) + self.clientUDID = value; + + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification + object:self]; + }); +} + +- (NSString *)clientAppDescription +{ + // enforce thread safety (only on main thread) + assert([NSThread isMainThread]); + NSMutableString *s = [[[NSMutableString alloc] init] autorelease]; + if (clientName != nil) + [s appendString:clientName]; + if (clientVersion != nil) + [s appendFormat:@" %@", clientVersion]; + if (clientName == nil && clientVersion == nil) + [s appendString:NSLocalizedString(@"", @"")]; + if (clientOSName != nil && clientOSVersion != nil) + [s appendFormat:@"%@(%@ %@)", [s length] ? @" " : @"", clientOSName, clientOSVersion]; + else if (clientOSName != nil) + [s appendFormat:@"%@(%@)", [s length] ? @" " : @"", clientOSName]; + + return s; +} + +- (NSString *)clientAddressDescription +{ + // subclasses should implement this + return @""; +} + +- (NSString *)clientDescription +{ + // enforce thread safety (only on main thread) + assert([NSThread isMainThread]); + return [NSString stringWithFormat:@"%@ @ %@", [self clientAppDescription], [self clientAddressDescription]]; +} + +- (NSString *)status +{ + // status is being observed by LoggerStatusWindowController and changes once + // when the connection gets disconnected + NSString *format; + if (connected) + format = NSLocalizedString(@"%@ connected", @""); + else + format = NSLocalizedString(@"%@ disconnected", @""); + if ([NSThread isMainThread]) + return [NSString stringWithFormat:format, [self clientDescription]]; + __block NSString *status; + dispatch_sync(dispatch_get_main_queue(), ^{ + status = [[NSString stringWithFormat:format, [self clientDescription]] retain]; + }); + return [status autorelease]; +} + +- (void)setConnected:(BOOL)newConnected +{ + if (connected != newConnected) + { + connected = newConnected; + + if (!connected && [(id)delegate respondsToSelector:@selector(remoteDisconnected:)]) + [(id)delegate performSelectorOnMainThread:@selector(remoteDisconnected:) withObject:self waitUntilDone:NO]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification + object:self]; + } +} + +- (void)shutdown +{ + self.connected = NO; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSCoding +// ----------------------------------------------------------------------------- +- (id)initWithCoder:(NSCoder *)aDecoder +{ + if ((self = [super init]) != nil) + { + clientName = [[aDecoder decodeObjectForKey:@"clientName"] retain]; + clientVersion = [[aDecoder decodeObjectForKey:@"clientVersion"] retain]; + clientOSName = [[aDecoder decodeObjectForKey:@"clientOSName"] retain]; + clientOSVersion = [[aDecoder decodeObjectForKey:@"clientOSVersion"] retain]; + clientDevice = [[aDecoder decodeObjectForKey:@"clientDevice"] retain]; + clientUDID = [[aDecoder decodeObjectForKey:@"clientUDID"] retain]; + parentIndexesStack = [[aDecoder decodeObjectForKey:@"parentIndexes"] retain]; + filenames = [[aDecoder decodeObjectForKey:@"filenames"] retain]; + if (filenames == nil) + filenames = [[NSMutableSet alloc] init]; + functionNames = [[aDecoder decodeObjectForKey:@"functionNames"] retain]; + if (functionNames == nil) + functionNames = [[NSMutableSet alloc] init]; + objc_setAssociatedObject(aDecoder, &sConnectionAssociatedObjectKey, self, OBJC_ASSOCIATION_ASSIGN); + messages = [[aDecoder decodeObjectForKey:@"messages"] retain]; + reconnectionCount = [aDecoder decodeIntForKey:@"reconnectionCount"]; + restoredFromSave = YES; + + // we need a messageProcessingQueue just for the ability to add/insert marks + // when user does post-mortem investigation + messageProcessingQueue = dispatch_queue_create("com.florentpillet.nslogger.messageProcessingQueue", NULL); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + if (clientName != nil) + [aCoder encodeObject:clientName forKey:@"clientName"]; + if (clientVersion != nil) + [aCoder encodeObject:clientVersion forKey:@"clientVersion"]; + if (clientOSName != nil) + [aCoder encodeObject:clientOSName forKey:@"clientOSName"]; + if (clientOSVersion != nil) + [aCoder encodeObject:clientOSVersion forKey:@"clientOSVersion"]; + if (clientDevice != nil) + [aCoder encodeObject:clientDevice forKey:@"clientDevice"]; + if (clientUDID != nil) + [aCoder encodeObject:clientUDID forKey:@"clientUDID"]; + [aCoder encodeObject:filenames forKey:@"filenames"]; + [aCoder encodeObject:functionNames forKey:@"functionNames"]; + [aCoder encodeInt:reconnectionCount forKey:@"reconnectionCount"]; + @synchronized (messages) + { + [aCoder encodeObject:messages forKey:@"messages"]; + [aCoder encodeObject:parentIndexesStack forKey:@"parentIndexes"]; + } +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerDetailsWindowController.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDetailsWindowController.h new file mode 100644 index 000000000..c313b6cc4 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDetailsWindowController.h @@ -0,0 +1,44 @@ +/* + * LoggerDetailsWindowController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@interface LoggerDetailsWindowController : NSWindowController +{ + IBOutlet NSTextView *detailsView; + IBOutlet NSTextField *detailsInfo; + IBOutlet NSProgressIndicator *progressIndicator; + + dispatch_queue_t detailsQueue; +} + +- (void)setMessages:(NSArray *)messages; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerDetailsWindowController.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDetailsWindowController.m new file mode 100644 index 000000000..0cbe3d9ca --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDetailsWindowController.m @@ -0,0 +1,115 @@ +/* + * LoggerDetailsWindowController.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerDetailsWindowController.h" +#import "LoggerWindowController.h" +#import "LoggerDocument.h" +#import "LoggerMessage.h" +#import "LoggerMessageCell.h" + +@implementation LoggerDetailsWindowController + +- (void)dealloc +{ + dispatch_release(detailsQueue); + [super dealloc]; +} + +- (NSString *)windowTitleForDocumentDisplayName:(NSString *)displayName +{ + return [[[self document] mainWindowController] windowTitleForDocumentDisplayName:displayName]; +} + +- (void)windowDidLoad +{ + [detailsView setTextContainerInset:NSMakeSize(2, 2)]; +} + +- (void)windowDidBecomeMain:(NSNotification *)notification +{ + [[self.document mainWindowController] updateMenuBar:YES]; +} + +- (void)windowDidResignMain:(NSNotification *)notification +{ + [[self.document mainWindowController] updateMenuBar:YES]; +} + +- (void)setMessages:(NSArray *)messages +{ + // defer text generation to queues + NSTextStorage *storage = [detailsView textStorage]; + [storage replaceCharactersInRange:NSMakeRange(0, [storage length]) withString:@""]; + + NSUInteger numMessages = [messages count]; + [detailsInfo setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Details for %d log messages", @""), numMessages]]; + [progressIndicator setHidden:NO]; + [progressIndicator startAnimation:self]; + + NSDictionary *textAttributes = [[LoggerMessageCell defaultAttributes] objectForKey:@"text"]; + NSDictionary *dataAttributes = [[LoggerMessageCell defaultAttributes] objectForKey:@"data"]; + + NSUInteger i = 0; + while (i < numMessages) + { + NSRange range = NSMakeRange(i, MIN(numMessages-i, 100)); + if (range.length == 0) + break; + i += range.length; + + if (detailsQueue == NULL) + detailsQueue = dispatch_queue_create("com.florentpillet.nslogger.detailsQueue", NULL); + + dispatch_async(detailsQueue, ^{ + NSMutableArray *strings = [[NSMutableArray alloc] initWithCapacity:range.length]; + for (LoggerMessage *msg in [messages subarrayWithRange:range]) + { + NSAttributedString *as = [[NSAttributedString alloc] initWithString:[msg textRepresentation] + attributes:(msg.contentsType == kMessageString) ? textAttributes : dataAttributes]; + [strings addObject:as]; + [as release]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + [storage beginEditing]; + for (NSAttributedString *as in strings) + [storage replaceCharactersInRange:NSMakeRange([storage length], 0) withAttributedString:as]; + [storage endEditing]; + if ((range.location + range.length) >= numMessages) + { + [progressIndicator stopAnimation:self]; + [progressIndicator setHidden:YES]; + } + }); + [strings release]; + }); + } +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerDocument.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDocument.h new file mode 100644 index 000000000..4aa84f2f3 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDocument.h @@ -0,0 +1,50 @@ +/* + * LoggerDocument.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerConnection.h" + +@class LoggerWindowController; + +@interface LoggerDocument : NSDocument +{ + NSMutableArray *attachedLogs; + LoggerConnection *currentConnection; // the connection currently visible in the main window +} + +@property (nonatomic, readonly) NSArray *attachedLogs; +@property (nonatomic, retain) NSNumber *indexOfCurrentVisibleLog; + +- (id)initWithConnection:(LoggerConnection *)aConnection; +- (LoggerWindowController *)mainWindowController; +- (NSArray *)attachedLogsPopupNames; +- (void)addConnection:(LoggerConnection *)newConnection; +- (void)clearLogs:(BOOL)includingPreviousRuns; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerDocument.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDocument.m new file mode 100644 index 000000000..1f66186a7 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerDocument.m @@ -0,0 +1,388 @@ +/* + * LoggerDocument.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerDocument.h" +#import "LoggerWindowController.h" +#import "LoggerTransport.h" +#import "LoggerCommon.h" +#import "LoggerConnection.h" +#import "LoggerNativeMessage.h" +#import "LoggerAppDelegate.h" + +@implementation LoggerDocument + +@synthesize attachedLogs; +@dynamic indexOfCurrentVisibleLog; + ++ (BOOL)canConcurrentlyReadDocumentsOfType:(NSString *)typeName +{ + return YES; +} + +- (id)init +{ + if ((self = [super init]) != nil) + { + attachedLogs = [[NSMutableArray alloc] init]; + } + return self; +} + +- (id)initWithConnection:(LoggerConnection *)aConnection +{ + if (self = [super init]) + { + attachedLogs = [[NSMutableArray alloc] init]; + aConnection.delegate = self; + [attachedLogs addObject:aConnection]; + currentConnection = aConnection; + } + return self; +} + +- (void)close +{ + // since delegate is retained, we need to set it to nil + [attachedLogs makeObjectsPerformSelector:@selector(setDelegate:) withObject:nil]; + [super close]; +} + +- (void)selectRun:(NSInteger)runIndex +{ + if (![attachedLogs count]) + return; + if (runIndex < 0 || runIndex >= [attachedLogs count]) + runIndex = [attachedLogs count] - 1; + currentConnection = [attachedLogs objectAtIndex:runIndex]; +} + +- (NSArray *)attachedLogsPopupNames +{ + NSMutableArray *array = [NSMutableArray arrayWithCapacity:[attachedLogs count]]; + NSUInteger count = [attachedLogs count]; + if (count == 1) + { + int reconnectionCount = ((LoggerConnection *)[attachedLogs lastObject]).reconnectionCount + 1; + [array addObject:[NSString stringWithFormat:NSLocalizedString(@"Run %d", @""), reconnectionCount]]; + } + else for (NSInteger i=0; i < count; i++) + [array addObject:[NSString stringWithFormat:NSLocalizedString(@"Run %d of %d", @""), i+1, count]]; + return array; +} + +- (void)addConnection:(LoggerConnection *)newConnection +{ + newConnection.delegate = self; + [attachedLogs addObject:newConnection]; + + dispatch_async(dispatch_get_main_queue(), ^{ + // add the new connection to our list, potentially clearing previous ones + // if prefs say we shouldn't keep previous logs around + currentConnection = nil; + [self willChangeValueForKey:@"attachedLogsPopupNames"]; + if (![[NSUserDefaults standardUserDefaults] boolForKey:kPrefKeepMultipleRuns]) + { + while ([attachedLogs count] > 1) + [attachedLogs removeObjectAtIndex:0]; + } + [self didChangeValueForKey:@"attachedLogsPopupNames"]; + currentConnection = newConnection; + + // switch the document's associated main window to show this new connection + self.indexOfCurrentVisibleLog = [NSNumber numberWithInteger:[attachedLogs indexOfObjectIdenticalTo:newConnection]]; + }); +} + +- (void)clearLogs:(BOOL)includingPreviousRuns +{ + LoggerConnection *connection = [attachedLogs lastObject]; + + if (includingPreviousRuns) + { + // Remove all previous run logs + [self willChangeValueForKey:@"attachedLogsPopupNames"]; + while ([attachedLogs count] > 1) + [attachedLogs removeObjectAtIndex:0]; + connection.reconnectionCount = 0; + [self didChangeValueForKey:@"attachedLogsPopupNames"]; + } + + // Remove all entries from current run log + dispatch_async(connection.messageProcessingQueue, ^{ + [connection clearMessages]; + dispatch_async(dispatch_get_main_queue(), ^{ + // this forces a full refresh of the view in a clean way + self.indexOfCurrentVisibleLog = self.indexOfCurrentVisibleLog; + }); + }); +} + +- (NSNumber *)indexOfCurrentVisibleLog +{ + NSInteger idx = [attachedLogs indexOfObjectIdenticalTo:currentConnection]; + assert(idx != NSNotFound || currentConnection == nil); + if (idx == NSNotFound) + idx = [attachedLogs count] - 1; + return [NSNumber numberWithInteger:idx]; +} + +- (void)setIndexOfCurrentVisibleLog:(NSNumber *)anIndex +{ + assert([NSThread isMainThread]); + + // First, close all non-main window attached windows + NSMutableArray *windowsToClose = [NSMutableArray array]; + LoggerWindowController *mainWindow = nil; + for (NSWindowController *wc in [self windowControllers]) + { + if (![wc isKindOfClass:[LoggerWindowController class]]) + [windowsToClose addObject:wc]; + else + mainWindow = (LoggerWindowController *)wc; + } + for (NSWindowController *wc in windowsToClose) + [wc close]; + + // Changed the attached connection + [self willChangeValueForKey:@"indexOfCurrentVisibleLog"]; + [self selectRun:[anIndex integerValue]]; + mainWindow.attachedConnection = currentConnection; + [self didChangeValueForKey:@"indexOfCurrentVisibleLog"]; + + // Bring window to front + [mainWindow showWindow:self]; +} + +- (void)dealloc +{ + for (LoggerConnection *connection in attachedLogs) + { + // close the connection (if not already done) and make sure it is removed from transport + for (LoggerTransport *t in ((LoggerAppDelegate *)[NSApp delegate]).transports) + [t removeConnection:connection]; + } + [attachedLogs release]; + [super dealloc]; +} + +- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError +{ + if ([typeName isEqualToString:@"NSLogger Data"]) + { + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:attachedLogs]; + if (data != nil) + return [data writeToURL:absoluteURL atomically:NO]; + } + else if ([typeName isEqualToString:@"public.plain-text"]) + { + // Export messages as text. Only the current visible connection is exported at text + // Make a copy of the array state now so we're not bothered with the array + // changing while we're processing it + NSInteger connectionIndex = [[self indexOfCurrentVisibleLog] integerValue]; + assert(connectionIndex != NSNotFound); + LoggerConnection *connection = [attachedLogs objectAtIndex:connectionIndex]; + __block NSArray *allMessages = nil; + dispatch_sync(connection.messageProcessingQueue , ^{ + allMessages = [[NSArray alloc] initWithArray:connection.messages]; + }); + + BOOL (^flushData)(NSOutputStream*, NSMutableData*) = ^(NSOutputStream *stream, NSMutableData *data) + { + NSUInteger length = [data length]; + const uint8_t *bytes = [data bytes]; + BOOL result = NO; + if (length && bytes != NULL) + { + NSInteger written = [stream write:bytes maxLength:length]; + result = (written == length); + } + [data setLength:0]; + return result; + }; + + BOOL result = NO; + NSOutputStream *stream = [[NSOutputStream alloc] initWithURL:absoluteURL append:NO]; + if (stream != nil) + { + const NSUInteger bufferCapacity = 1024 * 1024; + NSMutableData *data = [[NSMutableData alloc] initWithCapacity:bufferCapacity]; + uint8_t bom[3] = {0xEF, 0xBB, 0xBF}; + [data appendBytes:bom length:3]; + NSAutoreleasePool *pool = nil; + result = YES; + [stream open]; + for (LoggerMessage *message in allMessages) + { + [data appendData:[[message textRepresentation] dataUsingEncoding:NSUTF8StringEncoding]]; + if ([data length] >= bufferCapacity) + { + // periodic flush to reduce memory use while exporting + result = flushData(stream, data); + [pool release]; + pool = [[NSAutoreleasePool alloc] init]; + if (!result) + break; + } + } + if (result) + result = flushData(stream, data); + [stream close]; + [pool release]; + [data release]; + [stream release]; + } + [allMessages release]; + return result; + } + return NO; +} + +- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError +{ + assert([attachedLogs count] == 0); + NSUInteger previousLogs = [attachedLogs count]; + + if ([typeName isEqualToString:@"NSLogger Data"]) + { + id logs = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]; + if ([logs isKindOfClass:[LoggerConnection class]]) + [attachedLogs addObject:logs]; + else + [attachedLogs addObjectsFromArray:logs]; + } + else if ([typeName isEqualToString:@"NSLogger Raw Data"]) + { + LoggerConnection *connection = [[[LoggerConnection alloc] init] autorelease]; + [attachedLogs addObject:connection]; + + NSMutableArray *msgs = [[NSMutableArray alloc] init]; + long dataLength = [data length]; + const uint8_t *p = [data bytes]; + while (dataLength) + { + // check whether we have a full message + uint32_t length; + memcpy(&length, p, 4); + length = ntohl(length); + if (dataLength < (length + 4)) + break; // incomplete last message + + // get one message + CFDataRef subset = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + (unsigned char *)p + 4, + length, + kCFAllocatorNull); + if (subset != NULL) + { + LoggerMessage *message = [[LoggerNativeMessage alloc] initWithData:(NSData *)subset connection:connection]; + if (message.type == LOGMSG_TYPE_CLIENTINFO) + [connection clientInfoReceived:message]; + else + [msgs addObject:message]; + [message release]; + CFRelease(subset); + } + dataLength -= length + 4; + p += length + 4; + } + if ([msgs count]) + [connection messagesReceived:msgs]; + [msgs release]; + } + currentConnection = [attachedLogs lastObject]; + return ([attachedLogs count] != previousLogs); +} + +- (void)makeWindowControllers +{ + LoggerWindowController *controller = [[LoggerWindowController alloc] initWithWindowNibName:@"LoggerWindow"]; + [self addWindowController:controller]; + [controller release]; + + // force assignment of the current connection to the main window + self.indexOfCurrentVisibleLog = [NSNumber numberWithInteger:[attachedLogs indexOfObjectIdenticalTo:currentConnection]]; +} + +- (BOOL)prepareSavePanel:(NSSavePanel *)sp +{ + // assign defaults for the save panel + [sp setTitle:NSLocalizedString(@"Save Logs", @"")]; + [sp setExtensionHidden:NO]; + return YES; +} + +- (NSArray *)writableTypesForSaveOperation:(NSSaveOperationType)saveOperation +{ + NSArray *array = [super writableTypesForSaveOperation:saveOperation]; + if (saveOperation == NSSaveToOperation) + array = [array arrayByAddingObject:@"public.plain-text"]; + return array; +} + +- (LoggerWindowController *)mainWindowController +{ + for (LoggerWindowController *controller in [self windowControllers]) + { + if ([controller isKindOfClass:[LoggerWindowController class]]) + return controller; + } + assert(false); + return nil; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark LoggerConnectionDelegate +// ----------------------------------------------------------------------------- +- (void)connection:(LoggerConnection *)theConnection +didReceiveMessages:(NSArray *)theMessages + range:(NSRange)rangeInMessagesList +{ + LoggerWindowController *wc = [self mainWindowController]; + if (wc.attachedConnection == theConnection) + [wc connection:theConnection didReceiveMessages:theMessages range:rangeInMessagesList]; + if (theConnection.connected) + { + // fixed a crash where calling updateChangeCount: which does not appear to be + // safe when called from a secondary thread + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateChangeCount:NSChangeDone]; + }); + } +} + +- (void)remoteDisconnected:(LoggerConnection *)theConnection +{ + LoggerWindowController *wc = [self mainWindowController]; + if (wc.attachedConnection == theConnection) + [wc remoteDisconnected:theConnection]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerIPConnection.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerIPConnection.h new file mode 100644 index 000000000..83c205ba1 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerIPConnection.h @@ -0,0 +1,38 @@ +/* + * LoggerIPConnection.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerConnection.h" + + +@interface LoggerIPConnection : LoggerConnection +{ +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerIPConnection.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerIPConnection.m new file mode 100644 index 000000000..62d907e45 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerIPConnection.m @@ -0,0 +1,63 @@ +/* + * LoggerIPConnection.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#import "LoggerIPConnection.h" + +@implementation LoggerIPConnection + +- (NSString *)clientAddressDescription +{ + if ([clientAddress length] == sizeof(struct sockaddr_in6)) + { + struct sockaddr_in6 addr6; + [clientAddress getBytes:&addr6 length:sizeof(addr6)]; + return [NSString stringWithFormat:@"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + addr6.sin6_addr.__u6_addr.__u6_addr16[0], + addr6.sin6_addr.__u6_addr.__u6_addr16[1], + addr6.sin6_addr.__u6_addr.__u6_addr16[2], + addr6.sin6_addr.__u6_addr.__u6_addr16[3], + addr6.sin6_addr.__u6_addr.__u6_addr16[4], + addr6.sin6_addr.__u6_addr.__u6_addr16[5], + addr6.sin6_addr.__u6_addr.__u6_addr16[6], + addr6.sin6_addr.__u6_addr.__u6_addr16[7]]; + } + + struct sockaddr_in addr4; + [clientAddress getBytes:&addr4 length:sizeof(addr4)]; + char *inetname = inet_ntoa(addr4.sin_addr); + if (inetname != NULL) + return [NSString stringWithCString:inetname encoding:NSASCIIStringEncoding]; + + return nil; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerMarkerCell.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMarkerCell.h new file mode 100644 index 000000000..9ce4632e3 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMarkerCell.h @@ -0,0 +1,37 @@ +/* + * LoggerMarkerCell.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerMessageCell.h" + +@interface LoggerMarkerCell : LoggerMessageCell +{ +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerMarkerCell.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMarkerCell.m new file mode 100644 index 000000000..895ed7857 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMarkerCell.m @@ -0,0 +1,135 @@ +/* + * LoggerMarkerCell.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerMarkerCell.h" +#import "LoggerMessage.h" + +@implementation LoggerMarkerCell + ++ (NSDictionary *)markAttributes:(BOOL)highlighted +{ + NSMutableDictionary *attrs = [[self defaultAttributes] objectForKey:@"mark"]; + if (highlighted) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + } + return attrs; +} + ++ (CGFloat)heightForCellWithMessage:(LoggerMessage *)aMessage maxSize:(NSSize)sz showFunctionNames:(BOOL)showFunctionNames +{ + // return cached cell height if possible + CGFloat minimumHeight = [self minimumHeightForCell]; + NSSize cellSize = aMessage.cachedCellSize; + if (cellSize.width == sz.width) + return cellSize.height; + + cellSize.width = sz.width; + + // new width is larger, but cell already at minimum height, don't recompute + if (cellSize.width > 0 && cellSize.width < sz.width && cellSize.height == minimumHeight) + return minimumHeight; + + sz.width -= 8; + sz.height -= 4; + + NSRect lr = [aMessage.message boundingRectWithSize:sz + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:[self markAttributes:NO]]; + sz.height = fminf(NSHeight(lr), sz.height); + + // cache and return cell height + cellSize.height = fmaxf(sz.height + 4, minimumHeight); + aMessage.cachedCellSize = cellSize; + return cellSize.height; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + cellFrame.size = message.cachedCellSize; + + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + BOOL highlighted = [self isHighlighted]; + + CGColorRef separatorColor = CGColorCreateGenericRGB(162.0f / 255.0f, + 174.0f / 255.0f, + 10.0f / 255.0f, + 1.0f); + CGColorRef backgroundColor = CGColorCreateGenericRGB(1.0f, + 1.0f, + 197.0f / 255.0f, + 1.0f); + + if (!highlighted) + { + CGContextSetFillColorWithColor(ctx, backgroundColor); + CGContextFillRect(ctx, NSRectToCGRect(cellFrame)); + } + + CGContextSetShouldAntialias(ctx, false); + CGContextSetLineWidth(ctx, 1.0f); + CGContextSetLineCap(ctx, kCGLineCapSquare); + CGContextSetStrokeColorWithColor(ctx, separatorColor); + + CGContextBeginPath(ctx); + CGContextMoveToPoint(ctx, NSMinX(cellFrame), floorf(NSMinY(cellFrame))); + CGContextAddLineToPoint(ctx, floorf(NSMaxX(cellFrame)), floorf(NSMinY(cellFrame))); + CGContextMoveToPoint(ctx, NSMinX(cellFrame), floorf(NSMaxY(cellFrame))); + CGContextAddLineToPoint(ctx, NSMaxX(cellFrame), floorf(NSMaxY(cellFrame))); + CGContextStrokePath(ctx); + CGContextSetShouldAntialias(ctx, true); + + CGColorRelease(separatorColor); + CGColorRelease(backgroundColor); + + // If the window is not main, don't change the text color + if (highlighted && ![[controlView window] isMainWindow]) + highlighted = NO; + + NSRect r = NSMakeRect(NSMinX(cellFrame) + 3, + NSMinY(cellFrame), + NSWidth(cellFrame) - 6, + NSHeight(cellFrame)); + + NSDictionary *attrs = [[self class] markAttributes:highlighted]; + NSRect lr = [(NSString *)message.message boundingRectWithSize:r.size + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + r.size.height = lr.size.height; + CGFloat offset = floorf((NSHeight(cellFrame) - NSHeight(lr)) / 2.0f); + if (offset > 0) + r.origin.y += offset; + [(NSString *)message.message drawWithRect:r + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessage.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessage.h new file mode 100644 index 000000000..b51ddfbdd --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessage.h @@ -0,0 +1,89 @@ +/* + * LoggerMessage.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#import + +@class LoggerConnection; + +@interface LoggerMessage : NSObject +{ + struct timeval timestamp; // seconds and microseconds + + NSString *tag; // non-retained (we use a global pool for domains) + NSString *filename; // non-retained (we use a connection-attached pool for filenames) + NSString *functionName; // non-retained (we use a connection-attached pool for function names) + NSMutableDictionary *parts; // for non-standard parts transmitted by the clients, store the data in this dictionary + id message; // NSString, NSData or image data + NSImage *image; // if the message is an image, the image gets decoded once it's being accessed + + NSUInteger sequence; // message's number if order of reception + + NSString *threadID; + + int lineNumber; // line number in the file, if filename != nil + + short level; + short type; + short contentsType; // the type of message data (string, data, image) + + // unsaved cached data + NSSize imageSize; + NSSize cachedCellSize; // we use this to cache the cell's height when recomputing if the width didn't change +} + +@property (nonatomic, assign) short contentsType; +@property (nonatomic, retain) NSDictionary *parts; +@property (nonatomic, assign) struct timeval timestamp; // full timestamp (seconds & microseconds) +@property (nonatomic, retain) NSString *tag; +@property (nonatomic, retain) id message; +@property (nonatomic, assign) short type; +@property (nonatomic, assign) short level; +@property (nonatomic, retain) NSString *threadID; +@property (nonatomic, readonly) NSSize imageSize; +@property (nonatomic, assign) NSSize cachedCellSize; +@property (nonatomic, retain) NSImage *image; +@property (nonatomic, readonly, assign) NSString *filename; +@property (nonatomic, readonly, assign) NSString *functionName; +@property (nonatomic, assign) int lineNumber; + +- (void)computeTimeDelta:(struct timeval *)td since:(LoggerMessage *)previousMessage; +- (NSString *)textRepresentation; + +- (void)setFilename:(NSString *)aFilename connection:(LoggerConnection *)aConnection; +- (void)setFunctionName:(NSString *)aFunctionName connection:(LoggerConnection *)aConnection; + +@end + +enum { + kMessageString = 0, + kMessageData, + kMessageImage +}; diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessage.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessage.m new file mode 100644 index 000000000..5107e0c0b --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessage.m @@ -0,0 +1,339 @@ +/* + * LoggerMessage.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#import "LoggerMessage.h" +#import "LoggerCommon.h" +#import "LoggerConnection.h" + +static NSMutableArray *sTags = nil; + +@implementation LoggerMessage + +@synthesize tag, message, threadID; +@synthesize type, contentsType, level, timestamp; +@synthesize parts; +@synthesize cachedCellSize, image, imageSize; +@synthesize filename, functionName, lineNumber; + +- (id) init +{ + if ((self = [super init]) != nil) + { + filename = @""; + functionName = @""; + } + return self; +} + +- (void)dealloc +{ + // remember that tag is non-retained + [parts release]; + [message release]; + [image release]; + [threadID release]; + [super dealloc]; +} + +- (NSImage *)image +{ + if (contentsType != kMessageImage) + return nil; + if (image == nil) + image = [[NSImage alloc] initWithData:message]; + return image; +} + +- (NSSize)imageSize +{ + if (imageSize.width == 0 || imageSize.height == 0) + imageSize = self.image.size; + return imageSize; +} + +- (NSString *)textRepresentation +{ + // Prepare a text representation of the message, suitable for export of text field display + time_t sec = timestamp.tv_sec; + struct tm *t = localtime(&sec); + + if (contentsType == kMessageString) + { + if (type == LOGMSG_TYPE_MARK) + return [NSString stringWithFormat:@"%@\n", message]; + + /* commmon case */ + + // if message is empty, use the function name (typical case of using a log to record + // a "waypoint" in the code flow) + NSString *s = message; + if (![s length] && [functionName length]) + s = functionName; + + return [NSString stringWithFormat:@"[%-8lu] %02d:%02d:%02d.%03d | %@ | %@ | %@\n", + sequence, + t->tm_hour, t->tm_min, t->tm_sec, timestamp.tv_usec / 1000, + (tag == NULL) ? @"-" : tag, + threadID, + message]; + } + + NSString *header = [NSString stringWithFormat:@"[%-8lu] %02d:%02d:%02d.%03d | %@ | %@ | ", + sequence, t->tm_hour, t->tm_min, t->tm_sec, timestamp.tv_usec / 1000, + (tag == NULL) ? @"-" : tag, + threadID]; + + if (contentsType == kMessageImage) + return [NSString stringWithFormat:@"%@IMAGE size=%dx%d px\n", header, (int)self.imageSize.width, (int)self.imageSize.height]; + + assert([message isKindOfClass:[NSData class]]); + NSMutableString *s = [[NSMutableString alloc] init]; + [s appendString:header]; + NSUInteger offset = 0, dataLen = [message length]; + NSString *str; + char buffer[1+6+16*3+1+16+1+1+1]; + buffer[0] = '\0'; + const unsigned char *q = [message bytes]; + if (dataLen == 1) + [s appendString:NSLocalizedString(@"Raw data, 1 byte:\n", @"")]; + else + [s appendFormat:NSLocalizedString(@"Raw data, %u bytes:\n", @""), dataLen]; + while (dataLen) + { + int i, b = sprintf(buffer," %04x: ", offset); + for (i=0; i < 16 && i < dataLen; i++) + sprintf(&buffer[b+3*i], "%02x ", (int)q[i]); + for (int j=i; j < 16; j++) + strcat(buffer, " "); + + b = strlen(buffer); + buffer[b++] = '\''; + for (i=0; i < 16 && i < dataLen; i++) + { + if (q[i] >= 32 && q[i] < 128) + buffer[b++] = q[i]; + else + buffer[b++] = ' '; + } + for (int j=i; j < 16; j++) + buffer[b++] = ' '; + buffer[b++] = '\''; + buffer[b++] = '\n'; + buffer[b] = 0; + + str = [[NSString alloc] initWithBytes:buffer length:strlen(buffer) encoding:NSISOLatin1StringEncoding]; + [s appendString:str]; + [str release]; + + dataLen -= i; + offset += i; + q += i; + } + return [s autorelease]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSCoding +// ----------------------------------------------------------------------------- +- (id)initWithCoder:(NSCoder *)decoder +{ + if ((self = [super init]) != nil) + { + timestamp.tv_sec = [decoder decodeInt64ForKey:@"s"]; + timestamp.tv_usec = [decoder decodeInt64ForKey:@"us"]; + parts = [[decoder decodeObjectForKey:@"p"] retain]; + message = [[decoder decodeObjectForKey:@"m"] retain]; + sequence = [decoder decodeIntForKey:@"n"]; + threadID = [[decoder decodeObjectForKey:@"t"] retain]; + level = [decoder decodeIntForKey:@"l"]; + type = [decoder decodeIntForKey:@"mt"]; + contentsType = [decoder decodeIntForKey:@"ct"]; + + // reload the filename / function name / line number. Since this is a pool + // kept by the LoggerConnection itself, we use the runtime's associated objects + // feature to get a hold on the LoggerConnection object + LoggerConnection *cnx = objc_getAssociatedObject(decoder, &sConnectionAssociatedObjectKey); + NSString *s = [decoder decodeObjectForKey:@"f"]; + if (s != nil) + [self setFilename:s connection:cnx]; + else + filename = @""; + s = [decoder decodeObjectForKey:@"fn"]; + if (s != nil) + [self setFunctionName:s connection:cnx]; + else + functionName = @""; + lineNumber = [decoder decodeIntForKey:@"ln"]; + + self.tag = [decoder decodeObjectForKey:@"tag"]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)encoder +{ + // try to omit info with zero value to save space when saving + [encoder encodeInt64:timestamp.tv_sec forKey:@"s"]; + [encoder encodeInt64:timestamp.tv_usec forKey:@"us"]; + if ([tag length]) + [encoder encodeObject:tag forKey:@"tag"]; + if (parts != nil) + [encoder encodeObject:parts forKey:@"p"]; + if (message != nil) + [encoder encodeObject:message forKey:@"m"]; + [encoder encodeInt:sequence forKey:@"n"]; + if ([threadID length]) + [encoder encodeObject:threadID forKey:@"t"]; + if (level) + [encoder encodeInt:level forKey:@"l"]; + if (type) + [encoder encodeInt:type forKey:@"mt"]; + if (contentsType) + [encoder encodeInt:contentsType forKey:@"ct"]; + if (filename != nil) + [encoder encodeObject:filename forKey:@"f"]; + if (functionName != nil) + [encoder encodeObject:functionName forKey:@"fn"]; + if (lineNumber != 0) + [encoder encodeInt:lineNumber forKey:@"ln"]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSCopying +// ----------------------------------------------------------------------------- +- (id)copyWithZone:(NSZone *)zone +{ + // Used only for displaying, we can afford not providing a real copy here + return [self retain]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Special methods for use by predicates +// ----------------------------------------------------------------------------- +- (NSString *)messageText +{ + if (contentsType == kMessageString) + return message; + return @""; +} + +- (NSString *)messageType +{ + if (contentsType == kMessageString) + return @"text"; + if (contentsType == kMessageData) + return @"data"; + return @"img"; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Other +// ----------------------------------------------------------------------------- +- (void)setTag:(NSString *)aTag +{ + // we're accumulating the various domains in a global list + // so as to reduce memory use + if (aTag == nil) + return; + NSUInteger pos = [sTags indexOfObject:aTag]; + if (pos == NSNotFound || sTags == nil) + { + if (sTags == nil) + sTags = [[NSMutableArray alloc] init]; + [sTags addObject:aTag]; + tag = aTag; + } + else + tag = [sTags objectAtIndex:pos]; +} + +- (void)setFilename:(NSString *)aFilename connection:(LoggerConnection *)aConnection +{ + NSString *s = [aConnection.filenames member:aFilename]; + if (s == nil) + { + [aConnection.filenames addObject:aFilename]; + filename = aFilename; + } + else + filename = s; +} + +- (void)setFunctionName:(NSString *)aFunctionName connection:(LoggerConnection *)aConnection +{ + NSString *s = [aConnection.functionNames member:aFunctionName]; + if (s == nil) + { + [aConnection.functionNames addObject:aFunctionName]; + functionName = aFunctionName; + } + else + functionName = s; +} + +- (void)computeTimeDelta:(struct timeval *)td since:(LoggerMessage *)previousMessage +{ + assert(previousMessage != NULL); + double t1 = (double)timestamp.tv_sec + ((double)timestamp.tv_usec) / 1000000.0; + double t2 = (double)previousMessage->timestamp.tv_sec + ((double)previousMessage->timestamp.tv_usec) / 1000000.0; + double t = t1 - t2; + td->tv_sec = (__darwin_time_t)t; + td->tv_usec = (__darwin_suseconds_t)((t - (double)td->tv_sec) * 1000000.0); +} + +#ifdef DEBUG +-(NSString *)description +{ + NSString *typeString = ((type == LOGMSG_TYPE_LOG) ? @"Log" : + (type == LOGMSG_TYPE_CLIENTINFO) ? @"ClientInfo" : + (type == LOGMSG_TYPE_DISCONNECT) ? @"Disconnect" : + (type == LOGMSG_TYPE_BLOCKSTART) ? @"BlockStart" : + (type == LOGMSG_TYPE_BLOCKEND) ? @"BlockEnd" : + (type == LOGMSG_TYPE_MARK) ? @"Mark" : + @"Unknown"); + NSString *desc; + if (contentsType == kMessageData) + desc = [NSString stringWithFormat:@"{data %u bytes}", [message length]]; + else if (contentsType == kMessageImage) + desc = [NSString stringWithFormat:@"{image w=%d h=%d}", [self imageSize].width, [self imageSize].height]; + else + desc = (NSString *)message; + + return [NSString stringWithFormat:@"<%@ %p seq=%d type=%@ thread=%@ tag=%@ level=%d message=%@>", + [self class], self, sequence, typeString, threadID, tag, (int)level, desc]; +} +#endif + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessageCell.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessageCell.h new file mode 100644 index 000000000..dab987b9c --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessageCell.h @@ -0,0 +1,61 @@ +/* + * LoggerMessageCell.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerMessage; + +@interface LoggerMessageCell : NSCell +{ + LoggerMessage *message; + LoggerMessage *previousMessage; + + NSDictionary *messageAttributes; + + CGFloat timestampColumnWidth; + CGFloat threadIDColumnWidth; + + BOOL shouldShowFunctionNames; +} + +@property (nonatomic, retain) LoggerMessage *message; +@property (nonatomic, retain) LoggerMessage *previousMessage; +@property (nonatomic, retain) NSDictionary *messageAttributes; +@property (nonatomic, assign) BOOL shouldShowFunctionNames; + ++ (NSDictionary *)defaultAttributesDictionary; ++ (NSDictionary *)defaultAttributes; ++ (void)setDefaultAttributes:(NSDictionary *)newAttributes; ++ (CGFloat)heightForCellWithMessage:(LoggerMessage *)aMessage maxSize:(NSSize)sz showFunctionNames:(BOOL)showFunctionNames; ++ (CGFloat)minimumHeightForCell; + +@end + +extern NSString * const kMessageAttributesChangedNotification; diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessageCell.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessageCell.m new file mode 100644 index 000000000..24fb4f53f --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerMessageCell.m @@ -0,0 +1,923 @@ +/* + * LoggerMessageCell.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#import "LoggerMessageCell.h" +#import "LoggerMessage.h" +#import "LoggerUtils.h" + +#define MAX_DATA_LINES 16 // max number of data lines to show + +#define MINIMUM_CELL_HEIGHT 30.0f +#define INDENTATION_TAB_WIDTH 10.0f // in pixels + +#define TIMESTAMP_COLUMN_WIDTH 85.0f +#define THREAD_COLUMN_WIDTH 85.0f + +static NSMutableDictionary *sDefaultAttributes = nil; +static NSColor *sDefaultTagAndLevelColor = nil; +static CGFloat sMinimumHeightForCell = 0; +static CGFloat sDefaultFileLineFunctionHeight = 0; + +NSString * const kMessageAttributesChangedNotification = @"MessageAttributesChangedNotification"; +NSString * const kMessageColumnWidthsChangedNotification = @"MessageColumnWidthsChangedNotification"; + +@implementation LoggerMessageCell + +@synthesize message, previousMessage, messageAttributes; +@synthesize shouldShowFunctionNames; + +// ----------------------------------------------------------------------------- +// Class methods +// ----------------------------------------------------------------------------- + +#pragma mark - +#pragma mark Colors and text attributes + ++ (NSColor *)cellStandardBgColor +{ + static NSColor *sColor = nil; + if (sColor == nil) + sColor = [[NSColor colorWithCalibratedWhite:0.90 alpha:1.0] retain]; + return sColor; +} + ++ (NSColor *)cellSeparatorColor +{ + static NSColor *sColor = nil; + if (sColor == nil) + sColor = [[NSColor colorWithCalibratedWhite:0.75 alpha:1.0] retain]; + return sColor; +} + ++ (NSDictionary *)defaultAttributesDictionary +{ + NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; + + // Preferrably use Consolas, but revert to other fonts if not installed (fix by Steven Woolgar) + NSFont *defaultFont = [NSFont fontWithName:@"Lucida Grande" size:11]; + NSFont *defaultTagAndLevelFont = [NSFont fontWithName:@"Lucida Grande Bold" size:9]; + NSFont *defaultMonospacedFont = [NSFont fontWithName:@"Consolas" size:11]; + if (defaultMonospacedFont == nil) + defaultMonospacedFont = [NSFont fontWithName:@"Menlo" size:11]; + if (defaultMonospacedFont == nil) + defaultMonospacedFont = [NSFont fontWithName:@"Courier" size:11]; + + // Default text attributes + NSMutableDictionary *dict; + NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + [style setLineBreakMode:NSLineBreakByTruncatingTail]; + NSMutableDictionary *textAttrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + defaultFont, NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + style, NSParagraphStyleAttributeName, + nil]; + [style release]; + + // Timestamp attributes + [attrs setObject:textAttrs forKey:@"timestamp"]; + + // Time Delta attributes + dict = [textAttrs mutableCopy]; + [dict setObject:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; + [attrs setObject:dict forKey:@"timedelta"]; + [dict release]; + + // Thread ID attributes + dict = [textAttrs mutableCopy]; + [dict setObject:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; + [attrs setObject:dict forKey:@"threadID"]; + [dict release]; + + // Tag and Level attributes + dict = [textAttrs mutableCopy]; + [dict setObject:defaultTagAndLevelFont forKey:NSFontAttributeName]; + [dict setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + [attrs setObject:dict forKey:@"tag"]; + [attrs setObject:dict forKey:@"level"]; + [dict release]; + + // Text message attributes + dict = [textAttrs mutableCopy]; + [dict setObject:defaultMonospacedFont forKey:NSFontAttributeName]; + style = [[dict objectForKey:NSParagraphStyleAttributeName] mutableCopy]; + [style setLineBreakMode:NSLineBreakByWordWrapping]; + [dict setObject:style forKey:NSParagraphStyleAttributeName]; + [style release]; + [attrs setObject:dict forKey:@"text"]; + [dict release]; + + // Data message attributes + dict = [textAttrs mutableCopy]; + [dict setObject:defaultMonospacedFont forKey:NSFontAttributeName]; + [attrs setObject:dict forKey:@"data"]; + [dict release]; + + // Mark attributes + dict = [textAttrs mutableCopy]; + [dict setObject:defaultMonospacedFont forKey:NSFontAttributeName]; + style = [[dict objectForKey:NSParagraphStyleAttributeName] mutableCopy]; + [style setAlignment:NSCenterTextAlignment]; + [dict setObject:style forKey:NSParagraphStyleAttributeName]; + [style release]; + [attrs setObject:dict forKey:@"mark"]; + [dict release]; + + // File / Line / Function name attributes + dict = [textAttrs mutableCopy]; + [dict setObject:defaultTagAndLevelFont forKey:NSFontAttributeName]; + [dict setObject:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; + NSColor *fillColor = [NSColor colorWithCalibratedRed:(239.0f / 255.0f) + green:(233.0f / 255.0f) + blue:(252.0f / 255.0f) + alpha:1.0f]; + [dict setObject:fillColor forKey:NSBackgroundColorAttributeName]; + style = [[dict objectForKey:NSParagraphStyleAttributeName] mutableCopy]; + [style setLineBreakMode:NSLineBreakByTruncatingMiddle]; + [dict setObject:style forKey:NSParagraphStyleAttributeName]; + [style release]; + [attrs setObject:dict forKey:@"fileLineFunction"]; + [dict release]; + + return attrs; +} + ++ (NSDictionary *)defaultAttributes +{ + if (sDefaultAttributes == nil) + { + // Try to load the default text attributes from user defaults + NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"Message Attributes"]; + if (data != nil) + sDefaultAttributes = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]; + if (sDefaultAttributes == nil) + [self setDefaultAttributes:[self defaultAttributesDictionary]]; + + // upgrade from pre-1.0b5, adding attributes for markers + if ([sDefaultAttributes objectForKey:@"mark"] == nil) + { + NSMutableDictionary *attrs = [sDefaultAttributes mutableCopy]; + NSMutableDictionary *dict = [[sDefaultAttributes objectForKey:@"text"] mutableCopy]; + NSMutableParagraphStyle *style = [[dict objectForKey:NSParagraphStyleAttributeName] mutableCopy]; + [style setAlignment:NSCenterTextAlignment]; + [dict setObject:style forKey:NSParagraphStyleAttributeName]; + [style release]; + [attrs setObject:dict forKey:@"mark"]; + [dict release]; + [self setDefaultAttributes:attrs]; + [attrs release]; + } + + // update from pre-1.0b7, adding attributes for file / line / function + if ([sDefaultAttributes objectForKey:@"fileLineFunction"] == nil) + { + NSMutableDictionary *attrs = [sDefaultAttributes mutableCopy]; + NSMutableDictionary *dict = [[attrs objectForKey:@"tag"] mutableCopy]; + [dict setObject:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; + NSColor *fillColor = [NSColor colorWithCalibratedRed:(239.0f / 255.0f) + green:(233.0f / 255.0f) + blue:(252.0f / 255.0f) + alpha:1.0f]; + [dict setObject:fillColor forKey:NSBackgroundColorAttributeName]; + [attrs setObject:dict forKey:@"fileLineFunction"]; + [dict release]; + [self setDefaultAttributes:attrs]; + [attrs release]; + } + + // update from pre-1.0b9, setting middle truncation for file/line/function + NSParagraphStyle *style = [[sDefaultAttributes objectForKey:@"fileLineFunction"] objectForKey:NSParagraphStyleAttributeName]; + if ([style lineBreakMode] != NSLineBreakByTruncatingMiddle) + { + NSMutableDictionary *attrs = [sDefaultAttributes mutableCopy]; + NSMutableDictionary *dict = [[attrs objectForKey:@"fileLineFunction"] mutableCopy]; + NSMutableParagraphStyle *style = [[dict objectForKey:NSParagraphStyleAttributeName] mutableCopy]; + [style setLineBreakMode:NSLineBreakByTruncatingMiddle]; + [dict setObject:style forKey:NSParagraphStyleAttributeName]; + [style release]; + [attrs setObject:dict forKey:@"fileLineFunction"]; + [dict release]; + [self setDefaultAttributes:attrs]; + [attrs release]; + } + } + return sDefaultAttributes; +} + ++ (void)setDefaultAttributes:(NSDictionary *)newAttributes +{ + [sDefaultAttributes release]; + sDefaultAttributes = [newAttributes copy]; + sMinimumHeightForCell = 0; + sDefaultFileLineFunctionHeight = 0; + [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:sDefaultAttributes] forKey:@"Message Attributes"]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMessageAttributesChangedNotification object:nil]; +} + ++ (NSColor *)defaultTagAndLevelColor +{ + if (sDefaultTagAndLevelColor == nil) + sDefaultTagAndLevelColor = [[NSColor colorWithCalibratedRed:0.51f green:0.57f blue:0.79f alpha:1.0f] retain]; + return sDefaultTagAndLevelColor; +} + ++ (NSColor *)colorForTag:(NSString *)tag +{ + // @@@ TODO: tag color customization mechanism + return [self defaultTagAndLevelColor]; +} + +#pragma mark - +#pragma mark Helpers + ++ (NSArray *)stringsWithData:(NSData *)data +{ + // convert NSData block to hex-ascii strings + NSMutableArray *strings = [[NSMutableArray alloc] init]; + NSUInteger offset = 0, dataLen = [data length]; + NSString *str; + char buffer[6+16*3+1+16+1+1]; + buffer[0] = '\0'; + const unsigned char *q = [data bytes]; + if (dataLen == 1) + [strings addObject:NSLocalizedString(@"Raw data, 1 byte:", @"")]; + else + [strings addObject:[NSString stringWithFormat:NSLocalizedString(@"Raw data, %u bytes:", @""), dataLen]]; + while (dataLen) + { + if ([strings count] == MAX_DATA_LINES) + { + [strings addObject:NSLocalizedString(@"Double-click to see all data...", @"")]; + break; + } + int i, b = sprintf(buffer,"%04x: ", offset); + for (i=0; i < 16 && i < dataLen; i++) + sprintf(&buffer[b+3*i], "%02x ", (int)q[i]); + for (int j=i; j < 16; j++) + strcat(buffer, " "); + + b = strlen(buffer); + buffer[b++] = '\''; + for (i=0; i < 16 && i < dataLen; i++, q++) + { + if (*q >= 32 && *q < 128) + buffer[b++] = *q; + else + buffer[b++] = ' '; + } + for (int j=i; j < 16; j++) + buffer[b++] = ' '; + buffer[b++] = '\''; + buffer[b] = 0; + + str = [[NSString alloc] initWithBytes:buffer length:strlen(buffer) encoding:NSISOLatin1StringEncoding]; + [strings addObject:str]; + [str release]; + + dataLen -= i; + offset += i; + } + return [strings autorelease]; +} + +#pragma mark - +#pragma mark Cell size calculations + ++ (CGFloat)minimumHeightForCell +{ + if (sMinimumHeightForCell == 0) + { + NSRect r1 = [@"10:10:10.256" boundingRectWithSize:NSMakeSize(1024, 1024) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[[self defaultAttributes] objectForKey:@"timestamp"]]; + NSRect r2 = [@"+999ms" boundingRectWithSize:NSMakeSize(1024, 1024) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[[self defaultAttributes] objectForKey:@"timedelta"]]; + NSRect r3 = [@"Main Thread" boundingRectWithSize:NSMakeSize(1024, 1024) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[[self defaultAttributes] objectForKey:@"threadID"]]; + NSRect r4 = [@"qWTy" boundingRectWithSize:NSMakeSize(1024, 1024) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[[self defaultAttributes] objectForKey:@"tag"]]; + sMinimumHeightForCell = fmaxf(NSHeight(r1) + NSHeight(r2), NSHeight(r3) + NSHeight(r4)) + 4; + } + return sMinimumHeightForCell; +} + ++ (CGFloat)heightForFileLineFunction +{ + if (sDefaultFileLineFunctionHeight == 0) + { + NSRect r = [@"file:100 funcQyTg" boundingRectWithSize:NSMakeSize(1024, 1024) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[[self defaultAttributes] objectForKey:@"fileLineFunction"]]; + sDefaultFileLineFunctionHeight = NSHeight(r) + 6; + } + return sDefaultFileLineFunctionHeight; +} + ++ (CGFloat)heightForCellWithMessage:(LoggerMessage *)aMessage maxSize:(NSSize)sz showFunctionNames:(BOOL)showFunctionNames +{ + // return cached cell height if possible + CGFloat minimumHeight = [self minimumHeightForCell]; + NSSize cellSize = aMessage.cachedCellSize; + if (cellSize.width == sz.width) + return cellSize.height; + + cellSize.width = sz.width; + + // new width is larger, but cell already at minimum height, don't recompute + if (cellSize.width > 0 && cellSize.width < sz.width && cellSize.height == minimumHeight) + return minimumHeight; + + sz.width -= TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH + 8; + sz.height -= 4; + + switch (aMessage.contentsType) + { + case kMessageString: { + // restrict message length for very long contents + NSString *s = aMessage.message; + if ([s length] > 2048) + s = [s substringToIndex:2048]; + + NSRect lr = [s boundingRectWithSize:sz + options:(NSStringDrawingOneShot | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:[[self defaultAttributes] objectForKey:@"text"]]; + sz.height = fminf(NSHeight(lr), sz.height); + break; + } + + case kMessageData: { + NSUInteger numBytes = [(NSData *)aMessage.message length]; + int nLines = (numBytes >> 4) + ((numBytes & 15) ? 1 : 0) + 1; + if (nLines > MAX_DATA_LINES) + nLines = MAX_DATA_LINES + 1; + NSRect lr = [@"000:" boundingRectWithSize:sz + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:[[self defaultAttributes] objectForKey:@"data"]]; + sz.height = NSHeight(lr) * nLines; + break; + } + + case kMessageImage: { + // approximate, compute ratio then refine height + NSSize imgSize = aMessage.imageSize; + CGFloat ratio = fmaxf(1.0f, fmaxf(imgSize.width / sz.width, imgSize.height / (sz.height / 2.0f))); + sz.height = ceilf(imgSize.height / ratio); + break; + } + default: + break; + } + + // If there is file / line / function information, add its height + if (showFunctionNames && ([aMessage.filename length] || [aMessage.functionName length])) + sz.height += [self heightForFileLineFunction]; + + // cache and return cell height + cellSize.height = fmaxf(sz.height + 6, minimumHeight); + aMessage.cachedCellSize = cellSize; + return cellSize.height; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Instance methods +// ----------------------------------------------------------------------------- +- (id)copyWithZone:(NSZone *)zone +{ + LoggerMessageCell *c = [super copyWithZone:zone]; + c->message = [message retain]; + c->previousMessage = [previousMessage retain]; + c->messageAttributes = [messageAttributes retain]; + return c; +} + +- (void)dealloc +{ + [message release]; + [previousMessage release]; + [messageAttributes release]; + [super dealloc]; +} + +- (NSMutableDictionary *)timestampAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"timestamp"]; + return [messageAttributes objectForKey:@"timestamp"]; +} + +- (NSMutableDictionary *)timedeltaAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"timedelta"]; + return [messageAttributes objectForKey:@"timedelta"]; +} + +- (NSMutableDictionary *)threadIDAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"threadID"]; + return [messageAttributes objectForKey:@"threadID"]; +} + +- (NSMutableDictionary *)tagAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"tag"]; + return [messageAttributes objectForKey:@"tag"]; +} + +- (NSMutableDictionary *)levelAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"level"]; + return [messageAttributes objectForKey:@"level"]; +} + +- (NSMutableDictionary *)messageTextAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"text"]; + return [messageAttributes objectForKey:@"text"]; +} + +- (NSMutableDictionary *)messageDataAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"data"]; + return [messageAttributes objectForKey:@"data"]; +} + +- (NSMutableDictionary *)fileLineFunctionAttributes +{ + if (messageAttributes == nil) + return [[[self class] defaultAttributes] objectForKey:@"fileLineFunction"]; + return [messageAttributes objectForKey:@"fileLineFunction"]; +} + +#pragma mark - +#pragma mark Drawing + +- (void)drawTimestampAndDeltaInRect:(NSRect)r highlightedTextColor:(NSColor *)highlightedTextColor +{ + // Draw timestamp and time delta column + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(ctx); + CGContextClipToRect(ctx, NSRectToCGRect(r)); + NSRect tr = NSInsetRect(r, 2, 0); + + // Prepare time delta between this message and the previous displayed (filtered) message + struct timeval tv = message.timestamp; + struct timeval td; + if (previousMessage != nil) + [message computeTimeDelta:&td since:previousMessage]; + + time_t sec = tv.tv_sec; + struct tm *t = localtime(&sec); + NSString *timestampStr; + if (tv.tv_usec == 0) + timestampStr = [NSString stringWithFormat:@"%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec]; + else + timestampStr = [NSString stringWithFormat:@"%02d:%02d:%02d.%03d", t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000]; + + NSString *timeDeltaStr = nil; + if (previousMessage != nil) + timeDeltaStr = StringWithTimeDelta(&td); + + NSMutableDictionary *attrs = [self timestampAttributes]; + NSRect bounds = [timestampStr boundingRectWithSize:tr.size + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + NSRect timeRect = NSMakeRect(NSMinX(tr), NSMinY(tr), NSWidth(tr), NSHeight(bounds)); + NSRect deltaRect = NSMakeRect(NSMinX(tr), NSMaxY(timeRect)+1, NSWidth(tr), NSHeight(tr) - NSHeight(bounds) - 1); + + if (highlightedTextColor) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:highlightedTextColor forKey:NSForegroundColorAttributeName]; + } + [timestampStr drawWithRect:timeRect + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + + attrs = [self timedeltaAttributes]; + if (highlightedTextColor) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:highlightedTextColor forKey:NSForegroundColorAttributeName]; + } + [timeDeltaStr drawWithRect:deltaRect + options:NSStringDrawingUsesLineFragmentOrigin + attributes:attrs]; + CGContextRestoreGState(ctx); +} + +- (void)drawThreadIDAndTagInRect:(NSRect)drawRect highlightedTextColor:(NSColor *)highlightedTextColor +{ + NSRect r = drawRect; + + // Draw thread ID + NSMutableDictionary *attrs = [self threadIDAttributes]; + if (highlightedTextColor != nil) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:highlightedTextColor forKey:NSForegroundColorAttributeName]; + } + + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(ctx); + CGContextClipToRect(ctx, NSRectToCGRect(r)); + r.size.height = [message.threadID boundingRectWithSize:r.size + options:NSStringDrawingUsesLineFragmentOrigin + attributes:attrs].size.height; + [message.threadID drawWithRect:NSInsetRect(r, 3, 0) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:attrs]; + + // Draw tag and level, if provided + NSString *tag = message.tag; + int level = message.level; + if ([tag length] || level) + { + NSSize tagSize = NSZeroSize; + NSSize levelSize = NSZeroSize; + NSString *levelString = nil; + r.origin.y += NSHeight(r); + if ([tag length]) + { + tagSize = [tag boundingRectWithSize:NSMakeSize(THREAD_COLUMN_WIDTH, NSHeight(drawRect) - NSHeight(r)) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[self tagAttributes]].size; + tagSize.width += 4; + tagSize.height += 2; + } + if (level) + { + levelString = [NSString stringWithFormat:@"%d", level]; + levelSize = [levelString boundingRectWithSize:NSMakeSize(THREAD_COLUMN_WIDTH, NSHeight(drawRect) - NSHeight(r)) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[self levelAttributes]].size; + levelSize.width += 4; + levelSize.height += 2; + } + CGFloat h = fmaxf(tagSize.height, levelSize.height); + NSRect tagRect = NSMakeRect(NSMinX(r) + 3, + NSMinY(r), + tagSize.width, + h); + NSRect levelRect = NSMakeRect(NSMaxX(tagRect), + NSMinY(tagRect), + levelSize.width, + h); + NSRect tagAndLevelRect = NSUnionRect(tagRect, levelRect); + + MakeRoundedPath(ctx, NSRectToCGRect(tagAndLevelRect), 3.0f); + CGColorRef fillColor = CreateCGColorFromNSColor([[self class] colorForTag:tag]); + CGContextSetFillColorWithColor(ctx, fillColor); + CGColorRelease(fillColor); + CGContextFillPath(ctx); + if (levelSize.width) + { + CGColorRef black = CGColorCreateGenericGray(0.25f, 1.0f); + CGContextSetFillColorWithColor(ctx, black); + CGColorRelease(black); + CGContextSaveGState(ctx); + CGContextClipToRect(ctx, NSRectToCGRect(levelRect)); + MakeRoundedPath(ctx, NSRectToCGRect(tagAndLevelRect), 3.0f); + CGContextFillPath(ctx); + CGContextRestoreGState(ctx); + } + + if (tagSize.width) + { + [tag drawWithRect:NSInsetRect(tagRect, 2, 1) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[self tagAttributes]]; + } + if (levelSize.width) + { + [levelString drawWithRect:NSInsetRect(levelRect, 2, 1) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:[self levelAttributes]]; + } + } + CGContextRestoreGState(ctx); +} + +- (void)drawMessageInRect:(NSRect)r highlightedTextColor:(NSColor *)highlightedTextColor +{ + /* + * Draw the message portion of cells + * + */ + NSMutableDictionary *attrs; + + if (message.contentsType == kMessageString) + { + attrs = [self messageTextAttributes]; + if (highlightedTextColor != nil) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:highlightedTextColor forKey:NSForegroundColorAttributeName]; + } + + // in case the message text is empty, use the function name as message text + // this is typically used to record a waypoint in the code flow + NSString *s = message.message; + if (![s length] && message.functionName) + s = message.functionName; + + // very long messages can't be displayed entirely. No need to compute their full size, + // it slows down the UI to no avail. Just cut the string to a reasonable size, and take + // the calculations from here. + BOOL truncated = NO; + if ([s length] > 2048) + { + truncated = YES; + s = [s substringToIndex:2048]; + } + + // compute display string size, limit to cell height + NSRect lr = [s boundingRectWithSize:r.size + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + if (NSHeight(lr) > NSHeight(r)) + truncated = YES; + else + { + r.origin.y += floorf((NSHeight(r) - NSHeight(lr)) / 2.0f); + r.size.height = NSHeight(lr); + } + + CGFloat hintHeight = 0; + NSString *hint = nil; + NSMutableDictionary *hintAttrs = nil; + if (truncated) + { + // display a hint instructing user to double-click message in order + // to see all contents + hintAttrs = [[attrs mutableCopy] autorelease]; + [hintAttrs setObject:[NSNumber numberWithFloat:0.20f] forKey:NSObliquenessAttributeName]; + if (highlightedTextColor == nil) + [hintAttrs setObject:[NSColor darkGrayColor] forKey:NSForegroundColorAttributeName]; + + hint = NSLocalizedString(@"Double-click to see all text...", @""); + hintHeight = [hint boundingRectWithSize:r.size + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:hintAttrs].size.height; + } + + r.size.height -= hintHeight; + [s drawWithRect:r + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine) + attributes:attrs]; + + // Draw hint "Double click to see all text..." if needed + if (hint != nil) + { + r.origin.y += NSHeight(r); + r.size.height = hintHeight; + [hint drawWithRect:r + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:hintAttrs]; + } + } + else if (message.contentsType == kMessageData) + { + NSArray *strings = [[self class] stringsWithData:(NSData *)message.message]; + attrs = [self messageDataAttributes]; + if (highlightedTextColor != nil) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:highlightedTextColor forKey:NSForegroundColorAttributeName]; + } + CGFloat y = NSMinY(r); + CGFloat availHeight = NSHeight(r); + int lineIndex = 0; + for (NSString *s in strings) + { + if (lineIndex == 16) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:[NSNumber numberWithFloat:0.20f] forKey:NSObliquenessAttributeName]; + [attrs setObject:[NSColor darkGrayColor] forKey:NSForegroundColorAttributeName]; + } + NSRect lr = [s boundingRectWithSize:r.size + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + [s drawWithRect:NSMakeRect(NSMinX(r), + y, + NSWidth(r), + NSHeight(lr)) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:attrs]; + availHeight -= NSHeight(lr); + if (availHeight < NSHeight(lr)) + break; + y += NSHeight(lr); + lineIndex++; + } + } + else if (message.contentsType == kMessageImage) + { + // Scale the image to fit in the cell. Since we're flipped, we also must vertically flip + // the image + r = NSInsetRect(r, 0, 1); + NSSize srcSize = message.imageSize; + CGFloat ratio = fmaxf(1.0f, fmaxf(srcSize.width / NSWidth(r), srcSize.height / NSHeight(r))); + CGSize newSize = CGSizeMake(floorf(srcSize.width / ratio), floorf(srcSize.height / ratio)); + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(ctx); + CGContextTranslateCTM(ctx, NSMinX(r), NSMinY(r) + NSHeight(r)); + CGContextScaleCTM(ctx, 1.0f, -1.0f); + [message.image drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height) + fromRect:NSMakeRect(0, 0, srcSize.width, srcSize.height) + operation:NSCompositeCopy + fraction:1.0f]; + CGContextRestoreGState(ctx); + } +} + +- (void)drawFileLineFunctionInRect:(NSRect)r highlightedTextColor:(NSColor *)highlightedTextColor mouseOver:(BOOL)mouseOver +{ + // @@@ TODO: mouseOver support + + NSMutableDictionary *attrs = [self fileLineFunctionAttributes]; + if (highlightedTextColor == nil) + { + NSColor *fillColor = [attrs objectForKey:NSBackgroundColorAttributeName]; + if (fillColor != nil) + { + [fillColor set]; + NSRectFill(r); + } + } + NSString *s = @""; + BOOL hasFilename = ([message.filename length] != 0); + BOOL hasFunction = ([message.functionName length] != 0); + if (hasFunction && hasFilename) + { + if (message.lineNumber) + s = [NSString stringWithFormat:@"%@ (%@:%d)", message.functionName, [message.filename lastPathComponent], message.lineNumber]; + else + s = [NSString stringWithFormat:@"%@ (%@)", message.functionName, [message.filename lastPathComponent]]; + } + else if (hasFunction) + { + if (message.lineNumber) + s = [NSString stringWithFormat:NSLocalizedString(@"%@ (line %d)", @""), message.functionName, message.lineNumber]; + else + s = message.functionName; + } + else + { + if (message.lineNumber) + s = [NSString stringWithFormat:@"%@:%d", [message.filename lastPathComponent], message.lineNumber]; + else + s = [message.filename lastPathComponent]; + } + if ([s length]) + { + if (highlightedTextColor) + { + attrs = [[attrs mutableCopy] autorelease]; + [attrs setObject:highlightedTextColor forKey:NSForegroundColorAttributeName]; + [attrs setObject:[NSColor clearColor] forKey:NSBackgroundColorAttributeName]; + } + [s drawWithRect:NSInsetRect(r, 4, 2) + options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) + attributes:attrs]; + } +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + cellFrame.size = message.cachedCellSize; + + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + + BOOL highlighted = [self isHighlighted]; + + NSColor *highlightedTextColor = nil; + if (highlighted) + highlightedTextColor = [NSColor whiteColor]; + + // Draw cell background + if (!highlighted) + { + CGColorRef cellBgColor = CGColorCreateGenericGray(0.97f, 1.0f); + CGContextSetFillColorWithColor(ctx, cellBgColor); + CGContextFillRect(ctx, NSRectToCGRect(cellFrame)); + CGColorRelease(cellBgColor); + } + + // turn antialiasing off + CGContextSetShouldAntialias(ctx, false); + + // Draw separators + CGContextSetLineWidth(ctx, 1.0f); + CGContextSetLineCap(ctx, kCGLineCapSquare); + CGColorRef cellSeparatorColor; + if (highlighted) + cellSeparatorColor = CGColorCreateGenericGray(1.0f, 1.0f); + else + cellSeparatorColor = CGColorCreateGenericGray(0.80f, 1.0f); + CGContextSetStrokeColorWithColor(ctx, cellSeparatorColor); + CGColorRelease(cellSeparatorColor); + CGContextBeginPath(ctx); + + // horizontal bottom separator + CGContextMoveToPoint(ctx, NSMinX(cellFrame), floorf(NSMaxY(cellFrame))); + CGContextAddLineToPoint(ctx, NSMaxX(cellFrame), floorf(NSMaxY(cellFrame))); + + // timestamp/thread separator + CGContextMoveToPoint(ctx, floorf(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH), NSMinY(cellFrame)); + CGContextAddLineToPoint(ctx, floorf(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH), floorf(NSMaxY(cellFrame)-1)); + + // thread/message separator + CGContextMoveToPoint(ctx, floorf(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH), NSMinY(cellFrame)); + CGContextAddLineToPoint(ctx, floorf(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH), floorf(NSMaxY(cellFrame)-1)); + CGContextStrokePath(ctx); + + // restore antialiasing + CGContextSetShouldAntialias(ctx, true); + + // Draw timestamp and time delta column + NSRect r = NSMakeRect(NSMinX(cellFrame), + NSMinY(cellFrame), + TIMESTAMP_COLUMN_WIDTH, + NSHeight(cellFrame)); + [self drawTimestampAndDeltaInRect:r highlightedTextColor:highlightedTextColor]; + + // Draw thread ID and tag + r = NSMakeRect(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH, + NSMinY(cellFrame), + THREAD_COLUMN_WIDTH, + NSHeight(cellFrame)); + [self drawThreadIDAndTagInRect:r highlightedTextColor:highlightedTextColor]; + + // Draw message + r = NSMakeRect(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH + 3, + NSMinY(cellFrame), + NSWidth(cellFrame) - (TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH) - 6, + NSHeight(cellFrame)); + CGFloat fileLineFunctionHeight = 0; + if (shouldShowFunctionNames && ([message.filename length] || [message.functionName length])) + { + fileLineFunctionHeight = [[self class] heightForFileLineFunction]; + r.size.height -= fileLineFunctionHeight; + r.origin.y += fileLineFunctionHeight; + } + [self drawMessageInRect:r highlightedTextColor:highlightedTextColor]; + + // Draw File / Line / Function + if (fileLineFunctionHeight) + { + r = NSMakeRect(NSMinX(cellFrame) + TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH + 1, + NSMinY(cellFrame), + NSWidth(cellFrame) - (TIMESTAMP_COLUMN_WIDTH + THREAD_COLUMN_WIDTH), + fileLineFunctionHeight); + [self drawFileLineFunctionInRect:r highlightedTextColor:highlightedTextColor mouseOver:NO]; + } +} + +#pragma mark - +#pragma mark Contextual menu + +- (NSMenu *)menuForEvent:(NSEvent *)anEvent inRect:(NSRect)cellFrame ofView:(NSView *)aView +{ + // @@@ TODO: filter / highlight by same thread, same tag, same message, etc + return nil; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeConnection.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeConnection.h new file mode 100644 index 000000000..854fcd952 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeConnection.h @@ -0,0 +1,49 @@ +/* + * LoggerNativeConnection.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerIPConnection.h" + +@interface LoggerNativeConnection : LoggerIPConnection +{ + NSInputStream *readStream; + NSMutableData *buffer; + + uint8_t *tmpBuf; + NSUInteger tmpBufSize; +} + +@property (nonatomic, retain) NSInputStream *readStream; +@property (nonatomic, readonly) NSMutableData *buffer; +@property (nonatomic, readonly) uint8_t *tmpBuf; +@property (nonatomic, readonly) NSUInteger tmpBufSize; + +- (id)initWithInputStream:(NSInputStream *)anInputStream clientAddress:(NSData *)anAddress; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeConnection.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeConnection.m new file mode 100644 index 000000000..c55762d83 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeConnection.m @@ -0,0 +1,77 @@ +/* + * LoggerNativeConnection.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */#import "LoggerNativeConnection.h" + +#define TMP_BUF_SIZE ((size_t)32767) + +@implementation LoggerNativeConnection + +@synthesize readStream, buffer, tmpBuf, tmpBufSize; + +- (id)initWithInputStream:(NSInputStream *)anInputStream clientAddress:(NSData *)anAddress; +{ + if ((self = [super initWithAddress:anAddress]) != nil) + { + readStream = [anInputStream retain]; + + tmpBufSize = TMP_BUF_SIZE; + tmpBuf = (uint8_t *)malloc(TMP_BUF_SIZE); + if (tmpBuf == NULL) + return nil; + + buffer = [[NSMutableData alloc] initWithCapacity:2048]; + } + return self; +} + +- (void)dealloc +{ + assert(readStream == nil); + [buffer release]; + if (tmpBuf != NULL) + free(tmpBuf); + [super dealloc]; +} + +- (void)shutdown +{ + if (readStream != nil) + { + [readStream close]; + [readStream setDelegate:nil]; + [readStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [readStream release]; + readStream = nil; + } + [buffer setLength:0]; + [super shutdown]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeMessage.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeMessage.h new file mode 100644 index 000000000..3bf071d0d --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeMessage.h @@ -0,0 +1,41 @@ +/* + * LoggerNativeMessage.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerMessage.h" + +@class LoggerConnection; + +@interface LoggerNativeMessage : LoggerMessage +{ +} + +- (id)initWithData:(NSData *)data connection:(LoggerConnection *)aConnection; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeMessage.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeMessage.m new file mode 100644 index 000000000..c8fe2d8b1 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeMessage.m @@ -0,0 +1,206 @@ +/* + * LoggerNativeMessage.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerNativeMessage.h" +#import "LoggerCommon.h" + +@implementation LoggerNativeMessage + +- (id)initWithData:(NSData *)data connection:(LoggerConnection *)aConnection +{ + if ((self = [super init]) != nil) + { + // decode message contents + uint8_t *p = (uint8_t *)[data bytes]; + uint16_t partCount; + memcpy(&partCount, p, 2); + partCount = ntohs(partCount); + p += 2; + while (partCount--) + { + uint8_t partKey = *p++; + uint8_t partType = *p++; + uint32_t partSize; + if (partType == PART_TYPE_INT16) + partSize = 2; + else if (partType == PART_TYPE_INT32) + partSize = 4; + else if (partType == PART_TYPE_INT64) + partSize = 8; + else + { + memcpy(&partSize, p, 4); + p += 4; + partSize = ntohl(partSize); + } + id part = nil; + uint32_t value32 = 0; + uint64_t value64 = 0; + if (partSize > 0) + { + if (partType == PART_TYPE_STRING) + { + part = [[NSString alloc] initWithBytes:p length:partSize encoding:NSUTF8StringEncoding]; + } + else if (partType == PART_TYPE_BINARY || partType == PART_TYPE_IMAGE) + { + part = [[NSData alloc] initWithBytes:p length:partSize]; + } + else if (partType == PART_TYPE_INT16) + { + value32 = (((uint32_t)p[0]) << 8) | (uint32_t)p[1]; + } + else if (partType == PART_TYPE_INT32) + { + value32 = (((uint32_t)p[0]) << 24) | (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | (uint32_t)p[3]; + } + else if (partType == PART_TYPE_INT64) + { + memcpy(&value64, p, 8); + value64 = CFSwapInt64BigToHost(value64); + } + p += partSize; + } + switch (partKey) + { + case PART_KEY_MESSAGE_TYPE: + type = (short)value32; + break; + case PART_KEY_MESSAGE_SEQ: + sequence = value32; + break; + case PART_KEY_TIMESTAMP_S: // timestamp with seconds-level resolution + timestamp.tv_sec = (partType == PART_TYPE_INT64) ? (__darwin_time_t)value64 : (__darwin_time_t)value32; + break; + case PART_KEY_TIMESTAMP_MS: // millisecond part of the timestamp (optional) + timestamp.tv_usec = ((partType == PART_TYPE_INT64) ? (__darwin_suseconds_t)value64 : (__darwin_suseconds_t)value32) * 1000; + break; + case PART_KEY_TIMESTAMP_US: // microsecond part of the timestamp (optional) + timestamp.tv_usec = (partType == PART_TYPE_INT64) ? (__darwin_suseconds_t)value64 : (__darwin_suseconds_t)value32; + break; + case PART_KEY_THREAD_ID: + if (partType == PART_TYPE_INT32) + threadID = [[NSString alloc] initWithFormat:@"Thread 0x%x", value32]; + else if (partType == PART_TYPE_INT64) + threadID = [[NSString alloc] initWithFormat:@"Thread 0x%qx", value64]; + else if (partType == PART_TYPE_STRING) + threadID = [part retain]; + else + threadID = @""; + break; + case PART_KEY_TAG: + self.tag = (NSString *)part; + break; + case PART_KEY_LEVEL: + level = (short)value32; + break; + case PART_KEY_MESSAGE: + self.message = part; + if (partType == PART_TYPE_STRING) + contentsType = kMessageString; + else if (partType == PART_TYPE_BINARY) + contentsType = kMessageData; + else if (partType == PART_TYPE_IMAGE) + contentsType = kMessageImage; + break; + case PART_KEY_IMAGE_WIDTH: + if (partType == PART_TYPE_INT32) + imageSize.width = value32; + else if (partType == PART_TYPE_INT64) + imageSize.width = value64; + break; + case PART_KEY_IMAGE_HEIGHT: + if (partType == PART_TYPE_INT32) + imageSize.height = value32; + else if (partType == PART_TYPE_INT64) + imageSize.height = value64; + break; + case PART_KEY_FILENAME: + if (part != nil) + [self setFilename:part connection:aConnection]; + break; + case PART_KEY_FUNCTIONNAME: + if (part!= nil) + [self setFunctionName:part connection:aConnection]; + break; + case PART_KEY_LINENUMBER: + if (partType == PART_TYPE_INT32) + lineNumber = value32; + else + lineNumber = value64; + break; + default: { + // all other keys are automatically added to the parts dictionary + if (parts == nil) + parts = [[NSMutableDictionary alloc] init]; + NSNumber *partKeyNumber = [[NSNumber alloc] initWithUnsignedInteger:partKey]; + if (partType == PART_TYPE_INT32) + part = [[NSNumber alloc] initWithInteger:value32]; + else if (partType == PART_TYPE_INT64) + part = [[NSNumber alloc] initWithUnsignedLongLong:value64]; + if (part != nil) + [parts setObject:part forKey:partKeyNumber]; + [partKeyNumber release]; + break; + } + } + [part release]; + } + } +#if 0 + // Debug tool to log the original image (until we have DnD) + if (type == LOGMSG_TYPE_LOG && contentsType == kMessageImage) + { + // detect the image type to set the proper extension + NSString *ext = @"png"; + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)message, NULL); + if (imageSource != NULL) + { + CFStringRef imageType = CGImageSourceGetType(imageSource); + if (imageType != NULL) + { + NSDictionary *typeDef = (NSDictionary *)UTTypeCopyDeclaration(imageType); + NSDictionary *spec = [typeDef objectForKey:(id)kUTTypeTagSpecificationKey]; + NSArray *exts = [spec objectForKey:@"public.filename-extension"]; + if (exts != nil && [exts isKindOfClass:[NSArray class]] && [exts count] && [[exts lastObject] length]) + ext = [[[exts lastObject] retain] autorelease]; + [typeDef release]; + } + CFRelease(imageSource); + } + NSString *fn = [NSString stringWithFormat:@"%d.%@", sequence, ext]; + NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:fn]; + [(NSData *)message writeToFile:path atomically:NO]; + } +#endif + return self; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeTransport.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeTransport.h new file mode 100644 index 000000000..b097638c3 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeTransport.h @@ -0,0 +1,54 @@ +/* + * LoggerNativeTransport.h + * + * Default transport for NSLogger messages, publishes a Bonjour service, + * and can listen on a specific port (or by default on a port attributed by + * the OS). In case we listen on a specific, user-defined port, the Bonjour + * service name will be suffixed + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerTransport.h" + +@interface LoggerNativeTransport : LoggerTransport +{ + NSThread *listenerThread; + NSNetService *bonjourService; + CFSocketRef listenerSocket_ipv4; + CFSocketRef listenerSocket_ipv6; + NSString *bonjourServiceName; + int listenerPort; + BOOL publishBonjourService; +} + +@property (nonatomic, assign) int listenerPort; +@property (nonatomic, assign) BOOL publishBonjourService; +@property (nonatomic, readonly) CFSocketRef listenerSocket_ipv4; +@property (nonatomic, readonly) CFSocketRef listenerSocket_ipv6; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeTransport.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeTransport.m new file mode 100644 index 000000000..d105931ee --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerNativeTransport.m @@ -0,0 +1,787 @@ +/* + * LoggerNativeTransport.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include +#import "LoggerCommon.h" +#import "LoggerNativeTransport.h" +#import "LoggerNativeConnection.h" +#import "LoggerNativeMessage.h" +#import "LoggerStatusWindowController.h" +#import "LoggerAppDelegate.h" + +/* Local prototypes */ +static void AcceptSocketCallback(CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info); + +@implementation LoggerNativeTransport + +@synthesize listenerPort, listenerSocket_ipv4, listenerSocket_ipv6; +@synthesize publishBonjourService; + +- (void)dealloc +{ + [listenerThread cancel]; + [bonjourService release]; + [bonjourServiceName release]; + [super dealloc]; +} + +- (NSString *)transportInfoString +{ + if (publishBonjourService) + { + NSString *name = bonjourServiceName; + if (![name length]) + name = [bonjourService name]; + if ([name length]) + return [NSString stringWithFormat:NSLocalizedString(@"Bonjour (%@, port %d%s)", @"Named Bonjour transport info string"), + name, + listenerPort, + secure ? ", SSL" : ""]; + return [NSString stringWithFormat:NSLocalizedString(@"Bonjour (port %d%s)", @"Bonjour transport (default name) info string"), + listenerPort, + secure ? ", SSL" : ""]; + } + return [NSString stringWithFormat:NSLocalizedString(@"TCP/IP (port %d%s)", @"TCP/IP transport info string"), + listenerPort, + secure ? ", SSL" : ""]; +} + +- (NSString *)transportStatusString +{ + if (failed) + { + if (failureReason != nil) + return failureReason; + return NSLocalizedString(@"Failed opening service", @"Transport failed opening - unknown reason"); + } + if (active && ready) + { + __block NSInteger numConnected = 0; + [connections enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (((LoggerConnection *)obj).connected) + numConnected++; + }]; + + if (numConnected == 0) + return NSLocalizedString(@"Ready to accept connections", @"Transport ready status"); + if (numConnected == 1) + return NSLocalizedString(@"1 active connection", @"1 active connection for transport"); + return [NSString stringWithFormat:NSLocalizedString(@"%d active connections", @"Number of active connections for transport"), numConnected]; + } + if (active) + return NSLocalizedString(@"Opening service", @"Transport status: opening"); + return NSLocalizedString(@"Unavailable", @"Transport status: service unavailable"); +} + +- (void)restart +{ + if (active) + { + // Check whether we need to actually restart the service if the settings have changed + BOOL shouldRestart = NO; + if (publishBonjourService) + { + // Check whether the bonjour service name changed + NSString *newBonjourServiceName = [[NSUserDefaults standardUserDefaults] objectForKey:kPrefBonjourServiceName]; + shouldRestart = (([newBonjourServiceName length] != [bonjourServiceName length]) || + (bonjourServiceName != nil && [newBonjourServiceName compare:bonjourServiceName options:NSCaseInsensitiveSearch] != NSOrderedSame)); + } + else + { + int port = [[[NSUserDefaults standardUserDefaults] objectForKey:kPrefDirectTCPIPResponderPort] integerValue]; + shouldRestart = (listenerPort != port); + } + if (shouldRestart) + { + [self shutdown]; + [self performSelector:@selector(completeRestart) withObject:nil afterDelay:0.1]; + } + } + else + { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(completeRestart) object:nil]; + [self startup]; + } +} + +- (void)completeRestart +{ + if (active) + { + // wait for the service to be completely shut down, then restart it + [self performSelector:_cmd withObject:nil afterDelay:0.1]; + return; + } + if (!publishBonjourService) + listenerPort = [[[NSUserDefaults standardUserDefaults] objectForKey:kPrefDirectTCPIPResponderPort] integerValue]; + [self startup]; +} + +- (void)startup +{ + if (!active) + { + active = YES; + ready = NO; + failed = NO; + self.failureReason = nil; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(completeRestart) object:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification object:self]; + [NSThread detachNewThreadSelector:@selector(listenerThread) toTarget:self withObject:nil]; + } +} + +- (void)shutdown +{ + if (!active) + return; + + if ([NSThread currentThread] != listenerThread) + { + [self performSelector:_cmd onThread:listenerThread withObject:nil waitUntilDone:YES]; + return; + } + + // stop Bonjour service + [bonjourService setDelegate:nil]; + [bonjourService stop]; + [bonjourService release]; + bonjourService = nil; + + // close listener sockets (removing input sources) + if (listenerSocket_ipv4) + { + CFSocketInvalidate(listenerSocket_ipv4); + CFRelease(listenerSocket_ipv4); + listenerSocket_ipv4 = NULL; + } + if (listenerSocket_ipv6) + { + CFSocketInvalidate(listenerSocket_ipv6); + CFRelease(listenerSocket_ipv6); + listenerSocket_ipv6 = NULL; + } + + // shutdown all connections + while ([connections count]) + [self removeConnection:[connections objectAtIndex:0]]; + + [listenerThread cancel]; + + // when exiting this selector, we'll get out of the runloop. Thread being cancelled, it will be + // deactivated immediately. We can safely reset active and listener thread just now so that + // another startup with a different port can take place. + listenerThread = nil; + active = NO; + + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification object:self]; +} + +- (void)removeConnection:(LoggerConnection *)aConnection +{ + if (listenerThread != nil && [NSThread currentThread] != listenerThread) + { + [self performSelector:_cmd onThread:listenerThread withObject:aConnection waitUntilDone:NO]; + return; + } + [super removeConnection:aConnection]; +} + +- (BOOL)setup +{ + @try + { + CFSocketContext context = {0, self, NULL, NULL, NULL}; + + // create sockets + listenerSocket_ipv4 = CFSocketCreate(kCFAllocatorDefault, + PF_INET, + SOCK_STREAM, + IPPROTO_TCP, + kCFSocketAcceptCallBack, + &AcceptSocketCallback, + &context); + + listenerSocket_ipv6 = CFSocketCreate(kCFAllocatorDefault, + PF_INET6, + SOCK_STREAM, + IPPROTO_TCP, + kCFSocketAcceptCallBack, + &AcceptSocketCallback, + &context); + + if (listenerSocket_ipv4 == NULL || listenerSocket_ipv6 == NULL) + { + @throw [NSException exceptionWithName:@"CFSocketCreate" + reason:NSLocalizedString(@"Failed creating listener socket (CFSocketCreate failed)", @"") + userInfo:nil]; + } + + // set socket options & addresses + int yes = 1; + setsockopt(CFSocketGetNative(listenerSocket_ipv4), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); + setsockopt(CFSocketGetNative(listenerSocket_ipv6), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); + + // set up the IPv4 endpoint; if port is 0, this will cause the kernel to choose a port for us + struct sockaddr_in addr4; + memset(&addr4, 0, sizeof(addr4)); + addr4.sin_len = sizeof(addr4); + addr4.sin_family = AF_INET; + addr4.sin_port = htons(listenerPort); + addr4.sin_addr.s_addr = htonl(INADDR_ANY); + NSData *address4 = [NSData dataWithBytes:&addr4 length:sizeof(addr4)]; + + if (CFSocketSetAddress(listenerSocket_ipv4, (CFDataRef)address4) != kCFSocketSuccess) + { + @throw [NSException exceptionWithName:@"CFSocketSetAddress" + reason:NSLocalizedString(@"Failed setting IPv4 socket address", @"") + userInfo:nil]; + } + + if (listenerPort == 0) + { + // now that the binding was successful, we get the port number + // -- we will need it for the v6 endpoint and for NSNetService + NSData *addr = [(NSData *)CFSocketCopyAddress(listenerSocket_ipv4) autorelease]; + memcpy(&addr4, [addr bytes], [addr length]); + listenerPort = ntohs(addr4.sin_port); + } + + // set up the IPv6 endpoint + struct sockaddr_in6 addr6; + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_len = sizeof(addr6); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(listenerPort); + memcpy(&(addr6.sin6_addr), &in6addr_any, sizeof(addr6.sin6_addr)); + NSData *address6 = [NSData dataWithBytes:&addr6 length:sizeof(addr6)]; + + if (CFSocketSetAddress(listenerSocket_ipv6, (CFDataRef)address6) != kCFSocketSuccess) + { + @throw [NSException exceptionWithName:@"CFSocketSetAddress" + reason:NSLocalizedString(@"Failed setting IPv6 socket address", @"") + userInfo:nil]; + } + + // set up the run loop sources for the sockets + CFRunLoopRef rl = CFRunLoopGetCurrent(); + CFRunLoopSourceRef source4 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, listenerSocket_ipv4, 0); + CFRunLoopAddSource(rl, source4, kCFRunLoopCommonModes); + CFRelease(source4); + + CFRunLoopSourceRef source6 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, listenerSocket_ipv6, 0); + CFRunLoopAddSource(rl, source6, kCFRunLoopCommonModes); + CFRelease(source6); + + // register Bonjour service + if (publishBonjourService) + { + // The service type is nslogger-ssl (now the default), or nslogger for backwards + // compatibility with pre-1.0. + NSString *serviceType = (NSString *)(secure ? LOGGER_SERVICE_TYPE_SSL : LOGGER_SERVICE_TYPE); + + // The service name is either the one defined in the prefs, of by default + // the local computer name (as defined in the sharing prefs panel + // (see Technical Q&A QA1228 http://developer.apple.com/library/mac/#qa/qa2001/qa1228.html ) + NSString *serviceName = [[NSUserDefaults standardUserDefaults] objectForKey:kPrefBonjourServiceName]; + if (serviceName == nil || ![serviceName isKindOfClass:[NSString class]]) + serviceName = @""; + + [bonjourServiceName release]; + bonjourServiceName = [serviceName retain]; + + bonjourService = [[NSNetService alloc] initWithDomain:@"" + type:(NSString *)serviceType + name:(NSString *)serviceName + port:listenerPort]; + [bonjourService setDelegate:self]; + [bonjourService publish]; + } + else + { + ready = YES; + } + + } + @catch (NSException * e) + { + failed = YES; + if (publishBonjourService) + self.failureReason = NSLocalizedString(@"Failed creating sockets for Bonjour%s service.", @""); + else + self.failureReason = [NSString stringWithFormat:NSLocalizedString(@"Failed listening on port %d (port busy?)",@""), listenerPort]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification + object:self]; + + if (listenerSocket_ipv4 != NULL) + { + CFRelease(listenerSocket_ipv4); + listenerSocket_ipv4 = NULL; + } + if (listenerSocket_ipv6 != NULL) + { + CFRelease(listenerSocket_ipv6); + listenerSocket_ipv6 = NULL; + } + return NO; + } + @finally + { + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification + object:self]; + } + return YES; +} + +- (void)listenerThread +{ + listenerThread = [NSThread currentThread]; + [[listenerThread threadDictionary] setObject:[NSRunLoop currentRunLoop] forKey:@"runLoop"]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +#ifdef DEBUG + NSString *description = [self description]; + NSLog(@"Entering listenerThread for transport %@", description); +#endif + @try + { + if ([self setup]) + { + while (![listenerThread isCancelled]) + { + NSDate *next = [[NSDate alloc] initWithTimeIntervalSinceNow:0.10]; + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:next]; + [next release]; + } + } + } + @catch (NSException * e) + { +#ifdef DEBUG + NSLog(@"listenerThread catched exception %@", e); +#endif + } + @finally + { +#ifdef DEBUG + NSLog(@"Exiting listenerThread for transport %@", description); +#endif + [pool release]; + listenerThread = nil; + active = NO; + } +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@ %p listenerPort=%d publishBonjourService=%d secure=%d>", + [self class], self, listenerPort, (int)publishBonjourService, (int)secure]; +} + +#ifdef DEBUG +- (void)dumpBytes:(uint8_t *)bytes length:(int)dataLen +{ + NSMutableString *s = [[NSMutableString alloc] init]; + NSUInteger offset = 0; + NSString *str; + char buffer[1+6+16*3+1+16+1+1+1]; + buffer[0] = '\0'; + const unsigned char *q = bytes; + if (dataLen == 1) + [s appendString:NSLocalizedString(@"Raw data, 1 byte:\n", @"")]; + else + [s appendFormat:NSLocalizedString(@"Raw data, %u bytes:\n", @""), dataLen]; + while (dataLen) + { + int i, b = sprintf(buffer," %04x: ", offset); + for (i=0; i < 16 && i < dataLen; i++) + sprintf(&buffer[b+3*i], "%02x ", (int)q[i]); + for (int j=i; j < 16; j++) + strcat(buffer, " "); + + b = strlen(buffer); + buffer[b++] = '\''; + for (i=0; i < 16 && i < dataLen; i++, q++) + { + if (*q >= 32 && *q < 128) + buffer[b++] = *q; + else + buffer[b++] = ' '; + } + for (int j=i; j < 16; j++) + buffer[b++] = ' '; + buffer[b++] = '\''; + buffer[b++] = '\n'; + buffer[b] = 0; + + str = [[NSString alloc] initWithBytes:buffer length:strlen(buffer) encoding:NSISOLatin1StringEncoding]; + [s appendString:str]; + [str release]; + + dataLen -= i; + offset += i; + } + NSLog(@"Received bytes:\n%@", s); + [s release]; +} +#endif + +- (NSString *)clientInfoStringForMessage:(LoggerMessage *)message +{ + NSDictionary *parts = message.parts; + NSString *clientName = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_CLIENT_NAME]]; + NSString *clientVersion = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_CLIENT_VERSION]]; + NSString *clientAppInfo = @""; + if ([clientName length]) + clientAppInfo = [NSString stringWithFormat:NSLocalizedString(@"Client connected: %@ %@", @""), + clientName, + clientVersion ? clientVersion : @""]; + + NSString *osName = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_OS_NAME]]; + NSString *osVersion = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_OS_VERSION]]; + NSString *osInfo = @""; + if ([osName length]) + osInfo = [NSString stringWithFormat:NSLocalizedString(@"%@ (%@ %@)", @""), + [clientAppInfo length] ? @"" : NSLocalizedString(@"Client connected", @""), + osName, + osVersion ? osVersion : @""]; + + NSString *hardware = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_CLIENT_MODEL]]; + NSString *hardwareInfo = @""; + if ([hardware length]) + hardwareInfo = [NSString stringWithFormat:NSLocalizedString(@"\nHardware: %@", @""), hardware]; + + NSString *uniqueID = [parts objectForKey:[NSNumber numberWithInteger:PART_KEY_UNIQUEID]]; + NSString *uniqueIDString = @""; + if ([uniqueID length]) + uniqueIDString = [NSString stringWithFormat:NSLocalizedString(@"\nUDID: %@", @""), uniqueID]; + NSString *header = @""; + if (clientAppInfo == nil) + header = NSLocalizedString(@"Client connected\n", @""); + return [NSString stringWithFormat:@"%@%@%@%@%@", header, clientAppInfo, osInfo, hardwareInfo, uniqueIDString]; +} + +- (BOOL)canDoSSL +{ + // This method can BLOCK THE CURRENT THREAD and run security dialog UI from the main thread + LoggerAppDelegate *appDelegate = (LoggerAppDelegate *)[[NSApplication sharedApplication] delegate]; + if (!appDelegate.serverCertsLoadAttempted) + { + dispatch_sync(dispatch_get_main_queue(), ^{ + NSError *error = nil; + if (![appDelegate loadEncryptionCertificate:&error]) + { + [NSApp performSelector:@selector(presentError:) withObject:error afterDelay:0]; + } + }); + } + return (appDelegate.serverCerts != NULL); +} + +- (BOOL)setupSSLForStream:(NSInputStream *)readStream +{ + LoggerAppDelegate *appDelegate = (LoggerAppDelegate *)[[NSApplication sharedApplication] delegate]; +#ifdef DEBUG + NSLog(@"setupSSLForStream, stream=%@ self=%@ serverCerts=%@", readStream, self, appDelegate.serverCerts); +#endif + CFArrayRef serverCerts = appDelegate.serverCerts; + if (serverCerts != NULL) + { + // setup stream for SSL + const void *SSLKeys[] = { + kCFStreamSSLLevel, + kCFStreamSSLValidatesCertificateChain, + kCFStreamSSLIsServer, + kCFStreamSSLCertificates + }; + const void *SSLValues[] = { + kCFStreamSocketSecurityLevelNegotiatedSSL, + kCFBooleanFalse, // no certificate chain validation (we use a self-signed certificate) + kCFBooleanTrue, // we are server + serverCerts, + }; + CFDictionaryRef SSLDict = CFDictionaryCreate(NULL, SSLKeys, SSLValues, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFReadStreamSetProperty((CFReadStreamRef)readStream, kCFStreamPropertySSLSettings, SSLDict); + CFRelease(SSLDict); + return YES; + } + return NO; +} + +// ----------------------------------------------------------------------------- +// NSStream delegate +// ----------------------------------------------------------------------------- +- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @try + { + // Locate the connection to which this stream is attached + LoggerNativeConnection *cnx = nil; + for (cnx in connections) + { + if (cnx.readStream == theStream) + break; + cnx = nil; + } + if (cnx == nil) + return; + + NSInteger numBytes; + + switch(streamEvent) + { + case NSStreamEventHasBytesAvailable: + while ([cnx.readStream hasBytesAvailable]) + { + // read bytes + numBytes = [cnx.readStream read:cnx.tmpBuf maxLength:cnx.tmpBufSize]; + if (numBytes <= 0) + break; + + // append data to the data buffer + NSMutableArray *msgs = [[NSMutableArray alloc] init]; + //[self dumpBytes:cnx.tmpBuf length:numBytes]; + [cnx.buffer appendBytes:cnx.tmpBuf length:numBytes]; + NSUInteger bufferLength = [cnx.buffer length]; + while (bufferLength > 4) + { + // check whether we have a full message + uint32_t length; + [cnx.buffer getBytes:&length length:4]; + length = ntohl(length); + if (bufferLength < (length + 4)) + break; + + // get one message + CFDataRef subset = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + (unsigned char *)[cnx.buffer bytes] + 4, + length, + kCFAllocatorNull); + if (subset != NULL) + { + // we receive a ClientInfo message only when the client connects. Once we get this message, + // the connection is considered being "live" (we need to wait a bit to let SSL negotiation to + // take place, and not open a window if it fails). + LoggerMessage *message = [[LoggerNativeMessage alloc] initWithData:(NSData *)subset connection:cnx]; + CFRelease(subset); + if (message.type == LOGMSG_TYPE_CLIENTINFO) + { + message.message = [self clientInfoStringForMessage:message]; + message.threadID = @""; + [cnx clientInfoReceived:message]; + [self attachConnectionToWindow:cnx]; + } + else + { + [msgs addObject:message]; + } + [message release]; + } + [cnx.buffer replaceBytesInRange:NSMakeRange(0, length+4) withBytes:NULL length:0]; + bufferLength = [cnx.buffer length]; + } + + if ([msgs count]) + [cnx messagesReceived:msgs]; + [msgs release]; + } + break; + + case NSStreamEventErrorOccurred: { + NSLog(@"Stream error occurred: stream=%@ self=%@ error=%@", theStream, self, [theStream streamError]); + NSError *error = [theStream streamError]; + NSInteger errCode = [error code]; + if (errCode == errSSLDecryptionFail || errCode == errSSLBadRecordMac) + { + // SSL failure due to the application not being codesigned + // See https://devforums.apple.com/thread/77848?tstart=0 + dispatch_async(dispatch_get_main_queue(), ^{ + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"NSLogger SSL authentication failure", @""), NSLocalizedDescriptionKey, + NSLocalizedString(@"Your NSLogger build may not be codesigned. As a result, a conflict between Firewall and Keychain tagging of your viewer requires that you restart NSLogger to complete the SSL certificate authorization.\n\nRestart NSLogger now to fix the issue.", @""), NSLocalizedRecoverySuggestionErrorKey, + [NSString stringWithFormat:@"CFStream error %d", errCode], NSUnderlyingErrorKey, + NSLocalizedString(@"Click the Restart button to restart NSLogger now.", @""), NSLocalizedRecoverySuggestionErrorKey, + [NSArray arrayWithObject:NSLocalizedString(@"Restart", @"")], NSLocalizedRecoveryOptionsErrorKey, + [NSApp delegate], NSRecoveryAttempterErrorKey, + nil]; + [NSApp presentError:[NSError errorWithDomain:@"NSLogger" + code:errCode + userInfo:dict]]; + }); + } + break; + } + // fall through + case NSStreamEventEndEncountered: { + // Append a disconnect message for only one of the two streams + struct timeval t; + gettimeofday(&t, NULL); + LoggerMessage *msg = [[LoggerMessage alloc] init]; + msg.timestamp = t; + msg.type = LOGMSG_TYPE_DISCONNECT; + msg.message = NSLocalizedString(@"Client disconnected", @""); + [cnx messagesReceived:[NSArray arrayWithObject:msg]]; + [msg release]; + cnx.connected = NO; + [cnx.buffer setLength:0]; + break; + } + + case NSStreamEventOpenCompleted: + cnx.connected = YES; + break; + + default: + break; + } + } + @catch (NSException * e) + { + } + @finally + { + [pool release]; + } +} + +// ----------------------------------------------------------------------------- +// NSNetService delegate +// ----------------------------------------------------------------------------- +- (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict +{ + [self shutdown]; + + int errorCode = [[errorDict objectForKey:NSNetServicesErrorCode] integerValue]; + if (errorCode == NSNetServicesCollisionError) + self.failureReason = NSLocalizedString(@"Duplicate Bonjour service name on your network", @""); + else if (errorCode == NSNetServicesBadArgumentError) + self.failureReason = NSLocalizedString(@"Bonjour bad argument - please report bug.", @""); + else if (errorCode == NSNetServicesInvalidError) + self.failureReason = NSLocalizedString(@"Bonjour invalid configuration - please report bug.", @""); + else + self.failureReason = [NSString stringWithFormat:NSLocalizedString(@"Bonjour error %d", @""), errorCode]; + failed = YES; + + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification object:self]; +} + +- (void)netServiceDidPublish:(NSNetService *)sender +{ + ready = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:kShowStatusInStatusWindowNotification + object:self]; +} + +@end + +static void AcceptSocketCallback(CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @try + { + if (type == kCFSocketAcceptCallBack) + { + // we have a new incoming connection with a child socket + // reenable accept callback + CFSocketEnableCallBacks(sock, kCFSocketAcceptCallBack); + + // Get the native socket handle for the new incoming connection + CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data; + + LoggerNativeTransport *myself = (LoggerNativeTransport *)info; + if (myself.secure && ![myself canDoSSL]) + { + // should enable SSL but loading or authorization failed + close(nativeSocketHandle); + } + else + { + int addrSize; + BOOL ipv6 = (sock == myself.listenerSocket_ipv6); + if (!ipv6) + addrSize = sizeof(struct sockaddr_in); + else + addrSize = sizeof(struct sockaddr_in6); + + if (CFDataGetLength(address) == addrSize) + { + // create the input and output streams. We don't need an output stream, + // except for SSL negotiation. + CFReadStreamRef readStream = NULL; + CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, NULL); + if (readStream != NULL) + { + // although this is implied, just want to make sure + CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + if (myself.secure) + [myself setupSSLForStream:(NSInputStream *)readStream]; + + // Create the connection instance + LoggerNativeConnection *cnx = [[LoggerNativeConnection alloc] initWithInputStream:(NSInputStream *)readStream + clientAddress:(NSData *)address]; + [myself addConnection:cnx]; + + // Schedule & open stream + [(NSInputStream *)readStream setDelegate:myself]; + [(NSInputStream *)readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + + [(NSInputStream *)readStream open]; + [(NSInputStream *)readStream release]; + + [cnx release]; + } + else + { + // immediately close the child socket, we can't use it anymore + close(nativeSocketHandle); + } + } + else + { + // no valid address? + close(nativeSocketHandle); + } + } + } + } + @catch (NSException * e) + { +#ifdef DEBUG + NSLog(@"LoggerNativeTransport %p: exception catched in AcceptSocketCallback: %@", info, e); +#endif + } + @finally + { + [pool release]; + } +} diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerPrefsWindowController.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerPrefsWindowController.h new file mode 100644 index 000000000..82e37ea22 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerPrefsWindowController.h @@ -0,0 +1,79 @@ +/* + * LoggerPrefsWindowController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerConnection; + +@interface LoggerPrefsWindowController : NSWindowController +{ + IBOutlet NSObjectController *networkDefaultsController; + + IBOutlet NSControl *sampleMessage; + IBOutlet NSControl *sampleDataMessage; + + IBOutlet NSTextField *timestampFontName; + IBOutlet NSTextField *threadIDFontName; + IBOutlet NSTextField *tagFontName; + IBOutlet NSTextField *textFontName; + IBOutlet NSTextField *dataFontName; + IBOutlet NSTextField *fileFunctionFontName; + + IBOutlet NSColorWell *timestampForegroundColor; + IBOutlet NSColorWell *threadIDForegroundColor; + IBOutlet NSColorWell *tagLevelForegroundColor; + IBOutlet NSColorWell *textForegroundColor; + IBOutlet NSColorWell *dataForegroundColor; + IBOutlet NSColorWell *fileFunctionForegroundColor; + IBOutlet NSColorWell *fileFunctionBackgroundColor; + + LoggerConnection *fakeConnection; + + int currentFontSelection; + NSDictionary *attributes; + + NSMutableDictionary *networkPrefs; +} + +- (IBAction)selectFont:(id)sender; +- (IBAction)selectColor:(id)sender; + +- (IBAction)applyNetworkChanges:(id)sender; +- (IBAction)restoreNetworkDefaults:(id)sender; + +- (IBAction)applyFontChanges:(id)sender; +- (IBAction)restoreFontDefaults:(id)sender; + +@end + +@interface SampleMessageControl : NSControl +@end + +extern NSString * const kPrefsChangedNotification; \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerPrefsWindowController.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerPrefsWindowController.m new file mode 100644 index 000000000..b8f23e6c2 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerPrefsWindowController.m @@ -0,0 +1,427 @@ +/* + * LoggerPrefsWindowController.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#import "LoggerPrefsWindowController.h" +#import "LoggerAppDelegate.h" +#import "LoggerMessage.h" +#import "LoggerMessageCell.h" +#import "LoggerConnection.h" + +enum { + kTimestampFont = 1, + kThreadIDFont, + kTagAndLevelFont, + kTextFont, + kDataFont, + kFileFunctionFont +}; + +enum { + kTimestampFontColor = 1, + kThreadIDFontColor, + kTagAndLevelFontColor, + kTextFontColor, + kDataFontColor, + kFileFunctionFontColor, + kFileFunctionBackgroundColor +}; + +NSString * const kPrefsChangedNotification = @"PrefsChangedNotification"; + +@implementation SampleMessageControl +- (BOOL)isFlipped +{ + return YES; +} +@end + +@interface LoggerPrefsWindowController (Private) +- (void)updateUI; +- (NSMutableDictionary *)copyNetworkPrefs; +@end + +@implementation LoggerPrefsWindowController + +- (id)initWithWindowNibName:(NSString *)windowNibName +{ + if ((self = [super initWithWindowNibName:windowNibName]) != nil) + { + // Extract current prefs for bindings. We don't want to rely on a global NSUserDefaultsController + networkPrefs = [self copyNetworkPrefs]; + + // make a deep copy of default attributes by going back and forth with + // an archiver + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[LoggerMessageCell defaultAttributes]]; + attributes = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]; + } + return self; +} + +- (void)dealloc +{ + [fakeConnection release]; + [attributes release]; + [networkPrefs release]; + [super dealloc]; +} + +- (NSMutableDictionary *)copyNetworkPrefs +{ + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + return [[NSMutableDictionary alloc] initWithObjectsAndKeys: + [ud objectForKey:kPrefPublishesBonjourService], kPrefPublishesBonjourService, + [ud objectForKey:kPrefBonjourServiceName], kPrefBonjourServiceName, + [ud objectForKey:kPrefHasDirectTCPIPResponder], kPrefHasDirectTCPIPResponder, + [ud objectForKey:kPrefDirectTCPIPResponderPort], kPrefDirectTCPIPResponderPort, + nil]; +} + +- (void)awakeFromNib +{ + // Prepare a couple fake messages to get a sample display + struct timeval tv; + gettimeofday(&tv, NULL); + + LoggerMessage *prevMsg = [[LoggerMessage alloc] init]; + if (tv.tv_usec) + tv.tv_usec = 0; + else + { + tv.tv_sec--; + tv.tv_usec = 500000; + } + prevMsg.timestamp = tv; + + fakeConnection = [[LoggerConnection alloc] init]; + + LoggerMessage *msg = [[LoggerMessage alloc] init]; + msg.timestamp = tv; + msg.tag = @"database"; + msg.message = @"Example message text"; + msg.threadID = @"Main thread"; + msg.level = 0; + msg.contentsType = kMessageString; + msg.cachedCellSize = sampleMessage.frame.size; + [msg setFilename:@"file.m" connection:fakeConnection]; + msg.lineNumber = 100; + [msg setFunctionName:@"-[MyClass aMethod:withParameters:]" connection:fakeConnection]; + + LoggerMessageCell *cell = [[LoggerMessageCell alloc] init]; + cell.message = msg; + cell.previousMessage = prevMsg; + cell.shouldShowFunctionNames = YES; + [sampleMessage setCell:cell]; + [cell release]; + [msg release]; + + uint8_t bytes[32]; + for (int i = 0; i < sizeof(bytes); i++) + bytes[i] = (uint8_t)arc4random(); + + cell = [[LoggerMessageCell alloc] init]; + msg = [[LoggerMessage alloc] init]; + msg.timestamp = tv; + msg.tag = @"network"; + msg.message = [NSData dataWithBytes:bytes length:sizeof(bytes)]; + msg.threadID = @"Main thread"; + msg.level = 1; + msg.contentsType = kMessageData; + msg.cachedCellSize = sampleDataMessage.frame.size; + cell.message = msg; + cell.previousMessage = prevMsg; + [sampleDataMessage setCell:cell]; + [cell release]; + [msg release]; + [prevMsg release]; + + [self updateUI]; + [sampleMessage setNeedsDisplay]; + [sampleDataMessage setNeedsDisplay]; +} + +- (BOOL)hasNetworkChanges +{ + // Check whether attributes or network settings have changed + for (NSString *key in networkPrefs) + { + if (![[[NSUserDefaults standardUserDefaults] objectForKey:key] isEqual:[networkPrefs objectForKey:key]]) + return YES; + } + return NO; +} + +- (BOOL)hasFontChanges +{ + return (NO == [[LoggerMessageCell defaultAttributes] isEqual:attributes]); +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Close & Apply management +// ----------------------------------------------------------------------------- +- (BOOL)windowShouldClose:(id)sender +{ + if (![networkDefaultsController commitEditing]) + return NO; + if ([self hasNetworkChanges] || [self hasFontChanges]) + { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:NSLocalizedString(@"Would you like to apply your changes before closing the Preferences window?", @"")]; + [alert addButtonWithTitle:NSLocalizedString(@"Apply", @"")]; + [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"")]; + [alert addButtonWithTitle:NSLocalizedString(@"Don't Apply", @"")]; + [alert beginSheetModalForWindow:[self window] + modalDelegate:self + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:NULL]; + [alert release]; + return NO; + } + return YES; +} + +- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + [[alert window] orderOut:self]; + if (returnCode == NSAlertFirstButtonReturn) + { + // Apply (and close window) + if ([self hasNetworkChanges]) + [self applyNetworkChanges:nil]; + if ([self hasFontChanges]) + [self applyFontChanges:nil]; + [[self window] performSelector:@selector(close) withObject:nil afterDelay:0]; + } + else if (returnCode == NSAlertSecondButtonReturn) + { + // Cancel (don't close window) + // nothing more to do + } + else + { + // Don't Apply (and close window) + [[self window] performSelector:@selector(close) withObject:nil afterDelay:0]; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Network preferences +// ----------------------------------------------------------------------------- +- (IBAction)restoreNetworkDefaults:(id)sender +{ + [networkDefaultsController commitEditing]; + NSDictionary *dict = [LoggerAppDelegate defaultPreferences]; + for (NSString *key in dict) + { + if ([networkPrefs objectForKey:key] != nil) + [[networkDefaultsController selection] setValue:[dict objectForKey:key] forKey:key]; + } +} + +- (void)applyNetworkChanges:(id)sender +{ + if ([networkDefaultsController commitEditing]) + { + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + for (NSString *key in [networkPrefs allKeys]) + [ud setObject:[networkPrefs objectForKey:key] forKey:key]; + [ud synchronize]; + [[NSNotificationCenter defaultCenter] postNotificationName:kPrefsChangedNotification object:self]; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Font preferences +// ----------------------------------------------------------------------------- +- (IBAction)applyFontChanges:(id)sender +{ + [[LoggerMessageCell class] setDefaultAttributes:attributes]; + [[NSUserDefaults standardUserDefaults] synchronize]; + [[NSNotificationCenter defaultCenter] postNotificationName:kPrefsChangedNotification object:self]; +} + +- (IBAction)restoreFontDefaults:(id)sender +{ + [attributes release]; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[LoggerMessageCell defaultAttributesDictionary]]; + attributes = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]; + ((LoggerMessageCell *)[sampleMessage cell]).messageAttributes = attributes; + ((LoggerMessageCell *)[sampleDataMessage cell]).messageAttributes = attributes; + [sampleMessage setNeedsDisplay]; + [sampleDataMessage setNeedsDisplay]; + [self updateUI]; +} + +- (NSFont *)fontForCurrentFontSelection +{ + NSFont *font; + switch (currentFontSelection) + { + case kTimestampFont: + font = [[attributes objectForKey:@"timestamp"] objectForKey:NSFontAttributeName]; + break; + case kThreadIDFont: + font = [[attributes objectForKey:@"threadID"] objectForKey:NSFontAttributeName]; + break; + case kTagAndLevelFont: + font = [[attributes objectForKey:@"tag"] objectForKey:NSFontAttributeName]; + break; + case kDataFont: + font = [[attributes objectForKey:@"data"] objectForKey:NSFontAttributeName]; + break; + case kFileFunctionFont: + font = [[attributes objectForKey:@"fileLineFunction"] objectForKey:NSFontAttributeName]; + break; + default: + font = [[attributes objectForKey:@"text"] objectForKey:NSFontAttributeName]; + break; + } + return font; +} + +- (IBAction)selectFont:(id)sender +{ + currentFontSelection = [(NSView *)sender tag]; + [[NSFontManager sharedFontManager] setTarget:self]; + [[NSFontPanel sharedFontPanel] setPanelFont:[self fontForCurrentFontSelection] isMultiple:NO]; + [[NSFontPanel sharedFontPanel] makeKeyAndOrderFront:self]; +} + +- (IBAction)selectColor:(id)sender +{ + NSString *attrName = NSForegroundColorAttributeName, *dictName = nil, *dictName2 = nil; + int tag = [(NSView *)sender tag]; + if (tag == kTimestampFontColor) + dictName = @"timestamp"; + else if (tag == kThreadIDFontColor) + dictName = @"threadID"; + else if (tag == kTagAndLevelFontColor) + { + dictName = @"tag"; + dictName2 = @"level"; + } + else if (tag == kTextFontColor) + dictName = @"text"; + else if (tag == kDataFontColor) + dictName = @"data"; + else if (tag == kFileFunctionFontColor) + dictName = @"fileLineFunction"; + else if (tag == kFileFunctionBackgroundColor) + { + dictName = @"fileLineFunction"; + attrName = NSBackgroundColorAttributeName; + } + if (dictName != nil) + { + [[attributes objectForKey:dictName] setObject:[sender color] forKey:attrName]; + if (dictName2 != nil) + [[attributes objectForKey:dictName2] setObject:[sender color] forKey:attrName]; + ((LoggerMessageCell *)[sampleMessage cell]).messageAttributes = attributes; + ((LoggerMessageCell *)[sampleDataMessage cell]).messageAttributes = attributes; + [sampleMessage setNeedsDisplay]; + [sampleDataMessage setNeedsDisplay]; + } +} + +- (void)changeFont:(id)sender +{ + NSFont *newFont = [sender convertFont:[self fontForCurrentFontSelection]]; + switch (currentFontSelection) + { + case kTimestampFont: + [[attributes objectForKey:@"timestamp"] setObject:newFont forKey:NSFontAttributeName]; + [[attributes objectForKey:@"timedelta"] setObject:newFont forKey:NSFontAttributeName]; + break; + case kThreadIDFont: + [[attributes objectForKey:@"threadID"] setObject:newFont forKey:NSFontAttributeName]; + break; + case kTagAndLevelFont: + [[attributes objectForKey:@"tag"] setObject:newFont forKey:NSFontAttributeName]; + [[attributes objectForKey:@"level"] setObject:newFont forKey:NSFontAttributeName]; + break; + case kDataFont: + [[attributes objectForKey:@"data"] setObject:newFont forKey:NSFontAttributeName]; + break; + case kFileFunctionFont: + [[attributes objectForKey:@"fileLineFunction"] setObject:newFont forKey:NSFontAttributeName]; + break; + default: { + [[attributes objectForKey:@"text"] setObject:newFont forKey:NSFontAttributeName]; + [[attributes objectForKey:@"mark"] setObject:newFont forKey:NSFontAttributeName]; + break; + } + } + ((LoggerMessageCell *)[sampleMessage cell]).messageAttributes = attributes; + ((LoggerMessageCell *)[sampleDataMessage cell]).messageAttributes = attributes; + [sampleMessage setNeedsDisplay]; + [sampleDataMessage setNeedsDisplay]; + [self updateUI]; +} + +- (NSString *)fontNameForFont:(NSFont *)aFont +{ + return [NSString stringWithFormat:@"%@ %.1f", [aFont displayName], [aFont pointSize]]; +} + +- (void)updateColor:(NSColorWell *)well ofDict:(NSString *)dictName attribute:(NSString *)attrName +{ + NSColor *color = [[attributes objectForKey:dictName] objectForKey:attrName]; + if (color == nil) + { + if ([attrName isEqualToString:NSForegroundColorAttributeName]) + color = [NSColor blackColor]; + else + color = [NSColor clearColor]; + } + [well setColor:color]; +} + +- (void)updateUI +{ + [timestampFontName setStringValue:[self fontNameForFont:[[attributes objectForKey:@"timestamp"] objectForKey:NSFontAttributeName]]]; + [threadIDFontName setStringValue:[self fontNameForFont:[[attributes objectForKey:@"threadID"] objectForKey:NSFontAttributeName]]]; + [tagFontName setStringValue:[self fontNameForFont:[[attributes objectForKey:@"tag"] objectForKey:NSFontAttributeName]]]; + [textFontName setStringValue:[self fontNameForFont:[[attributes objectForKey:@"text"] objectForKey:NSFontAttributeName]]]; + [dataFontName setStringValue:[self fontNameForFont:[[attributes objectForKey:@"data"] objectForKey:NSFontAttributeName]]]; + [fileFunctionFontName setStringValue:[self fontNameForFont:[[attributes objectForKey:@"fileLineFunction"] objectForKey:NSFontAttributeName]]]; + + [self updateColor:timestampForegroundColor ofDict:@"timestamp" attribute:NSForegroundColorAttributeName]; + [self updateColor:threadIDForegroundColor ofDict:@"threadID" attribute:NSForegroundColorAttributeName]; + [self updateColor:tagLevelForegroundColor ofDict:@"tag" attribute:NSForegroundColorAttributeName]; + [self updateColor:textForegroundColor ofDict:@"text" attribute:NSForegroundColorAttributeName]; + [self updateColor:dataForegroundColor ofDict:@"data" attribute:NSForegroundColorAttributeName]; + [self updateColor:fileFunctionForegroundColor ofDict:@"fileLineFunction" attribute:NSForegroundColorAttributeName]; + [self updateColor:fileFunctionBackgroundColor ofDict:@"fileLineFunction" attribute:NSBackgroundColorAttributeName]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerSplitView.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerSplitView.h new file mode 100644 index 000000000..9b683ca06 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerSplitView.h @@ -0,0 +1,37 @@ +/* + * LoggerSplitView.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "BWToolkitFramework.h" + +@interface LoggerSplitView : BWSplitView +{ +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerSplitView.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerSplitView.m new file mode 100644 index 000000000..0d792a398 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerSplitView.m @@ -0,0 +1,56 @@ +/* + * LoggerSplitView.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerSplitView.h" + +@implementation LoggerSplitView + +- (void)mouseDown:(NSEvent *)theEvent +{ + // hack: to detect the end of a split view drag, post a message that will be sent + // only when the runloop returns to the default run loop mode. At this point, we will + // send a notification that will force a logTable re-tile if needed + // (explanation: during a split view divided drag, the runloop is being set in a + // special mode and will exit this mode only when dragging ends -- since we don't + // get any notification that a divider drag ended, I had to find another way to + // detect the end of a divider drag). + [self performSelector:@selector(sendTableRetileNotification) + withObject:nil + afterDelay:0 + inModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]]; + [super mouseDown:theEvent]; +} + +- (void)sendTableRetileNotification +{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"TileLogTableNotification" object:nil]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerStatusWindowController.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerStatusWindowController.h new file mode 100644 index 000000000..3aa89d93a --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerStatusWindowController.h @@ -0,0 +1,43 @@ +/* + * LoggerStatusWindowController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +@class LoggerTransportStatusCell; + +@interface LoggerStatusWindowController : NSWindowController +{ + LoggerTransportStatusCell *transportStatusCell; + + IBOutlet NSTableView *statusTable; +} + +@end + +extern NSString * const kShowStatusInStatusWindowNotification; \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerStatusWindowController.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerStatusWindowController.m new file mode 100644 index 000000000..2ca637fdf --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerStatusWindowController.m @@ -0,0 +1,101 @@ +/* + * LoggerStatusWindowController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerStatusWindowController.h" +#import "LoggerAppDelegate.h" +#import "LoggerTransport.h" +#import "LoggerConnection.h" +#import "LoggerTransportStatusCell.h" + +NSString * const kShowStatusInStatusWindowNotification = @"ShowStatusInStatusWindowNotification"; + +@implementation LoggerStatusWindowController + +- (void)dealloc +{ + [transportStatusCell release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)windowDidLoad +{ + transportStatusCell = [[LoggerTransportStatusCell alloc] init]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(showStatus:) + name:kShowStatusInStatusWindowNotification + object:nil]; + + [[self window] setLevel:NSNormalWindowLevel]; +} + +- (void)showStatus:(NSNotification *)notification +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [statusTable reloadData]; + }); +} + + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSTableDelegate +// ----------------------------------------------------------------------------- +- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + if (row < [((LoggerAppDelegate *)[NSApp delegate]).transports count]) + return transportStatusCell; + return nil; +} + +- (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(NSInteger)rowIndex +{ + return NO; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSTableDataSource +// ----------------------------------------------------------------------------- +- (int)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [((LoggerAppDelegate *)[NSApp delegate]).transports count]; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex +{ + NSArray *transports = ((LoggerAppDelegate *)[NSApp delegate]).transports; + if (rowIndex >= 0 && rowIndex < [transports count]) + return [NSNumber numberWithInteger:rowIndex]; + return nil; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerTableView.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTableView.h new file mode 100644 index 000000000..ffd624bf5 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTableView.h @@ -0,0 +1,45 @@ +/* + * LoggerTableView.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +@interface LoggerTableView : NSTableView +{ + NSTrackingArea *tableTrackingArea; + NSTrackingArea *timestampSeparatorTrackingArea; + NSTrackingArea *threadSeparatorTrackingArea; + + CGFloat timestampColumnWidth; + CGFloat threadIDColumnWidth; +} + +@property (nonatomic, assign) CGFloat timestampColumnWidth; +@property (nonatomic, assign) CGFloat threadIDColumnWidth; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerTableView.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTableView.m new file mode 100644 index 000000000..bc2248ad8 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTableView.m @@ -0,0 +1,64 @@ +/* + * LoggerTableView.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-1011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerTableView.h" + +@implementation LoggerTableView + +@synthesize timestampColumnWidth, threadIDColumnWidth; + +- (void) dealloc +{ + [tableTrackingArea release]; + [timestampSeparatorTrackingArea release]; + [threadSeparatorTrackingArea release]; + [super dealloc]; +} + +#pragma mark - +#pragma mark MouseOver support + +- (void)updateTrackingAreas +{ + // @@@ TODO +} + +#pragma mark - +#pragma mark Dragging support + +- (BOOL)canDragRowsWithIndexes:(NSIndexSet *)rowIndexes atPoint:(NSPoint)mouseDownPoint +{ + // Don't understand why I have to override this method, but it's the only + // way I could get dragging from table to work. Tried various additional + // things with no luck... + return YES; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransport.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransport.h new file mode 100644 index 000000000..117ee1ab4 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransport.h @@ -0,0 +1,62 @@ +/* + * LoggerTransport.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +@class LoggerConnection; + +@interface LoggerTransport : NSObject +{ + NSMutableArray *connections; + NSString *failureReason; + BOOL secure; + BOOL active; + BOOL ready; + BOOL failed; +} + +@property (nonatomic, assign) BOOL secure; +@property (nonatomic, readonly) BOOL active; +@property (nonatomic, readonly) BOOL failed; +@property (nonatomic, readonly) BOOL ready; +@property (nonatomic, readonly) NSMutableArray *connections; +@property (nonatomic, retain) NSString *failureReason; + +- (void)startup; +- (void)shutdown; +- (void)restart; +- (void)addConnection:(LoggerConnection *)aConnection; +- (void)removeConnection:(LoggerConnection *)aConnection; +- (void)attachConnectionToWindow:(LoggerConnection *)aConnection; + +- (NSString *)transportInfoString; +- (NSString *)transportStatusString; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransport.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransport.m new file mode 100644 index 000000000..1a39a4e1a --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransport.m @@ -0,0 +1,108 @@ +/* + * LoggerTransport.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerTransport.h" +#import "LoggerConnection.h" +#import "LoggerAppDelegate.h" +#import "LoggerStatusWindowController.h" + +@implementation LoggerTransport + +@synthesize connections; +@synthesize secure, active, ready, failed, failureReason; + +- (id)init +{ + if ((self = [super init]) != nil) + { + connections = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)dealloc +{ + [failureReason release]; + [connections release]; + [super dealloc]; +} + +- (void)addConnection:(LoggerConnection *)aConnection +{ + [connections addObject:aConnection]; +} + +- (void)removeConnection:(LoggerConnection *)aConnection +{ + if ([connections containsObject:aConnection]) + { + [aConnection shutdown]; + [connections removeObject:aConnection]; + } +} + +- (void)attachConnectionToWindow:(LoggerConnection *)aConnection +{ + // make a new document for a connection (it is considered live once we have received + // the ClientInfo message) or reuse an existing document if this is a reconnection + dispatch_sync(dispatch_get_main_queue(), ^{ + if (!aConnection.attachedToWindow) + [(LoggerAppDelegate *)[NSApp delegate] newConnection:aConnection fromTransport:self]; + }); +} + +- (void)startup +{ + // subclasses should implement this +} + +- (void)shutdown +{ + // subclasses should implement this +} + +- (void)restart +{ + // subclasses should implement this +} + +- (NSString *)transportInfoString +{ + // subclasses should implement this, LoggerStatusWindowController uses it + return @""; +} + +- (NSString *)transportStatusString +{ + // subclasses should implement this, LoggerStatusWindowController uses it + return @""; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransportStatusCell.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransportStatusCell.h new file mode 100644 index 000000000..b4daf4209 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransportStatusCell.h @@ -0,0 +1,36 @@ +/* + * LoggerTransportStatusCell.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +@interface LoggerTransportStatusCell : NSCell +{ +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransportStatusCell.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransportStatusCell.m new file mode 100644 index 000000000..ddfaf2c51 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerTransportStatusCell.m @@ -0,0 +1,130 @@ +/* + * LoggerTransportStatusCell.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import "LoggerTransportStatusCell.h" +#import "LoggerAppDelegate.h" +#import "LoggerTransport.h" + +@implementation LoggerTransportStatusCell + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + NSArray *transports = ((LoggerAppDelegate *)[NSApp delegate]).transports; + LoggerTransport *transport = [transports objectAtIndex:[[self objectValue] integerValue]]; + + BOOL highlighted = [self isHighlighted]; + + // Display status image + NSString *imgName; + if (transport.ready) + imgName = @"status_ready_connected.png"; + else if (transport.failed) + imgName = @"status_error.png"; + else + imgName = @"status_disconnected.png"; + + NSImage *img = [NSImage imageNamed:imgName]; + NSImage *sslImg = [NSImage imageNamed:@"ssl_badge.png"]; + NSSize sz = [img size]; + NSSize szSSL = NSZeroSize; + if (sslImg != nil) + szSSL = [sslImg size]; + if (!transport.secure) + sslImg = nil; + CGFloat w = fmaxf(szSSL.width, sz.width) + 10; + + if (img != nil) + { + CGFloat h = sz.height; + if (sslImg) + h += szSSL.height; + [img drawInRect:NSMakeRect(NSMinX(cellFrame) + floorf((w - sz.width) / 2.0f), + NSMinY(cellFrame) + floorf((NSHeight(cellFrame) - h) / 2.0f), + sz.width, + sz.height) + fromRect:NSMakeRect(0, 0, sz.width, sz.height) + operation:NSCompositeSourceOver + fraction:1.0f + respectFlipped:YES + hints:nil]; + if (sslImg != nil) + { + [sslImg drawInRect:NSMakeRect(NSMinX(cellFrame) + floorf((w - szSSL.width) / 2.0f), + NSMinY(cellFrame) + floorf((NSHeight(cellFrame)-h) / 2.0f) + sz.height + 3, + szSSL.width, + szSSL.height) + fromRect:NSMakeRect(0, 0, szSSL.width, szSSL.height) + operation:NSCompositeSourceOver + fraction:1.0f + respectFlipped:YES + hints:nil]; + } + } + + // Display transport name and connections information + NSString *desc = [transport transportInfoString]; + NSString *status = [transport transportStatusString]; + NSFont *descFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]]; + NSFont *statusFont = [NSFont systemFontOfSize:[NSFont systemFontSize] - 2]; + + NSColor *textColor = (highlighted ? [NSColor grayColor] : [NSColor whiteColor]); + NSDictionary *descAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + descFont, NSFontAttributeName, + textColor, NSForegroundColorAttributeName, + [NSColor clearColor], NSBackgroundColorAttributeName, + nil]; + + if (!highlighted) + { + if (transport.failed) + textColor = [NSColor redColor]; + else + textColor = [NSColor grayColor]; + } + NSDictionary *statusAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + statusFont, NSFontAttributeName, + textColor, NSForegroundColorAttributeName, + [NSColor clearColor], NSBackgroundColorAttributeName, + nil]; + + NSSize descSize = [desc sizeWithAttributes:descAttrs]; + NSSize statusSize = [status sizeWithAttributes:statusAttrs]; + + CGFloat h = descSize.height + statusSize.height + 2; + + NSRect r = NSMakeRect(NSMinX(cellFrame) + w, NSMinY(cellFrame) + floorf((NSHeight(cellFrame) - h) / 2.0f), NSWidth(cellFrame) - w, descSize.height); + [desc drawInRect:r withAttributes:descAttrs]; + r.origin.y += r.size.height + 2; + r.size.height = statusSize.height; + [status drawInRect:r withAttributes:statusAttrs]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerUtils.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerUtils.h new file mode 100644 index 000000000..a3a05fd75 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerUtils.h @@ -0,0 +1,38 @@ +/* + * LoggerUtils.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +// String utils +extern NSString *StringWithTimeDelta(struct timeval *td); + +// Graphics utils +extern CGColorRef CreateCGColorFromNSColor(NSColor * color); +void MakeRoundedPath(CGContextRef ctx, CGRect r, CGFloat radius); diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerUtils.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerUtils.m new file mode 100644 index 000000000..ca1afbfc0 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerUtils.m @@ -0,0 +1,82 @@ +/* + * LoggerUtils.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerUtils.h" + +NSString *StringWithTimeDelta(struct timeval *td) +{ + if (td->tv_sec) + { + int hrs,mn,s,ms; + hrs = td->tv_sec / 3600; + mn = (td->tv_sec % 3600) / 60; + s = td->tv_sec % 60; + ms = td->tv_usec / 1000; + if (hrs != 0) + return [NSString stringWithFormat:@"+%dh %dmn %d.%03ds", hrs, mn, s, ms]; + if (mn != 0) + return [NSString stringWithFormat:@"+%dmn %d.%03ds", mn, s, ms]; + if (s != 0) + { + if (ms != 0) + return [NSString stringWithFormat:@"+%d.%03ds", s, ms]; + return [NSString stringWithFormat:@"+%ds", s]; + } + } + if (td->tv_usec == 0) + return @""; + + // millisecond resolution + if (td->tv_usec > 10 || (td->tv_usec % 1000) == 0) + return [NSString stringWithFormat:@"+%dms", td->tv_usec / 1000]; + + // microsecond resolution + return [NSString stringWithFormat:@"+%d.%03dms", td->tv_usec / 1000, td->tv_usec % 1000]; +} + +CGColorRef CreateCGColorFromNSColor(NSColor * color) +{ + NSColor * rgbColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; + CGFloat r, g, b, a; + [rgbColor getRed:&r green:&g blue:&b alpha:&a]; + return CGColorCreateGenericRGB(r, g, b, a); +} + +void MakeRoundedPath(CGContextRef ctx, CGRect r, CGFloat radius) +{ + CGContextBeginPath(ctx); + CGContextMoveToPoint(ctx, CGRectGetMinX(r), CGRectGetMidY(r)); + CGContextAddArcToPoint(ctx, CGRectGetMinX(r), CGRectGetMinY(r), CGRectGetMidX(r), CGRectGetMinY(r), radius); + CGContextAddArcToPoint(ctx, CGRectGetMaxX(r), CGRectGetMinY(r), CGRectGetMaxX(r), CGRectGetMidY(r), radius); + CGContextAddArcToPoint(ctx, CGRectGetMaxX(r), CGRectGetMaxY(r), CGRectGetMidX(r), CGRectGetMaxY(r), radius); + CGContextAddArcToPoint(ctx, CGRectGetMinX(r), CGRectGetMaxY(r), CGRectGetMinX(r), CGRectGetMidY(r), radius); + CGContextClosePath(ctx); +} + diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerWindowController.h b/External Source/NSLogger/Desktop Viewer/Classes/LoggerWindowController.h new file mode 100644 index 000000000..7696935aa --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerWindowController.h @@ -0,0 +1,127 @@ +/* + * LoggerWindowController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "LoggerConnection.h" +#import "BWToolkitFramework.h" + +@class LoggerMessageCell, LoggerClientInfoCell, LoggerMarkerCell, LoggerTableView, LoggerSplitView; +@class LoggerDetailsWindowController; + +@interface LoggerWindowController : NSWindowController +{ + IBOutlet LoggerTableView *logTable; + IBOutlet NSTableView *filterSetsTable; + IBOutlet NSTableView *filterTable; + IBOutlet NSPopUpButton *quickFilter; + IBOutlet NSButton *showFunctionNamesButton; + IBOutlet NSSearchField *quickFilterTextField; + IBOutlet BWAnchoredButtonBar *buttonBar; + + IBOutlet NSArrayController *filterSetsListController; + IBOutlet NSArrayController *filterListController; + + IBOutlet NSWindow *filterEditorWindow; + IBOutlet NSPredicateEditor *filterEditor; + IBOutlet NSTextField *filterName; + + IBOutlet NSWindow *markTitleWindow; + IBOutlet NSTextField *markTitleField; + IBOutlet LoggerSplitView *splitView; + + LoggerConnection *attachedConnection; + LoggerDetailsWindowController *detailsWindowController; + + LoggerMessageCell *messageCell; + LoggerClientInfoCell *clientInfoCell; + LoggerMarkerCell *markerCell; + + NSString *info; + NSMutableArray *displayedMessages; + NSMutableSet *tags; + + NSPredicate *filterPredicate; // created from current selected filters, + quick filter string / tag / log level + + NSString *filterString; + NSString *filterTag; + int logLevel; + + dispatch_queue_t messageFilteringQueue; + dispatch_group_t lastTilingGroup; + + int lastMessageRow; + BOOL messagesSelected; + BOOL hasQuickFilter; + BOOL initialRefreshDone; + BOOL showFunctionNames; + BOOL clientAppSettingsRestored; +} + +@property (nonatomic, retain) LoggerConnection *attachedConnection; +@property (nonatomic, assign) BOOL messagesSelected; +@property (nonatomic, assign) BOOL hasQuickFilter; +@property (nonatomic, assign) NSNumber* showFunctionNames; + +- (IBAction)openDetailsWindow:(id)sender; + +- (IBAction)selectQuickFilterTag:(id)sender; +- (IBAction)selectQuickFilterLevel:(id)sender; +- (IBAction)resetQuickFilter:(id)sender; + +- (IBAction)addFilterSet:(id)sender; +- (IBAction)deleteSelectedFilterSet:(id)sender; + +- (IBAction)addFilter:(id)sender; +- (IBAction)startEditingFilter:(id)sender; +- (IBAction)cancelFilterEdition:(id)sender; +- (IBAction)validateFilterEdition:(id)sender; +- (IBAction)deleteSelectedFilters:(id)sender; +- (IBAction)createNewFilterFromQuickFilter:(id) sender; + +- (IBAction)addMark:(id)sender; +- (IBAction)addMarkWithTitle:(id)sender; +- (IBAction)insertMarkWithTitle:(id)sender; +- (IBAction)cancelAddMark:(id)sender; +- (IBAction)validateAddMark:(id)sender; +- (IBAction)deleteMark:(id)sender; + +- (IBAction)clearCurrentLog:(id)sender; +- (IBAction)clearAllLogs:(id)sender; + +- (IBAction)collapseTaskbar:(id)sender; + +- (void)updateMenuBar:(BOOL)documentIsFront; + +@end + +@interface LoggerTableView : NSTableView +{ +} +@end + diff --git a/External Source/NSLogger/Desktop Viewer/Classes/LoggerWindowController.m b/External Source/NSLogger/Desktop Viewer/Classes/LoggerWindowController.m new file mode 100644 index 000000000..d94d4399f --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/LoggerWindowController.m @@ -0,0 +1,1778 @@ +/* + * LoggerWindowController.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import +#import "LoggerWindowController.h" +#import "LoggerDetailsWindowController.h" +#import "LoggerMessageCell.h" +#import "LoggerClientInfoCell.h" +#import "LoggerMarkerCell.h" +#import "LoggerMessage.h" +#import "LoggerUtils.h" +#import "LoggerAppDelegate.h" +#import "LoggerCommon.h" +#import "LoggerDocument.h" + +@interface LoggerWindowController () +@property (nonatomic, retain) NSString *info; +@property (nonatomic, retain) NSString *filterString; +@property (nonatomic, retain) NSString *filterTag; +- (void)rebuildQuickFilterPopup; +- (void)updateClientInfo; +- (void)updateFilterPredicate; +- (void)refreshAllMessages:(NSArray *)selectMessages; +- (void)filterIncomingMessages:(NSArray *)messages withFilter:(NSPredicate *)aFilter tableFrameSize:(NSSize)tableFrameSize; +- (NSPredicate *)filterPredicateFromCurrentSelection; +- (void)tileLogTable:(BOOL)forceUpdate; +- (void)rebuildMarksSubmenu; +- (void)clearMarksSubmenu; +- (void)rebuildRunsSubmenu; +- (void)clearRunsSubmenu; +@end + +static NSString * const kNSLoggerFilterPasteboardType = @"com.florentpillet.NSLoggerFilter"; + +@implementation LoggerWindowController + +@synthesize info, filterString, filterTag; +@synthesize attachedConnection; +@synthesize messagesSelected, hasQuickFilter; +@dynamic showFunctionNames; + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma Standard NSWindowController stuff +// ----------------------------------------------------------------------------- +- (id)initWithWindowNibName:(NSString *)nibName +{ + if ((self = [super initWithWindowNibName:nibName]) != nil) + { + messageFilteringQueue = dispatch_queue_create("com.florentpillet.nslogger.messageFiltering", NULL); + displayedMessages = [[NSMutableArray alloc] initWithCapacity:4096]; + tags = [[NSMutableSet alloc] init]; + [self setShouldCloseDocument:YES]; + } + return self; +} + +- (void)dealloc +{ + [detailsWindowController release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [filterSetsListController removeObserver:self forKeyPath:@"arrangedObjects"]; + [filterSetsListController removeObserver:self forKeyPath:@"selectedObjects"]; + [filterListController removeObserver:self forKeyPath:@"selectedObjects"]; + dispatch_release(messageFilteringQueue); + [attachedConnection release]; + [info release]; + [filterString release]; + [filterTag release]; + [filterPredicate release]; + [displayedMessages release]; + [tags release]; + [messageCell release]; + [clientInfoCell release]; + [markerCell release]; + if (lastTilingGroup) + dispatch_release(lastTilingGroup); + [super dealloc]; +} + +- (NSUndoManager *)undoManager +{ + return [[self document] undoManager]; +} + +- (void)windowDidLoad +{ + if ([[self window] respondsToSelector:@selector(setRestorable:)]) + [[self window] setRestorable:NO]; + + messageCell = [[LoggerMessageCell alloc] init]; + clientInfoCell = [[LoggerClientInfoCell alloc] init]; + markerCell = [[LoggerMarkerCell alloc] init]; + + [logTable setIntercellSpacing:NSMakeSize(0,0)]; + [logTable setTarget:self]; + [logTable setDoubleAction:@selector(openDetailsWindow:)]; + + [logTable registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeString]]; + [logTable setDraggingSourceOperationMask:NSDragOperationNone forLocal:YES]; + [logTable setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO]; + + [filterSetsTable registerForDraggedTypes:[NSArray arrayWithObject:kNSLoggerFilterPasteboardType]]; + [filterSetsTable setIntercellSpacing:NSMakeSize(0,0)]; + + [filterTable registerForDraggedTypes:[NSArray arrayWithObject:kNSLoggerFilterPasteboardType]]; + [filterTable setVerticalMotionCanBeginDrag:YES]; + [filterTable setTarget:self]; + [filterTable setIntercellSpacing:NSMakeSize(0,0)]; + [filterTable setDoubleAction:@selector(startEditingFilter:)]; + + [filterSetsListController addObserver:self forKeyPath:@"arrangedObjects" options:0 context:NULL]; + [filterSetsListController addObserver:self forKeyPath:@"selectedObjects" options:0 context:NULL]; + [filterListController addObserver:self forKeyPath:@"selectedObjects" options:0 context:NULL]; + + buttonBar.splitViewDelegate = self; + + [self rebuildQuickFilterPopup]; + [self updateFilterPredicate]; + [logTable sizeToFit]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applyFontChanges) + name:kMessageAttributesChangedNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(tileLogTableNotification:) + name:@"TileLogTableNotification" + object:nil]; +} + +- (NSString *)windowTitleForDocumentDisplayName:(NSString *)displayName +{ + if ([[self document] fileURL] != nil) + return displayName; + if (attachedConnection.connected) + return [attachedConnection clientAppDescription]; + return [NSString stringWithFormat:NSLocalizedString(@"%@ (disconnected)", @""), + [attachedConnection clientDescription]]; +} + +- (void)updateClientInfo +{ + // Update the source label + assert([NSThread isMainThread]); + [self synchronizeWindowTitleWithDocumentName]; +} + +- (void)updateMenuBar:(BOOL)documentIsFront +{ + if (documentIsFront) + { + [self rebuildMarksSubmenu]; + [self rebuildRunsSubmenu]; + } + else + { + [self clearRunsSubmenu]; + [self clearMarksSubmenu]; + } +} + +- (void)tileLogTableMessages:(NSArray *)messages + withSize:(NSSize)tableSize + forceUpdate:(BOOL)forceUpdate + group:(dispatch_group_t)group +{ + NSMutableArray *updatedMessages = [[NSMutableArray alloc] initWithCapacity:[messages count]]; + for (LoggerMessage *msg in messages) + { + // detect cancellation + if (group != NULL && dispatch_get_context(group) == NULL) + break; + + // compute size + NSSize cachedSize = msg.cachedCellSize; + if (forceUpdate || cachedSize.width != tableSize.width) + { + CGFloat cachedHeight = cachedSize.height; + CGFloat newHeight = cachedHeight; + if (forceUpdate) + msg.cachedCellSize = NSZeroSize; + switch (msg.type) + { + case LOGMSG_TYPE_LOG: + case LOGMSG_TYPE_BLOCKSTART: + case LOGMSG_TYPE_BLOCKEND: + newHeight = [LoggerMessageCell heightForCellWithMessage:msg maxSize:tableSize showFunctionNames:showFunctionNames]; + break; + case LOGMSG_TYPE_CLIENTINFO: + case LOGMSG_TYPE_DISCONNECT: + newHeight = [LoggerClientInfoCell heightForCellWithMessage:msg maxSize:tableSize showFunctionNames:showFunctionNames]; + break; + case LOGMSG_TYPE_MARK: + newHeight = [LoggerMarkerCell heightForCellWithMessage:msg maxSize:tableSize showFunctionNames:showFunctionNames]; + break; + } + if (newHeight != cachedHeight) + [updatedMessages addObject:msg]; + else if (forceUpdate) + msg.cachedCellSize = cachedSize; + } + } + if ([updatedMessages count]) + { + dispatch_async(dispatch_get_main_queue(), ^{ + if (group == NULL || dispatch_get_context(group) != NULL) + { + NSMutableIndexSet *set = [[NSMutableIndexSet alloc] init]; + for (LoggerMessage *msg in updatedMessages) + { + NSUInteger pos = [displayedMessages indexOfObjectIdenticalTo:msg]; + if (pos == NSNotFound || pos > lastMessageRow) + break; + [set addIndex:pos]; + } + if ([set count]) + [logTable noteHeightOfRowsWithIndexesChanged:set]; + [set release]; + } + }); + } + [updatedMessages release]; +} + +- (void)tileLogTable:(BOOL)forceUpdate +{ + // tile the visible rows (and a bit more) first, then tile all the rest + // this gives us a better perceived speed + NSSize tableSize = [logTable frame].size; + NSRect r = [[logTable superview] convertRect:[[logTable superview] bounds] toView:logTable]; + NSRange visibleRows = [logTable rowsInRect:r]; + visibleRows.location = MAX((int)0, (int)visibleRows.location - 10); + visibleRows.length = MIN(visibleRows.location + visibleRows.length + 10, [displayedMessages count] - visibleRows.location); + if (visibleRows.length) + { + [self tileLogTableMessages:[displayedMessages subarrayWithRange:visibleRows] + withSize:tableSize + forceUpdate:forceUpdate + group:NULL]; + } + + // cancel previous tiling group + if (lastTilingGroup != NULL) + { + dispatch_set_context(lastTilingGroup, NULL); + dispatch_release(lastTilingGroup); + } + + // create new group, set it a non-NULL context to indicate that it is running + lastTilingGroup = dispatch_group_create(); + dispatch_set_context(lastTilingGroup, "running"); + + // perform layout in chunks in the background + for (NSUInteger i = 0; i < [displayedMessages count]; i += 1024) + { + // tiling is executed on a parallel queue, and checks for cancellation + // by looking at its group's context object + NSRange range = NSMakeRange(i, MIN(1024, [displayedMessages count] - i)); + if (range.length > 0) + { + NSArray *subArray = [displayedMessages subarrayWithRange:range]; + dispatch_group_t group = lastTilingGroup; // careful with self dereference, could use the wrong group at run time, hence the copy here + dispatch_group_async(group, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), + ^{ + [self tileLogTableMessages:subArray + withSize:tableSize + forceUpdate:forceUpdate + group:group]; + }); + } + } +} + +- (void)tileLogTableNotification:(NSNotification *)note +{ + [self tileLogTable:NO]; +} + +- (void)applyFontChanges +{ + [self tileLogTable:YES]; + [logTable reloadData]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Support for multiple runs in same window +// ----------------------------------------------------------------------------- +- (void)rebuildRunsSubmenu +{ + LoggerDocument *doc = (LoggerDocument *)self.document; + NSMenuItem *runsSubmenu = [[[[NSApp mainMenu] itemWithTag:VIEW_MENU_ITEM_TAG] submenu] itemWithTag:VIEW_MENU_SWITCH_TO_RUN_TAG]; + NSArray *runsNames = [doc attachedLogsPopupNames]; + NSMenu *menu = [runsSubmenu submenu]; + [menu removeAllItems]; + NSInteger i = 0; + NSInteger currentRun = [[doc indexOfCurrentVisibleLog] integerValue]; + for (NSString *name in runsNames) + { + NSMenuItem *runItem = [[NSMenuItem alloc] initWithTitle:name + action:@selector(selectRun:) + keyEquivalent:@""]; + if (i == currentRun) + [runItem setState:NSOnState]; + [runItem setTag:i++]; + [runItem setTarget:self]; + [menu addItem:runItem]; + [runItem release]; + } +} + +- (void)clearRunsSubmenu +{ + NSMenuItem *runsSubmenu = [[[[NSApp mainMenu] itemWithTag:VIEW_MENU_ITEM_TAG] submenu] itemWithTag:VIEW_MENU_SWITCH_TO_RUN_TAG]; + NSMenu *menu = [runsSubmenu submenu]; + [menu removeAllItems]; + NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"No Run Log", @"") action:nil keyEquivalent:@""]; + [dummyItem setEnabled:NO]; + [menu addItem:dummyItem]; + [dummyItem release]; +} + +- (void)selectRun:(NSMenuItem *)anItem +{ + ((LoggerDocument *)self.document).indexOfCurrentVisibleLog = [NSNumber numberWithInteger:[anItem tag]]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Filter predicate assembly +// ----------------------------------------------------------------------------- +- (NSPredicate *)filterPredicateFromCurrentSelection +{ + // the current filter is the aggregate (OR clause) of all the selected filters + NSArray *predicates = [[filterListController selectedObjects] valueForKey:@"predicate"]; + if (![predicates count]) + return nil; + if ([predicates count] == 1) + return [predicates lastObject]; + + // Isolate the NOT type predicates, merge predicates this way: + // result = (AND all NOT predicates)) AND (OR all ANY/ALL predicates) + NSMutableArray *anyAllPredicates = [NSMutableArray arrayWithCapacity:[predicates count]]; + NSMutableArray *notPredicates = [NSMutableArray arrayWithCapacity:[predicates count]]; + for (NSCompoundPredicate *pred in predicates) + { + if ([pred isKindOfClass:[NSCompoundPredicate class]] && [pred compoundPredicateType] == NSNotPredicateType) + [notPredicates addObject:pred]; + else + [anyAllPredicates addObject:pred]; + } + if ([notPredicates count] && [anyAllPredicates count]) + { + return [NSCompoundPredicate andPredicateWithSubpredicates: + [NSArray arrayWithObjects: + [NSCompoundPredicate andPredicateWithSubpredicates:notPredicates], + [NSCompoundPredicate orPredicateWithSubpredicates:anyAllPredicates], + nil]]; + } + if ([notPredicates count]) + return [NSCompoundPredicate andPredicateWithSubpredicates:notPredicates]; + return [NSCompoundPredicate orPredicateWithSubpredicates:predicates]; +} + +- (NSPredicate *)alwaysVisibleEntriesPredicate +{ + NSExpression *lhs = [NSExpression expressionForKeyPath:@"type"]; + NSExpression *rhs = [NSExpression expressionForConstantValue:[NSSet setWithObjects: + [NSNumber numberWithInteger:LOGMSG_TYPE_MARK], + [NSNumber numberWithInteger:LOGMSG_TYPE_CLIENTINFO], + [NSNumber numberWithInteger:LOGMSG_TYPE_DISCONNECT], + nil]]; + return [NSComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:NSDirectPredicateModifier + type:NSInPredicateOperatorType + options:0]; +} + +- (void)updateFilterPredicate +{ + assert([NSThread isMainThread]); + NSPredicate *p = [self filterPredicateFromCurrentSelection]; + NSMutableArray *andPredicates = [[NSMutableArray alloc] initWithCapacity:3]; + if (logLevel) + { + NSExpression *lhs = [NSExpression expressionForKeyPath:@"level"]; + NSExpression *rhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInteger:logLevel]]; + [andPredicates addObject:[NSComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:NSDirectPredicateModifier + type:NSLessThanPredicateOperatorType + options:0]]; + } + if (filterTag != nil) + { + NSExpression *lhs = [NSExpression expressionForKeyPath:@"tag"]; + NSExpression *rhs = [NSExpression expressionForConstantValue:filterTag]; + [andPredicates addObject:[NSComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:NSDirectPredicateModifier + type:NSEqualToPredicateOperatorType + options:0]]; + } + if ([filterString length]) + { + // "refine filter" string looks up in both message text and function name + NSExpression *lhs = [NSExpression expressionForKeyPath:@"messageText"]; + NSExpression *rhs = [NSExpression expressionForConstantValue:filterString]; + NSPredicate *messagePredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:NSDirectPredicateModifier + type:NSContainsPredicateOperatorType + options:NSCaseInsensitivePredicateOption]; + lhs = [NSExpression expressionForKeyPath:@"functionName"]; + NSPredicate *functionPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:NSDirectPredicateModifier + type:NSContainsPredicateOperatorType + options:NSCaseInsensitivePredicateOption]; + + [andPredicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates: + [NSArray arrayWithObjects:messagePredicate, functionPredicate, nil]]]; + } + if ([andPredicates count]) + { + if (p != nil) + [andPredicates addObject:p]; + p = [NSCompoundPredicate andPredicateWithSubpredicates:andPredicates]; + } + if (p == nil) + p = [NSPredicate predicateWithValue:YES]; + else + p = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:[self alwaysVisibleEntriesPredicate], p, nil]]; + [filterPredicate autorelease]; + filterPredicate = [p retain]; + [andPredicates release]; +} + +- (void)refreshMessagesIfPredicateChanged +{ + assert([NSThread isMainThread]); + NSPredicate *currentPredicate = [[filterPredicate retain] autorelease]; + [self updateFilterPredicate]; + if (![filterPredicate isEqual:currentPredicate]) + { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshAllMessages:) object:nil]; + [self rebuildQuickFilterPopup]; + [self performSelector:@selector(refreshAllMessages:) withObject:nil afterDelay:0]; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Per-Application settings +// ----------------------------------------------------------------------------- +- (NSDictionary *)settingsForClientApplication +{ + NSString *clientAppIdentifier = [attachedConnection clientName]; + if (![clientAppIdentifier length]) + return nil; + + NSDictionary *clientSettings = [[NSUserDefaults standardUserDefaults] objectForKey:kPrefClientApplicationSettings]; + if (clientSettings == nil) + return [NSDictionary dictionary]; + + NSDictionary *appSettings = [clientSettings objectForKey:clientAppIdentifier]; + if (appSettings == nil) + return [NSDictionary dictionary]; + return appSettings; +} + +- (void)saveSettingsForClientApplication:(NSDictionary *)newSettings +{ + NSString *clientAppIdentifier = [attachedConnection clientName]; + if (![clientAppIdentifier length]) + return; + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + NSMutableDictionary *clientSettings = [[[ud objectForKey:kPrefClientApplicationSettings] mutableCopy] autorelease]; + if (clientSettings == nil) + clientSettings = [NSMutableDictionary dictionary]; + [clientSettings setObject:newSettings forKey:clientAppIdentifier]; + [ud setObject:clientSettings forKey:kPrefClientApplicationSettings]; +} + +- (void)setSettingForClientApplication:(id)aValue forKey:(NSString *)aKey +{ + NSMutableDictionary *dict = [[self settingsForClientApplication] mutableCopy]; + [dict setObject:aValue forKey:aKey]; + [self saveSettingsForClientApplication:dict]; + [dict release]; +} + +- (void)rememberFiltersSelection +{ + // remember the last filter set selected for this application identifier, + // we will use it to automatically reassociate it the next time the same + // application connects or a log file from this application is reopened + NSDictionary *filterSet = [[filterSetsListController selectedObjects] lastObject]; + if (filterSet != nil) + [self setSettingForClientApplication:[filterSet objectForKey:@"uid"] forKey:@"selectedFilterSet"]; +} + +- (void)restoreClientApplicationSettings +{ + NSDictionary *clientAppSettings = [self settingsForClientApplication]; + if (clientAppSettings == nil) + return; + + clientAppSettingsRestored = YES; + + // when an application connects, we restore some saved settings so the user + // comes back to about the same configuration she was using the last time + id showFuncs = [clientAppSettings objectForKey:@"showFunctionNames"]; + if (showFuncs != nil) + [self setShowFunctionNames:showFuncs]; + + // try to restore the last filter set that was + // selected for this application. Usually, you have a filter set per application + // (this is how it is intended to be used), so it makes sense to preselect it + // when the application connects. + NSNumber *filterSetUID = [clientAppSettings objectForKey:@"selectedFilterSet"]; + if (filterSetUID != nil) + { + // try retrieving the filter set + NSArray *matchingFilters = [[filterSetsListController arrangedObjects] filteredArrayUsingPredicate: + [NSPredicate predicateWithFormat:@"uid == %@", filterSetUID]]; + if ([matchingFilters count] == 1) + [filterSetsListController setSelectedObjects:matchingFilters]; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Splitview delegate +// ----------------------------------------------------------------------------- +- (void)splitViewDidResizeSubviews:(NSNotification *)notification +{ +// tableNeedsTiling = YES; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Window delegate +// ----------------------------------------------------------------------------- +- (void)windowDidResize:(NSNotification *)notification +{ + if (![[self window] inLiveResize]) + [self tileLogTable:NO]; +} + +- (void)windowDidEndLiveResize:(NSNotification *)notification +{ + [self tileLogTable:NO]; +} + +- (void)windowDidBecomeMain:(NSNotification *)notification +{ + [self updateMenuBar:YES]; + + NSColor *bgColor = [NSColor colorWithCalibratedRed:(218.0 / 255.0) + green:(221.0 / 255.0) + blue:(229.0 / 255.0) + alpha:1.0f]; + [filterSetsTable setBackgroundColor:bgColor]; + [filterTable setBackgroundColor:bgColor]; +} + +- (void)windowDidResignMain:(NSNotification *)notification +{ + [self updateMenuBar:NO]; + + // constants by Brandon Walkin + NSColor *bgColor = [NSColor colorWithCalibratedRed:(234.0 / 255.0) + green:(234.0 / 255.0) + blue:(234.0 / 255.0) + alpha:1.0f]; + [filterSetsTable setBackgroundColor:bgColor]; + [filterTable setBackgroundColor:bgColor]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Quick filter +// ----------------------------------------------------------------------------- +- (void)rebuildQuickFilterPopup +{ + NSMenu *menu = [quickFilter menu]; + + // remove all tags + while ([[menu itemAtIndex:[menu numberOfItems]-1] tag] != -1) + [menu removeItemAtIndex:[menu numberOfItems]-1]; + + // set selected level checkmark + NSString *levelTitle = nil; + for (NSMenuItem *menuItem in [menu itemArray]) + { + if ([menuItem isSeparatorItem]) + continue; + if ([menuItem tag] == logLevel) + { + [menuItem setState:NSOnState]; + levelTitle = [menuItem title]; + } + else + [menuItem setState:NSOffState]; + } + + NSString *tagTitle; + NSMenuItem *item = [[menu itemArray] lastObject]; + if (filterTag == nil) + { + [item setState:NSOnState]; + tagTitle = [item title]; + } + else + { + [item setState:NSOffState]; + tagTitle = [NSString stringWithFormat:NSLocalizedString(@"Tag: %@", @""), filterTag]; + } + + for (NSString *tag in [[tags allObjects] sortedArrayUsingSelector:@selector(localizedCompare:)]) + { + item = [[NSMenuItem alloc] initWithTitle:tag action:@selector(selectQuickFilterTag:) keyEquivalent:@""]; + [item setRepresentedObject:tag]; + [item setIndentationLevel:1]; + if ([filterTag isEqualToString:tag]) + [item setState:NSOnState]; + [menu addItem:item]; + [item release]; + } + + [quickFilter setTitle:[NSString stringWithFormat:@"%@ | %@", levelTitle, tagTitle]]; + + self.hasQuickFilter = (filterString != nil || filterTag != nil || logLevel != 0); +} + +- (void)addTags:(NSArray *)newTags +{ + // complete the set of "seen" tags in messages + // if changed, update the quick filter popup + NSUInteger numTags = [tags count]; + [tags addObjectsFromArray:newTags]; + if ([tags count] != numTags) + [self rebuildQuickFilterPopup]; +} + +- (IBAction)selectQuickFilterTag:(id)sender +{ + if (filterTag != [sender representedObject]) + { + self.filterTag = [sender representedObject]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMessagesIfPredicateChanged) object:nil]; + [self performSelector:@selector(refreshMessagesIfPredicateChanged) withObject:nil afterDelay:0]; + } +} + +- (IBAction)selectQuickFilterLevel:(id)sender +{ + int level = [(NSView *)sender tag]; + if (level != logLevel) + { + logLevel = level; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMessagesIfPredicateChanged) object:nil]; + [self performSelector:@selector(refreshMessagesIfPredicateChanged) withObject:nil afterDelay:0]; + } +} + +- (IBAction)resetQuickFilter:(id)sender +{ + [filterString release]; + filterString = @""; + [filterTag release]; + filterTag = nil; + logLevel = 0; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMessagesIfPredicateChanged) object:nil]; + [self performSelector:@selector(refreshMessagesIfPredicateChanged) withObject:nil afterDelay:0]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Table management +// ----------------------------------------------------------------------------- +- (void)messagesAppendedToTable +{ + assert([NSThread isMainThread]); + if (attachedConnection.connected) + { + NSRect r = [[logTable superview] convertRect:[[logTable superview] bounds] toView:logTable]; + NSRange visibleRows = [logTable rowsInRect:r]; + BOOL lastVisible = (visibleRows.location == NSNotFound || + visibleRows.length == 0 || + (visibleRows.location + visibleRows.length) >= lastMessageRow); + [logTable noteNumberOfRowsChanged]; + if (lastVisible) + [logTable scrollRowToVisible:[displayedMessages count] - 1]; + } + else + { + [logTable noteNumberOfRowsChanged]; + } + lastMessageRow = [displayedMessages count]; + self.info = [NSString stringWithFormat:NSLocalizedString(@"%u messages", @""), [displayedMessages count]]; +} + +- (void)appendMessagesToTable:(NSArray *)messages +{ + assert([NSThread isMainThread]); + [displayedMessages addObjectsFromArray:messages]; + + // schedule a table reload. Do this asynchronously (and cancellable-y) so we can limit the + // number of reload requests in case of high load + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(messagesAppendedToTable) object:nil]; + [self performSelector:@selector(messagesAppendedToTable) withObject:nil afterDelay:0]; +} + +- (IBAction)openDetailsWindow:(id)sender +{ + // open a details view window for the selected messages + if (detailsWindowController == nil) + { + detailsWindowController = [[LoggerDetailsWindowController alloc] initWithWindowNibName:@"LoggerDetailsWindow"]; + [detailsWindowController window]; // force window to load + [[self document] addWindowController:detailsWindowController]; + } + [detailsWindowController setMessages:[displayedMessages objectsAtIndexes:[logTable selectedRowIndexes]]]; + [detailsWindowController showWindow:self]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Filtering +// ----------------------------------------------------------------------------- +- (void)refreshAllMessages:(NSArray *)selectedMessages +{ + assert([NSThread isMainThread]); + @synchronized (attachedConnection.messages) + { + BOOL quickFilterWasFirstResponder = ([[self window] firstResponder] == [quickFilterTextField currentEditor]); + id messageToMakeVisible = [selectedMessages objectAtIndex:0]; + if (messageToMakeVisible == nil) + { + // Remember the currently selected messages + NSIndexSet *selectedRows = [logTable selectedRowIndexes]; + if ([selectedRows count]) + selectedMessages = [displayedMessages objectsAtIndexes:selectedRows]; + + NSRect r = [[logTable superview] convertRect:[[logTable superview] bounds] toView:logTable]; + NSRange visibleRows = [logTable rowsInRect:r]; + if (visibleRows.length != 0) + { + NSIndexSet *selectedVisible = [selectedRows indexesInRange:visibleRows options:0 passingTest:^(NSUInteger idx, BOOL *stop){return YES;}]; + if ([selectedVisible count]) + messageToMakeVisible = [displayedMessages objectAtIndex:[selectedVisible firstIndex]]; + else + messageToMakeVisible = [displayedMessages objectAtIndex:visibleRows.location]; + } + } + + LoggerConnection *theConnection = attachedConnection; + + NSSize tableFrameSize = [logTable frame].size; + NSUInteger numMessages = [attachedConnection.messages count]; + for (int i = 0; i < numMessages;) + { + if (i == 0) + { + dispatch_async(messageFilteringQueue, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + lastMessageRow = 0; + [displayedMessages removeAllObjects]; + [logTable reloadData]; + self.info = NSLocalizedString(@"No message", @""); + }); + }); + } + NSUInteger length = MIN(4096, numMessages - i); + if (length) + { + NSPredicate *aFilter = filterPredicate; + NSArray *subArray = [attachedConnection.messages subarrayWithRange:NSMakeRange(i, length)]; + dispatch_async(messageFilteringQueue, ^{ + // Check that the connection didn't change + if (attachedConnection == theConnection) + [self filterIncomingMessages:subArray withFilter:aFilter tableFrameSize:tableFrameSize]; + }); + } + i += length; + } + + // Stuff we want to do only when filtering is complete. To do this, we enqueue + // one more operation to the message filtering queue, with the only goal of + // being executed only at the end of the filtering process + dispatch_async(messageFilteringQueue, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + // if the connection changed since the last refreshAll call, stop now + if (attachedConnection == theConnection) // note that block retains self, not self.attachedConnection. + { + if (lastMessageRow < [displayedMessages count]) + { + // perform table updates now, so we can properly reselect afterwards + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(messagesAppendedToTable) + object:nil]; + [self messagesAppendedToTable]; + } + + if ([selectedMessages count]) + { + // If there were selected rows, try to reselect them + NSMutableIndexSet *newSelectionIndexes = [[NSMutableIndexSet alloc] init]; + for (id msg in selectedMessages) + { + NSInteger msgIndex = [displayedMessages indexOfObjectIdenticalTo:msg]; + if (msgIndex != NSNotFound) + [newSelectionIndexes addIndex:(NSUInteger)msgIndex]; + } + if ([newSelectionIndexes count]) + { + [logTable selectRowIndexes:newSelectionIndexes byExtendingSelection:NO]; + if (!quickFilterWasFirstResponder) + [[self window] makeFirstResponder:logTable]; + } + [newSelectionIndexes release]; + } + + if (messageToMakeVisible != nil) + { + // Restore the logical location in the message flow, to keep the user + // in-context + NSUInteger msgIndex; + id msg = messageToMakeVisible; + @synchronized(attachedConnection.messages) + { + while ((msgIndex = [displayedMessages indexOfObjectIdenticalTo:msg]) == NSNotFound) + { + NSUInteger where = [attachedConnection.messages indexOfObjectIdenticalTo:msg]; + if (where == NSNotFound) + break; + if (where == 0) + { + msgIndex = 0; + break; + } + else + msg = [attachedConnection.messages objectAtIndex:where-1]; + } + if (msgIndex != NSNotFound) + [logTable scrollRowToVisible:msgIndex]; + } + } + + [self rebuildMarksSubmenu]; + } + initialRefreshDone = YES; + }); + }); + } +} + +- (void)filterIncomingMessages:(NSArray *)messages +{ + assert([NSThread isMainThread]); + NSPredicate *aFilter = filterPredicate; // catch value now rather than dereference it from self later + NSSize tableFrameSize = [logTable frame].size; + dispatch_async(messageFilteringQueue, ^{ + [self filterIncomingMessages:(NSArray *)messages withFilter:aFilter tableFrameSize:tableFrameSize]; + }); +} + +- (void)filterIncomingMessages:(NSArray *)messages + withFilter:(NSPredicate *)aFilter + tableFrameSize:(NSSize)tableFrameSize +{ + // collect all tags + NSArray *msgTags = [messages valueForKeyPath:@"@distinctUnionOfObjects.tag"]; + + // find out which messages we want to keep. Executed on the message filtering queue + NSArray *filteredMessages = [messages filteredArrayUsingPredicate:aFilter]; + if ([filteredMessages count]) + { + [self tileLogTableMessages:filteredMessages withSize:tableFrameSize forceUpdate:NO group:NULL]; + LoggerConnection *theConnection = attachedConnection; + dispatch_async(dispatch_get_main_queue(), ^{ + if (attachedConnection == theConnection) + { + [self appendMessagesToTable:filteredMessages]; + [self addTags:msgTags]; + } + }); + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Properties and bindings +// ----------------------------------------------------------------------------- +- (void)setAttachedConnection:(LoggerConnection *)aConnection +{ + assert([NSThread isMainThread]); + + if (attachedConnection != nil) + { + // Completely clear log table + [logTable deselectAll:self]; + lastMessageRow = 0; + [displayedMessages removeAllObjects]; + self.info = NSLocalizedString(@"No message", @""); + [logTable reloadData]; + [self rebuildMarksSubmenu]; + + // Close filter editor sheet (with cancel) if open + if ([filterEditorWindow isVisible]) + [NSApp endSheet:filterEditorWindow returnCode:0]; + + // Cancel pending tasks + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshAllMessages:) object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMessagesIfPredicateChanged) object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(messagesAppendedToTable) object:nil]; + if (lastTilingGroup != NULL) + { + dispatch_set_context(lastTilingGroup, NULL); + dispatch_release(lastTilingGroup); + lastTilingGroup = NULL; + } + + // Detach previous connection + attachedConnection.attachedToWindow = NO; + [attachedConnection release]; + attachedConnection = nil; + } + if (aConnection != nil) + { + attachedConnection = [aConnection retain]; + attachedConnection.attachedToWindow = YES; + //dispatch_async(dispatch_get_main_queue(), ^{ + initialRefreshDone = NO; + [self updateClientInfo]; + if (!clientAppSettingsRestored) + [self restoreClientApplicationSettings]; + [self rebuildRunsSubmenu]; + [self refreshAllMessages:nil]; + //}); + } +} + +- (NSNumber *)shouldEnableRunsPopup +{ + NSUInteger numRuns = [((LoggerDocument *)[self document]).attachedLogs count]; + if (![[NSUserDefaults standardUserDefaults] boolForKey:kPrefKeepMultipleRuns] && numRuns <= 1) + return (id)kCFBooleanFalse; + return (id)kCFBooleanTrue; +} + +- (void)setFilterString:(NSString *)newString +{ + if (newString == nil) + newString = @""; + + if (newString != filterString && ![filterString isEqualToString:newString]) + { + [filterString autorelease]; + filterString = [newString copy]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMessagesIfPredicateChanged) object:nil]; + [self performSelector:@selector(refreshMessagesIfPredicateChanged) withObject:nil afterDelay:0]; + self.hasQuickFilter = (filterString != nil || filterTag != nil || logLevel != 0); + } +} + +- (void)setShowFunctionNames:(NSNumber *)value +{ + BOOL b = [value boolValue]; + if (b != showFunctionNames) + { + [self willChangeValueForKey:@"showFunctionNames"]; + showFunctionNames = b; + [self tileLogTable:YES]; + dispatch_async(dispatch_get_main_queue(), ^{ + [logTable reloadData]; + }); + [self didChangeValueForKey:@"showFunctionNames"]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [self setSettingForClientApplication:value forKey:@"showFunctionNames"]; + }); + } +} + +- (NSNumber *)showFunctionNames +{ + return [NSNumber numberWithBool:showFunctionNames]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark LoggerConnectionDelegate +// ----------------------------------------------------------------------------- +- (void)connection:(LoggerConnection *)theConnection +didReceiveMessages:(NSArray *)theMessages + range:(NSRange)rangeInMessagesList +{ + // We need to hop thru the main thread to have a recent and stable copy of the filter string and current filter + dispatch_async(dispatch_get_main_queue(), ^{ + if (initialRefreshDone) + [self filterIncomingMessages:theMessages]; + }); +} + +- (void)remoteDisconnected:(LoggerConnection *)theConnection +{ + // we always get called on the main thread + [self updateClientInfo]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark KVO / Bindings +// ----------------------------------------------------------------------------- +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (object == attachedConnection) + { + if ([keyPath isEqualToString:@"clientIDReceived"]) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateClientInfo]; + if (!clientAppSettingsRestored) + [self restoreClientApplicationSettings]; + }); + } + } + else if (object == filterListController) + { + if ([keyPath isEqualToString:@"selectedObjects"]) + { + if ([filterListController selectionIndex] != NSNotFound) + { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMessagesIfPredicateChanged) object:nil]; + [self performSelector:@selector(refreshMessagesIfPredicateChanged) withObject:nil afterDelay:0]; + } + } + } + else if (object == filterSetsListController) + { + if ([keyPath isEqualToString:@"arrangedObjects"]) + { + // we'll be called when arrangedObjects change, that is when a filter set is added, + // removed or renamed. Use this occasion to save the filters definition. + [(LoggerAppDelegate *)[NSApp delegate] saveFiltersDefinition]; + } + else if ([keyPath isEqualToString:@"selectedObjects"]) + { + [self rememberFiltersSelection]; + } + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSTableDelegate +// ----------------------------------------------------------------------------- +- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + if (tableView == logTable && row >= 0 && row < [displayedMessages count]) + { + LoggerMessage *msg = [displayedMessages objectAtIndex:row]; + switch (msg.type) + { + case LOGMSG_TYPE_LOG: + case LOGMSG_TYPE_BLOCKSTART: + case LOGMSG_TYPE_BLOCKEND: + return messageCell; + case LOGMSG_TYPE_CLIENTINFO: + case LOGMSG_TYPE_DISCONNECT: + return clientInfoCell; + case LOGMSG_TYPE_MARK: + return markerCell; + default: + assert(false); + break; + } + } + return nil; +} + +- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex +{ + if (aTableView == logTable && rowIndex >= 0 && rowIndex < [displayedMessages count]) + { + // setup the message to be displayed + LoggerMessageCell *cell = (LoggerMessageCell *)aCell; + cell.message = [displayedMessages objectAtIndex:rowIndex]; + cell.shouldShowFunctionNames = showFunctionNames; + + // if previous message is a Mark, go back a bit more to get the real previous message + // if previous message is ClientInfo, don't use it. + NSInteger idx = rowIndex - 1; + LoggerMessage *prev = nil; + while (prev == nil && idx >= 0) + { + prev = [displayedMessages objectAtIndex:idx--]; + if (prev.type == LOGMSG_TYPE_CLIENTINFO || prev.type == LOGMSG_TYPE_MARK) + prev = nil; + } + + cell.previousMessage = prev; + } + else if (aTableView == filterSetsTable) + { + NSArray *filterSetsList = [filterSetsListController arrangedObjects]; + if (rowIndex >= 0 && rowIndex < [filterSetsList count]) + { + NSTextFieldCell *tc = (NSTextFieldCell *)aCell; + NSDictionary *filterSet = [filterSetsList objectAtIndex:rowIndex]; + if ([[filterSet objectForKey:@"uid"] integerValue] == 1) + [tc setFont:[NSFont boldSystemFontOfSize:[NSFont systemFontSize]]]; + else + [tc setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; + } + } + else if (aTableView == filterTable) + { + // want the "All Logs" entry (immutable) in Bold + NSArray *filterList = [filterListController arrangedObjects]; + if (rowIndex >= 0 && rowIndex < [filterList count]) + { + NSTextFieldCell *tc = (NSTextFieldCell *)aCell; + NSDictionary *filter = [filterList objectAtIndex:rowIndex]; + if ([[filter objectForKey:@"uid"] integerValue] == 1) + [tc setFont:[NSFont boldSystemFontOfSize:[NSFont systemFontSize]]]; + else + [tc setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; + } + } +} + +- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row +{ + assert([NSThread isMainThread]); + if (tableView == logTable && row >= 0 && row < [displayedMessages count]) + { + // use only cached sizes + LoggerMessage *message = [displayedMessages objectAtIndex:row]; + NSSize cachedSize = message.cachedCellSize; + if (cachedSize.height) + return cachedSize.height; + } + return [tableView rowHeight]; +} + +- (void)tableViewSelectionDidChange:(NSNotification *)aNotification +{ + if ([aNotification object] == logTable) + { + self.messagesSelected = ([logTable selectedRow] >= 0); + if (messagesSelected && detailsWindowController != nil && [[detailsWindowController window] isVisible]) + [detailsWindowController setMessages:[displayedMessages objectsAtIndexes:[logTable selectedRowIndexes]]]; + } +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark NSTableDataSource +// ----------------------------------------------------------------------------- +- (int)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [displayedMessages count]; +} + +- (id)tableView:(NSTableView *)tableView + objectValueForTableColumn:(NSTableColumn *)tableColumn + row:(int)rowIndex +{ + if (rowIndex >= 0 && rowIndex < [displayedMessages count]) + return [displayedMessages objectAtIndex:rowIndex]; + return nil; +} + +- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard +{ + if (tv == logTable) + { + NSArray *draggedMessages = [displayedMessages objectsAtIndexes:rowIndexes]; + NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[draggedMessages count] * 128]; + for (LoggerMessage *msg in draggedMessages) + [string appendString:[msg textRepresentation]]; + [pboard writeObjects:[NSArray arrayWithObject:string]]; + [string release]; + return YES; + } + if (tv == filterTable) + { + NSPasteboardItem *item = [[NSPasteboardItem alloc] init]; + NSArray *filters = [[filterListController arrangedObjects] objectsAtIndexes:rowIndexes]; + [item setData:[NSKeyedArchiver archivedDataWithRootObject:filters] forType:kNSLoggerFilterPasteboardType]; + [pboard writeObjects:[NSArray arrayWithObject:item]]; + [item release]; + return YES; + } + return NO; +} + +- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id )dragInfo proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)op +{ + if (tv == filterSetsTable) + { + NSArray *filterSets = [filterSetsListController arrangedObjects]; + if (row >= 0 && row < [filterSets count] && row != [filterSetsListController selectionIndex]) + { + if (op != NSTableViewDropOn) + [filterSetsTable setDropRow:row dropOperation:NSTableViewDropOn]; + return NSDragOperationCopy; + } + } + else if (tv == filterTable && [dragInfo draggingSource] != filterTable) + { + NSArray *filters = [filterListController arrangedObjects]; + if (row >= 0 && row < [filters count]) + { + // highlight entire table + [filterTable setDropRow:-1 dropOperation:NSTableViewDropOn]; + return NSDragOperationCopy; + } + } + return NSDragOperationNone; +} + +- (BOOL)tableView:(NSTableView *)tv + acceptDrop:(id )dragInfo + row:(NSInteger)row + dropOperation:(NSTableViewDropOperation)operation +{ + BOOL added = NO; + NSPasteboard* pboard = [dragInfo draggingPasteboard]; + NSArray *newFilters = [NSKeyedUnarchiver unarchiveObjectWithData:[pboard dataForType:kNSLoggerFilterPasteboardType]]; + if (tv == filterSetsTable) + { + // Only add those filters which don't exist yet + NSArray *filterSets = [filterSetsListController arrangedObjects]; + NSMutableDictionary *filterSet = [filterSets objectAtIndex:row]; + NSMutableArray *existingFilters = [filterSet mutableArrayValueForKey:@"filters"]; + for (NSMutableDictionary *filter in newFilters) + { + if ([existingFilters indexOfObject:filter] == NSNotFound) + { + [existingFilters addObject:filter]; + added = YES; + } + } + [filterSetsListController setSelectedObjects:[NSArray arrayWithObject:filterSet]]; + } + else if (tv == filterTable) + { + NSMutableArray *addedFilters = [[NSMutableArray alloc] init]; + for (NSMutableDictionary *filter in newFilters) + { + if ([[filterListController arrangedObjects] indexOfObject:filter] == NSNotFound) + { + [filterListController addObject:filter]; + [addedFilters addObject:filter]; + added = YES; + } + } + if (added) + [filterListController setSelectedObjects:addedFilters]; + [addedFilters release]; + } + if (added) + [(LoggerAppDelegate *)[NSApp delegate] saveFiltersDefinition]; + return added; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Filter sets management +// ----------------------------------------------------------------------------- +- (void)undoableAddFilterSet:(id)set +{ + NSUndoManager *um = [self undoManager]; + [um registerUndoWithTarget:self selector:_cmd object:set]; + [um setActionName:NSLocalizedString(@"Add Application Set", @"")]; + if ([um isUndoing]) + [filterSetsListController removeObject:set]; + else + { + [filterSetsListController addObject:set]; + if (![um isRedoing]) + { + NSUInteger index = [[filterSetsListController arrangedObjects] indexOfObject:set]; + [filterSetsTable editColumn:0 row:index withEvent:nil select:YES]; + } + } +} + +- (void)undoableDeleteFilterSet:(id)set +{ + NSUndoManager *um = [self undoManager]; + [um registerUndoWithTarget:self selector:_cmd object:set]; + [um setActionName:NSLocalizedString(@"Delete Application Set", @"")]; + if ([um isUndoing]) + [filterSetsListController addObjects:set]; + else + [filterSetsListController removeObjects:set]; +} + +- (IBAction)addFilterSet:(id)sender +{ + id dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [(LoggerAppDelegate *)[NSApp delegate] nextUniqueFilterIdentifier:[filterSetsListController arrangedObjects]], @"uid", + NSLocalizedString(@"New App. Set", @""), @"title", + [(LoggerAppDelegate *)[NSApp delegate] defaultFilters], @"filters", + nil]; + [self undoableAddFilterSet:dict]; +} + +- (IBAction)deleteSelectedFilterSet:(id)sender +{ + [self undoableDeleteFilterSet:[filterSetsListController selectedObjects]]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Filter editor +// ----------------------------------------------------------------------------- +- (void)undoableModifyFilter:(NSDictionary *)filter +{ + NSMutableDictionary *previousFilter = nil; + for (NSMutableDictionary *dict in [filterListController content]) + { + if ([[dict objectForKey:@"uid"] isEqual:[filter objectForKey:@"uid"]]) + { + previousFilter = dict; + break; + } + } + assert(previousFilter != nil); + [[self undoManager] registerUndoWithTarget:self selector:_cmd object:[[previousFilter mutableCopy] autorelease]]; + [[self undoManager] setActionName:NSLocalizedString(@"Modify Filter", @"")]; + [previousFilter addEntriesFromDictionary:filter]; + [filterListController setSelectedObjects:[NSArray arrayWithObject:previousFilter]]; +} + +- (void)undoableCreateFilter:(NSDictionary *)filter +{ + NSUndoManager *um = [self undoManager]; + [um registerUndoWithTarget:self selector:_cmd object:filter]; + [um setActionName:NSLocalizedString(@"Create Filter", @"")]; + if ([um isUndoing]) + [filterListController removeObject:filter]; + else + { + [filterListController addObject:filter]; + [filterListController setSelectedObjects:[NSArray arrayWithObject:filter]]; + } +} + +- (void)undoableDeleteFilters:(NSArray *)filters +{ + NSUndoManager *um = [self undoManager]; + [um registerUndoWithTarget:self selector:_cmd object:filters]; + [um setActionName:NSLocalizedString(@"Delete Filters", @"")]; + if ([um isUndoing]) + { + [filterListController addObjects:filters]; + [filterListController setSelectedObjects:filters]; + } + else + [filterListController removeObjects:filters]; +} + +- (void)openFilterEditSheet:(NSDictionary *)dict +{ + [filterName setStringValue:[dict objectForKey:@"title"]]; + NSPredicate *predicate = [dict objectForKey:@"predicate"]; + [filterEditor setObjectValue:[[predicate copy] autorelease]]; + + [NSApp beginSheet:filterEditorWindow + modalForWindow:[self window] + modalDelegate:self + didEndSelector:@selector(filterEditSheetDidEnd:returnCode:contextInfo:) + contextInfo:[dict retain]]; +} + +- (void)filterEditSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + if (returnCode) + { + NSMutableDictionary *dict = [[(NSDictionary *)contextInfo mutableCopy] autorelease]; + BOOL exists = [[filterListController content] containsObject:(id)contextInfo]; + + NSPredicate *predicate = [filterEditor predicate]; + if (predicate == nil) + predicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray array]]; + [dict setObject:predicate forKey:@"predicate"]; + + NSString *title = [[filterName stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + if ([title length]) + [dict setObject:title forKey:@"title"]; + + if (exists) + [self undoableModifyFilter:dict]; + else + [self undoableCreateFilter:dict]; + + [filterListController setSelectedObjects:[NSArray arrayWithObject:dict]]; + + [(LoggerAppDelegate *)[NSApp delegate] saveFiltersDefinition]; + } + [(id)contextInfo release]; + [filterEditorWindow orderOut:self]; +} + +- (IBAction)deleteSelectedFilters:(id)sender +{ + [self undoableDeleteFilters:[filterListController selectedObjects]]; +} + +- (IBAction)addFilter:(id)sender +{ + NSDictionary *filterSet = [[filterSetsListController selectedObjects] lastObject]; + assert(filterSet != nil); + NSDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [(LoggerAppDelegate *)[NSApp delegate] nextUniqueFilterIdentifier:[filterSet objectForKey:@"filters"]], @"uid", + NSLocalizedString(@"New filter", @""), @"title", + [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray array]], @"predicate", + nil]; + [self openFilterEditSheet:dict]; + [filterEditor addRow:self]; +} + +- (IBAction)startEditingFilter:(id)sender +{ + // start editing filter, unless no selection (happens when double-clicking the header) + // or when trying to edit the "All Logs" entry which is immutable + NSDictionary *dict = [[filterListController selectedObjects] lastObject]; + if (dict == nil || [[dict objectForKey:@"uid"] integerValue] == 1) + return; + [self openFilterEditSheet:dict]; + +} + +- (IBAction)cancelFilterEdition:(id)sender +{ + [NSApp endSheet:filterEditorWindow returnCode:0]; +} + +- (IBAction)validateFilterEdition:(id)sender +{ + [NSApp endSheet:filterEditorWindow returnCode:1]; +} + + +- (IBAction)createNewFilterFromQuickFilter:(id) sender +{ + NSDictionary *filterSet = [[filterSetsListController selectedObjects] lastObject]; + assert(filterSet != nil); + + NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:3]; + NSString *newFilterTitle; + + if ([filterString length]) + { + [predicates addObject:[NSPredicate predicateWithFormat:@"messageText contains %@", filterString]]; + newFilterTitle = [NSString stringWithFormat:NSLocalizedString(@"Quick Filter: %@", @""), filterString]; + } + else + newFilterTitle = NSLocalizedString(@"Quick Filter", @""); + + if (logLevel) + [predicates addObject:[NSPredicate predicateWithFormat:@"level <= %d", logLevel - 1]]; + + if (self.filterTag) + [predicates addObject:[NSPredicate predicateWithFormat:@"tag = %@", self.filterTag]]; + + NSDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [(LoggerAppDelegate *)[NSApp delegate] nextUniqueFilterIdentifier:[filterSet objectForKey:@"filters"]], @"uid", + newFilterTitle, @"title", + [NSCompoundPredicate andPredicateWithSubpredicates:predicates], @"predicate", + nil]; + [self openFilterEditSheet:dict]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Markers +// ----------------------------------------------------------------------------- +- (void)rebuildMarksSubmenu +{ + NSMenuItem *marksSubmenu = [[[[NSApp mainMenu] itemWithTag:TOOLS_MENU_ITEM_TAG] submenu] itemWithTag:TOOLS_MENU_JUMP_TO_MARK_TAG]; + NSExpression *lhs = [NSExpression expressionForKeyPath:@"type"]; + NSExpression *rhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInteger:LOGMSG_TYPE_MARK]]; + NSPredicate *predicate = [NSComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:NSDirectPredicateModifier + type:NSEqualToPredicateOperatorType + options:0]; + NSArray *marks = [displayedMessages filteredArrayUsingPredicate:predicate]; + NSMenu *menu = [marksSubmenu submenu]; + [menu removeAllItems]; + if (![marks count]) + { + NSMenuItem *noMarkItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"No Mark", @"") + action:nil + keyEquivalent:@""]; + [noMarkItem setEnabled:NO]; + [menu addItem:noMarkItem]; + [noMarkItem release]; + } + else for (LoggerMessage *mark in marks) + { + NSMenuItem *markItem = [[NSMenuItem alloc] initWithTitle:mark.message + action:@selector(jumpToMark:) + keyEquivalent:@""]; + [markItem setRepresentedObject:mark]; + [markItem setTarget:self]; + [menu addItem:markItem]; + [markItem release]; + } +} + +- (void)clearMarksSubmenu +{ + NSMenuItem *marksSubmenu = [[[[NSApp mainMenu] itemWithTag:TOOLS_MENU_ITEM_TAG] submenu] itemWithTag:TOOLS_MENU_JUMP_TO_MARK_TAG]; + NSMenu *menu = [marksSubmenu submenu]; + [menu removeAllItems]; + NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"No Mark", @"") action:nil keyEquivalent:@""]; + [dummyItem setEnabled:NO]; + [menu addItem:dummyItem]; + [dummyItem release]; +} + +- (void)jumpToMark:(NSMenuItem *)markMenuItem +{ + LoggerMessage *mark = [markMenuItem representedObject]; + NSUInteger idx = [displayedMessages indexOfObjectIdenticalTo:mark]; + if (idx == NSNotFound) + { + // actually, shouldn't happen + NSBeep(); + } + else + { + [logTable scrollRowToVisible:idx]; + [logTable selectRowIndexes:[NSIndexSet indexSetWithIndex:idx] byExtendingSelection:NO]; + [self.window makeMainWindow]; + } +} + +- (void)addMarkWithTitleString:(NSString *)title beforeMessage:(LoggerMessage *)beforeMessage +{ + if (![title length]) + { + title = [NSString stringWithFormat:NSLocalizedString(@"Mark - %@", @""), + [NSDateFormatter localizedStringFromDate:[NSDate date] + dateStyle:NSDateFormatterShortStyle + timeStyle:NSDateFormatterMediumStyle]]; + } + + LoggerMessage *mark = [[LoggerMessage alloc] init]; + struct timeval tv; + gettimeofday(&tv, NULL); + mark.type = LOGMSG_TYPE_MARK; + mark.timestamp = tv; + mark.message = title; + mark.threadID = @""; + mark.contentsType = kMessageString; + + // we want to process the mark after all current scheduled filtering operations + // (including refresh All) are done + dispatch_async(messageFilteringQueue, ^{ + // then we serialize all operations modifying the messages list in the connection's + // message processing queue + dispatch_async(attachedConnection.messageProcessingQueue, ^{ + NSRange range; + @synchronized(attachedConnection.messages) + { + range.location = [attachedConnection.messages count]; + range.length = 1; + if (beforeMessage != nil) + { + NSUInteger pos = [attachedConnection.messages indexOfObjectIdenticalTo:beforeMessage]; + if (pos != NSNotFound) + range.location = pos; + } + [attachedConnection.messages insertObject:mark atIndex:range.location]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + [[self document] updateChangeCount:NSChangeDone]; + [self refreshAllMessages:[NSArray arrayWithObjects:mark, beforeMessage, nil]]; + }); + }); + }); + + [mark release]; +} + +- (void)addMarkWithTitleBeforeMessage:(LoggerMessage *)aMessage +{ + NSString *s = [NSString stringWithFormat:NSLocalizedString(@"Mark - %@", @""), + [NSDateFormatter localizedStringFromDate:[NSDate date] + dateStyle:NSDateFormatterShortStyle + timeStyle:NSDateFormatterMediumStyle]]; + [markTitleField setStringValue:s]; + + [NSApp beginSheet:markTitleWindow + modalForWindow:[self window] + modalDelegate:self + didEndSelector:@selector(addMarkSheetDidEnd:returnCode:contextInfo:) + contextInfo:[aMessage retain]]; +} + +- (IBAction)addMark:(id)sender +{ + [self addMarkWithTitleString:nil beforeMessage:nil]; +} + +- (IBAction)addMarkWithTitle:(id)sender +{ + [self addMarkWithTitleBeforeMessage:nil]; +} + +- (IBAction)insertMarkWithTitle:(id)sender +{ + NSInteger rowIndex = [logTable selectedRow]; + if (rowIndex >= 0 && rowIndex < (NSInteger)[displayedMessages count]) + [self addMarkWithTitleBeforeMessage:[displayedMessages objectAtIndex:(NSUInteger)rowIndex]]; +} + +- (IBAction)deleteMark:(id)sender +{ + NSInteger rowIndex = [logTable selectedRow]; + if (rowIndex >= 0 && rowIndex < (NSInteger)[displayedMessages count]) + { + LoggerMessage *markMessage = [displayedMessages objectAtIndex:(NSUInteger)rowIndex]; + assert(markMessage.type == LOGMSG_TYPE_MARK); + [displayedMessages removeObjectAtIndex:(NSUInteger)rowIndex]; + [logTable reloadData]; + [self rebuildMarksSubmenu]; + dispatch_async(messageFilteringQueue, ^{ + // then we serialize all operations modifying the messages list in the connection's + // message processing queue + dispatch_async(attachedConnection.messageProcessingQueue, ^{ + @synchronized(attachedConnection.messages) { + [attachedConnection.messages removeObjectIdenticalTo:markMessage]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + [[self document] updateChangeCount:NSChangeDone]; + }); + }); + }); + } +} + +- (IBAction)cancelAddMark:(id)sender +{ + [NSApp endSheet:markTitleWindow returnCode:0]; +} + +- (IBAction)validateAddMark:(id)sender +{ + [NSApp endSheet:markTitleWindow returnCode:1]; +} + +- (void)addMarkSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + if (returnCode) + [self addMarkWithTitleString:[markTitleField stringValue] beforeMessage:(LoggerMessage *)contextInfo]; + if (contextInfo != NULL) + [(id)contextInfo release]; + [markTitleWindow orderOut:self]; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark User Interface Items Validation +// ----------------------------------------------------------------------------- +- (BOOL)validateUserInterfaceItem:(id)anItem +{ + SEL action = [anItem action]; + if (action == @selector(deleteMark:)) + { + NSInteger rowIndex = [logTable selectedRow]; + if (rowIndex >= 0 && rowIndex < (NSInteger)[displayedMessages count]) + { + LoggerMessage *markMessage = [displayedMessages objectAtIndex:(NSUInteger)rowIndex]; + return (markMessage.type == LOGMSG_TYPE_MARK); + } + return NO; + } + else if (action == @selector(clearCurrentLog:)) + { + // Allow "Clear Log" only if the log was not restored from save + if (attachedConnection == nil || attachedConnection.restoredFromSave) + return NO; + } + else if (action == @selector(clearAllLogs:)) + { + // Allow "Clear All Run Logs" only if the log was not restored from save + // and there are multiple run logs + if (attachedConnection == nil || attachedConnection.restoredFromSave || [((LoggerDocument *)[self document]).attachedLogs count] <= 1) + return NO; + } + return YES; +} + +// ----------------------------------------------------------------------------- +#pragma mark - +#pragma mark Support for clear current // all logs +// ----------------------------------------------------------------------------- +- (BOOL)canClearCurrentLog +{ + return (attachedConnection != nil && !attachedConnection.restoredFromSave); +} + +- (IBAction)clearCurrentLog:(id)sender +{ + [(LoggerDocument *)[self document] clearLogs:NO]; +} + +- (BOOL)canClearAllLogs +{ + return (attachedConnection != nil && !attachedConnection.restoredFromSave && [((LoggerDocument *)[self document]).attachedLogs count] > 1); +} + +- (IBAction)clearAllLogs:(id)sender +{ + [(LoggerDocument *)[self document] clearLogs:YES]; +} + +#pragma mark - +#pragma mark - Collapsing Taskbar + +- (IBAction)collapseTaskbar:(id)sender{ + + NSMenuItem *hideShowButton = [[[[NSApp mainMenu] itemWithTag:VIEW_MENU_ITEM_TAG] submenu] itemWithTag:TOOLS_MENU_HIDE_SHOW_TOOLBAR]; + + if (![splitView collapsibleSubviewCollapsed]) { + [hideShowButton setTitle:NSLocalizedString(@"Show Taskbar", @"Show Taskbar")]; + } + else{ + [hideShowButton setTitle:NSLocalizedString(@"Hide Taskbar", @"Hide Taskbar")]; + } + + [splitView toggleCollapse:nil]; + +} + +@end + diff --git a/External Source/NSLogger/Desktop Viewer/Classes/ValueTransformers.h b/External Source/NSLogger/Desktop Viewer/Classes/ValueTransformers.h new file mode 100644 index 000000000..bd243441b --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/ValueTransformers.h @@ -0,0 +1,41 @@ +/* + * ValueTransformers.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Value transformer for bindings that returns YES when the filter selection can be deleted +// (to enable the Delete button in the filters list) +@interface CanFilterSelectionBeDeletedValueTransformer : NSValueTransformer +@end + +@interface FilterColumnHeaderValueTransformer : NSValueTransformer +@end + +@interface BonjourServiceNameValueTransformer : NSValueTransformer +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/ValueTransformers.m b/External Source/NSLogger/Desktop Viewer/Classes/ValueTransformers.m new file mode 100644 index 000000000..ce8f6ddde --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/ValueTransformers.m @@ -0,0 +1,107 @@ +/* + * ValueTransformers.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import "ValueTransformers.h" + +@implementation CanFilterSelectionBeDeletedValueTransformer + ++ (void)load +{ + CanFilterSelectionBeDeletedValueTransformer *t = [[self alloc] init]; + [NSValueTransformer setValueTransformer:t forName:@"CanDeleteFilterSelection"]; + [t release]; +} + ++ (Class)transformedValueClass +{ + return [NSNumber class]; +} + +- (id)transformedValue:(id)value +{ + // check if the All Logs entry (the only one with UID 1) is in selection + BOOL result = NO; + NSArray *selection = (NSArray *)value; + if ([selection count]) + { + // the All Logs entry always has UID 1 + result = (([selection count] > 1) || + ([[[selection lastObject] objectForKey:@"uid"] integerValue] != 1)); + } + return [NSNumber numberWithBool:result]; +} + +@end + +@implementation FilterColumnHeaderValueTransformer + ++ (void)load +{ + FilterColumnHeaderValueTransformer *t = [[self alloc] init]; + [NSValueTransformer setValueTransformer:t forName:@"FilterColumnHeader"]; + [t release]; +} + ++ (Class)transformedValueClass +{ + return [NSString class]; +} + +- (id)transformedValue:(id)value +{ + return [NSString stringWithFormat:NSLocalizedString(@"Filters for “%@â€", @""), value]; +} +@end + +@implementation BonjourServiceNameValueTransformer + ++ (void)load +{ + BonjourServiceNameValueTransformer *t = [[self alloc] init]; + [NSValueTransformer setValueTransformer:t forName:@"TrimmedBonjourServiceName"]; + [t release]; +} + ++ (Class)transformedValueClass +{ + return [NSString class]; +} + ++ (BOOL)allowsReverseTransformation +{ + return YES; +} + +- (id)transformedValue:(id)value +{ + return [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Classes/relaunch.m b/External Source/NSLogger/Desktop Viewer/Classes/relaunch.m new file mode 100644 index 000000000..05b78fddc --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Classes/relaunch.m @@ -0,0 +1,62 @@ +// Relaunch tool, extracted from Sparkle.framework + +#import +#import + +@interface TerminationListener : NSObject +{ +@private + const char *executablePath; + pid_t parentProcessId; +} + +- (void)relaunch __dead2; + +@end + +@implementation TerminationListener + +- (void)watchdog:(NSTimer *)timer +{ + ProcessSerialNumber psn; + if (GetProcessForPID(parentProcessId, &psn) == procNotFound) + { + [self relaunch]; + [timer invalidate]; + } +} + +- (id) initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid +{ + self = [super init]; + if (self != nil) + { + executablePath = execPath; + parentProcessId = ppid; + [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(watchdog:) userInfo:nil repeats:YES]; + } + return self; +} + +- (void)relaunch +{ + NSString *path = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:executablePath length:strlen(executablePath)]; + [[NSWorkspace sharedWorkspace] launchApplication:path]; + exit(0); +} + +@end + +int main (int argc, const char * argv[]) +{ + if (argc != 3) + return EXIT_FAILURE; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [[[TerminationListener alloc] initWithExecutablePath:argv[1] parentProcessId:atoi(argv[2])] autorelease]; + [[NSApplication sharedApplication] run]; + + [pool drain]; + + return EXIT_SUCCESS; +} diff --git a/External Source/NSLogger/Desktop Viewer/Info.plist b/External Source/NSLogger/Desktop Viewer/Info.plist new file mode 100644 index 000000000..408197dca --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Info.plist @@ -0,0 +1,101 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + nsloggerdata + + CFBundleTypeIconFile + logfile.icns + CFBundleTypeName + NSLogger Data + CFBundleTypeRole + Editor + LSHandlerRank + Owner + LSTypeIsPackage + + NSDocumentClass + LoggerDocument + NSExportableTypes + + public.plain-text + + NSPersistentStoreTypeKey + Binary + + + CFBundleTypeExtensions + + rawnsloggerdata + + CFBundleTypeIconFile + rawlogfile.icns + CFBundleTypeName + NSLogger Raw Data + CFBundleTypeRole + Viewer + LSHandlerRank + Owner + LSTypeIsPackage + + NSDocumentClass + LoggerDocument + NSExportableTypes + + public.plain-text + + NSPersistentStoreTypeKey + Binary + + + CFBundleTypeName + Text File + CFBundleTypeRole + None + LSHandlerRank + None + LSItemContentTypes + + public.plain-text + + LSTypeIsPackage + + NSPersistentStoreTypeKey + InMemory + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + Icon.icns + CFBundleIdentifier + com.florentpillet.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + Git-949aa30 + LSApplicationCategoryType + public.app-category.developer-tools + LSMinimumSystemVersion + 10.6.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/External Source/NSLogger/Desktop Viewer/LoggerDocumentController.h b/External Source/NSLogger/Desktop Viewer/LoggerDocumentController.h new file mode 100644 index 000000000..6efdc2b2d --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/LoggerDocumentController.h @@ -0,0 +1,34 @@ +/* + * LoggerDocumentController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +@interface LoggerDocumentController : NSDocumentController + +@end diff --git a/External Source/NSLogger/Desktop Viewer/LoggerDocumentController.m b/External Source/NSLogger/Desktop Viewer/LoggerDocumentController.m new file mode 100644 index 000000000..4a75f8049 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/LoggerDocumentController.m @@ -0,0 +1,60 @@ +/* + * LoggerDocumentController.h + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import "LoggerDocumentController.h" + +@implementation LoggerDocumentController + ++ (NSDocumentController *)sharedDocumentController +{ + static LoggerDocumentController *sSharedController = nil; + if (sSharedController == nil) + sSharedController = [[LoggerDocumentController alloc] init]; + assert([NSDocumentController sharedDocumentController] == sSharedController); + return sSharedController; +} + +- (id)openUntitledDocumentAndDisplay:(BOOL)displayDocument error:(NSError **)outError +{ + if (outError != NULL) + *outError = [[NSError alloc] initWithDomain:@"NSLogger" code:-1 userInfo:nil]; + return nil; +} + +- (void)reopenDocumentForURL:(NSURL *)urlOrNil + withContentsOfURL:(NSURL *)contentsURL + display:(BOOL)displayDocument + completionHandler:(void (^)(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error))completionHandler +{ + completionHandler(nil, NO, nil); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/TemplateIcon.icns b/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/TemplateIcon.icns new file mode 100644 index 000000000..62cb7015e Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/TemplateIcon.icns differ diff --git a/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/project.pbxproj b/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/project.pbxproj new file mode 100644 index 000000000..cc7a40d91 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/project.pbxproj @@ -0,0 +1,746 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 182FF3071333F29C00EA7910 /* Load.png in Resources */ = {isa = PBXBuildFile; fileRef = 182FF3051333F29C00EA7910 /* Load.png */; }; + 182FF3081333F29C00EA7910 /* Save.png in Resources */ = {isa = PBXBuildFile; fileRef = 182FF3061333F29C00EA7910 /* Save.png */; }; + 182FF3161333F8EC00EA7910 /* Export.png in Resources */ = {isa = PBXBuildFile; fileRef = 182FF3151333F8EC00EA7910 /* Export.png */; }; + 3D027B2C12663E1200E6F241 /* LoggerPrefs.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D027B2B12663E1200E6F241 /* LoggerPrefs.xib */; }; + 3D027B2F12663E3F00E6F241 /* LoggerPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D027B2E12663E3F00E6F241 /* LoggerPrefsWindowController.m */; }; + 3D062E7B129D18160067DB8C /* NSLoggerCertReq.conf in Resources */ = {isa = PBXBuildFile; fileRef = 3D062E75129D17640067DB8C /* NSLoggerCertReq.conf */; }; + 3D18EFA10F553B3800EC6DCC /* LoggerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D18EFA00F553B3800EC6DCC /* LoggerUtils.m */; }; + 3D24C40C125638A500435837 /* BWToolkitFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D24C4091256387900435837 /* BWToolkitFramework.framework */; }; + 3D24C4A812563DCF00435837 /* BWToolkitFramework.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3D24C4091256387900435837 /* BWToolkitFramework.framework */; }; + 3D369CB71290009800462E79 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D369CB61290009800462E79 /* Security.framework */; }; + 3D4EA0580F3768EA00DF81E6 /* LoggerMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D4EA0570F3768EA00DF81E6 /* LoggerMessage.m */; }; + 3D4EA05B0F3769B000DF81E6 /* LoggerNativeMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D4EA05A0F3769B000DF81E6 /* LoggerNativeMessage.m */; }; + 3D4EA1E10F3854C300DF81E6 /* LoggerWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D4EA1E00F3854C300DF81E6 /* LoggerWindowController.m */; }; + 3D65634F13ED896400004DB6 /* ToolbarItemFonts.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 3D65634E13ED896400004DB6 /* ToolbarItemFonts.tiff */; }; + 3D65635513ED9C6800004DB6 /* LoggerDocumentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D65635413ED9C6600004DB6 /* LoggerDocumentController.m */; }; + 3D6A346A1262F60400D0EC3A /* LoggerDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D6A34691262F60400D0EC3A /* LoggerDocument.m */; }; + 3D6A34AB1262FD5D00D0EC3A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3D6A34A31262FD5500D0EC3A /* InfoPlist.strings */; }; + 3D6A34AC1262FD6300D0EC3A /* LoggerWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D6A34A51262FD5500D0EC3A /* LoggerWindow.xib */; }; + 3D6A34AD1262FD6C00D0EC3A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D6A34A71262FD5500D0EC3A /* MainMenu.xib */; }; + 3D6A37C51263998A00D0EC3A /* LoggerStatusWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D6A37C41263998A00D0EC3A /* LoggerStatusWindowController.m */; }; + 3D6A37C9126399D700D0EC3A /* LoggerStatus.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D6A37C8126399D700D0EC3A /* LoggerStatus.xib */; }; + 3D6ED56912A3A55E0005DD57 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3D6ED56812A3A55E0005DD57 /* Icon.icns */; }; + 3D7C74FD0F3CA8AB006B55AD /* LoggerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7C74FC0F3CA8AB006B55AD /* LoggerConnection.m */; }; + 3D7C75330F401B35006B55AD /* LoggerNativeConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7C75320F401B35006B55AD /* LoggerNativeConnection.m */; }; + 3D7C75510F4025A7006B55AD /* LoggerTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7C75500F4025A7006B55AD /* LoggerTransport.m */; }; + 3D8B63DD126B79CA00659751 /* LoggerSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8B63DC126B79CA00659751 /* LoggerSplitView.m */; }; + 3D8E060F1305AE690024917B /* status_disconnected.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D8E060C1305AE690024917B /* status_disconnected.png */; }; + 3D8E06101305AE690024917B /* status_error.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D8E060D1305AE690024917B /* status_error.png */; }; + 3D8E06111305AE690024917B /* status_ready_connected.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D8E060E1305AE690024917B /* status_ready_connected.png */; }; + 3D8E06241306C06A0024917B /* LoggerTransportStatusCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8E06231306C06A0024917B /* LoggerTransportStatusCell.m */; }; + 3D8E078113097D6E0024917B /* ssl_badge.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D8E078013097D6E0024917B /* ssl_badge.png */; }; + 3DA319AB12E37088003F68E6 /* LoggerTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DA319AA12E37088003F68E6 /* LoggerTableView.m */; }; + 3DAB6E2E0F2FA0BA00BB3236 /* LoggerAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DAB6E2D0F2FA0BA00BB3236 /* LoggerAppDelegate.m */; }; + 3DAC10E313ED5A7E00D5E6BA /* SSSelectableToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DAC10E013ED5A7E00D5E6BA /* SSSelectableToolbar.m */; }; + 3DAC10E413ED5A7E00D5E6BA /* SSSelectableToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DAC10E213ED5A7E00D5E6BA /* SSSelectableToolbarItem.m */; }; + 3DADCBA0125FC3B200807A7D /* ValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DADCB9F125FC3B200807A7D /* ValueTransformers.m */; }; + 3DBB562712829BCC004F729D /* LoggerMarkerCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB562612829BCC004F729D /* LoggerMarkerCell.m */; }; + 3DC55EF30F436BBA005C61FD /* LoggerMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC55EF20F436BBA005C61FD /* LoggerMessageCell.m */; }; + 3DD2EB9314334BA8004EEB19 /* logfile.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3DD2EB9114334BA8004EEB19 /* logfile.icns */; }; + 3DD2EB9414334BA8004EEB19 /* rawlogfile.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3DD2EB9214334BA8004EEB19 /* rawlogfile.icns */; }; + 3DD61AB7127F7617009871F1 /* LoggerClientInfoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD61AB6127F7617009871F1 /* LoggerClientInfoCell.m */; }; + 3DDAE1630F405CE5001B1408 /* LoggerIPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DDAE1620F405CE5001B1408 /* LoggerIPConnection.m */; }; + 3DE01E901268D30C00A39E7E /* LoggerDetailsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3DE01E8F1268D30C00A39E7E /* LoggerDetailsWindow.xib */; }; + 3DE01E941268D32100A39E7E /* LoggerDetailsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DE01E931268D32100A39E7E /* LoggerDetailsWindowController.m */; }; + 3DE8CE7D12AE4A60005C83D0 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 3D6ED59C12A3AE0C0005DD57 /* Credits.rtf */; }; + 3DE8CE7E12AE4A67005C83D0 /* relaunch.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DE8CE7312AE49E7005C83D0 /* relaunch.m */; }; + 3DE8CEEC12AE50A8005C83D0 /* relaunch in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DE8CE7812AE4A17005C83D0 /* relaunch */; }; + 3DEE27B712B773D8009ADA67 /* LoggerNativeTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7C75550F4026D2006B55AD /* LoggerNativeTransport.m */; }; + 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 3D24C4081256387900435837 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3D24C3FD1256387900435837 /* BWToolkit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 53DF68FD067E5B5A0090B5B0; + remoteInfo = BWToolkitFramework; + }; + 3D6A34A01262FCB100D0EC3A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3D24C3FD1256387900435837 /* BWToolkit.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 53DF68FC067E5B5A0090B5B0; + remoteInfo = BWToolkitFramework; + }; + 3DE8CE8A12AE4A96005C83D0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3DE8CE7712AE4A17005C83D0; + remoteInfo = "relaunch tool"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 3D4EA21C0F385B6100DF81E6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3D24C4A812563DCF00435837 /* BWToolkitFramework.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3DE8CE8712AE4A74005C83D0 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 12; + files = ( + 3DE8CEEC12AE50A8005C83D0 /* relaunch in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + 182FF3051333F29C00EA7910 /* Load.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Load.png; path = Resources/Icon/Load.png; sourceTree = ""; }; + 182FF3061333F29C00EA7910 /* Save.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Save.png; path = Resources/Icon/Save.png; sourceTree = ""; }; + 182FF3151333F8EC00EA7910 /* Export.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Export.png; path = Resources/Icon/Export.png; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* NSLogger_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSLogger_Prefix.pch; sourceTree = ""; }; + 3D027B2B12663E1200E6F241 /* LoggerPrefs.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = LoggerPrefs.xib; path = Resources/LoggerPrefs.xib; sourceTree = ""; }; + 3D027B2D12663E3F00E6F241 /* LoggerPrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerPrefsWindowController.h; path = Classes/LoggerPrefsWindowController.h; sourceTree = ""; }; + 3D027B2E12663E3F00E6F241 /* LoggerPrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerPrefsWindowController.m; path = Classes/LoggerPrefsWindowController.m; sourceTree = ""; }; + 3D062E75129D17640067DB8C /* NSLoggerCertReq.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = NSLoggerCertReq.conf; path = Resources/NSLoggerCertReq.conf; sourceTree = ""; }; + 3D18EF9F0F553B3800EC6DCC /* LoggerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerUtils.h; path = Classes/LoggerUtils.h; sourceTree = ""; }; + 3D18EFA00F553B3800EC6DCC /* LoggerUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerUtils.m; path = Classes/LoggerUtils.m; sourceTree = ""; }; + 3D24C36912560C1700435837 /* LoggerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerCommon.h; path = "../Client Logger/iOS/LoggerCommon.h"; sourceTree = SOURCE_ROOT; }; + 3D24C3FD1256387900435837 /* BWToolkit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = BWToolkit.xcodeproj; path = "Third Party/BWToolkit/BWToolkit.xcodeproj"; sourceTree = ""; }; + 3D369CB61290009800462E79 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 3D4EA0560F3768EA00DF81E6 /* LoggerMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerMessage.h; path = Classes/LoggerMessage.h; sourceTree = ""; }; + 3D4EA0570F3768EA00DF81E6 /* LoggerMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerMessage.m; path = Classes/LoggerMessage.m; sourceTree = ""; }; + 3D4EA0590F3769B000DF81E6 /* LoggerNativeMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerNativeMessage.h; path = Classes/LoggerNativeMessage.h; sourceTree = ""; }; + 3D4EA05A0F3769B000DF81E6 /* LoggerNativeMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerNativeMessage.m; path = Classes/LoggerNativeMessage.m; sourceTree = ""; }; + 3D4EA1DF0F3854C300DF81E6 /* LoggerWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerWindowController.h; path = Classes/LoggerWindowController.h; sourceTree = ""; }; + 3D4EA1E00F3854C300DF81E6 /* LoggerWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerWindowController.m; path = Classes/LoggerWindowController.m; sourceTree = ""; }; + 3D65634E13ED896400004DB6 /* ToolbarItemFonts.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = ToolbarItemFonts.tiff; path = "Third Party/BWToolkit/ToolbarItemFonts.tiff"; sourceTree = ""; }; + 3D65635313ED9C6500004DB6 /* LoggerDocumentController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggerDocumentController.h; sourceTree = ""; }; + 3D65635413ED9C6600004DB6 /* LoggerDocumentController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoggerDocumentController.m; sourceTree = ""; }; + 3D6A34681262F60400D0EC3A /* LoggerDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerDocument.h; path = Classes/LoggerDocument.h; sourceTree = ""; }; + 3D6A34691262F60400D0EC3A /* LoggerDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerDocument.m; path = Classes/LoggerDocument.m; sourceTree = ""; }; + 3D6A34A31262FD5500D0EC3A /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = Resources/InfoPlist.strings; sourceTree = ""; }; + 3D6A34A51262FD5500D0EC3A /* LoggerWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = LoggerWindow.xib; path = Resources/LoggerWindow.xib; sourceTree = ""; }; + 3D6A34A71262FD5500D0EC3A /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = Resources/MainMenu.xib; sourceTree = ""; }; + 3D6A37C31263998A00D0EC3A /* LoggerStatusWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerStatusWindowController.h; path = Classes/LoggerStatusWindowController.h; sourceTree = ""; }; + 3D6A37C41263998A00D0EC3A /* LoggerStatusWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerStatusWindowController.m; path = Classes/LoggerStatusWindowController.m; sourceTree = ""; }; + 3D6A37C8126399D700D0EC3A /* LoggerStatus.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = LoggerStatus.xib; path = Resources/LoggerStatus.xib; sourceTree = ""; }; + 3D6ED56812A3A55E0005DD57 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Icon.icns; path = Resources/Icon/Icon.icns; sourceTree = ""; }; + 3D6ED59C12A3AE0C0005DD57 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = Credits.rtf; path = Resources/Credits.rtf; sourceTree = ""; }; + 3D7C74FB0F3CA8AB006B55AD /* LoggerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerConnection.h; path = Classes/LoggerConnection.h; sourceTree = ""; }; + 3D7C74FC0F3CA8AB006B55AD /* LoggerConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerConnection.m; path = Classes/LoggerConnection.m; sourceTree = ""; }; + 3D7C75310F401B35006B55AD /* LoggerNativeConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerNativeConnection.h; path = Classes/LoggerNativeConnection.h; sourceTree = ""; }; + 3D7C75320F401B35006B55AD /* LoggerNativeConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerNativeConnection.m; path = Classes/LoggerNativeConnection.m; sourceTree = ""; }; + 3D7C754F0F4025A7006B55AD /* LoggerTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerTransport.h; path = Classes/LoggerTransport.h; sourceTree = ""; }; + 3D7C75500F4025A7006B55AD /* LoggerTransport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerTransport.m; path = Classes/LoggerTransport.m; sourceTree = ""; }; + 3D7C75540F4026D2006B55AD /* LoggerNativeTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerNativeTransport.h; path = Classes/LoggerNativeTransport.h; sourceTree = ""; }; + 3D7C75550F4026D2006B55AD /* LoggerNativeTransport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerNativeTransport.m; path = Classes/LoggerNativeTransport.m; sourceTree = ""; }; + 3D8B63DB126B79CA00659751 /* LoggerSplitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerSplitView.h; path = Classes/LoggerSplitView.h; sourceTree = ""; }; + 3D8B63DC126B79CA00659751 /* LoggerSplitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerSplitView.m; path = Classes/LoggerSplitView.m; sourceTree = ""; }; + 3D8E060C1305AE690024917B /* status_disconnected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = status_disconnected.png; path = Resources/status_disconnected.png; sourceTree = ""; }; + 3D8E060D1305AE690024917B /* status_error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = status_error.png; path = Resources/status_error.png; sourceTree = ""; }; + 3D8E060E1305AE690024917B /* status_ready_connected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = status_ready_connected.png; path = Resources/status_ready_connected.png; sourceTree = ""; }; + 3D8E06221306C06A0024917B /* LoggerTransportStatusCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerTransportStatusCell.h; path = Classes/LoggerTransportStatusCell.h; sourceTree = ""; }; + 3D8E06231306C06A0024917B /* LoggerTransportStatusCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerTransportStatusCell.m; path = Classes/LoggerTransportStatusCell.m; sourceTree = ""; }; + 3D8E078013097D6E0024917B /* ssl_badge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ssl_badge.png; path = Resources/ssl_badge.png; sourceTree = ""; }; + 3DA319A912E37088003F68E6 /* LoggerTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerTableView.h; path = Classes/LoggerTableView.h; sourceTree = ""; }; + 3DA319AA12E37088003F68E6 /* LoggerTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerTableView.m; path = Classes/LoggerTableView.m; sourceTree = ""; }; + 3DAB6E2C0F2FA0BA00BB3236 /* LoggerAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerAppDelegate.h; path = Classes/LoggerAppDelegate.h; sourceTree = ""; }; + 3DAB6E2D0F2FA0BA00BB3236 /* LoggerAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerAppDelegate.m; path = Classes/LoggerAppDelegate.m; sourceTree = ""; }; + 3DAC10DF13ED5A7E00D5E6BA /* SSSelectableToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SSSelectableToolbar.h; path = "Third Party/SSSelectableToolbar/SSSelectableToolbar.h"; sourceTree = ""; }; + 3DAC10E013ED5A7E00D5E6BA /* SSSelectableToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SSSelectableToolbar.m; path = "Third Party/SSSelectableToolbar/SSSelectableToolbar.m"; sourceTree = ""; }; + 3DAC10E113ED5A7E00D5E6BA /* SSSelectableToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SSSelectableToolbarItem.h; path = "Third Party/SSSelectableToolbar/SSSelectableToolbarItem.h"; sourceTree = ""; }; + 3DAC10E213ED5A7E00D5E6BA /* SSSelectableToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SSSelectableToolbarItem.m; path = "Third Party/SSSelectableToolbar/SSSelectableToolbarItem.m"; sourceTree = ""; }; + 3DADCB9E125FC3B200807A7D /* ValueTransformers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueTransformers.h; path = Classes/ValueTransformers.h; sourceTree = ""; }; + 3DADCB9F125FC3B200807A7D /* ValueTransformers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ValueTransformers.m; path = Classes/ValueTransformers.m; sourceTree = ""; }; + 3DBB562512829BCC004F729D /* LoggerMarkerCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerMarkerCell.h; path = Classes/LoggerMarkerCell.h; sourceTree = ""; }; + 3DBB562612829BCC004F729D /* LoggerMarkerCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerMarkerCell.m; path = Classes/LoggerMarkerCell.m; sourceTree = ""; }; + 3DC55EF10F436BBA005C61FD /* LoggerMessageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerMessageCell.h; path = Classes/LoggerMessageCell.h; sourceTree = ""; }; + 3DC55EF20F436BBA005C61FD /* LoggerMessageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerMessageCell.m; path = Classes/LoggerMessageCell.m; sourceTree = ""; }; + 3DD2EB9114334BA8004EEB19 /* logfile.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = logfile.icns; path = Resources/Icon/logfile.icns; sourceTree = ""; }; + 3DD2EB9214334BA8004EEB19 /* rawlogfile.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = rawlogfile.icns; path = Resources/Icon/rawlogfile.icns; sourceTree = ""; }; + 3DD61AB5127F7617009871F1 /* LoggerClientInfoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerClientInfoCell.h; path = Classes/LoggerClientInfoCell.h; sourceTree = ""; }; + 3DD61AB6127F7617009871F1 /* LoggerClientInfoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerClientInfoCell.m; path = Classes/LoggerClientInfoCell.m; sourceTree = ""; }; + 3DDAE1610F405CE5001B1408 /* LoggerIPConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerIPConnection.h; path = Classes/LoggerIPConnection.h; sourceTree = ""; }; + 3DDAE1620F405CE5001B1408 /* LoggerIPConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerIPConnection.m; path = Classes/LoggerIPConnection.m; sourceTree = ""; }; + 3DE01E8F1268D30C00A39E7E /* LoggerDetailsWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = LoggerDetailsWindow.xib; path = Resources/LoggerDetailsWindow.xib; sourceTree = ""; }; + 3DE01E921268D32100A39E7E /* LoggerDetailsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoggerDetailsWindowController.h; path = Classes/LoggerDetailsWindowController.h; sourceTree = ""; }; + 3DE01E931268D32100A39E7E /* LoggerDetailsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggerDetailsWindowController.m; path = Classes/LoggerDetailsWindowController.m; sourceTree = ""; }; + 3DE8CE7312AE49E7005C83D0 /* relaunch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = relaunch.m; path = Classes/relaunch.m; sourceTree = ""; }; + 3DE8CE7812AE4A17005C83D0 /* relaunch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = relaunch; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8D1107320486CEB800E47090 /* NSLogger.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NSLogger.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3DE8CE7612AE4A17005C83D0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D11072E0486CEB800E47090 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, + 3D369CB71290009800462E79 /* Security.framework in Frameworks */, + 3D24C40C125638A500435837 /* BWToolkitFramework.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 3DAB6E2C0F2FA0BA00BB3236 /* LoggerAppDelegate.h */, + 3DAB6E2D0F2FA0BA00BB3236 /* LoggerAppDelegate.m */, + 3D6A37C31263998A00D0EC3A /* LoggerStatusWindowController.h */, + 3D6A37C41263998A00D0EC3A /* LoggerStatusWindowController.m */, + 3D6A34681262F60400D0EC3A /* LoggerDocument.h */, + 3D6A34691262F60400D0EC3A /* LoggerDocument.m */, + 3D65635313ED9C6500004DB6 /* LoggerDocumentController.h */, + 3D65635413ED9C6600004DB6 /* LoggerDocumentController.m */, + 3D4EA1DF0F3854C300DF81E6 /* LoggerWindowController.h */, + 3D4EA1E00F3854C300DF81E6 /* LoggerWindowController.m */, + 3DE01E921268D32100A39E7E /* LoggerDetailsWindowController.h */, + 3DE01E931268D32100A39E7E /* LoggerDetailsWindowController.m */, + 3D027B2D12663E3F00E6F241 /* LoggerPrefsWindowController.h */, + 3D027B2E12663E3F00E6F241 /* LoggerPrefsWindowController.m */, + 3D18EF9F0F553B3800EC6DCC /* LoggerUtils.h */, + 3D18EFA00F553B3800EC6DCC /* LoggerUtils.m */, + 3DADCB9E125FC3B200807A7D /* ValueTransformers.h */, + 3DADCB9F125FC3B200807A7D /* ValueTransformers.m */, + 3D0D601B0F4068A100EDB93B /* Views & Cells */, + 3DDAE1570F405CD4001B1408 /* Model */, + 3DE8CE6E12AE49C7005C83D0 /* Relaunch */, + ); + name = Classes; + sourceTree = ""; + }; + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, + 3D369CB61290009800462E79 /* Security.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 29B97324FDCFA39411CA2CEA /* AppKit.framework */, + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, + 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47090 /* NSLogger.app */, + 3DE8CE7812AE4A17005C83D0 /* relaunch */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* NSLogger */ = { + isa = PBXGroup; + children = ( + 3D24C3FD1256387900435837 /* BWToolkit.xcodeproj */, + 3D65635B13EDA75800004DB6 /* Third Party */, + 3D65635C13EDA78600004DB6 /* Shared */, + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = NSLogger; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* NSLogger_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 3D65634E13ED896400004DB6 /* ToolbarItemFonts.tiff */, + 182FF3151333F8EC00EA7910 /* Export.png */, + 182FF3051333F29C00EA7910 /* Load.png */, + 182FF3061333F29C00EA7910 /* Save.png */, + 3D6ED56812A3A55E0005DD57 /* Icon.icns */, + 3DD2EB9114334BA8004EEB19 /* logfile.icns */, + 3DD2EB9214334BA8004EEB19 /* rawlogfile.icns */, + 3D062E75129D17640067DB8C /* NSLoggerCertReq.conf */, + 8D1107310486CEB800E47090 /* Info.plist */, + 3D6A34A31262FD5500D0EC3A /* InfoPlist.strings */, + 3D6A34A71262FD5500D0EC3A /* MainMenu.xib */, + 3D6A37C8126399D700D0EC3A /* LoggerStatus.xib */, + 3D6A34A51262FD5500D0EC3A /* LoggerWindow.xib */, + 3D027B2B12663E1200E6F241 /* LoggerPrefs.xib */, + 3DE01E8F1268D30C00A39E7E /* LoggerDetailsWindow.xib */, + 3D8E060C1305AE690024917B /* status_disconnected.png */, + 3D8E060D1305AE690024917B /* status_error.png */, + 3D8E060E1305AE690024917B /* status_ready_connected.png */, + 3D8E078013097D6E0024917B /* ssl_badge.png */, + 3D6ED59C12A3AE0C0005DD57 /* Credits.rtf */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3D0D601B0F4068A100EDB93B /* Views & Cells */ = { + isa = PBXGroup; + children = ( + 3DA319A912E37088003F68E6 /* LoggerTableView.h */, + 3DA319AA12E37088003F68E6 /* LoggerTableView.m */, + 3D8B63DB126B79CA00659751 /* LoggerSplitView.h */, + 3D8B63DC126B79CA00659751 /* LoggerSplitView.m */, + 3DC55EF10F436BBA005C61FD /* LoggerMessageCell.h */, + 3DC55EF20F436BBA005C61FD /* LoggerMessageCell.m */, + 3DD61AB5127F7617009871F1 /* LoggerClientInfoCell.h */, + 3DD61AB6127F7617009871F1 /* LoggerClientInfoCell.m */, + 3DBB562512829BCC004F729D /* LoggerMarkerCell.h */, + 3DBB562612829BCC004F729D /* LoggerMarkerCell.m */, + 3D8E06221306C06A0024917B /* LoggerTransportStatusCell.h */, + 3D8E06231306C06A0024917B /* LoggerTransportStatusCell.m */, + ); + name = "Views & Cells"; + sourceTree = ""; + }; + 3D24C3FE1256387900435837 /* Products */ = { + isa = PBXGroup; + children = ( + 3D24C4091256387900435837 /* BWToolkitFramework.framework */, + ); + name = Products; + sourceTree = ""; + }; + 3D65635B13EDA75800004DB6 /* Third Party */ = { + isa = PBXGroup; + children = ( + 3DAC10DE13ED5A6D00D5E6BA /* SSSelectableToolbar */, + ); + name = "Third Party"; + sourceTree = ""; + }; + 3D65635C13EDA78600004DB6 /* Shared */ = { + isa = PBXGroup; + children = ( + 3D24C36912560C1700435837 /* LoggerCommon.h */, + ); + name = Shared; + sourceTree = ""; + }; + 3D7C75530F4025DE006B55AD /* Native log format */ = { + isa = PBXGroup; + children = ( + 3D7C75540F4026D2006B55AD /* LoggerNativeTransport.h */, + 3D7C75550F4026D2006B55AD /* LoggerNativeTransport.m */, + 3D7C75310F401B35006B55AD /* LoggerNativeConnection.h */, + 3D7C75320F401B35006B55AD /* LoggerNativeConnection.m */, + 3D4EA0590F3769B000DF81E6 /* LoggerNativeMessage.h */, + 3D4EA05A0F3769B000DF81E6 /* LoggerNativeMessage.m */, + ); + name = "Native log format"; + sourceTree = ""; + }; + 3DAC10DE13ED5A6D00D5E6BA /* SSSelectableToolbar */ = { + isa = PBXGroup; + children = ( + 3DAC10DF13ED5A7E00D5E6BA /* SSSelectableToolbar.h */, + 3DAC10E013ED5A7E00D5E6BA /* SSSelectableToolbar.m */, + 3DAC10E113ED5A7E00D5E6BA /* SSSelectableToolbarItem.h */, + 3DAC10E213ED5A7E00D5E6BA /* SSSelectableToolbarItem.m */, + ); + name = SSSelectableToolbar; + sourceTree = ""; + }; + 3DDAE1570F405CD4001B1408 /* Model */ = { + isa = PBXGroup; + children = ( + 3D7C754F0F4025A7006B55AD /* LoggerTransport.h */, + 3D7C75500F4025A7006B55AD /* LoggerTransport.m */, + 3D7C74FB0F3CA8AB006B55AD /* LoggerConnection.h */, + 3D7C74FC0F3CA8AB006B55AD /* LoggerConnection.m */, + 3DDAE1610F405CE5001B1408 /* LoggerIPConnection.h */, + 3DDAE1620F405CE5001B1408 /* LoggerIPConnection.m */, + 3D4EA0560F3768EA00DF81E6 /* LoggerMessage.h */, + 3D4EA0570F3768EA00DF81E6 /* LoggerMessage.m */, + 3D7C75530F4025DE006B55AD /* Native log format */, + ); + name = Model; + sourceTree = ""; + }; + 3DE8CE6E12AE49C7005C83D0 /* Relaunch */ = { + isa = PBXGroup; + children = ( + 3DE8CE7312AE49E7005C83D0 /* relaunch.m */, + ); + name = Relaunch; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3DE8CE7712AE4A17005C83D0 /* relaunch tool */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3DE8CE8812AE4A74005C83D0 /* Build configuration list for PBXNativeTarget "relaunch tool" */; + buildPhases = ( + 3DE8CE7512AE4A17005C83D0 /* Sources */, + 3DE8CE7612AE4A17005C83D0 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "relaunch tool"; + productName = relaunch; + productReference = 3DE8CE7812AE4A17005C83D0 /* relaunch */; + productType = "com.apple.product-type.tool"; + }; + 8D1107260486CEB800E47090 /* NSLogger */ = { + isa = PBXNativeTarget; + buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "NSLogger" */; + buildPhases = ( + 3DEE27A312B771DC009ADA67 /* ShellScript */, + 8D1107290486CEB800E47090 /* Resources */, + 8D11072C0486CEB800E47090 /* Sources */, + 8D11072E0486CEB800E47090 /* Frameworks */, + 3D4EA21C0F385B6100DF81E6 /* CopyFiles */, + 3DE8CE8712AE4A74005C83D0 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 3D6A34A11262FCB100D0EC3A /* PBXTargetDependency */, + 3DE8CE8B12AE4A96005C83D0 /* PBXTargetDependency */, + ); + name = NSLogger; + productInstallPath = "$(HOME)/Applications"; + productName = NSLogger; + productReference = 8D1107320486CEB800E47090 /* NSLogger.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + ORGANIZATIONNAME = "Florent Pillet"; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLogger" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + English, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* NSLogger */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 3D24C3FE1256387900435837 /* Products */; + ProjectRef = 3D24C3FD1256387900435837 /* BWToolkit.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 8D1107260486CEB800E47090 /* NSLogger */, + 3DE8CE7712AE4A17005C83D0 /* relaunch tool */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 3D24C4091256387900435837 /* BWToolkitFramework.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = BWToolkitFramework.framework; + remoteRef = 3D24C4081256387900435837 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47090 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D6A34AB1262FD5D00D0EC3A /* InfoPlist.strings in Resources */, + 3D6A34AC1262FD6300D0EC3A /* LoggerWindow.xib in Resources */, + 3D6A34AD1262FD6C00D0EC3A /* MainMenu.xib in Resources */, + 3D6A37C9126399D700D0EC3A /* LoggerStatus.xib in Resources */, + 3D027B2C12663E1200E6F241 /* LoggerPrefs.xib in Resources */, + 3DE01E901268D30C00A39E7E /* LoggerDetailsWindow.xib in Resources */, + 3D062E7B129D18160067DB8C /* NSLoggerCertReq.conf in Resources */, + 3D6ED56912A3A55E0005DD57 /* Icon.icns in Resources */, + 3DE8CE7D12AE4A60005C83D0 /* Credits.rtf in Resources */, + 3D8E060F1305AE690024917B /* status_disconnected.png in Resources */, + 3D8E06101305AE690024917B /* status_error.png in Resources */, + 3D8E06111305AE690024917B /* status_ready_connected.png in Resources */, + 3D8E078113097D6E0024917B /* ssl_badge.png in Resources */, + 182FF3071333F29C00EA7910 /* Load.png in Resources */, + 182FF3081333F29C00EA7910 /* Save.png in Resources */, + 182FF3161333F8EC00EA7910 /* Export.png in Resources */, + 3D65634F13ED896400004DB6 /* ToolbarItemFonts.tiff in Resources */, + 3DD2EB9314334BA8004EEB19 /* logfile.icns in Resources */, + 3DD2EB9414334BA8004EEB19 /* rawlogfile.icns in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3DEE27A312B771DC009ADA67 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/bin/bash\nif [ -z \"$CODE_SIGN_IDENTITY\" ] || [ \"$CODE_SIGN_IDENTITY\" == \"Don't Code Sign\" ] ; then\n osascript -e \"tell application \\\"Xcode\\\"\n display alert \\\"Your build is not code signed\\\" message \\\"Signing your build will prevent an issue with SSL connections failing the first time and requiring a NSLogger restart (or even failing altogether on OS X 10.7).\\n\\nTo sign your build, open the NSLogger target and select your developer certificate in the Code Signing Identity build setting.\\n\\nFurther instructions can be found in the README.txt file in the project folder.\\\"\n end tell\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3DE8CE7512AE4A17005C83D0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3DE8CE7E12AE4A67005C83D0 /* relaunch.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D11072C0486CEB800E47090 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072D0486CEB800E47090 /* main.m in Sources */, + 3DAB6E2E0F2FA0BA00BB3236 /* LoggerAppDelegate.m in Sources */, + 3D4EA0580F3768EA00DF81E6 /* LoggerMessage.m in Sources */, + 3D4EA05B0F3769B000DF81E6 /* LoggerNativeMessage.m in Sources */, + 3D4EA1E10F3854C300DF81E6 /* LoggerWindowController.m in Sources */, + 3D7C74FD0F3CA8AB006B55AD /* LoggerConnection.m in Sources */, + 3D7C75330F401B35006B55AD /* LoggerNativeConnection.m in Sources */, + 3D7C75510F4025A7006B55AD /* LoggerTransport.m in Sources */, + 3DDAE1630F405CE5001B1408 /* LoggerIPConnection.m in Sources */, + 3DC55EF30F436BBA005C61FD /* LoggerMessageCell.m in Sources */, + 3D18EFA10F553B3800EC6DCC /* LoggerUtils.m in Sources */, + 3DADCBA0125FC3B200807A7D /* ValueTransformers.m in Sources */, + 3D6A346A1262F60400D0EC3A /* LoggerDocument.m in Sources */, + 3D6A37C51263998A00D0EC3A /* LoggerStatusWindowController.m in Sources */, + 3D027B2F12663E3F00E6F241 /* LoggerPrefsWindowController.m in Sources */, + 3DE01E941268D32100A39E7E /* LoggerDetailsWindowController.m in Sources */, + 3D8B63DD126B79CA00659751 /* LoggerSplitView.m in Sources */, + 3DD61AB7127F7617009871F1 /* LoggerClientInfoCell.m in Sources */, + 3DBB562712829BCC004F729D /* LoggerMarkerCell.m in Sources */, + 3DEE27B712B773D8009ADA67 /* LoggerNativeTransport.m in Sources */, + 3DA319AB12E37088003F68E6 /* LoggerTableView.m in Sources */, + 3D8E06241306C06A0024917B /* LoggerTransportStatusCell.m in Sources */, + 3DAC10E313ED5A7E00D5E6BA /* SSSelectableToolbar.m in Sources */, + 3DAC10E413ED5A7E00D5E6BA /* SSSelectableToolbarItem.m in Sources */, + 3D65635513ED9C6800004DB6 /* LoggerDocumentController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3D6A34A11262FCB100D0EC3A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = BWToolkitFramework; + targetProxy = 3D6A34A01262FCB100D0EC3A /* PBXContainerItemProxy */; + }; + 3DE8CE8B12AE4A96005C83D0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3DE8CE7712AE4A17005C83D0 /* relaunch tool */; + targetProxy = 3DE8CE8A12AE4A96005C83D0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3DE8CE7A12AE4A18005C83D0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "Don't Code Sign"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = relaunch; + }; + name = Debug; + }; + 3DE8CE7B12AE4A18005C83D0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "Don't Code Sign"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = relaunch; + }; + name = Release; + }; + C01FCF4B08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLogger_Prefix.pch; + HEADER_SEARCH_PATHS = ( + "\"Third Party/BWToolkit\"", + ); + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = NSLogger; + PROVISIONING_PROFILE = ""; + }; + name = Debug; + }; + C01FCF4C08A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = NSLogger_Prefix.pch; + HEADER_SEARCH_PATHS = ( + "\"Third Party/BWToolkit\"", + ); + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = NSLogger; + PROVISIONING_PROFILE = ""; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3DE8CE8812AE4A74005C83D0 /* Build configuration list for PBXNativeTarget "relaunch tool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3DE8CE7A12AE4A18005C83D0 /* Debug */, + 3DE8CE7B12AE4A18005C83D0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "NSLogger" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4B08A954540054247B /* Debug */, + C01FCF4C08A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NSLogger" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..84ab3f303 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/NSLogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,6 @@ + + + + + diff --git a/External Source/NSLogger/Desktop Viewer/NSLogger_Prefix.pch b/External Source/NSLogger/Desktop Viewer/NSLogger_Prefix.pch new file mode 100644 index 000000000..bb07f82f0 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/NSLogger_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'NSLogger' target in the 'NSLogger' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/External Source/NSLogger/Desktop Viewer/README.txt b/External Source/NSLogger/Desktop Viewer/README.txt new file mode 100644 index 000000000..672772be6 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/README.txt @@ -0,0 +1,32 @@ +This is the Mac OS X logs viewer source code (NSLogger) + +BUILDING NSLogger +----------------- + +1) Make sure BWToolkit.ibplugin is installed + +NSLogger uses Brandon Walkin's BWToolkit in the user interface. +To compile or open the xib files, you will need to install the BWToolkit IB plugin on your system. +If you don't have it installed yet, take the following steps: + +- download the BWToolkit IB plugin from http://brandonwalkin.com/bwtoolkit/ +- copy it to your ~/Library/Application Support/Interface Builder 3.0/ folder +- double click this copy + +It will install in Interface Builder. + + +2) Code sign your build + +Since NSLogger generates a self-signed certificate for SSL connections, you'll want to codesign +your build to avoid an issue with SSL connections failing the first time NSLogger is launched. + +If you are a member of the iOS Developer Program or Mac Developer Program, you already have +such an identity. If you need to create an identity for the sole purpose of signing your +builds, you can read Apple's Code Signing guide: + +http://developer.apple.com/library/mac/#documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html%23//apple_ref/doc/uid/TP40005929-CH4-SW1 + +You are not _required_ to codesign your build. If you don't, the first time you launch NSLogger +and the firewall is activated, incoming SSL connections will fail. You'll need to restart the +application once to get the authorization dialog allowing you to use the SSL certificate. diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Credits.rtf b/External Source/NSLogger/Desktop Viewer/Resources/Credits.rtf new file mode 100644 index 000000000..d009019ec --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/Credits.rtf @@ -0,0 +1,46 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1138 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red0\green0\blue255;} +\paperw12240\paperh15840\viewkind0 +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 + +\f0\b\fs26 \cf0 NSLogger +\b0 \ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 + +\fs22 \cf0 \ +A modern, flexible logging tool.\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/fpillet/NSLogger"}}{\fldrslt +\b \cf2 \ul \ulc2 https://github.com/fpillet/NSLogger}}\ +\ +Contributors:\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/fpillet"}}{\fldrslt +\b \cf0 Florent Pillet}} - NSLogger design, architecture, coding\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/seqoy"}}{\fldrslt +\b \cf0 Paulo Oliveira }}- Desktop Viewer UI improvements\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/gcerquant"}}{\fldrslt +\b \cf0 Guillaume Cerquant }}- Fixes and improvements to Desktop Viewer\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/aharren"}}{\fldrslt +\b \cf0 Arne Harren}} - LibComponentLogging-NSLogger backend, improvements\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/steipete"}}{\fldrslt +\b \cf0 Peter Steinberger}} - NSLogger-CocoaLumberjack backend\ +\pard\tx1440\tx2880\tx4320\tx5760\tx7200 +{\field{\*\fldinst{HYPERLINK "https://github.com/hotwick"}}{\fldrslt +\b \cf0 Dirk Holtwick}} - Found & prepared Louis Harboe's icon for use in NSLogger\ +\ +`Console' icon designed by {\field{\*\fldinst{HYPERLINK "http://graphicpeel.com"}}{\fldrslt +\b Louis Harboe}}, used with permission.\ +Document icons generated with {\field{\*\fldinst{HYPERLINK "http://code.google.com/p/docerator/"}}{\fldrslt Docerator}}\ +\ +License:\ +NSLogger is open source, {\field{\*\fldinst{HYPERLINK "http://www.opensource.org/licenses/bsd-license.php"}}{\fldrslt New BSD License}}.\ +\ +NSLogger is Copyright \'a9 2010-2011 {\field{\*\fldinst{HYPERLINK "mailto:fpillet@gmail.com"}}{\fldrslt Florent Pillet}}\ +All Rights Reserved, All Wrongs Revenged.\ +} \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/1290083967_Console.png b/External Source/NSLogger/Desktop Viewer/Resources/Icon/1290083967_Console.png new file mode 100644 index 000000000..95d82c999 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/1290083967_Console.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/Console icon | Icon Search Engine.webloc b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Console icon | Icon Search Engine.webloc new file mode 100644 index 000000000..98138de4d --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Console icon | Icon Search Engine.webloc @@ -0,0 +1,8 @@ + + + + + URL + http://www.iconfinder.com/icondetails/51889/128/console_icon + + diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/Export.png b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Export.png new file mode 100644 index 000000000..8233ea148 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Export.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/Icon.icns b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Icon.icns new file mode 100644 index 000000000..5c9488afe Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Icon.icns differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/Icon.opacity b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Icon.opacity new file mode 100644 index 000000000..a36fe8906 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Icon.opacity differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/Load.png b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Load.png new file mode 100755 index 000000000..c58705295 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Load.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/Save.png b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Save.png new file mode 100755 index 000000000..800827546 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/Save.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/logfile.icns b/External Source/NSLogger/Desktop Viewer/Resources/Icon/logfile.icns new file mode 100644 index 000000000..2b6836ced Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/logfile.icns differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/Icon/rawlogfile.icns b/External Source/NSLogger/Desktop Viewer/Resources/Icon/rawlogfile.icns new file mode 100644 index 000000000..d6797ab57 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/Icon/rawlogfile.icns differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/InfoPlist.strings b/External Source/NSLogger/Desktop Viewer/Resources/InfoPlist.strings new file mode 100644 index 000000000..5e45963c3 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/InfoPlist.strings differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/LoggerDetailsWindow.xib b/External Source/NSLogger/Desktop Viewer/Resources/LoggerDetailsWindow.xib new file mode 100644 index 000000000..1ff61d9e1 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/LoggerDetailsWindow.xib @@ -0,0 +1,463 @@ + + + + 1060 + 10K549 + 1864 + 1038.36 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1864 + + + NSView + NSTextField + NSScrollView + NSWindowTemplate + NSTextFieldCell + NSProgressIndicator + NSTextView + NSCustomView + NSScroller + NSCustomObject + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + LoggerDetailsWindowController + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{196, 40}, {490, 470}} + 544735232 + Details + NSWindow + + + + 256 + + + + 274 + + + + 2304 + + + + 2322 + {153, 14} + + + + + + + + + + + + + 6 + + + + 153 + 1 + + + 67111169 + 0 + + + 3 + MQA + + + + 6 + System + selectedTextBackgroundColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + selectedTextColor + + 3 + MAA + + + + + + + 1 + MCAwIDEAA + + + {8, -8} + 13 + + + + + + 7 + {482, 1e+07} + {153, 0} + + + + {475, 421} + + + + + 6 + System + controlBackgroundColor + + + + {4, 5} + + 12582912 + + + + + + TU0AKgAAAHCAFUqgBVKsAAAAwdVQUqwaEQeIRGJRGFlYqwWLQ+JxuOQpVRmEx2RROKwOQyOUQSPyaUym +SxqWyKXyeYxyZzWbSuJTScRCbz2Nz+gRKhUOfTqeUai0OSxiWTiBQSHSGFquGwekxyAgAAAOAQAAAwAA +AAEAEAAAAQEAAwAAAAEAEAAAAQIAAwAAAAIACAAIAQMAAwAAAAEABQAAAQYAAwAAAAEAAQAAAREABAAA +AAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAgAAARYAAwAAAAEAEAAAARcABAAAAAEAAABnARwAAwAA +AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA + + + + + + 3 + MCAwAA + + + + 4 + + + + 256 + {{475, 0}, {15, 421}} + + + _doScroller: + 1 + 0.85256409645080566 + + + + 256 + {{0, 421}, {475, 15}} + + 1 + + _doScroller: + 1 + 0.94565218687057495 + + + {{0, 34}, {490, 436}} + + + 48 + + + + + + + 268 + {{76, 7}, {46, 46}} + + BWAddRegularBottomBar + + + + 290 + {{17, 9}, {423, 17}} + + YES + + 68288064 + 272630784 + + + LucidaGrande + 13 + 1044 + + + + 6 + System + controlColor + + + + 6 + System + controlTextColor + + + + + + + -2147482335 + + {{445, 9}, {16, 16}} + + 20746 + 100 + + + {490, 470} + + + {{0, 0}, {1600, 1178}} + {1e+13, 1e+13} + DetailsWindow + + + + + + + window + + + + 7 + + + + detailsView + + + + 8 + + + + delegate + + + + 9 + + + + detailsInfo + + + + 14 + + + + progressIndicator + + + + 15 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + + + + + + 2 + + + + + + + + + + + 3 + + + + + + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 10 + + + + + 11 + + + + + + + + 12 + + + + + 13 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{28, 673}, {490, 470}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 15 + + + + + BWAddRegularBottomBar + NSView + + IBProjectSource + ./Classes/BWAddRegularBottomBar.h + + + + LoggerDetailsWindowController + NSWindowController + + NSTextField + NSTextView + NSProgressIndicator + + + + detailsInfo + NSTextField + + + detailsView + NSTextView + + + progressIndicator + NSProgressIndicator + + + + IBProjectSource + ./Classes/LoggerDetailsWindowController.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + diff --git a/External Source/NSLogger/Desktop Viewer/Resources/LoggerPrefs.xib b/External Source/NSLogger/Desktop Viewer/Resources/LoggerPrefs.xib new file mode 100644 index 000000000..8e4ab9e93 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/LoggerPrefs.xib @@ -0,0 +1,2341 @@ + + + + 1070 + 11A511 + 1617 + 1138 + 566.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1617 + + + NSObjectController + NSToolbar + NSNumberFormatter + NSToolbarFlexibleSpaceItem + NSButton + NSUserDefaultsController + NSTextFieldCell + NSButtonCell + NSColorWell + NSCustomView + NSCustomObject + NSView + NSWindowTemplate + NSTextField + NSToolbarItem + + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + LoggerPrefsWindowController + + + FirstResponder + + + NSApplication + + + 7 + 2 + {{599, 731}, {487, 209}} + 611845120 + Preferences + NSWindow + + + 5E22C339-8E3D-475D-AFF7-0EFED589CB07 + + + YES + YES + NO + NO + 1 + 1 + + + + B274BBA0-9382-4CDF-B829-D663C11BCB81 + + General + General + Show Network Panel + + + NSImage + NSPreferencesGeneral + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + + D1574EE7-78AE-41B6-9106-BBE2FA059C96 + + Fonts & Colors + Fonts & Colors + Show Fonts Panel + + + NSImage + ToolbarItemFonts + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + + DF654628-F7E4-43D8-943E-884B968CAF8F + + Network + Network + Show Network Panel + + + NSImage + NSNetwork + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + NSToolbarFlexibleSpaceItem + + Flexible Space + + + + + + {1, 5} + {20000, 32} + YES + YES + -1 + YES + 0 + + YES + YES + + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + + + + + + + + + + + + + + + + + + + + + 274 + {487, 209} + + + + + {{0, 0}, {1600, 1178}} + {10000000000000, 10000000000000} + + YES + + + + publishesBonjourService + bonjourServiceName + hasDirectTCPIPResponder + directTCPIPResponderPort + + YES + + + + + 268 + + + + 268 + {{377, 12}, {96, 32}} + + YES + + 67239424 + 134217728 + Apply + + LucidaGrande + 13 + 1044 + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + + 268 + {{233, 12}, {144, 32}} + + + YES + + 67239424 + 134217728 + Restore Defaults + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + + 268 + {{163, 127}, {307, 68}} + + + YES + + 67239424 + 272629760 + Choose a service name if there are multiple NSLogger instances on your network and you want your client to specifically direct traces to your computer. + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + disabledControlTextColor + + 3 + MC4zMzMzMzMzMzMzAA + + + + + + + 268 + {{166, 203}, {301, 22}} + + + YES + + -1804468671 + 272630784 + + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + + + + 268 + {{17, 205}, {144, 17}} + + + YES + + 68288064 + 272630784 + Bonjour service name: + + + + + 6 + System + controlTextColor + + + + + + + 268 + {{241, 87}, {76, 22}} + + + YES + + -1804468671 + 272630784 + + + + + + + + + + + + + + -∞ + + + #0 + +∞ + + #0 + #0000 + + + + + + + + NaN + + + + + + 3 + YES + YES + YES + + . + , + NO + NO + NO + + + YES + + + + + + + 268 + {{18, 89}, {217, 18}} + + + YES + + -2080244224 + 0 + Listen for loggers on TCP port: + + + 1211912703 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{18, 239}, {430, 18}} + + + YES + + -2080244224 + 0 + Publish Bonjour service for automatic discovery on local network + + + 1211912703 + 2 + + + + + 200 + 25 + + + + {487, 275} + + NSView + + + + 256 + + + + 290 + {{22, 129}, {506, 55}} + + + SampleMessageControl + + + + 290 + {{22, 59}, {506, 70}} + + + SampleMessageControl + + + + 268 + {{15, 357}, {87, 17}} + + + YES + + 68288064 + 71304192 + Time Stamp: + + LucidaGrande-Bold + 13 + 16 + + + + + + + + + 268 + {{19, 325}, {83, 17}} + + + YES + + 68288064 + 71304192 + Thread ID: + + + + + + + + + 268 + {{19, 293}, {83, 17}} + + + YES + + 68288064 + 71304192 + Tag/Level: + + + + + + + + + 268 + {{19, 261}, {83, 17}} + + + YES + + 68288064 + 71304192 + Text: + + + + + + + + + 268 + {{19, 229}, {83, 17}} + + + YES + + 68288064 + 71304192 + Data: + + + + + + + + + 266 + {{104, 357}, {256, 17}} + + + YES + + 67239488 + 272631808 + * + + + + + + + + + 266 + {{104, 325}, {256, 17}} + + + YES + + 67239488 + 272631808 + * + + + + + + + + + 266 + {{104, 293}, {256, 17}} + + + YES + + 67239488 + 272631808 + * + + + + + + + + + 266 + {{104, 261}, {256, 17}} + + + YES + + 67239488 + 272631808 + * + + + + + + + + + 266 + {{104, 229}, {256, 17}} + + + YES + + 67239488 + 272631808 + * + + + + + + + + + 265 + {{418, 347}, {116, 32}} + + + 1 + YES + + 67239424 + 134217728 + Select Font + + + -2038284033 + 129 + + + 200 + 25 + + + + + 265 + {{418, 315}, {116, 32}} + + + 2 + YES + + 67239424 + 134217728 + Select Font + + + -2038284033 + 129 + + + 200 + 25 + + + + + 265 + {{418, 283}, {116, 32}} + + + 3 + YES + + 67239424 + 134217728 + Select Font + + + -2038284033 + 129 + + + 200 + 25 + + + + + 265 + {{418, 251}, {116, 32}} + + + 4 + YES + + 67239424 + 134217728 + Select Font + + + -2038284033 + 129 + + + 200 + 25 + + + + + 265 + {{418, 219}, {116, 32}} + + + 5 + YES + + 67239424 + 134217728 + Select Font + + + -2038284033 + 129 + + + 200 + 25 + + + + + 268 + {{-3, 198}, {105, 17}} + + + YES + + 68288064 + 71304192 + File/Function: + + + + + + + + + 266 + {{104, 198}, {211, 17}} + + + YES + + 67239488 + 272631808 + * + + + + + + + + + 265 + {{418, 187}, {116, 32}} + + + 6 + YES + + 67239424 + 134217728 + Select Font + + + -2038284033 + 129 + + + 200 + 25 + + + + + 268 + + NSColor pasteboard type + + {{320, 193}, {44, 23}} + + + 7 + YES + YES + + 1 + MC4wNTgxMzA0OTg5OCAwLjA1NTU0MTg5OTA2IDEAA + + + + + 268 + + NSColor pasteboard type + + {{372, 193}, {44, 23}} + + + 6 + YES + YES + + + + + 268 + + NSColor pasteboard type + + {{372, 226}, {44, 23}} + + + 5 + YES + YES + + + + + 268 + + NSColor pasteboard type + + {{372, 258}, {44, 23}} + + + 4 + YES + YES + + + + + 268 + + NSColor pasteboard type + + {{372, 290}, {44, 23}} + + + 3 + YES + YES + + + + + 268 + + NSColor pasteboard type + + {{372, 322}, {44, 23}} + + + 2 + YES + YES + + + + + 268 + + NSColor pasteboard type + + {{372, 354}, {44, 23}} + + + 1 + YES + YES + + + + + 268 + {{438, 12}, {96, 32}} + + YES + + 67239424 + 134217728 + Apply + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + + 268 + {{294, 12}, {144, 32}} + + + YES + + 67239424 + 134217728 + Restore Defaults + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + {548, 397} + + + + + 268 + + + + 268 + {{18, 142}, {451, 49}} + + + YES + + -2080244224 + 0 + Keep previous run logs of same application + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 268 + {{37, 96}, {438, 56}} + + YES + + 67239424 + 272629760 + NSLogger will remember each run and let you access it from the Runs pop-up menu in the toolbar + + LucidaGrande + 13 + 16 + + + + + + + + {487, 209} + + + NSView + + + YES + + + + + + + selectFont: + + + + 301 + + + + selectColor: + + + + 302 + + + + selectColor: + + + + 303 + + + + selectColor: + + + + 304 + + + + selectFont: + + + + 305 + + + + selectFont: + + + + 306 + + + + selectColor: + + + + 307 + + + + selectFont: + + + + 308 + + + + selectColor: + + + + 309 + + + + selectFont: + + + + 310 + + + + selectColor: + + + + 311 + + + + selectColor: + + + + 312 + + + + selectFont: + + + + 313 + + + + timestampFontName + + + + 317 + + + + timestampForegroundColor + + + + 318 + + + + threadIDFontName + + + + 319 + + + + threadIDForegroundColor + + + + 320 + + + + textFontName + + + + 321 + + + + textForegroundColor + + + + 322 + + + + tagFontName + + + + 323 + + + + tagLevelForegroundColor + + + + 324 + + + + sampleMessage + + + + 325 + + + + sampleDataMessage + + + + 326 + + + + fileFunctionForegroundColor + + + + 327 + + + + fileFunctionBackgroundColor + + + + 328 + + + + fileFunctionFontName + + + + 329 + + + + dataForegroundColor + + + + 330 + + + + dataFontName + + + + 331 + + + + window + + + + 332 + + + + restoreFontDefaults: + + + + 365 + + + + applyFontChanges: + + + + 366 + + + + networkDefaultsController + + + + 385 + + + + contentObject: networkPrefs + + + + + + contentObject: networkPrefs + contentObject + networkPrefs + + NSValidatesImmediately + + + 2 + + + 386 + + + + delegate + + + + 392 + + + + value: selection.bonjourServiceName + + + + + + value: selection.bonjourServiceName + value + selection.bonjourServiceName + 2 + + + 415 + + + + value: selection.hasDirectTCPIPResponder + + + + + + value: selection.hasDirectTCPIPResponder + value + selection.hasDirectTCPIPResponder + 2 + + + 416 + + + + value: selection.publishesBonjourService + + + + + + value: selection.publishesBonjourService + value + selection.publishesBonjourService + 2 + + + 417 + + + + value: selection.directTCPIPResponderPort + + + + + + value: selection.directTCPIPResponderPort + value + selection.directTCPIPResponderPort + 2 + + + 418 + + + + enabled: selection.hasDirectTCPIPResponder + + + + + + enabled: selection.hasDirectTCPIPResponder + enabled + selection.hasDirectTCPIPResponder + 2 + + + 419 + + + + applyNetworkChanges: + + + + 420 + + + + restoreNetworkDefaults: + + + + 421 + + + + window + + + + 436 + + + + linkedView + + + + 438 + + + + linkedView + + + + 471 + + + + linkedView + + + + 472 + + + + value: values.keepMultipleRuns + + + + + + value: values.keepMultipleRuns + value + values.keepMultipleRuns + + NSValidatesImmediately + + + 2 + + + 478 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 222 + + + + + + + + + 223 + + + + + + 367 + + + Network Prefs Controller + + + 397 + + + + + + + + + + + + + Network Prefs Panel + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + + + + 401 + + + + + + + + 402 + + + + + + + + 403 + + + + + + + + 404 + + + + + + + + 405 + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 394 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Font Prefs Panel + + + 336 + + + + + + + + 335 + + + + + + + + 282 + + + + + 281 + + + + + 280 + + + + + 279 + + + + + 278 + + + + + 277 + + + + + 276 + + + + + 275 + + + + + + + + 274 + + + + + + + + 273 + + + + + + + + 272 + + + + + + + + 271 + + + + + + + + 270 + + + + + + + + 269 + + + + + + + + 268 + + + + + + + + 267 + + + + + + + + 266 + + + + + + + + 265 + + + + + + + + 264 + + + + + + + + 263 + + + + + + + + 262 + + + + + + + + 261 + + + + + + + + 260 + + + + + + + + 259 + + + + + + + + 258 + + + + + + + + 257 + + + + + 256 + + + + + 300 + + + + + 299 + + + + + 298 + + + + + 297 + + + + + 296 + + + + + 295 + + + + + 294 + + + + + 293 + + + + + 292 + + + + + 291 + + + + + 290 + + + + + 289 + + + + + 288 + + + + + 287 + + + + + 286 + + + + + 285 + + + + + 284 + + + + + 283 + + + + + 338 + + + + + 337 + + + + + 427 + + + + + + + + + + + 432 + + + + + 433 + + + + + 437 + + + + + 464 + + + + + + + General Prefs Panel + + + 465 + + + + + + Check Box + + + 466 + + + + + 467 + + + + + + + + 468 + + + + + 470 + + + + + 475 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{487, 780}, {487, 275}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + SSSelectableToolbar + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + SSSelectableToolbarItem + com.apple.InterfaceBuilder.CocoaPlugin + SSSelectableToolbarItem + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + SSSelectableToolbarItem + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 478 + + + + + LoggerPrefsWindowController + NSWindowController + + id + id + id + id + id + id + + + + applyFontChanges: + id + + + applyNetworkChanges: + id + + + restoreFontDefaults: + id + + + restoreNetworkDefaults: + id + + + selectColor: + id + + + selectFont: + id + + + + NSTextField + NSColorWell + NSColorWell + NSTextField + NSColorWell + NSObjectController + NSControl + NSControl + NSTextField + NSColorWell + NSTextField + NSColorWell + NSTextField + NSColorWell + NSTextField + NSColorWell + + + + dataFontName + NSTextField + + + dataForegroundColor + NSColorWell + + + fileFunctionBackgroundColor + NSColorWell + + + fileFunctionFontName + NSTextField + + + fileFunctionForegroundColor + NSColorWell + + + networkDefaultsController + NSObjectController + + + sampleDataMessage + NSControl + + + sampleMessage + NSControl + + + tagFontName + NSTextField + + + tagLevelForegroundColor + NSColorWell + + + textFontName + NSTextField + + + textForegroundColor + NSColorWell + + + threadIDFontName + NSTextField + + + threadIDForegroundColor + NSColorWell + + + timestampFontName + NSTextField + + + timestampForegroundColor + NSColorWell + + + + IBProjectSource + ./Classes/LoggerPrefsWindowController.h + + + + SSSelectableToolbar + NSToolbar + + window + NSWindow + + + window + + window + NSWindow + + + + IBProjectSource + ./Classes/SSSelectableToolbar.h + + + + SSSelectableToolbarItem + NSToolbarItem + + linkedView + NSView + + + linkedView + + linkedView + NSView + + + + IBProjectSource + ./Classes/SSSelectableToolbarItem.h + + + + SampleMessageControl + NSControl + + IBProjectSource + ./Classes/SampleMessageControl.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {9, 8} + {7, 2} + {32, 32} + {32, 32} + {15, 15} + {32, 32} + + + diff --git a/External Source/NSLogger/Desktop Viewer/Resources/LoggerStatus.xib b/External Source/NSLogger/Desktop Viewer/Resources/LoggerStatus.xib new file mode 100644 index 000000000..244d6c088 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/LoggerStatus.xib @@ -0,0 +1,349 @@ + + + + 1060 + 10K549 + 1864 + 1038.36 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1864 + + + NSView + NSTableView + NSScrollView + NSWindowTemplate + NSTextFieldCell + NSTableColumn + NSScroller + NSCustomObject + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + LoggerStatusWindowController + + + FirstResponder + + + NSApplication + + + 8217 + 2 + {{126, 724}, {414, 228}} + 611844096 + Logger Status + NSPanel + + {340, 130} + + + 274 + + + + 274 + + + + 2304 + + + + 274 + {416, 230} + + YES + + + -2147483392 + {{224, 0}, {16, 17}} + + + + 413 + 40 + 5000 + + 75628096 + 2048 + + + LucidaGrande + 11 + 3100 + + + 3 + MC4zMzMzMzI5ODU2AA + + + 6 + System + headerTextColor + + 3 + MAA + + + + + 337772096 + 2048 + Text Cell + + LucidaGrande + 13 + 1044 + + + + 3 + MSAwAA + + + 3 + MQA + + + 3 + YES + YES + + + + 3 + 2 + + 3 + MSAwAA + + + 3 + MSAwLjEyAA + + 40 + 37748736 + + + 2 + 5 + 15 + 0 + NO + 0 + + + {416, 230} + + + + + 3 + MSAwAA + + 2 + + + + -2147483392 + {{224, 17}, {15, 102}} + + + _doScroller: + 0.095652173913043467 + 0.99567097425460815 + + + + -2147483392 + {{1, 119}, {223, 15}} + + 1 + + _doScroller: + 0.12740384615384615 + 0.99284011125564575 + + + {{-1, -1}, {416, 230}} + + + 560 + + + + QSAAAEEgAABCKAAAQigAAA + + + {414, 228} + + + {{0, 0}, {1280, 778}} + {340, 149} + {1e+13, 1e+13} + loggerStatusWindow + + + + + + + window + + + + 16 + + + + statusTable + + + + 27 + + + + dataSource + + + + 28 + + + + delegate + + + + 29 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 6 + + + + + + + + 7 + + + + + + + + 18 + + + + + + + + + + 19 + + + + + 20 + + + + + 21 + + + + + + + + 23 + + + + + + + + 26 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{126, 724}, {414, 228}} + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 29 + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + diff --git a/External Source/NSLogger/Desktop Viewer/Resources/LoggerWindow.xib b/External Source/NSLogger/Desktop Viewer/Resources/LoggerWindow.xib new file mode 100644 index 000000000..ca8fa9cfa --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/LoggerWindow.xib @@ -0,0 +1,5648 @@ + + + + 1060 + 11D50 + 1938 + 1138.32 + 568.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1938 + + + NSTableHeaderView + NSMenu + NSToolbarItem + NSButton + NSToolbarFlexibleSpaceItem + NSCustomObject + NSArrayController + NSSplitView + NSPredicateEditor + NSTableView + NSCustomView + NSTextField + NSSearchField + NSPredicateEditorRowTemplate + NSToolbarSeparatorItem + NSSearchFieldCell + NSWindowTemplate + NSTextFieldCell + NSButtonCell + NSTableColumn + NSToolbarSpaceItem + NSView + NSPopUpButtonCell + NSScrollView + NSToolbar + NSUserDefaultsController + NSScroller + NSMenuItem + NSPopUpButton + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + LoggerWindowController + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{154, 384}, {885, 666}} + 1946157056 + NSLogger + NSWindow + + + 5DBD9D22-9164-4AF7-9E9B-5493625C1150 + + + YES + YES + YES + YES + 1 + 2 + + + + 1982BF4A-3218-428E-B152-FE3A19027668 + + Quick Search + Quick Search + Refine by filtering the current filter/tag/level settings on a search term + + + 268 + {{0, 14}, {117, 22}} + YES + + 343014976 + 268436544 + + + LucidaGrande + 13 + 1044 + + + YES + 1 + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + 130560 + 0 + search + + _searchFieldSearch: + + 138690815 + 0 + + 400 + 75 + + + 130560 + 0 + clear + + + cancel + + + + + _searchFieldCancel: + + 138690815 + 0 + + 400 + 75 + + 255 + + + + + + {96, 22} + {162, 22} + YES + YES + 0 + YES + 0 + + + + 6294782E-4A83-4551-9D6A-CC59FA9ABC83 + + Save + Save + Save this log file + + + NSImage + Save + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + + 7DE133D5-E674-4629-B2D2-B312C9263D42 + + Preferences + Preferences + Open the Preferences window + + + NSImage + NSAdvanced + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + + 9B2629AC-F52B-4881-AE8F-19A7A561CE6C + + Application Runs + Application Runs + + + + 268 + {{0, 14}, {100, 25}} + YES + + -2080244160 + 2048 + + + -2038284033 + 163 + + + 400 + 75 + + + Item 1 + + 1048576 + 2147483647 + 1 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + _popUpItemAction: + + + YES + + OtherViews + + + + + Item 2 + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Item 3 + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + -1 + 1 + YES + YES + 2 + + + + + + {100, 25} + {100, 25} + YES + YES + 0 + YES + 0 + + + + A2826872-EE4D-44ED-94BA-C345D69E3C78 + + Export + Export + Export this log file to text format + + + NSImage + Export + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + + C88273F1-A03E-4796-BE78-D3529CFE1C4C + + Open + Open + Open a log file + + + NSImage + Load + + + + {0, 0} + {0, 0} + YES + YES + -1 + YES + 0 + + + NSToolbarFlexibleSpaceItem + + Flexible Space + + + + + + {1, 5} + {20000, 32} + YES + YES + -1 + YES + 0 + + YES + YES + + + 1048576 + 2147483647 + + + + + + NSToolbarSeparatorItem + + Separator + + + + + + {12, 5} + {12, 1000} + YES + YES + -1 + YES + 0 + + YES + YES + + + 1048576 + 2147483647 + + + + + + NSToolbarSpaceItem + + Space + + + + + + {32, 5} + {32, 32} + YES + YES + -1 + YES + 0 + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {700, 500} + + + 256 + + + + 4370 + + + + 274 + + + + 274 + + + + 272 + + + + 274 + + + + 2304 + + + + 4352 + {221, 405} + + + + 2 + YES + + + 8448 + {221, 17} + + + + + + + + -2147483392 + {{-26, 0}, {16, 17}} + + + + filtersets + 218 + 40 + 1000 + + 75628096 + 2048 + Application Sets + + LucidaGrande + 11 + 3100 + + + 3 + MC4zMzMzMzI5ODU2AA + + + 6 + System + headerTextColor + + + + + 67239488 + 4200448 + Text Cell + + + + 6 + System + controlBackgroundColor + + 3 + MC42NjY2NjY2NjY3AA + + + + + 3 + YES + YES + + + + 3 + 2 + + 6 + System + _sourceListBackgroundColor + + 6 + System + alternateSelectedControlColor + + 1 + MCAwIDEAA + + + + + 6 + System + gridColor + + 3 + MC41AA + + + 20 + 37748736 + + + 5 + 15 + 0 + NO + 1 + 1 + 1 + + + {{0, 17}, {218, 405}} + + + + + + 4 + + + + -2147483392 + {{201, 17}, {15, 614}} + + + + + _doScroller: + 0.46957153231663029 + 0.99642854928970337 + + + + -2147483392 + {{-100, -100}, {200, 15}} + + + + YES + 1 + + _doScroller: + 0.96598637104034424 + + + + 2304 + + + + {218, 17} + + + + + + 4 + + + {{0, 24}, {218, 422}} + + + + 133776 + + + + + QSAAAEEgAABBsAAAQbAAAA + + + + 290 + + + + 268 + {{-1, -1}, {32, 24}} + + + + YES + + 67239424 + 134348800 + + + + -2033958657 + 163 + + NSImage + NSAddTemplate + + + + 200 + 25 + + + + + 268 + {{30, -1}, {32, 24}} + + + + YES + + 67239424 + 134348800 + + + + -2033434369 + 163 + + NSImage + NSRemoveTemplate + + + + 200 + 25 + + + + {218, 24} + + + + BWAnchoredButtonBar + + + {217, 446} + + + + NSView + + + + 272 + + + + 274 + + + + 2304 + + + + 4352 + {221, 173} + + + + 2 + YES + + + 8448 + {221, 17} + + + + + + + + -2147483392 + {{-26, 0}, {16, 17}} + + + + filters + 218 + 40 + 1000 + + 75628096 + 2048 + Filters + + + 3 + MC4zMzMzMzI5ODU2AA + + + + + 337772096 + 2048 + Text Cell + + + + + + 3 + YES + + + + 3 + 2 + + 6 + System + _sourceListBackgroundColor + + + + 20 + 171966464 + + + 5 + 15 + 0 + YES + 1 + 1 + 1 + + + {{0, 17}, {218, 173}} + + + + + + 4 + + + + -2147483392 + {{201, 17}, {15, 614}} + + + + + _doScroller: + 0.98051947355270386 + + + + -2147483392 + {{-100, -100}, {200, 15}} + + + + YES + 1 + + _doScroller: + 0.38532110091743121 + 0.96598637104034424 + + + + 2304 + + + + {218, 17} + + + + + + 4 + + + {{0, 1}, {218, 190}} + + + + 133776 + + + + + QSAAAEEgAABBsAAAQbAAAA + + + {{0, 455}, {217, 191}} + + + + NSView + + + {{0, 20}, {217, 646}} + + + + + + + 290 + + + + 268 + {{-1, -1}, {32, 24}} + + + + YES + + 67239424 + 134348800 + + + + 147079423 + 35 + + + + 200 + 25 + + + + + 268 + {{30, -1}, {32, 24}} + + + + YES + + 67239424 + 134348800 + + + + 147603711 + 35 + + + + 200 + 25 + + + + {217, 23} + + + + BWAnchoredButtonBar + + + {217, 673} + + + + NSView + + + + 274 + + + + 4386 + + + + 289 + {{486, -1}, {165, 23}} + + + + YES + + 71433792 + 134220032 + + LucidaGrande + 11 + 16 + + + -2036842241 + 164 + + + 400 + 75 + + + YES + + + 2147483647 + + + _popUpItemAction: + + + YES + + OtherViews + + + + + All Levels + = + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + 1 + Level 0 + 0 + 1048576 + 2147483647 + + + _popUpItemAction: + 1 + + + + + 1 + Level ≤ 1 + 1 + 1048576 + 2147483647 + + + _popUpItemAction: + 2 + + + + + 1 + Level ≤ 2 + 2 + 1048576 + 2147483647 + + + _popUpItemAction: + 3 + + + + + 1 + Level ≤ 3 + 3 + 1048576 + 2147483647 + + + _popUpItemAction: + 4 + + + + + 1 + Level ≤ 4 + 4 + 1048576 + 2147483647 + + + _popUpItemAction: + 5 + + + + + YES + YES + + + 2147483647 + + + _popUpItemAction: + -1 + + + + + All Tags + * + 1048576 + 2147483647 + + + _popUpItemAction: + -1 + + + + + + YES + 2 + YES + YES + 2 + + + + + 266 + {{63, 3}, {418, 14}} + + + + YES + + 67239488 + 272763392 + + + + + 1 + MSAxIDAuNDAwMDAwMDA2AA + + + + + + + 268 + {{30, -1}, {28, 24}} + + + + YES + + 68288064 + 134349824 + Æ’ + + LucidaGrande-Bold + 11 + 16 + + + -927710977 + 35 + + + 200 + 25 + + + + + 268 + {{-1, -1}, {32, 24}} + + + + YES + + -2076049856 + 134350848 + + LucidaGrande + 13 + 16 + + + -2038284033 + 163 + + + 400 + 75 + + + YES + + + 1048576 + 2147483647 + + NSImage + NSActionTemplate + + + + _popUpItemAction: + + + YES + + OtherViews + + + + + Open Details Window + i + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + YES + YES + + + 2147483647 + + + _popUpItemAction: + + + + + YES + Reset Quick Filter + + 2147483647 + + + _popUpItemAction: + + + + + YES + New Filter from Quick Filter + + 2147483647 + + + _popUpItemAction: + + + + + YES + YES + + + 2147483647 + + + _popUpItemAction: + + + + + YES + Clear Log + + 2147483647 + + + _popUpItemAction: + + + + + YES + Clear All Run Logs + + 2147483647 + + + _popUpItemAction: + + + + + YES + 1 + YES + YES + 2 + + + + {667, 23} + + + + BWAnchoredButtonBar + + + + 274 + + + + 2304 + + + + 4370 + {667, 644} + + + + YES + + + -2147483392 + {{652, 0}, {16, 17}} + + + + message + 664 + 200 + 10000 + + 75628096 + 2048 + + + + 3 + MC4zMzMzMzI5ODU2AA + + + + + 337772096 + 2048 + Text Cell + + + + + + 1 + YES + YES + + + + 3 + 2 + + 3 + MC45NzAwMDAwMjg2AA + + + 1 + MC45MzkyMzg1NDgzIDAuOTM5MjM4NTQ4MyAwLjkzOTIzODU0ODMAA + + 44 + 1514143744 + + + 5 + 15 + 0 + NO + 0 + 1 + + + {667, 644} + + + + + + 6 + + + + 256 + {{652, 0}, {15, 644}} + + + + + _doScroller: + 0.97981366459627328 + 0.9972299337387085 + + + + -2147483392 + {{-100, -100}, {650, 15}} + + + + 1 + + _doScroller: + 0.59969325153374209 + 0.95238101482391357 + + + {{0, 22}, {667, 644}} + + + + 133136 + + + + QSAAAEEgAABCOAAAQjgAAA + + + {{218, 0}, {667, 673}} + + + + NSView + + + {885, 673} + + + + YES + 2 + + + {885, 666} + + + + + {{0, 0}, {1600, 1178}} + {700, 569} + {10000000000000, 10000000000000} + YES + + + 265 + 2 + {{183, 289}, {480, 270}} + 1685586944 + Filter Editor + NSWindow + + + {400, 200} + + + 256 + + + + 274 + + + + 2304 + + + + 290 + + + + 274 + + + + 290 + + + + 257 + {{450, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + + + + LucidaGrande-Bold + 12 + 16 + + + + add + + + + + _addOption: + + -2038284033 + 36 + + LucidaGrande + 12 + 4883 + + + 400 + 75 + + + + + -2147483391 + {{430, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + - + + + + remove + + + + + _deleteOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 256 + {{7, 3}, {58, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + + -2038284033 + 36 + + + 400 + 75 + + + Any + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + All + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + None + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{71, 3}, {167, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + -2038284033 + 36 + + + 400 + 75 + + + of the following are true + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + YES + + + + + + + + 3 + YES + YES + 2 + + + + {478, 25} + + + 0 + 0 + + + + + + + 2 + {{7, 3}, {58, 19}} + {{71, 3}, {167, 19}} + + + + + 2 + 0 + 0 + 0 + 0 + + + + + NO + NO + + + + + + + + 2 + {{7, 3}, {58, 19}} + {{71, 3}, {167, 19}} + + + 0 + 0 + YES + + + + 290 + + + + 257 + {{450, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + + + + + + add + + + + + _addOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 257 + {{430, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + - + + + + remove + + + + + _deleteOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 256 + {{37, 3}, {113, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + 3 + valueForKey: + + 1 + + + + 10 + messageType + + + + + -2038284033 + 36 + + + 400 + 75 + + + Message Type + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{156, 3}, {67, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + + -2038284033 + 36 + + + 400 + 75 + + + is + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + is not + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{229, 3}, {155, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + 0 + text + + + -2038284033 + 36 + + + 400 + 75 + + + Text + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + Binary Data + + 1048576 + 2147483647 + + + _popUpItemAction: + + 0 + data + + + + + + Image + + 1048576 + 2147483647 + + + _popUpItemAction: + + 0 + img + + + + + + 3 + YES + YES + 2 + + + + {{0, 25}, {478, 25}} + + + 1 + 1 + + + + + + + + 3 + {{37, 3}, {113, 19}} + {{156, 3}, {67, 19}} + {{229, 3}, {155, 19}} + + + + + 1 + 0 + 0 + 0 + 0 + + + + + + NO + NO + + + + + + + + + + + + 3 + {{37, 3}, {113, 19}} + {{156, 3}, {67, 19}} + {{229, 3}, {155, 19}} + + + 0 + 0 + YES + + + + 290 + + + + 257 + {{450, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + + + + + + add + + + + + _addOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 257 + {{430, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + - + + + + remove + + + + + _deleteOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 256 + {{37, 3}, {79, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + 3 + valueForKey: + + + + 10 + messageText + + + + + -2038284033 + 36 + + + 400 + 75 + + + Message + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + Tag + + 1048576 + 2147483647 + + + _popUpItemAction: + + 3 + valueForKey: + + + + 10 + tag + + + + + + + + Thread Name + + 1048576 + 2147483647 + + + _popUpItemAction: + + 3 + valueForKey: + + + + 10 + threadID + + + + + + + + File Name + + 1048576 + 2147483647 + + + _popUpItemAction: + + 3 + valueForKey: + + + + 10 + filename + + + + + + + + Function / Method Name + + 1048576 + 2147483647 + + + _popUpItemAction: + + 3 + valueForKey: + + + + 10 + functionName + + + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{122, 3}, {99, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + + -2038284033 + 36 + + + 400 + 75 + + + contains + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + begins with + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + ends with + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is not + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + matches + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is like + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{227, 4}, {160, 18}} + + + YES + + 343014976 + 4326400 + + + + YES + + + + + + {{0, 50}, {478, 25}} + + + 2 + 1 + + + + + + + + 3 + {{37, 3}, {79, 19}} + {{122, 3}, {99, 19}} + {{227, 4}, {160, 18}} + + + + + 1 + 1 + 0 + 0 + 700 + + + + + + NO + YES + + + + + + + + + + + + 3 + {{37, 3}, {79, 19}} + {{122, 3}, {99, 19}} + {{227, 4}, {160, 18}} + + + 0 + 0 + YES + + + + 290 + + + + 257 + {{450, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + + + + + + add + + + + + _addOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 257 + {{430, 4}, {18, 18}} + + + -1 + YES + + 67239424 + 134348800 + - + + + + remove + + + + + _deleteOption: + + -2038284033 + 36 + + + 400 + 75 + + + + + 256 + {{37, 3}, {94, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + 3 + valueForKey: + + + + 10 + level + + + + + -2038284033 + 36 + + + 400 + 75 + + + Log Level + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + Line Number + + 1048576 + 2147483647 + + + _popUpItemAction: + + 3 + valueForKey: + + + + 10 + lineNumber + + + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{137, 3}, {99, 19}} + + + -1 + YES + + 67239488 + 4196352 + + + + -2038284033 + 36 + + + 400 + 75 + + + is + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + + YES + + + + + + + is not + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is greater than or equal to + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is less than or equal to + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is less than + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + is greater than + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + + 3 + YES + YES + 2 + + + + + 256 + {{242, 4}, {25, 18}} + + + YES + + 343014976 + 4326400 + + + + YES + + + + + + {{0, 75}, {478, 25}} + + + 3 + 1 + + + + + + + + 3 + {{37, 3}, {94, 19}} + {{137, 3}, {99, 19}} + {{242, 4}, {25, 18}} + + + + + 1 + 0 + 0 + 0 + 300 + + + + + + NO + YES + + + + + + + + + + + + 3 + {{37, 3}, {94, 19}} + {{137, 3}, {99, 19}} + {{242, 4}, {25, 18}} + + + 0 + 0 + YES + + + {{1, 1}, {478, 160}} + + + + + + NSRuleEditorItemPBoardType + + {480, 160} + + + YES + 75 + 25 + YES + NO + YES + 3 + rowType + subrows + criteria + displayValues + boundArray + NSMutableDictionary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{1, 1}, {480, 160}} + + + + + 3 + MC45MTAwMDAwMjYyAA + + 4 + + + + -2147483392 + {{466, 1}, {15, 146}} + + + _doScroller: + 0.97333335876464844 + + + + -2147483392 + {{-100, -100}, {360, 15}} + + 1 + + _doScroller: + + + {{-1, 60}, {482, 162}} + + + 133650 + + + + + + + 289 + {{370, 12}, {96, 32}} + + YES + + 67239424 + 134217728 + OK + + + -2038284033 + 129 + + DQ + 200 + 25 + + + + + 289 + {{274, 12}, {96, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + + 266 + {{102, 231}, {358, 22}} + + YES + + -1804468671 + 272630784 + + + filter name + + YES + + + 6 + System + textColor + + + + + + + 268 + {{17, 233}, {81, 17}} + + YES + + 68288064 + 272630784 + Filter Name: + + + + 6 + System + controlColor + + + + + + + {480, 270} + + + {{0, 0}, {1600, 1178}} + {400, 222} + {10000000000000, 10000000000000} + YES + + + 257 + 2 + {{183, 448}, {480, 111}} + 1685586944 + New Mark + NSWindow + + + + + 256 + + + + 266 + {{94, 72}, {366, 22}} + + + + YES + + -1804468671 + 272630784 + + + Mark title + + YES + + + + + + + 268 + {{17, 74}, {72, 17}} + + + + YES + + 68288064 + 272630784 + New mark: + + + + + + + + + 289 + {{370, 12}, {96, 32}} + + + + YES + + 67239424 + 134217728 + OK + + + -2038284033 + 129 + + DQ + 200 + 25 + + + + + 289 + {{269, 12}, {96, 32}} + + + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + {480, 111} + + + + + {{0, 0}, {1600, 1178}} + {10000000000000, 10000000000000} + YES + + + + filters + title + uid + + YES + + YES + YES + YES + YES + YES + YES + + + + title + predicate + uid + + YES + + YES + YES + YES + YES + YES + YES + + + YES + + + + + + + logTable + + + + 535 + + + + addFilter: + + + + 701 + + + + filterListController + + + + 702 + + + + window + + + + 813 + + + + filterEditorWindow + + + + 814 + + + + filterEditor + + + + 815 + + + + validateFilterEdition: + + + + 816 + + + + cancelFilterEdition: + + + + 817 + + + + filterName + + + + 818 + + + + filterTable + + + + 893 + + + + quickFilter + + + + 912 + + + + selectQuickFilterLevel: + + + + 916 + + + + selectQuickFilterLevel: + + + + 917 + + + + selectQuickFilterLevel: + + + + 918 + + + + selectQuickFilterLevel: + + + + 919 + + + + selectQuickFilterLevel: + + + + 920 + + + + selectQuickFilterLevel: + + + + 921 + + + + deleteSelectedFilters: + + + + 926 + + + + buttonBar + + + + 934 + + + + selectQuickFilterLevel: + + + + 937 + + + + selectQuickFilterTag: + + + + 940 + + + + filterSetsTable + + + + 972 + + + + filterSetsListController + + + + 973 + + + + addFilterSet: + + + + 974 + + + + deleteSelectedFilterSet: + + + + 975 + + + + resetQuickFilter: + + + + 1099 + + + + openDetailsWindow: + + + + 1100 + + + + markTitleWindow + + + + 1160 + + + + markTitleField + + + + 1161 + + + + validateAddMark: + + + + 1162 + + + + cancelAddMark: + + + + 1163 + + + + showFunctionNamesButton + + + + 1221 + + + + createNewFilterFromQuickFilter: + + + + 1248 + + + + quickFilterTextField + + + + 1301 + + + + clearAllLogs: + + + + 1442 + + + + clearCurrentLog: + + + + 1443 + + + + splitView + + + + 1444 + + + + showPreferences: + + + + 1311 + + + + openDocument: + + + + 1328 + + + + saveDocument: + + + + 1329 + + + + saveDocumentTo: + + + + 1331 + + + + delegate + + + + 913 + + + + delegate + + + + 935 + + + + dataSource + + + + 998 + + + + value: arrangedObjects.title + + + + + + value: arrangedObjects.title + value + arrangedObjects.title + + + + + 2 + + + 981 + + + + headerTitle: selection.title + + + + + + headerTitle: selection.title + headerTitle + selection.title + + No Selection + No Selection + FilterColumnHeader + + 2 + + + 1191 + + + + dataSource + + + + 941 + + + + delegate + + + + 942 + + + + value: info + + + + + + value: info + value + info + + NSNullPlaceholder + Logs from unidentified source + + 2 + + + 859 + + + + enabled: selectedObjects + + + + + + enabled: selectedObjects + enabled + selectedObjects + + + + + CanDeleteFilterSelection + + 2 + + + 985 + + + + sortDescriptors: delegate.filtersSortDescriptors + + + + + + sortDescriptors: delegate.filtersSortDescriptors + sortDescriptors + delegate.filtersSortDescriptors + 2 + + + 990 + + + + contentArray: selection.filters + + + + + + contentArray: selection.filters + contentArray + selection.filters + 2 + + + 996 + + + + selectedIndex: logLevel + + + + + + selectedIndex: logLevel + selectedIndex + logLevel + + + + + + 2 + + + 901 + + + + enabled: selectedObjects + + + + + + enabled: selectedObjects + enabled + selectedObjects + + + + + CanDeleteFilterSelection + + 2 + + + 976 + + + + delegate + + + + 971 + + + + dataSource + + + + 997 + + + + value: arrangedObjects.title + + + + + + value: arrangedObjects.title + value + arrangedObjects.title + + + + + 2 + + + 980 + + + + contentArray: delegate.filterSets + + + + + + contentArray: delegate.filterSets + contentArray + delegate.filterSets + 2 + + + 969 + + + + sortDescriptors: delegate.filtersSortDescriptors + + + + + + sortDescriptors: delegate.filtersSortDescriptors + sortDescriptors + delegate.filtersSortDescriptors + 2 + + + 983 + + + + enabled: hasQuickFilter + + + + + + enabled: hasQuickFilter + enabled + hasQuickFilter + 2 + + + 1098 + + + + value: showFunctionNames + + + + + + value: showFunctionNames + value + showFunctionNames + + + + + + + 2 + + + 1239 + + + + enabled: hasQuickFilter + + + + + + enabled: hasQuickFilter + enabled + hasQuickFilter + 2 + + + 1247 + + + + value: filterString + + + + + + value: filterString + value + filterString + + + + + + + 2 + + + 1308 + + + + contentValues: document.attachedLogsPopupNames + + + + + + contentValues: document.attachedLogsPopupNames + contentValues + document.attachedLogsPopupNames + 2 + + + 1419 + + + + selectedIndex: document.indexOfCurrentVisibleLog + + + + + + selectedIndex: document.indexOfCurrentVisibleLog + selectedIndex + document.indexOfCurrentVisibleLog + + + + + + + 2 + + + 1424 + + + + enabled: shouldEnableRunsPopup + + + + + + enabled: shouldEnableRunsPopup + enabled + shouldEnableRunsPopup + 2 + + + 1430 + + + + enabled: canClearCurrentLog + + + + + + enabled: canClearCurrentLog + enabled + canClearCurrentLog + 2 + + + 1439 + + + + enabled: canClearAllLogs + + + + + + enabled: canClearAllLogs + enabled + canClearAllLogs + 2 + + + 1441 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 371 + + + + + + + + + 372 + + + + + + + + 455 + + + + + + + + + 456 + + + + + + + + + 457 + + + + + + + + + 532 + + + Filter Array Controller + + + 493 + + + + + + + + + + + 488 + + + + + + + + 489 + + + + + 458 + + + + + + + + + 510 + + + + + + + + 511 + + + + + 508 + + + + + + + + 509 + + + + + 586 + + + + + + Sheet (Filter Editor) + + + 587 + + + + + + + + + + + + 588 + + + + + + + + + + 589 + + + + + 590 + + + + + 591 + + + + + + + + + + + 592 + + + + + + + + + 593 + + + + + + + + + + 594 + + + + + + + + 595 + + + + + + + + + 599 + + + + + 600 + + + + + 604 + + + + + + + + + + 605 + + + + + + + + 606 + + + + + 607 + + + + + 608 + + + + + 609 + + + + + + + + 610 + + + + + 611 + + + + + + + + 612 + + + + + 613 + + + + + 617 + + + + + 688 + + + + + + + + 689 + + + + + 690 + + + + + + + + 691 + + + + + 819 + + + + + + + + + 820 + + + + + + + + + + + + 824 + + + + + + + + + + + + + + 825 + + + + + 826 + + + + + 827 + + + + + 828 + + + + + 829 + + + + + 830 + + + + + 831 + + + + + 854 + + + + + + + + + + 855 + + + + + 856 + + + + + 857 + + + + + 860 + + + + + + + + + 861 + + + + + + + + + 865 + + + + + + + + + + + + + 869 + + + + + 870 + + + + + 875 + + + + + 876 + + + + + 877 + + + + + 878 + + + + + 894 + + + + + + + + 895 + + + + + + + + 896 + + + + + + + + + + + + + + + + 900 + + + + + 908 + + + + + 909 + + + + + 910 + + + + + 911 + + + + + 914 + + + + + 915 + + + + + 477 + + + + + + + + + + 478 + + + + + 479 + + + + + 480 + + + + + + + + 482 + + + + + + + + 485 + + + + + 936 + + + + + 938 + + + + + 943 + + + + + + + + + 944 + + + + + + + + + 945 + + + + + + + + 468 + + + + + + + + + + + 469 + + + + + 470 + + + + + 471 + + + + + + + + 472 + + + + + 473 + + + + + + + + 476 + + + + + 946 + + + + + + + + + 947 + + + + + + + + 948 + + + + + + + + 949 + + + + + 950 + + + + + 954 + + + + + + + + + + + 955 + + + + + 956 + + + + + + + + 957 + + + + + 958 + + + + + 959 + + + + + + + + 960 + + + + + 963 + + + Filter Sets Array Controller + + + 1090 + + + + + + + + 1091 + + + + + + + + 1092 + + + + + + + + + + + + + + + 1095 + + + + + 1094 + + + + + 1093 + + + + + 1104 + + + + + + Sheet (Add Mark) + + + 1105 + + + + + + + + + + + 1107 + + + + + + + + 1108 + + + + + + + + 1109 + + + + + + + + 1110 + + + + + + + + 1111 + + + + + 1112 + + + + + 1113 + + + + + 1114 + + + + + 1206 + + + + + + + + 1207 + + + + + 1229 + + + + + 1230 + + + + + 1231 + + + + + 1232 + + + + + 1233 + + + + + 1234 + + + + + 1235 + + + + + 1245 + + + + + 1270 + + + + + + + + + + + + + + + + 1273 + + + + + 1275 + + + + + 1276 + + + + + 1300 + + + + + + + + 1298 + + + + + + + + 1299 + + + + + 1309 + + + + + 1324 + + + + + 1325 + + + + + 1330 + + + + + 1416 + + + + + + + + 1410 + + + + + + + + 1411 + + + + + + + + 1412 + + + + + + + + + + 1415 + + + + + 1414 + + + + + 1413 + + + + + 1426 + + + + + 1432 + + + + + 1433 + + + + + 1434 + + + + + 1435 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredPopUpButton + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredPopUpButtonCell + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{25, 380}, {480, 111}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButton + + ToolTip + + ToolTip + + Show / Hide file, line and function names + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButtonCell + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + LoggerWindowToolbar + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{139, 145}, {885, 666}} + + com.apple.InterfaceBuilder.CocoaPlugin + LoggerSplitView + + IBUserDefinedRuntimeAttributesPlaceholderName + + IBUserDefinedRuntimeAttributesPlaceholderName + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + colorIsEnabled + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + dividerCanCollapse + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + collapsiblePopupSelection + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + IBUserDefinedRuntimeAttributesPlaceholderName + + IBUserDefinedRuntimeAttributesPlaceholderName + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + selectedIndex + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Select one or more items to filter log messages + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + LoggerTableView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Number of messages displayed + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + IBUserDefinedRuntimeAttributesPlaceholderName + + IBUserDefinedRuntimeAttributesPlaceholderName + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + selectedIndex + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButton + + ToolTip + + ToolTip + + Add a new filter + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButtonCell + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButton + + ToolTip + + ToolTip + + Delete selected filter + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButtonCell + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{196, 223}, {480, 270}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Refine filter to display only messages with the selected level and/or tag + + + com.apple.InterfaceBuilder.CocoaPlugin + + + 1 + MC41MTYzMDQzNDc4IDAuNTE2MzA0MzQ3OCAwLjUxNjMwNDM0NzgAA + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + BWSplitView + + IBUserDefinedRuntimeAttributesPlaceholderName + + IBUserDefinedRuntimeAttributesPlaceholderName + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + colorIsEnabled + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + dividerCanCollapse + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + collapsiblePopupSelection + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + IBUserDefinedRuntimeAttributesPlaceholderName + + IBUserDefinedRuntimeAttributesPlaceholderName + + + + com.apple.InterfaceBuilder.userDefinedRuntimeAttributeType.number + selectedIndex + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButton + + ToolTip + + ToolTip + + Add a new filter set + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButton + + ToolTip + + ToolTip + + Delete selected filter set + + + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButtonCell + com.apple.InterfaceBuilder.CocoaPlugin + BWAnchoredButtonCell + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 1444 + + + + + BWAnchoredButton + NSButton + + IBProjectSource + ./Classes/BWAnchoredButton.h + + + + BWAnchoredButtonBar + NSView + + IBProjectSource + ./Classes/BWAnchoredButtonBar.h + + + + BWAnchoredButtonCell + NSButtonCell + + IBProjectSource + ./Classes/BWAnchoredButtonCell.h + + + + BWAnchoredPopUpButton + NSPopUpButton + + IBProjectSource + ./Classes/BWAnchoredPopUpButton.h + + + + BWAnchoredPopUpButtonCell + NSPopUpButtonCell + + IBProjectSource + ./Classes/BWAnchoredPopUpButtonCell.h + + + + BWSplitView + NSSplitView + + toggleCollapse: + id + + + toggleCollapse: + + toggleCollapse: + id + + + + IBProjectSource + ./Classes/BWSplitView.h + + + + LoggerAppDelegate + NSObject + + showPreferences: + id + + + showPreferences: + + showPreferences: + id + + + + IBProjectSource + ./Classes/LoggerAppDelegate.h + + + + LoggerSplitView + BWSplitView + + IBProjectSource + ./Classes/LoggerSplitView.h + + + + LoggerTableView + NSTableView + + IBProjectSource + ./Classes/LoggerTableView.h + + + + LoggerWindowController + NSWindowController + + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + addFilter: + id + + + addFilterSet: + id + + + addMark: + id + + + addMarkWithTitle: + id + + + cancelAddMark: + id + + + cancelFilterEdition: + id + + + clearAllLogs: + id + + + clearCurrentLog: + id + + + collapseTaskbar: + id + + + createNewFilterFromQuickFilter: + id + + + deleteMark: + id + + + deleteSelectedFilterSet: + id + + + deleteSelectedFilters: + id + + + insertMarkWithTitle: + id + + + openDetailsWindow: + id + + + resetQuickFilter: + id + + + selectQuickFilterLevel: + id + + + selectQuickFilterTag: + id + + + startEditingFilter: + id + + + validateAddMark: + id + + + validateFilterEdition: + id + + + + BWAnchoredButtonBar + NSPredicateEditor + NSWindow + NSArrayController + NSTextField + NSArrayController + NSTableView + NSTableView + LoggerTableView + NSTextField + NSWindow + NSPopUpButton + NSSearchField + NSButton + LoggerSplitView + + + + buttonBar + BWAnchoredButtonBar + + + filterEditor + NSPredicateEditor + + + filterEditorWindow + NSWindow + + + filterListController + NSArrayController + + + filterName + NSTextField + + + filterSetsListController + NSArrayController + + + filterSetsTable + NSTableView + + + filterTable + NSTableView + + + logTable + LoggerTableView + + + markTitleField + NSTextField + + + markTitleWindow + NSWindow + + + quickFilter + NSPopUpButton + + + quickFilterTextField + NSSearchField + + + showFunctionNamesButton + NSButton + + + splitView + LoggerSplitView + + + + IBProjectSource + ./Classes/LoggerWindowController.h + + + + NSDocument + + id + id + id + id + id + id + + + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + IBProjectSource + ./Classes/NSDocument.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {32, 32} + {48, 48} + {15, 15} + {8, 8} + {32, 32} + {11, 11} + {10, 3} + {8, 8} + {48, 48} + + + diff --git a/External Source/NSLogger/Desktop Viewer/Resources/MainMenu.xib b/External Source/NSLogger/Desktop Viewer/Resources/MainMenu.xib new file mode 100644 index 000000000..d8074e384 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/MainMenu.xib @@ -0,0 +1,2632 @@ + + + + 1050 + 11D50 + 1938 + 1138.32 + 568.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1938 + + + YES + NSMenu + NSMenuItem + NSCustomObject + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + NSLogger + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + NSLogger + + YES + + + About NSLogger + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide NSLogger + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit NSLogger + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Export... + + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling… + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + 2 + + View + + YES + + + View Run Log + + 2147483647 + + + submenuAction: + 6 + + View Run Log + + YES + + + YES + No Run Log + + 2147483647 + + + + + + + + + Clear Log + R + 1048576 + 2147483647 + + + + + + Clear All Run Logs + R + 524288 + 2147483647 + + + + + + Hide Taskbar + 1 + 1310720 + 2147483647 + + + 7 + + + + YES + YES + + + 2147483647 + + + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Tools + + 1048576 + 2147483647 + + + submenuAction: + 1 + + Tools + + YES + + + Add Mark At End + m + 1048576 + 2147483647 + + + 1 + + + + Add Mark With Title... + M + 1048576 + 2147483647 + + + 2 + + + + Insert Mark Before Selection... + M + 1572864 + 2147483647 + + + 3 + + + + Delete Mark + + 1048576 + 2147483647 + + + 4 + + + + Jump + + 1048576 + 2147483647 + + + submenuAction: + 5 + + Jump + + YES + + + YES + No Mark + + 2147483647 + + + + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + NSLogger Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + NSFontManager + + + LoggerAppDelegate + + + + + YES + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 451 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + openDocument: + + + + 374 + + + + saveDocumentTo: + + + + 547 + + + + addMark: + + + + 599 + + + + addMarkWithTitle: + + + + 600 + + + + insertMarkWithTitle: + + + + 601 + + + + deleteMark: + + + + 603 + + + + clearCurrentLog + + + + 612 + + + + clearAllLogs + + + + 613 + + + + collapseTaskbar: + + + + 615 + + + + showPreferences: + + + + 544 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 420 + + + + + 450 + + + + + 545 + + + 8 + + + 548 + + + YES + + + + + + 549 + + + YES + + + + + + + + + + 553 + + + YES + + + + + + 556 + + + + + 557 + + + + + 558 + + + + + 562 + + + + + 563 + + + YES + + + + + + 602 + + + + + 605 + + + + + 606 + + + YES + + + + + + 607 + + + YES + + + + + + 609 + + + + + 610 + + + + + 611 + + + + + 614 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 106.IBPluginDependency + 111.IBPluginDependency + 112.IBPluginDependency + 124.IBPluginDependency + 125.IBPluginDependency + 126.IBPluginDependency + 129.IBPluginDependency + 130.IBPluginDependency + 131.IBPluginDependency + 134.IBPluginDependency + 136.IBPluginDependency + 143.IBPluginDependency + 144.IBPluginDependency + 145.IBPluginDependency + 149.IBPluginDependency + 150.IBPluginDependency + 19.IBPluginDependency + 195.IBPluginDependency + 196.IBPluginDependency + 197.IBPluginDependency + 198.IBPluginDependency + 199.IBPluginDependency + 200.IBPluginDependency + 201.IBPluginDependency + 202.IBPluginDependency + 203.IBPluginDependency + 204.IBPluginDependency + 205.IBPluginDependency + 206.IBPluginDependency + 207.IBPluginDependency + 208.IBPluginDependency + 209.IBPluginDependency + 210.IBPluginDependency + 211.IBPluginDependency + 212.IBPluginDependency + 213.IBPluginDependency + 214.IBPluginDependency + 215.IBPluginDependency + 216.IBPluginDependency + 217.IBPluginDependency + 218.IBPluginDependency + 219.IBPluginDependency + 220.IBPluginDependency + 221.IBPluginDependency + 23.IBPluginDependency + 236.IBPluginDependency + 239.IBPluginDependency + 24.IBPluginDependency + 29.IBPluginDependency + 295.IBPluginDependency + 296.IBPluginDependency + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 348.IBPluginDependency + 349.IBPluginDependency + 350.IBPluginDependency + 351.IBPluginDependency + 354.IBPluginDependency + 420.IBPluginDependency + 450.IBPluginDependency + 5.IBPluginDependency + 545.IBPluginDependency + 548.IBPluginDependency + 549.IBPluginDependency + 553.IBPluginDependency + 556.IBPluginDependency + 557.IBPluginDependency + 558.IBPluginDependency + 56.IBPluginDependency + 562.IBPluginDependency + 563.IBPluginDependency + 57.IBPluginDependency + 58.IBPluginDependency + 602.IBPluginDependency + 605.IBPluginDependency + 606.IBPluginDependency + 607.IBPluginDependency + 609.IBPluginDependency + 610.IBPluginDependency + 611.IBPluginDependency + 614.IBPluginDependency + 72.IBPluginDependency + 73.IBPluginDependency + 74.IBPluginDependency + 75.IBPluginDependency + 77.IBPluginDependency + 78.IBPluginDependency + 79.IBPluginDependency + 80.IBPluginDependency + 81.IBPluginDependency + 83.IBPluginDependency + 92.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + + + + YES + + + + + 615 + + + + YES + + BWAnchoredButtonBar + NSView + + IBProjectSource + ./Classes/BWAnchoredButtonBar.h + + + + BWSplitView + NSSplitView + + toggleCollapse: + id + + + toggleCollapse: + + toggleCollapse: + id + + + + IBProjectSource + ./Classes/BWSplitView.h + + + + LoggerAppDelegate + NSObject + + showPreferences: + id + + + showPreferences: + + showPreferences: + id + + + + IBProjectSource + ./Classes/LoggerAppDelegate.h + + + + LoggerSplitView + BWSplitView + + IBProjectSource + ./Classes/LoggerSplitView.h + + + + LoggerTableView + NSTableView + + IBProjectSource + ./Classes/LoggerTableView.h + + + + LoggerWindowController + NSWindowController + + YES + + YES + addFilter: + addFilterSet: + addMark: + addMarkWithTitle: + cancelAddMark: + cancelFilterEdition: + clearAllLogs: + clearCurrentLog: + collapseTaskbar: + createNewFilterFromQuickFilter: + deleteMark: + deleteSelectedFilterSet: + deleteSelectedFilters: + insertMarkWithTitle: + openDetailsWindow: + resetQuickFilter: + selectQuickFilterLevel: + selectQuickFilterTag: + startEditingFilter: + validateAddMark: + validateFilterEdition: + + + YES + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + addFilter: + addFilterSet: + addMark: + addMarkWithTitle: + cancelAddMark: + cancelFilterEdition: + clearAllLogs: + clearCurrentLog: + collapseTaskbar: + createNewFilterFromQuickFilter: + deleteMark: + deleteSelectedFilterSet: + deleteSelectedFilters: + insertMarkWithTitle: + openDetailsWindow: + resetQuickFilter: + selectQuickFilterLevel: + selectQuickFilterTag: + startEditingFilter: + validateAddMark: + validateFilterEdition: + + + YES + + addFilter: + id + + + addFilterSet: + id + + + addMark: + id + + + addMarkWithTitle: + id + + + cancelAddMark: + id + + + cancelFilterEdition: + id + + + clearAllLogs: + id + + + clearCurrentLog: + id + + + collapseTaskbar: + id + + + createNewFilterFromQuickFilter: + id + + + deleteMark: + id + + + deleteSelectedFilterSet: + id + + + deleteSelectedFilters: + id + + + insertMarkWithTitle: + id + + + openDetailsWindow: + id + + + resetQuickFilter: + id + + + selectQuickFilterLevel: + id + + + selectQuickFilterTag: + id + + + startEditingFilter: + id + + + validateAddMark: + id + + + validateFilterEdition: + id + + + + + YES + + YES + buttonBar + filterEditor + filterEditorWindow + filterListController + filterName + filterSetsListController + filterSetsTable + filterTable + logTable + markTitleField + markTitleWindow + quickFilter + quickFilterTextField + showFunctionNamesButton + splitView + + + YES + BWAnchoredButtonBar + NSPredicateEditor + NSWindow + NSArrayController + NSTextField + NSArrayController + NSTableView + NSTableView + LoggerTableView + NSTextField + NSWindow + NSPopUpButton + NSSearchField + NSButton + LoggerSplitView + + + + YES + + YES + buttonBar + filterEditor + filterEditorWindow + filterListController + filterName + filterSetsListController + filterSetsTable + filterTable + logTable + markTitleField + markTitleWindow + quickFilter + quickFilterTextField + showFunctionNamesButton + splitView + + + YES + + buttonBar + BWAnchoredButtonBar + + + filterEditor + NSPredicateEditor + + + filterEditorWindow + NSWindow + + + filterListController + NSArrayController + + + filterName + NSTextField + + + filterSetsListController + NSArrayController + + + filterSetsTable + NSTableView + + + filterTable + NSTableView + + + logTable + LoggerTableView + + + markTitleField + NSTextField + + + markTitleWindow + NSWindow + + + quickFilter + NSPopUpButton + + + quickFilterTextField + NSSearchField + + + showFunctionNamesButton + NSButton + + + splitView + LoggerSplitView + + + + + IBProjectSource + ./Classes/LoggerWindowController.h + + + + NSDocument + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + + IBProjectSource + ./Classes/NSDocument.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {11, 11} + {10, 3} + + + + diff --git a/External Source/NSLogger/Desktop Viewer/Resources/NSLoggerCertReq.conf b/External Source/NSLogger/Desktop Viewer/Resources/NSLoggerCertReq.conf new file mode 100644 index 000000000..5f48a5820 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Resources/NSLoggerCertReq.conf @@ -0,0 +1,11 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +[ req_distinguished_name ] +C = FR +ST = NA +L = NA +O = NSLogger +OU = Open Source +CN = NSLogger SSL +emailAddress = fpillet@gmail.com diff --git a/External Source/NSLogger/Desktop Viewer/Resources/ssl_badge.png b/External Source/NSLogger/Desktop Viewer/Resources/ssl_badge.png new file mode 100644 index 000000000..f54b37737 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/ssl_badge.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/status_disconnected.png b/External Source/NSLogger/Desktop Viewer/Resources/status_disconnected.png new file mode 100644 index 000000000..bf06ce7cb Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/status_disconnected.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/status_error.png b/External Source/NSLogger/Desktop Viewer/Resources/status_error.png new file mode 100644 index 000000000..d92a517ca Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/status_error.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Resources/status_ready_connected.png b/External Source/NSLogger/Desktop Viewer/Resources/status_ready_connected.png new file mode 100644 index 000000000..e70f66f69 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Resources/status_ready_connected.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/.hgignore b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/.hgignore new file mode 100644 index 000000000..7514c6fac --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/.hgignore @@ -0,0 +1,9 @@ +syntax: glob + +*.pbxuser +*.mode1 +*.mode1v3 +*~.nib +*~ +*.orig +.DS_Store diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddMiniBottomBar.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddMiniBottomBar.h new file mode 100644 index 000000000..0e1683ecd --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddMiniBottomBar.h @@ -0,0 +1,16 @@ +// +// BWAddMiniBottomBar.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAddMiniBottomBar : NSView +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddMiniBottomBar.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddMiniBottomBar.m new file mode 100644 index 000000000..a25af1a5b --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddMiniBottomBar.m @@ -0,0 +1,51 @@ +// +// BWAddMiniBottomBar.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAddMiniBottomBar.h" +//#import "NSWindow-NSTimeMachineSupport.h" + +@interface NSWindow (BWBBPrivate) +- (void)setBottomCornerRounded:(BOOL)flag; +@end + +@implementation BWAddMiniBottomBar + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + } + return self; +} + +- (void)awakeFromNib +{ + [[self window] setContentBorderThickness:16 forEdge:NSMinYEdge]; + + // Private method + if ([[self window] respondsToSelector:@selector(setBottomCornerRounded:)]) + [[self window] setBottomCornerRounded:NO]; +} + +- (void)drawRect:(NSRect)aRect +{ + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] && [[self window] contentBorderThicknessForEdge:NSMinYEdge] == 0) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + + if ([[self window] isSheet] && [[self window] respondsToSelector:@selector(setMovable:)]) + [[self window] setMovable:NO]; +} + +- (NSRect)bounds +{ + return NSMakeRect(-10000,-10000,0,0); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddRegularBottomBar.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddRegularBottomBar.h new file mode 100644 index 000000000..e042df9cc --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddRegularBottomBar.h @@ -0,0 +1,16 @@ +// +// BWAddRegularBottomBar.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAddRegularBottomBar : NSView +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddRegularBottomBar.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddRegularBottomBar.m new file mode 100644 index 000000000..b0acaf266 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddRegularBottomBar.m @@ -0,0 +1,43 @@ +// +// BWAddRegularBottomBar.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAddRegularBottomBar.h" +//#import "NSWindow-NSTimeMachineSupport.h" + +@implementation BWAddRegularBottomBar + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + } + return self; +} + +- (void)awakeFromNib +{ + [[self window] setContentBorderThickness:34 forEdge:NSMinYEdge]; +} + +- (void)drawRect:(NSRect)aRect +{ + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] && [[self window] contentBorderThicknessForEdge:NSMinYEdge] == 0) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + + if ([[self window] isSheet] && [[self window] respondsToSelector:@selector(setMovable:)]) + [[self window] setMovable:NO]; +} + +- (NSRect)bounds +{ + return NSMakeRect(-10000,-10000,0,0); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSheetBottomBar.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSheetBottomBar.h new file mode 100644 index 000000000..9ef90ea07 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSheetBottomBar.h @@ -0,0 +1,16 @@ +// +// BWAddSheetBottomBar.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAddSheetBottomBar : NSView +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSheetBottomBar.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSheetBottomBar.m new file mode 100644 index 000000000..274a6c5bd --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSheetBottomBar.m @@ -0,0 +1,51 @@ +// +// BWAddSheetBottomBar.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAddSheetBottomBar.h" +//#import "NSWindow-NSTimeMachineSupport.h" + +@interface NSWindow (BWPrivate) +- (void)setBottomCornerRounded:(BOOL)flag; +@end + +@implementation BWAddSheetBottomBar + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + } + return self; +} + +- (void)awakeFromNib +{ + [[self window] setContentBorderThickness:40 forEdge:NSMinYEdge]; + + // Private method + if ([[self window] respondsToSelector:@selector(setBottomCornerRounded:)]) + [[self window] setBottomCornerRounded:NO]; +} + +- (void)drawRect:(NSRect)aRect +{ + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] && [[self window] contentBorderThicknessForEdge:NSMinYEdge] == 0) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + + if ([[self window] isSheet] && [[self window] respondsToSelector:@selector(setMovable:)]) + [[self window] setMovable:NO]; +} + +- (NSRect)bounds +{ + return NSMakeRect(-10000,-10000,0,0); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSmallBottomBar.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSmallBottomBar.h new file mode 100644 index 000000000..70e0b6173 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSmallBottomBar.h @@ -0,0 +1,16 @@ +// +// BWAddSmallBottomBar.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAddSmallBottomBar : NSView +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSmallBottomBar.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSmallBottomBar.m new file mode 100644 index 000000000..51cdebda9 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAddSmallBottomBar.m @@ -0,0 +1,43 @@ +// +// BWAddSmallBottomBar.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAddSmallBottomBar.h" +//#import "NSWindow-NSTimeMachineSupport.h" + +@implementation BWAddSmallBottomBar + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + } + return self; +} + +- (void)awakeFromNib +{ + [[self window] setContentBorderThickness:24 forEdge:NSMinYEdge]; +} + +- (void)drawRect:(NSRect)aRect +{ + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] && [[self window] contentBorderThicknessForEdge:NSMinYEdge] == 0) + [self performSelector:@selector(addBottomBar) withObject:nil afterDelay:0]; + + if ([[self window] isSheet] && [[self window] respondsToSelector:@selector(setMovable:)]) + [[self window] setMovable:NO]; +} + +- (NSRect)bounds +{ + return NSMakeRect(-10000,-10000,0,0); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButton.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButton.h new file mode 100644 index 000000000..29edb975e --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButton.h @@ -0,0 +1,21 @@ +// +// BWAnchoredButton.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAnchoredButton : NSButton +{ + BOOL isAtLeftEdgeOfBar; + BOOL isAtRightEdgeOfBar; + NSPoint topAndLeftInset; +} + +@property BOOL isAtLeftEdgeOfBar; +@property BOOL isAtRightEdgeOfBar; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButton.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButton.m new file mode 100644 index 000000000..051bcc5cb --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButton.m @@ -0,0 +1,43 @@ +// +// BWAnchoredButton.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAnchoredButton.h" +#import "BWAnchoredButtonBar.h" +#import "NSView+BWAdditions.h" + +@implementation BWAnchoredButton + +@synthesize isAtLeftEdgeOfBar; +@synthesize isAtRightEdgeOfBar; + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([BWAnchoredButtonBar wasBorderedBar]) + topAndLeftInset = NSMakePoint(0, 0); + else + topAndLeftInset = NSMakePoint(1, 1); + } + return self; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + [self bwBringToFront]; + [super mouseDown:theEvent]; +} + +- (NSRect)frame +{ + NSRect frame = [super frame]; + frame.size.height = 24; + return frame; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonBar.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonBar.h new file mode 100644 index 000000000..4ff4a7374 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonBar.h @@ -0,0 +1,27 @@ +// +// BWAnchoredButtonBar.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAnchoredButtonBar : NSView +{ + BOOL isResizable, isAtBottom, handleIsRightAligned; + int selectedIndex; + id splitViewDelegate; +} + +@property BOOL isResizable, isAtBottom, handleIsRightAligned; +@property int selectedIndex; + +// The mode of this bar with a resize handle makes use of some NSSplitView delegate methods. Use the splitViewDelegate for any custom delegate implementations +// you'd like to provide. +@property (assign) id splitViewDelegate; + ++ (BOOL)wasBorderedBar; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonBar.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonBar.m new file mode 100644 index 000000000..425438506 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonBar.m @@ -0,0 +1,428 @@ +// +// BWAnchoredButtonBar.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAnchoredButtonBar.h" +#import "NSColor+BWAdditions.h" +#import "NSView+BWAdditions.h" +#import "BWAnchoredButton.h" +#import "BWSplitView.h" + +static NSColor *topLineColor, *bottomLineColor; +static NSColor *topColor, *middleTopColor, *middleBottomColor, *bottomColor; +static NSColor *sideInsetColor, *borderedTopLineColor; +static NSColor *resizeHandleColor, *resizeInsetColor; +static NSGradient *gradient; +static BOOL wasBorderedBar; +static float scaleFactor = 0.0f; + +@interface BWAnchoredButtonBar (BWABBPrivate) +- (void)drawResizeHandleInRect:(NSRect)handleRect withColor:(NSColor *)color; +- (void)drawLastButtonInsetInRect:(NSRect)rect; +- (BOOL)isInLastSubview; +- (NSSplitView *)splitView; +- (NSInteger)dividerIndexNearestToHandle; +@end + +@implementation BWAnchoredButtonBar + +@synthesize selectedIndex, isAtBottom, isResizable, handleIsRightAligned, splitViewDelegate; + ++ (void)initialize; +{ + topLineColor = [[NSColor colorWithCalibratedWhite:(202.0f / 255.0f) alpha:1] retain]; + bottomLineColor = [[NSColor colorWithCalibratedWhite:(170.0f / 255.0f) alpha:1] retain]; + topColor = [[NSColor colorWithCalibratedWhite:(253.0f / 255.0f) alpha:1] retain]; + middleTopColor = [[NSColor colorWithCalibratedWhite:(242.0f / 255.0f) alpha:1] retain]; + middleBottomColor = [[NSColor colorWithCalibratedWhite:(230.0f / 255.0f) alpha:1] retain]; + bottomColor = [[NSColor colorWithCalibratedWhite:(230.0f / 255.0f) alpha:1] retain]; + sideInsetColor = [[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.5] retain]; + borderedTopLineColor = [[NSColor colorWithCalibratedWhite:(190.0f / 255.0f) alpha:1] retain]; + + gradient = [[NSGradient alloc] initWithColorsAndLocations: + topColor, (CGFloat)0.0, + middleTopColor, (CGFloat)0.45454, + middleBottomColor, (CGFloat)0.45454, + bottomColor, (CGFloat)1.0, + nil]; + + resizeHandleColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.598] retain]; + resizeInsetColor = [[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.55] retain]; +} + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) + { + scaleFactor = [[NSScreen mainScreen] userSpaceScaleFactor]; + [self setIsResizable:YES]; + [self setIsAtBottom:YES]; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + [self setIsResizable:[decoder decodeBoolForKey:@"BWABBIsResizable"]]; + [self setIsAtBottom:[decoder decodeBoolForKey:@"BWABBIsAtBottom"]]; + [self setHandleIsRightAligned:[decoder decodeBoolForKey:@"BWABBHandleIsRightAligned"]]; + [self setSelectedIndex:[decoder decodeIntForKey:@"BWABBSelectedIndex"]]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + + [coder encodeBool:[self isResizable] forKey:@"BWABBIsResizable"]; + [coder encodeBool:[self isAtBottom] forKey:@"BWABBIsAtBottom"]; + [coder encodeBool:[self handleIsRightAligned] forKey:@"BWABBHandleIsRightAligned"]; + [coder encodeInt:[self selectedIndex] forKey:@"BWABBSelectedIndex"]; +} + +- (void)awakeFromNib +{ + scaleFactor = [[NSScreen mainScreen] userSpaceScaleFactor]; + + // See if we're in a split view, and set its delegate + NSSplitView *splitView = [self splitView]; + + if (splitView != nil && [splitView isVertical] && [self isResizable]) + { + if ([splitView delegate] != nil && ([[splitView delegate] isKindOfClass:[BWAnchoredButtonBar class]] || + [splitView isKindOfClass:[BWSplitView class]] && [[(BWSplitView *)splitView secondaryDelegate] isKindOfClass:[BWAnchoredButtonBar class]])) + { + // There's already an Anchored Button Bar set as the delegate so we need to set ourself as the split view delegate on + // the button bar. But since there can be multiple button bars, we need to set ourself as the delegate on the last + // button bar of the delegate chain. + + BWAnchoredButtonBar *currentDelegate = [splitView isKindOfClass:[BWSplitView class]] ? [(BWSplitView *)splitView secondaryDelegate] : [splitView delegate]; + BWAnchoredButtonBar *lastDelegate = currentDelegate; + + while (currentDelegate != nil) + { + if ([currentDelegate splitViewDelegate] != nil && [[currentDelegate splitViewDelegate] isKindOfClass:[BWAnchoredButtonBar class]]) + { + currentDelegate = [currentDelegate splitViewDelegate]; + lastDelegate = currentDelegate; + } + else + { + currentDelegate = nil; + } + } + + [lastDelegate setSplitViewDelegate:self]; + } + else + { + [splitView setDelegate:self]; + } + } + + [self bwBringToFront]; +} + +- (void)drawRect:(NSRect)rect +{ + rect = self.bounds; + + // Draw gradient + NSRect gradientRect; + if (isAtBottom) + gradientRect = NSMakeRect(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height - 1); + else + gradientRect = NSInsetRect(rect, 0, 1); + [gradient drawInRect:gradientRect angle:270]; + + // Draw top line + if (isAtBottom) + [topLineColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + else + [borderedTopLineColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + + // Draw resize handle + if (isResizable) + { + NSRect handleRect = NSMakeRect(NSMaxX(rect)-11,6,6,10); + + if ([self handleIsRightAligned]) + handleRect.origin.x = 4; + + [self drawResizeHandleInRect:handleRect withColor:resizeHandleColor]; + + NSRect insetRect = NSOffsetRect(handleRect,1,-1); + [self drawResizeHandleInRect:insetRect withColor:resizeInsetColor]; + } + + [self drawLastButtonInsetInRect:rect]; + + // Draw bottom line and sides if it's in non-bottom mode + if (!isAtBottom) + { + [bottomLineColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + [bottomLineColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:rect inView:self horizontal:NO flip:NO]; + [bottomLineColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:rect inView:self horizontal:NO flip:YES]; + } +} + +- (void)drawResizeHandleInRect:(NSRect)handleRect withColor:(NSColor *)color +{ + [color bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:handleRect inView:self horizontal:NO flip:NO]; + [color bwDrawPixelThickLineAtPosition:3 withInset:0 inRect:handleRect inView:self horizontal:NO flip:NO]; + [color bwDrawPixelThickLineAtPosition:6 withInset:0 inRect:handleRect inView:self horizontal:NO flip:NO]; +} + +- (void)drawLastButtonInsetInRect:(NSRect)rect +{ + NSView *rightMostView = nil; + + if ([[self subviews] count] > 0) + { + rightMostView = [[self subviews] objectAtIndex:0]; + + NSView *currentSubview = nil; + for (currentSubview in [self subviews]) + { + if ([[currentSubview className] isEqualToString:@"BWAnchoredButton"] || [[currentSubview className] isEqualToString:@"BWAnchoredPopUpButton"]) + { + if (NSMaxX([currentSubview frame]) > NSMaxX([rightMostView frame])) + rightMostView = currentSubview; + + if ([currentSubview frame].origin.x == 0) + [(BWAnchoredButton *)currentSubview setIsAtLeftEdgeOfBar:YES]; + else + [(BWAnchoredButton *)currentSubview setIsAtLeftEdgeOfBar:NO]; + + if (NSMaxX([currentSubview frame]) == NSMaxX([self bounds])) + [(BWAnchoredButton *)currentSubview setIsAtRightEdgeOfBar:YES]; + else + [(BWAnchoredButton *)currentSubview setIsAtRightEdgeOfBar:NO]; + } + } + } + + if (rightMostView != nil && ([[rightMostView className] isEqualToString:@"BWAnchoredButton"] || [[rightMostView className] isEqualToString:@"BWAnchoredPopUpButton"])) + { + NSRect newRect = NSOffsetRect(rect,0,-1); + [sideInsetColor bwDrawPixelThickLineAtPosition:NSMaxX([rightMostView frame]) withInset:0 inRect:newRect inView:self horizontal:NO flip:NO]; + } +} + +- (void)viewDidMoveToSuperview +{ + if ([self splitView] != nil) + self.handleIsRightAligned = [self isInLastSubview]; +} + +- (BOOL)isInLastSubview +{ + // This method could be made more robust. Right now it assumes that the button bar's direct parent is the split view. + if ([self splitView] != nil && [self superview] == [[[self splitView] subviews] lastObject]) + return YES; + + return NO; +} + +- (NSInteger)dividerIndexNearestToHandle +{ + if ([self isInLastSubview]) + return self.splitView.subviews.count - 2; + + return [[[self splitView] subviews] indexOfObject:[self superview]]; +} + +- (NSSplitView *)splitView +{ + NSSplitView *splitView = nil; + id currentView = self; + + while (![currentView isKindOfClass:[NSSplitView class]] && currentView != nil) + { + currentView = [currentView superview]; + if ([currentView isKindOfClass:[NSSplitView class]]) + splitView = currentView; + } + + return splitView; +} + +- (void)setIsAtBottom:(BOOL)flag +{ + isAtBottom = flag; + + if (flag) + { + [self setFrameSize:NSMakeSize(self.frame.size.width,23)]; + wasBorderedBar = NO; + } + else + { + [self setFrameSize:NSMakeSize(self.frame.size.width,24)]; + wasBorderedBar = YES; + } + + [self setNeedsDisplay:YES]; +} + +- (void)setSelectedIndex:(int)anIndex +{ + if (anIndex == 0) + { + [self setIsAtBottom:YES]; + [self setIsResizable:YES]; + } + else if (anIndex == 1) + { + [self setIsAtBottom:YES]; + [self setIsResizable:NO]; + } + else if (anIndex == 2) + { + [self setIsAtBottom:NO]; + [self setIsResizable:NO]; + } + selectedIndex = anIndex; + + [self setNeedsDisplay:YES]; +} + ++ (BOOL)wasBorderedBar +{ + return wasBorderedBar; +} + +- (void)dealloc +{ + NSSplitView *splitView = [self splitView]; + + if ([splitView delegate] == self) + [splitView setDelegate:nil]; + + [super dealloc]; +} + +#pragma mark NSSplitView Delegate Methods + +// Add the resize handle rect to the split view hot zone +- (NSRect)splitView:(NSSplitView *)aSplitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex +{ + if (dividerIndex == [self dividerIndexNearestToHandle]) + { + NSRect paddedHandleRect; + paddedHandleRect.origin.y = [aSplitView frame].size.height - [self frame].origin.y - [self bounds].size.height; + + // Note: Assumes button bar is nested directly in a split view subview + if (self.handleIsRightAligned) + paddedHandleRect.origin.x = NSMinX([[self superview] frame]); + else + paddedHandleRect.origin.x = NSMaxX([[self superview] frame]) - 15; + + paddedHandleRect.size.width = 15; + paddedHandleRect.size.height = [self bounds].size.height; + + return paddedHandleRect; + } + else + { + if ([splitViewDelegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)]) + return [splitViewDelegate splitView:aSplitView additionalEffectiveRectOfDividerAtIndex:dividerIndex]; + } + + return NSZeroRect; +} + +// Remaining delegate methods. They test for an implementation by the splitViewDelegate (otherwise perform default behavior) + +- (CGFloat)splitView:(NSSplitView *)sender constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)offset +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)]) + return [splitViewDelegate splitView:sender constrainMinCoordinate:proposedMin ofSubviewAt:offset]; + + return proposedMin; +} + +- (CGFloat)splitView:(NSSplitView *)sender constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)offset +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)]) + return [splitViewDelegate splitView:sender constrainMaxCoordinate:proposedMax ofSubviewAt:offset]; + + return proposedMax; +} + +- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)]) + return [splitViewDelegate splitView:sender resizeSubviewsWithOldSize:oldSize]; + + [sender adjustSubviews]; +} + +- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:canCollapseSubview:)]) + return [splitViewDelegate splitView:sender canCollapseSubview:subview]; + + return NO; +} + +- (CGFloat)splitView:(NSSplitView *)sender constrainSplitPosition:(CGFloat)proposedPosition ofSubviewAt:(NSInteger)offset +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)]) + return [splitViewDelegate splitView:sender constrainSplitPosition:proposedPosition ofSubviewAt:offset]; + + return proposedPosition; +} + +- (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect ofDividerAtIndex:(NSInteger)dividerIndex +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)]) + return [splitViewDelegate splitView:splitView effectiveRect:proposedEffectiveRect forDrawnRect:drawnRect ofDividerAtIndex:dividerIndex]; + + return proposedEffectiveRect; +} + +- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)]) + return [splitViewDelegate splitView:splitView shouldCollapseSubview:subview forDoubleClickOnDividerAtIndex:dividerIndex]; + + return NO; +} + +- (BOOL)splitView:(NSSplitView *)splitView shouldHideDividerAtIndex:(NSInteger)dividerIndex +{ + if ([splitViewDelegate respondsToSelector:@selector(splitView:shouldHideDividerAtIndex:)]) + return [splitViewDelegate splitView:splitView shouldHideDividerAtIndex:dividerIndex]; + + return NO; +} + +- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview +{ + if ([splitViewDelegate respondsToSelector:_cmd]) + return [splitViewDelegate splitView:splitView shouldAdjustSizeOfSubview:subview]; + return YES; +} + +- (void)splitViewWillResizeSubviews:(NSNotification *)aNotification +{ + if ([splitViewDelegate respondsToSelector:_cmd]) + [splitViewDelegate splitViewWillResizeSubviews:aNotification]; +} + +- (void)splitViewDidResizeSubviews:(NSNotification *)aNotification +{ + if ([splitViewDelegate respondsToSelector:_cmd]) + [splitViewDelegate splitViewDidResizeSubviews:aNotification]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonCell.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonCell.h new file mode 100644 index 000000000..3a157e8cb --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonCell.h @@ -0,0 +1,16 @@ +// +// BWAnchoredButtonCell.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAnchoredButtonCell : NSButtonCell +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonCell.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonCell.m new file mode 100644 index 000000000..1384b817c --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredButtonCell.m @@ -0,0 +1,185 @@ +// +// BWAnchoredButtonCell.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAnchoredButtonCell.h" +#import "BWAnchoredButtonBar.h" +#import "BWAnchoredButton.h" +#import "NSColor+BWAdditions.h" +#import "NSImage+BWAdditions.h" + +static NSColor *fillStop1, *fillStop2, *fillStop3, *fillStop4; +static NSColor *topBorderColor, *bottomBorderColor, *sideBorderColor, *sideInsetColor, *pressedColor; +static NSColor *enabledTextColor, *disabledTextColor, *enabledImageColor, *disabledImageColor; +static NSColor *borderedSideBorderColor, *borderedTopBorderColor; +static NSGradient *fillGradient; +static NSShadow *contentShadow; + +@interface NSCell (BWABCPrivate) +- (NSDictionary *)_textAttributes; +@end + +@interface BWAnchoredButtonCell (BWABCPrivate) +- (NSColor *)textColor; +- (NSColor *)imageColor; +- (NSRect)highlightRectForBounds:(NSRect)cellFrame; +@end + +@implementation BWAnchoredButtonCell + ++ (void)initialize; +{ + fillStop1 = [[NSColor colorWithCalibratedWhite:(253.0f / 255.0f) alpha:1] retain]; + fillStop2 = [[NSColor colorWithCalibratedWhite:(242.0f / 255.0f) alpha:1] retain]; + fillStop3 = [[NSColor colorWithCalibratedWhite:(230.0f / 255.0f) alpha:1] retain]; + fillStop4 = [[NSColor colorWithCalibratedWhite:(230.0f / 255.0f) alpha:1] retain]; + + fillGradient = [[NSGradient alloc] initWithColorsAndLocations: + fillStop1, (CGFloat)0.0, + fillStop2, (CGFloat)0.45454, + fillStop3, (CGFloat)0.45454, + fillStop4, (CGFloat)1.0, + nil]; + + topBorderColor = [[NSColor colorWithCalibratedWhite:(202.0f / 255.0f) alpha:1] retain]; + bottomBorderColor = [[NSColor colorWithCalibratedWhite:(170.0f / 255.0f) alpha:1] retain]; + sideBorderColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.2] retain]; + sideInsetColor = [[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.5] retain]; + + pressedColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.35] retain]; + + enabledTextColor = [[NSColor colorWithCalibratedWhite:(10.0f / 255.0f) alpha:1] retain]; + disabledTextColor = [[enabledTextColor colorWithAlphaComponent:0.6] retain]; + + enabledImageColor = [[NSColor colorWithCalibratedWhite:(72.0f / 255.0f) alpha:1] retain]; + disabledImageColor = [[enabledImageColor colorWithAlphaComponent:0.6] retain]; + + borderedSideBorderColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.25] retain]; + borderedTopBorderColor = [[NSColor colorWithCalibratedWhite:(190.0f / 255.0f) alpha:1] retain]; + + contentShadow = [[NSShadow alloc] init]; + [contentShadow setShadowOffset:NSMakeSize(0,-1)]; + [contentShadow setShadowColor:[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.75]]; +} + +- (NSControlSize)controlSize +{ + return NSSmallControlSize; +} + +- (void)setControlSize:(NSControlSize)size +{ + +} + +#pragma mark Draw Bezel + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + [super drawWithFrame:cellFrame inView:controlView]; + + // @fpillet: added checks for showState and state if NSOnState should highlight + if ([self isHighlighted] || ([self showsStateBy] && [self state] != NSOffState)) + { + [pressedColor set]; + NSRectFillUsingOperation([self highlightRectForBounds:cellFrame], NSCompositeSourceOver); + } +} + +- (NSRect)highlightRectForBounds:(NSRect)bounds +{ + return bounds; +} + +- (void)drawBezelWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + BOOL inBorderedBar = YES; + + if ([[[self controlView] superview] respondsToSelector:@selector(isAtBottom)]) + { + if ([(BWAnchoredButtonBar *)[[self controlView] superview] isAtBottom]) + inBorderedBar = NO; + } + + [fillGradient drawInRect:cellFrame angle:90]; + + [bottomBorderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:YES]; + [sideInsetColor bwDrawPixelThickLineAtPosition:1 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + [sideInsetColor bwDrawPixelThickLineAtPosition:1 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + + if (inBorderedBar) + { + [borderedTopBorderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:NO]; + [borderedSideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + [borderedSideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + } + else + { + [topBorderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:NO]; + [sideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + [sideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + } + + if (inBorderedBar && [[self controlView] respondsToSelector:@selector(isAtLeftEdgeOfBar)]) + { + if ([(BWAnchoredButton *)[self controlView] isAtLeftEdgeOfBar]) + [bottomBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + if ([(BWAnchoredButton *)[self controlView] isAtRightEdgeOfBar]) + [bottomBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + } +} + +#pragma mark Draw Title + +- (NSColor *)textColor +{ + return [self isEnabled] ? enabledTextColor : disabledTextColor; +} + +- (NSDictionary *)_textAttributes +{ + NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] init] autorelease]; + [attributes addEntriesFromDictionary:[super _textAttributes]]; + [attributes setObject:[self textColor] forKey:NSForegroundColorAttributeName]; + [attributes setObject:[NSFont systemFontOfSize:11] forKey:NSFontAttributeName]; + [attributes setObject:contentShadow forKey:NSShadowAttributeName]; + + return attributes; +} + +- (NSRect)titleRectForBounds:(NSRect)bounds +{ + return NSOffsetRect([super titleRectForBounds:bounds], 0, 1); +} + +#pragma mark Draw Image + +- (NSColor *)imageColor +{ + return [self isEnabled] ? enabledImageColor : disabledImageColor; +} + +- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView +{ + if ([[image name] isEqualToString:@"NSActionTemplate"]) + [image setSize:NSMakeSize(10,10)]; + + NSImage *newImage = image; + + // Only tint if the image is a template and shouldn't be rendered as a blue active state + if ([image isTemplate] && !([self showsStateBy] == NSContentsCellMask && [self intValue] == 1)) + { + newImage = [image bwTintedImageWithColor:[self imageColor]]; + [newImage setTemplate:NO]; + + [contentShadow set]; + } + + [super drawImage:newImage withFrame:NSOffsetRect(frame, 0, 1) inView:controlView]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButton.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButton.h new file mode 100644 index 000000000..150db4332 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButton.h @@ -0,0 +1,21 @@ +// +// BWAnchoredPopUpButton.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAnchoredPopUpButton : NSPopUpButton +{ + BOOL isAtLeftEdgeOfBar; + BOOL isAtRightEdgeOfBar; + NSPoint topAndLeftInset; +} + +@property BOOL isAtLeftEdgeOfBar; +@property BOOL isAtRightEdgeOfBar; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButton.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButton.m new file mode 100644 index 000000000..a4c04c270 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButton.m @@ -0,0 +1,43 @@ +// +// BWAnchoredPopUpButton.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAnchoredPopUpButton.h" +#import "BWAnchoredButtonBar.h" +#import "NSView+BWAdditions.h" + +@implementation BWAnchoredPopUpButton + +@synthesize isAtLeftEdgeOfBar; +@synthesize isAtRightEdgeOfBar; + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([BWAnchoredButtonBar wasBorderedBar]) + topAndLeftInset = NSMakePoint(0, 0); + else + topAndLeftInset = NSMakePoint(1, 1); + } + return self; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + [self bwBringToFront]; + [super mouseDown:theEvent]; +} + +- (NSRect)frame +{ + NSRect frame = [super frame]; + frame.size.height = 24; + return frame; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButtonCell.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButtonCell.h new file mode 100644 index 000000000..8de4fe89b --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButtonCell.h @@ -0,0 +1,16 @@ +// +// BWAnchoredPopUpButtonCell.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWAnchoredPopUpButtonCell : NSPopUpButtonCell +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButtonCell.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButtonCell.m new file mode 100644 index 000000000..bf8ff18e8 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWAnchoredPopUpButtonCell.m @@ -0,0 +1,260 @@ +// +// BWAnchoredPopUpButtonCell.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWAnchoredPopUpButtonCell.h" +#import "BWAnchoredPopUpButton.h" +#import "BWAnchoredButtonBar.h" +#import "NSColor+BWAdditions.h" +#import "NSImage+BWAdditions.h" + +static NSColor *fillStop1, *fillStop2, *fillStop3, *fillStop4; +static NSColor *topBorderColor, *bottomBorderColor, *sideBorderColor, *sideInsetColor, *pressedColor; +static NSColor *enabledTextColor, *disabledTextColor, *enabledImageColor, *disabledImageColor; +static NSColor *borderedSideBorderColor, *borderedTopBorderColor; +static NSGradient *fillGradient; +static NSImage *pullDownArrow; +static NSShadow *contentShadow; +static float arrowInset = 11.0; + +@interface NSCell (BWAPUBCPrivate) +- (NSDictionary *)_textAttributes; +@end + +@interface BWAnchoredPopUpButtonCell (BWAPUBCPrivate) +- (NSColor *)textColor; +- (NSColor *)imageColor; +- (NSRect)highlightRectForBounds:(NSRect)cellFrame; +- (void)drawArrowInFrame:(NSRect)cellFrame; +@end + +@implementation BWAnchoredPopUpButtonCell + ++ (void)initialize; +{ + fillStop1 = [[NSColor colorWithCalibratedWhite:(253.0f / 255.0f) alpha:1] retain]; + fillStop2 = [[NSColor colorWithCalibratedWhite:(242.0f / 255.0f) alpha:1] retain]; + fillStop3 = [[NSColor colorWithCalibratedWhite:(230.0f / 255.0f) alpha:1] retain]; + fillStop4 = [[NSColor colorWithCalibratedWhite:(230.0f / 255.0f) alpha:1] retain]; + + fillGradient = [[NSGradient alloc] initWithColorsAndLocations: + fillStop1, (CGFloat)0.0, + fillStop2, (CGFloat)0.45454, + fillStop3, (CGFloat)0.45454, + fillStop4, (CGFloat)1.0, + nil]; + + topBorderColor = [[NSColor colorWithCalibratedWhite:(202.0f / 255.0f) alpha:1] retain]; + bottomBorderColor = [[NSColor colorWithCalibratedWhite:(170.0f / 255.0f) alpha:1] retain]; + sideBorderColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.2] retain]; + sideInsetColor = [[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.5] retain]; + + pressedColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.35] retain]; + + enabledTextColor = [[NSColor colorWithCalibratedWhite:(10.0f / 255.0f) alpha:1] retain]; + disabledTextColor = [[enabledTextColor colorWithAlphaComponent:0.6] retain]; + + enabledImageColor = [[NSColor colorWithCalibratedWhite:(72.0f / 255.0f) alpha:1] retain]; + disabledImageColor = [[enabledImageColor colorWithAlphaComponent:0.6] retain]; + + borderedSideBorderColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.25] retain]; + borderedTopBorderColor = [[NSColor colorWithCalibratedWhite:(190.0f / 255.0f) alpha:1] retain]; + + contentShadow = [[NSShadow alloc] init]; + [contentShadow setShadowOffset:NSMakeSize(0,-1)]; + [contentShadow setShadowColor:[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.75]]; + + NSBundle *bundle = [NSBundle bundleForClass:[BWAnchoredPopUpButtonCell class]]; + pullDownArrow = [[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:@"ButtonBarPullDownArrow.pdf"]]; +} + +- (NSControlSize)controlSize +{ + return NSSmallControlSize; +} + +- (void)setControlSize:(NSControlSize)size +{ + +} + +#pragma mark Draw Bezel & Arrows + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + [super drawWithFrame:cellFrame inView:controlView]; + + if ([self isHighlighted]) + { + [pressedColor set]; + NSRectFillUsingOperation([self highlightRectForBounds:cellFrame], NSCompositeSourceOver); + } +} + +- (NSRect)highlightRectForBounds:(NSRect)bounds +{ + return bounds; +} + +- (void)drawBorderAndBackgroundWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + BOOL inBorderedBar = YES; + + if ([[[self controlView] superview] respondsToSelector:@selector(isAtBottom)]) + { + if ([(BWAnchoredButtonBar *)[[self controlView] superview] isAtBottom]) + inBorderedBar = NO; + } + + [fillGradient drawInRect:cellFrame angle:90]; + + [bottomBorderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:YES]; + [sideInsetColor bwDrawPixelThickLineAtPosition:1 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + [sideInsetColor bwDrawPixelThickLineAtPosition:1 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + + if (inBorderedBar) + { + [borderedTopBorderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:NO]; + [borderedSideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + [borderedSideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + } + else + { + [topBorderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:NO]; + [sideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + [sideBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + } + + if (inBorderedBar && [[self controlView] respondsToSelector:@selector(isAtLeftEdgeOfBar)]) + { + if ([(BWAnchoredPopUpButton *)[self controlView] isAtLeftEdgeOfBar]) + [bottomBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; + if ([(BWAnchoredPopUpButton *)[self controlView] isAtRightEdgeOfBar]) + [bottomBorderColor bwDrawPixelThickLineAtPosition:0 withInset:1 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + } + + [self drawArrowInFrame:cellFrame]; +} + +- (void)drawArrowInFrame:(NSRect)cellFrame +{ + NSPoint drawPoint; + drawPoint.x = NSMaxX(cellFrame) - arrowInset; + + NSImage *arrow = [pullDownArrow bwTintedImageWithColor:[self imageColor]]; + + NSAffineTransform* transform = [NSAffineTransform transform]; + [transform translateXBy:0.0 yBy:cellFrame.size.height]; + [transform scaleXBy:1.0 yBy:-1.0]; + [transform concat]; + + [contentShadow set]; + + if ([self pullsDown]) + { + // Draw pull-down arrow + drawPoint.y = roundf(cellFrame.size.height / 2) - 2; + [arrow drawAtPoint:drawPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + } + else + { + // Draw bottom pop-up arrow + drawPoint.y = roundf(cellFrame.size.height / 2) - 4; + [arrow drawAtPoint:drawPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + + // Draw top pop-up arrow + drawPoint.y -= 1; + + NSAffineTransform* transform2 = [NSAffineTransform transform]; + [transform2 translateXBy:0.0 yBy:cellFrame.size.height]; + [transform2 scaleXBy:1.0 yBy:-1.0]; + [transform2 concat]; + + [arrow drawAtPoint:drawPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + + [transform2 invert]; + [transform2 concat]; + } + + [transform invert]; + [transform concat]; +} + +#pragma mark Draw Title + +- (NSColor *)textColor +{ + return [self isEnabled] ? enabledTextColor : disabledTextColor; +} + +- (NSDictionary *)_textAttributes +{ + NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] init] autorelease]; + [attributes addEntriesFromDictionary:[super _textAttributes]]; + [attributes setObject:[self textColor] forKey:NSForegroundColorAttributeName]; + [attributes setObject:[NSFont systemFontOfSize:11] forKey:NSFontAttributeName]; + [attributes setObject:contentShadow forKey:NSShadowAttributeName]; + + return attributes; +} + +- (NSRect)titleRectForBounds:(NSRect)bounds +{ + NSRect titleRect = [super titleRectForBounds:bounds]; + + titleRect.origin.y -= 1; + titleRect = NSInsetRect(titleRect, 3, 0); + + return titleRect; +} + +#pragma mark Draw Image + +- (NSColor *)imageColor +{ + return [self isEnabled] ? enabledImageColor : disabledImageColor; +} + +- (NSRect)imageRectForBounds:(NSRect)theRect +{ + NSRect imageRect = [super imageRectForBounds:theRect]; + + if (imageRect.size.width < [self image].size.width) + imageRect.size.width += 1; + + imageRect.origin.x += 1; + + return imageRect; +} + +- (void)drawImageWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + NSImage *image = [self image]; + + if (image != nil) + { + if ([[image name] isEqualToString:@"NSActionTemplate"]) + [image setSize:NSMakeSize(10,10)]; + + NSImage *newImage = image; + + if ([image isTemplate]) + newImage = [image bwTintedImageWithColor:[self imageColor]]; + + NSAffineTransform* transform = [NSAffineTransform transform]; + [transform translateXBy:0.0 yBy:cellFrame.size.height]; + [transform scaleXBy:1.0 yBy:-1.0]; + [transform concat]; + + [newImage drawInRect:[self imageRectForBounds:cellFrame] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1]; + + [transform invert]; + [transform concat]; + } +} + +@end \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWCustomView.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWCustomView.h new file mode 100644 index 000000000..aef213bd6 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWCustomView.h @@ -0,0 +1,17 @@ +// +// BWGradientSplitViewSubview.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import +#import "NSCustomView.h" + +@interface BWCustomView : NSCustomView +{ + BOOL isOnItsOwn; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWCustomView.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWCustomView.m new file mode 100644 index 000000000..a9b3f1848 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWCustomView.m @@ -0,0 +1,186 @@ +// +// BWGradientSplitViewSubview.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWCustomView.h" +#import "NSColor+BWAdditions.h" +#import "NSWindow+BWAdditions.h" +#import "NSApplication+BWAdditions.h" +//#import "IBColor.h" + +@interface BWCustomView (BWCVPrivate) +- (void)drawTextInRect:(NSRect)rect; +- (NSColor *)containerCustomViewBackgroundColor; +- (NSColor *)childlessCustomViewBackgroundColor; +- (NSColor *)customViewDarkTexturedBorderColor; +- (NSColor *)customViewDarkBorderColor; +- (NSColor *)customViewLightBorderColor; +@end + +@implementation BWCustomView + +- (void)drawRect:(NSRect)rect +{ + rect = self.bounds; + + NSColor *insetColor = [self customViewLightBorderColor]; + NSColor *borderColor; + + if ([[self window] bwIsTextured]) + borderColor = [self customViewDarkTexturedBorderColor]; + else + borderColor = [self customViewDarkBorderColor]; + + // Note: These two colors are reversed in IBColor in 10.5 + if (self.subviews.count == 0) + { + if ([NSApplication bwIsOnLeopard]) + [[self containerCustomViewBackgroundColor] set]; + else + [[self childlessCustomViewBackgroundColor] set]; + NSRectFillUsingOperation(rect,NSCompositeSourceOver); + } + else + { + if ([NSApplication bwIsOnLeopard]) + [[self childlessCustomViewBackgroundColor] set]; + else + [[self containerCustomViewBackgroundColor] set]; + NSRectFillUsingOperation(rect,NSCompositeSourceOver); + } + + if ([[self superview] isKindOfClass:NSClassFromString(@"BWSplitView")] && [[self superview] subviews].count > 1) + { + isOnItsOwn = NO; + NSArray *subviews = [[self superview] subviews]; + + if ([subviews objectAtIndex:0] == self) + { + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + + if ([(NSSplitView *)[self superview] isVertical]) + { + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + } + else + { + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + } + + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + } + else if ([subviews lastObject] == self) + { + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + + if ([(NSSplitView *)[self superview] isVertical]) + { + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + } + else + { + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + } + + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + } + else + { + if ([(NSSplitView *)[self superview] isVertical]) + { + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + } + else + { + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + } + } + } + else + { + isOnItsOwn = YES; + + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [insetColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:NO flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:rect inView:self horizontal:YES flip:NO]; + } + + if (rect.size.height > 16) + [self drawTextInRect:rect]; +} + +- (void)drawTextInRect:(NSRect)rect +{ + NSString *text; + + if (isOnItsOwn) + text = [NSString stringWithFormat:@"%d x %d pt",(int)rect.size.width,(int)rect.size.height]; + else if ([(NSSplitView *)[self superview] isVertical]) + text = [NSString stringWithFormat:@"%d pt",(int)rect.size.width]; + else + text = [NSString stringWithFormat:@"%d pt",(int)rect.size.height]; + + if (![self.className isEqualToString:@"NSView"]) + text = self.className; + + NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] init] autorelease]; + [attributes setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + [attributes setObject:[NSFont boldSystemFontOfSize:12] forKey:NSFontAttributeName]; + + NSShadow *shadow = [[[NSShadow alloc] init] autorelease]; + [shadow setShadowOffset:NSMakeSize(0,-1)]; + [shadow setShadowColor:[[NSColor blackColor] colorWithAlphaComponent:0.4]]; + [attributes setObject:shadow forKey:NSShadowAttributeName]; + + NSMutableAttributedString *string = [[[NSMutableAttributedString alloc] initWithString:text attributes:attributes] autorelease]; + + NSRect boundingRect = [string boundingRectWithSize:rect.size options:0]; + + NSPoint rectCenter; + rectCenter.x = rect.size.width / 2; + rectCenter.y = rect.size.height / 2; + + NSPoint drawPoint = rectCenter; + drawPoint.x -= boundingRect.size.width / 2; + drawPoint.y -= boundingRect.size.height / 2; + + drawPoint.x = roundf(drawPoint.x); + drawPoint.y = roundf(drawPoint.y); + + [string drawAtPoint:drawPoint]; +} + +@end \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWRemoveBottomBar.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWRemoveBottomBar.h new file mode 100644 index 000000000..7d69c7792 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWRemoveBottomBar.h @@ -0,0 +1,16 @@ +// +// BWRemoveBottomBar.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWRemoveBottomBar : NSView +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWRemoveBottomBar.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWRemoveBottomBar.m new file mode 100644 index 000000000..f806b9d77 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWRemoveBottomBar.m @@ -0,0 +1,18 @@ +// +// BWRemoveBottomBar.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWRemoveBottomBar.h" + +@implementation BWRemoveBottomBar + +- (NSRect)bounds +{ + return NSMakeRect(-10000,-10000,0,0); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWSplitView.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWSplitView.h new file mode 100644 index 000000000..ed9731a65 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWSplitView.h @@ -0,0 +1,45 @@ +// +// BWSplitView.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) and Fraser Kuyvenhoven. +// All code is provided under the New BSD license. +// + +#import + +@interface BWSplitView : NSSplitView +{ + NSColor *color; + BOOL colorIsEnabled, checkboxIsEnabled, dividerCanCollapse, collapsibleSubviewCollapsed; + id secondaryDelegate; + NSMutableDictionary *minValues, *maxValues, *minUnits, *maxUnits; + NSMutableDictionary *resizableSubviewPreferredProportion, *nonresizableSubviewPreferredSize; + NSArray *stateForLastPreferredCalculations; + int collapsiblePopupSelection; + float uncollapsedSize; + + // Collapse button + NSButton *toggleCollapseButton; + BOOL isAnimating; +} + +@property (retain) NSMutableDictionary *minValues, *maxValues, *minUnits, *maxUnits; +@property (retain) NSMutableDictionary *resizableSubviewPreferredProportion, *nonresizableSubviewPreferredSize; +@property (retain) NSArray *stateForLastPreferredCalculations; +@property (retain) NSButton *toggleCollapseButton; +@property (assign) id secondaryDelegate; +@property BOOL collapsibleSubviewCollapsed; +@property int collapsiblePopupSelection; +@property BOOL dividerCanCollapse; + +// The split view divider color +@property (copy) NSColor *color; + +// Flag for whether a custom divider color is enabled. If not, the standard divider color is used. +@property BOOL colorIsEnabled; + +// Call this method to collapse or expand a subview configured as collapsible in the IB inspector. +- (IBAction)toggleCollapse:(id)sender; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWSplitView.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWSplitView.m new file mode 100644 index 000000000..5cc53e7ac --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWSplitView.m @@ -0,0 +1,1441 @@ +// +// BWSplitView.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) and Fraser Kuyvenhoven. +// All code is provided under the New BSD license. +// + +#import "BWSplitView.h" +#import "BWAnchoredButtonBar.h" +#import "NSColor+BWAdditions.h" +#import "NSEvent+BWAdditions.h" + +static NSGradient *gradient; +static NSImage *dimpleImageBitmap, *dimpleImageVector; +static NSColor *borderColor, *gradientStartColor, *gradientEndColor; +static float scaleFactor = 1.0f; + +#define dimpleDimension 4.0f + +#define RESIZE_DEBUG_LOGS 0 + +@interface BWSplitView (BWSVPrivate) + +- (void)drawDimpleInRect:(NSRect)aRect; +- (void)drawGradientDividerInRect:(NSRect)aRect; +- (int)resizableSubviews; +- (BOOL)subviewIsResizable:(NSView *)subview; + +- (BOOL)subviewIsCollapsible:(NSView *)subview; +- (BOOL)subviewIsCollapsed:(NSView *)subview; +- (int)collapsibleSubviewIndex; +- (NSView *)collapsibleSubview; +- (BOOL)hasCollapsibleSubview; +- (BOOL)collapsibleSubviewIsCollapsed; + +- (CGFloat)subviewMinimumSize:(int)subviewIndex; +- (CGFloat)subviewMaximumSize:(int)subviewIndex; + +- (void)recalculatePreferredProportionsAndSizes; +- (BOOL)validatePreferredProportionsAndSizes; +- (void)validateAndCalculatePreferredProportionsAndSizes; +- (void)clearPreferredProportionsAndSizes; + +- (void)resizeAndAdjustSubviews; + +@end + +@interface BWSplitView () +@property BOOL checkboxIsEnabled; +@end + +@implementation BWSplitView + +@synthesize color, colorIsEnabled, checkboxIsEnabled, minValues, maxValues, minUnits, maxUnits, collapsiblePopupSelection, dividerCanCollapse, collapsibleSubviewCollapsed; +@synthesize resizableSubviewPreferredProportion, nonresizableSubviewPreferredSize, stateForLastPreferredCalculations; +@synthesize toggleCollapseButton, secondaryDelegate; + ++ (void)initialize; +{ + borderColor = [[NSColor colorWithCalibratedWhite:(165.0f / 255.0f) alpha:1] retain]; + gradientStartColor = [[NSColor colorWithCalibratedWhite:(253.0f / 255.0f) alpha:1] retain]; + gradientEndColor = [[NSColor colorWithCalibratedWhite:(222.0f / 255.0f) alpha:1] retain]; + + gradient = [[NSGradient alloc] initWithStartingColor:gradientStartColor endingColor:gradientEndColor]; + + NSBundle *bundle = [NSBundle bundleForClass:[BWSplitView class]]; + dimpleImageBitmap = [[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:@"GradientSplitViewDimpleBitmap.tif"]]; + dimpleImageVector = [[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:@"GradientSplitViewDimpleVector.pdf"]]; + [dimpleImageBitmap setFlipped:YES]; + [dimpleImageVector setFlipped:YES]; +} + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + [self setColor:[decoder decodeObjectForKey:@"BWSVColor"]]; + [self setColorIsEnabled:[decoder decodeBoolForKey:@"BWSVColorIsEnabled"]]; + [self setMinValues:[decoder decodeObjectForKey:@"BWSVMinValues"]]; + [self setMaxValues:[decoder decodeObjectForKey:@"BWSVMaxValues"]]; + [self setMinUnits:[decoder decodeObjectForKey:@"BWSVMinUnits"]]; + [self setMaxUnits:[decoder decodeObjectForKey:@"BWSVMaxUnits"]]; + [self setCollapsiblePopupSelection:[decoder decodeIntForKey:@"BWSVCollapsiblePopupSelection"]]; + [self setDividerCanCollapse:[decoder decodeBoolForKey:@"BWSVDividerCanCollapse"]]; + + // Delegate set in nib has been decoded, but we want that to be the secondary delegate + [self setDelegate:[super delegate]]; + [super setDelegate:self]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder*)coder +{ + // Temporarily change delegate + [super setDelegate:secondaryDelegate]; + + [super encodeWithCoder:coder]; + + [coder encodeObject:[self color] forKey:@"BWSVColor"]; + [coder encodeBool:[self colorIsEnabled] forKey:@"BWSVColorIsEnabled"]; + [coder encodeObject:[self minValues] forKey:@"BWSVMinValues"]; + [coder encodeObject:[self maxValues] forKey:@"BWSVMaxValues"]; + [coder encodeObject:[self minUnits] forKey:@"BWSVMinUnits"]; + [coder encodeObject:[self maxUnits] forKey:@"BWSVMaxUnits"]; + [coder encodeInt:[self collapsiblePopupSelection] forKey:@"BWSVCollapsiblePopupSelection"]; + [coder encodeBool:[self dividerCanCollapse] forKey:@"BWSVDividerCanCollapse"]; + + // Set delegate back + [self setDelegate:[super delegate]]; + [super setDelegate:self]; +} + +- (void)awakeFromNib +{ + scaleFactor = [[NSScreen mainScreen] userSpaceScaleFactor]; +} + +- (void)drawDividerInRect:(NSRect)aRect +{ + if ([self dividerThickness] < 1.01) + { + if (colorIsEnabled && color != nil) + [color drawSwatchInRect:aRect]; + else + [super drawDividerInRect:aRect]; + } + else + { + [self drawGradientDividerInRect:aRect]; + } +} + +- (void)drawGradientDividerInRect:(NSRect)aRect +{ + aRect = [self centerScanRect:aRect]; + + if ([self isVertical]) + { + // Draw gradient + NSRect gradRect = NSMakeRect(aRect.origin.x + 1 / scaleFactor,aRect.origin.y,aRect.size.width - 1 / scaleFactor,aRect.size.height); + [gradient drawInRect:gradRect angle:0]; + + // Draw left and right borders + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:aRect inView:self horizontal:NO flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:aRect inView:self horizontal:NO flip:YES]; + } + else + { + // Draw gradient + NSRect gradRect = NSMakeRect(aRect.origin.x,aRect.origin.y + 1 / scaleFactor,aRect.size.width,aRect.size.height - 1 / scaleFactor); + [gradient drawInRect:gradRect angle:90]; + + // Draw top and bottom borders + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:aRect inView:self horizontal:YES flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:aRect inView:self horizontal:YES flip:YES]; + } + + [self drawDimpleInRect:aRect]; +} + +- (void)drawDimpleInRect:(NSRect)aRect +{ + float startY = aRect.origin.y + roundf((aRect.size.height / 2) - (dimpleDimension / 2)); + float startX = aRect.origin.x + roundf((aRect.size.width / 2) - (dimpleDimension / 2)); + NSRect destRect = NSMakeRect(startX,startY,dimpleDimension,dimpleDimension); + + // Draw at pixel bounds + destRect = [self convertRectToBase:destRect]; + destRect.origin.x = floor(destRect.origin.x); + + double param, fractPart, intPart; + param = destRect.origin.y; + fractPart = modf(param, &intPart); + if (fractPart < 0.99) + destRect.origin.y = floor(destRect.origin.y); + destRect = [self convertRectFromBase:destRect]; + + if (scaleFactor == 1) + { + NSRect dimpleRect = NSMakeRect(0,0,dimpleDimension,dimpleDimension); + [dimpleImageBitmap drawInRect:destRect fromRect:dimpleRect operation:NSCompositeSourceOver fraction:1]; + } + else + { + NSRect dimpleRect = NSMakeRect(0,0,[dimpleImageVector size].width,[dimpleImageVector size].height); + [dimpleImageVector drawInRect:destRect fromRect:dimpleRect operation:NSCompositeSourceOver fraction:1]; + } +} + +- (void)setDelegate:(id)anObj +{ + if (secondaryDelegate != self) + secondaryDelegate = anObj; + else + secondaryDelegate = nil; +} + +- (BOOL)subviewIsCollapsible:(NSView *)subview; +{ + // check if this is the collapsible subview + int subviewIndex = [[self subviews] indexOfObject:subview]; + + BOOL isCollapsibleSubview = (([self collapsiblePopupSelection] == 1 && subviewIndex == 0) || ([self collapsiblePopupSelection] == 2 && subviewIndex == [[self subviews] count] - 1)); + + return isCollapsibleSubview; +} + +- (BOOL)subviewIsCollapsed:(NSView *)subview; +{ + BOOL isCollapsibleSubview = [self subviewIsCollapsible:subview]; + + return [super isSubviewCollapsed:subview] || (isCollapsibleSubview && collapsibleSubviewCollapsed); +} + +- (BOOL)collapsibleSubviewIsCollapsed; +{ + return [self subviewIsCollapsed:[self collapsibleSubview]]; +} + +- (int)collapsibleSubviewIndex; +{ + switch ([self collapsiblePopupSelection]) { + case 1: + return 0; + break; + case 2: + return [[self subviews] count] - 1; + break; + default: + return -1; + break; + } +} + +- (NSView *)collapsibleSubview; +{ + int index = [self collapsibleSubviewIndex]; + + if (index >= 0) + return [[self subviews] objectAtIndex:index]; + else + return nil; +} + +- (BOOL)hasCollapsibleSubview; +{ + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + return NO; + + return [self collapsiblePopupSelection] != 0; +} + +// This is done to support the use of Core Animation to collapse subviews +- (void)adjustSubviews +{ + [super adjustSubviews]; + [[self window] invalidateCursorRectsForView:self]; +} + +- (void)setCollapsibleSubviewCollapsedHelper:(NSNumber *)flag +{ + [self setCollapsibleSubviewCollapsed:[flag boolValue]]; +} + +- (void)animationEnded +{ + isAnimating = NO; +} + +- (float)animationDuration +{ + if ([NSEvent bwShiftKeyIsDown]) + return 2.0; + + return 0.25; +} + +- (BOOL)hasCollapsibleDivider +{ + if ([self hasCollapsibleSubview] && (dividerCanCollapse || [self dividerThickness] < 1.01)) + return YES; + + return NO; +} + +- (int)collapsibleDividerIndex +{ + if ([self hasCollapsibleDivider]) + { + if ([self collapsiblePopupSelection] == 1) + return 0; + else if ([self collapsiblePopupSelection] == 2) + return [self subviews].count - 2; + } + + return -1; +} + +- (void)setCollapsibleSubviewCollapsed:(BOOL)flag +{ + collapsibleSubviewCollapsed = flag; + + if (flag) + [[self toggleCollapseButton] setState:0]; + else + [[self toggleCollapseButton] setState:1]; +} + +- (void)setMinSizeForCollapsibleSubview:(NSNumber *)minSize +{ + if ([self hasCollapsibleSubview]) + { + NSMutableDictionary *tempMinValues = [[[self minValues] mutableCopy] autorelease]; + [tempMinValues setObject:minSize forKey:[NSNumber numberWithInt:[[self subviews] indexOfObject:[self collapsibleSubview]]]]; + [self setMinValues:tempMinValues]; + } +} + +- (void)removeMinSizeForCollapsibleSubview +{ + if ([self hasCollapsibleSubview]) + { + NSMutableDictionary *tempMinValues = [[[self minValues] mutableCopy] autorelease]; + [tempMinValues removeObjectForKey:[NSNumber numberWithInt:[[self subviews] indexOfObject:[self collapsibleSubview]]]]; + [self setMinValues:tempMinValues]; + } +} + +- (void)restoreAutoresizesSubviews:(NSNumber *)flag +{ + [[self collapsibleSubview] setAutoresizesSubviews:[flag boolValue]]; +} + +- (IBAction)toggleCollapse:(id)sender +{ + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + return; + + if ([self hasCollapsibleSubview] == NO || [self collapsibleSubview] == nil) + return; + + if (isAnimating) + return; + + + // Check to see if the collapsible subview has a minimum width/height and record it. + // We'll later remove the min size temporarily while animating and then restore it. + BOOL hasMinSize = NO; + NSNumber *minSize = [minValues objectForKey:[NSNumber numberWithInt:[[self subviews] indexOfObject:[self collapsibleSubview]]]]; + minSize = [[minSize copy] autorelease]; + + if (minSize != nil || [minSize intValue] != 0) + hasMinSize = YES; + + + // Get a reference to the button and modify its behavior + if ([self toggleCollapseButton] == nil) + { + [self setToggleCollapseButton:sender]; + + [[toggleCollapseButton cell] setHighlightsBy:NSPushInCellMask]; + [[toggleCollapseButton cell] setShowsStateBy:NSContentsCellMask]; + } + + + // Temporary: For simplicty, there should only be 1 subview other than the collapsible subview that's resizable for the collapse to happen + NSView *resizableSubview = nil; + + for (NSView *subview in [self subviews]) + { + if ([self subviewIsResizable:subview] && subview != [self collapsibleSubview]) + { + resizableSubview = subview; + } + + } + + if (resizableSubview == nil) + return; + + // Record whether the collapsible subview is set to autoresize subviews so we can restore it after the animation + BOOL autoresizesSubviews = [[self collapsibleSubview] autoresizesSubviews]; + + // Turn off autoresizesSubviews on the collapsible subview + [[self collapsibleSubview] setAutoresizesSubviews:NO]; + + // Get the thickness of the collapsible divider. If the divider cannot collapse, we set it to 0 so it doesn't affect our calculations. + float collapsibleDividerThickness = [self dividerThickness]; + + if ([self hasCollapsibleDivider] == NO) + collapsibleDividerThickness = 0; + + // Collapsing by dragging the divider sets the view to be hidden, so unhide it + [[self collapsibleSubview] setHidden:NO]; + + if ([self isVertical]) + { + float constantHeight = [self collapsibleSubview].frame.size.height; + + if ([self collapsibleSubviewCollapsed] == NO) + { + uncollapsedSize = [self collapsibleSubview].frame.size.width; + + if (hasMinSize) + [self removeMinSizeForCollapsibleSubview]; + + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:([self animationDuration])]; + [[[self collapsibleSubview] animator] setFrameSize:NSMakeSize(0.0, constantHeight)]; + [[resizableSubview animator] setFrameSize:NSMakeSize(resizableSubview.frame.size.width + uncollapsedSize + collapsibleDividerThickness, constantHeight)]; + [NSAnimationContext endGrouping]; + + if (hasMinSize) + [self performSelector:@selector(setMinSizeForCollapsibleSubview:) withObject:minSize afterDelay:[self animationDuration]]; + + [self performSelector:@selector(setCollapsibleSubviewCollapsedHelper:) withObject:[NSNumber numberWithBool:YES] afterDelay:[self animationDuration]]; + } + else + { + if (hasMinSize) + [self removeMinSizeForCollapsibleSubview]; + + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:([self animationDuration])]; + [[[self collapsibleSubview] animator] setFrameSize:NSMakeSize(uncollapsedSize, constantHeight)]; + [[resizableSubview animator] setFrameSize:NSMakeSize(resizableSubview.frame.size.width - uncollapsedSize - collapsibleDividerThickness, constantHeight)]; + [NSAnimationContext endGrouping]; + + if (hasMinSize) + [self performSelector:@selector(setMinSizeForCollapsibleSubview:) withObject:minSize afterDelay:[self animationDuration]]; + + [self setCollapsibleSubviewCollapsed:NO]; + } + } + else + { + float constantWidth = [self collapsibleSubview].frame.size.width; + + if ([self collapsibleSubviewCollapsed] == NO) + { + uncollapsedSize = [self collapsibleSubview].frame.size.height; + + if (hasMinSize) + [self removeMinSizeForCollapsibleSubview]; + + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:([self animationDuration])]; + [[[self collapsibleSubview] animator] setFrameSize:NSMakeSize(constantWidth, 0.0)]; + [[resizableSubview animator] setFrameSize:NSMakeSize(constantWidth, resizableSubview.frame.size.height + uncollapsedSize + collapsibleDividerThickness)]; + [NSAnimationContext endGrouping]; + + if (hasMinSize) + [self performSelector:@selector(setMinSizeForCollapsibleSubview:) withObject:minSize afterDelay:[self animationDuration]]; + + [self performSelector:@selector(setCollapsibleSubviewCollapsedHelper:) withObject:[NSNumber numberWithBool:YES] afterDelay:[self animationDuration]]; + } + else + { + if (hasMinSize) + [self removeMinSizeForCollapsibleSubview]; + + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:([self animationDuration])]; + [[[self collapsibleSubview] animator] setFrameSize:NSMakeSize(constantWidth, uncollapsedSize)]; + [[resizableSubview animator] setFrameSize:NSMakeSize(constantWidth, resizableSubview.frame.size.height - uncollapsedSize - collapsibleDividerThickness)]; + [NSAnimationContext endGrouping]; + + if (hasMinSize) + [self performSelector:@selector(setMinSizeForCollapsibleSubview:) withObject:minSize afterDelay:[self animationDuration]]; + + [self setCollapsibleSubviewCollapsed:NO]; + } + } + + isAnimating = YES; + [self performSelector:@selector(animationEnded) withObject:nil afterDelay:[self animationDuration]]; + [self performSelector:@selector(restoreAutoresizesSubviews:) withObject:[NSNumber numberWithBool:autoresizesSubviews] afterDelay:[self animationDuration]]; + + [self performSelector:@selector(resizeAndAdjustSubviews) withObject:nil afterDelay:[self animationDuration]]; +} + +#pragma mark Mouse Tracking Methods + +- (void)mouseDown:(NSEvent *)theEvent +{ + // Set the uncollapsed size whenever the split view is clicked or a drag has began. This lets us uncollapse to the size of the subview before the drag-collapse. + if ([self hasCollapsibleSubview]) + { + CGFloat collapsibleViewSize = [self isVertical] ? [self collapsibleSubview].frame.size.width : [self collapsibleSubview].frame.size.height; + + if (!isAnimating && collapsibleViewSize > 0) + uncollapsedSize = collapsibleViewSize; + } + + [super mouseDown:theEvent]; +} + +#pragma mark NSSplitView Delegate Methods + +- (BOOL)splitView:(NSSplitView *)splitView shouldHideDividerAtIndex:(NSInteger)dividerIndex +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:shouldHideDividerAtIndex:)] && + [secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]] == NO) + return [secondaryDelegate splitView:splitView shouldHideDividerAtIndex:dividerIndex]; + + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] == NO) + { + if ([self hasCollapsibleDivider] && [self collapsibleDividerIndex] == dividerIndex) + { + [self setDividerCanCollapse:YES]; + return YES; + } + } + + return NO; +} + +- (NSRect)splitView:(NSSplitView *)splitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)]) + return [secondaryDelegate splitView:splitView additionalEffectiveRectOfDividerAtIndex:dividerIndex]; + + return NSZeroRect; +} + +- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:canCollapseSubview:)] && + [secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]] == NO) + return [secondaryDelegate splitView:sender canCollapseSubview:subview]; + + int subviewIndex = [[self subviews] indexOfObject:subview]; + + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] == NO) + { + if ([self collapsiblePopupSelection] == 1 && subviewIndex == 0) + return YES; + else if ([self collapsiblePopupSelection] == 2 && subviewIndex == [[self subviews] count] - 1) + return YES; + } + + return NO; +} + +- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)] && + [secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]] == NO) + return [secondaryDelegate splitView:splitView shouldCollapseSubview:subview forDoubleClickOnDividerAtIndex:dividerIndex]; + + int subviewIndex = [[self subviews] indexOfObject:subview]; + + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)] == NO) + { + if (([self collapsiblePopupSelection] == 1 && subviewIndex == 0 && dividerIndex == 0) || + ([self collapsiblePopupSelection] == 2 && subviewIndex == [[self subviews] count] - 1 && dividerIndex == [[splitView subviews] count] - 2)) + { + if ([self isVertical]) + uncollapsedSize = [self collapsibleSubview].frame.size.width; + else + uncollapsedSize = [self collapsibleSubview].frame.size.height; + + [self setCollapsibleSubviewCollapsed:YES]; + + // Cause the collapse ourselves by calling the resize method + [self resizeAndAdjustSubviews]; + [self setNeedsDisplay:YES]; + + // Since we manually did the resize above, we pretend that we don't want to collapse + return NO; + } + } + + return NO; +} + +- (CGFloat)splitView:(NSSplitView *)sender constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)offset +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)] && + [secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]] == NO) + return [secondaryDelegate splitView:sender constrainMaxCoordinate:proposedMax ofSubviewAt:offset]; + + // Max coordinate depends on max of subview offset, and the min of subview offset + 1 + CGFloat newMaxFromThisSubview = proposedMax; + CGFloat newMaxFromNextSubview = proposedMax; + + // Max from this subview + CGFloat maxValue = [self subviewMaximumSize:offset]; + if (maxValue != FLT_MAX) + { + NSView *subview = [[self subviews] objectAtIndex:offset]; + CGFloat originCoord = [self isVertical] ? [subview frame].origin.x : [subview frame].origin.y; + + newMaxFromThisSubview = originCoord + maxValue; + } + + // Max from the next subview + int nextOffset = offset + 1; + if ([[self subviews] count] > nextOffset) + { + CGFloat minValue = [self subviewMinimumSize:nextOffset]; + if (minValue != 0) + { + NSView *subview = [[self subviews] objectAtIndex:nextOffset]; + CGFloat endCoord = [self isVertical] ? [subview frame].origin.x + [subview frame].size.width : [subview frame].origin.y + [subview frame].size.height; + + newMaxFromNextSubview = endCoord - minValue - [self dividerThickness]; + // This could cause trouble when over constrained (TODO) + } + } + + CGFloat newMax = fminf(newMaxFromThisSubview, newMaxFromNextSubview); + + if (newMax < proposedMax) + return newMax; + + return proposedMax; +} + +- (CGFloat)splitView:(NSSplitView *)sender constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)offset +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)] && + [secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]] == NO) + return [secondaryDelegate splitView:sender constrainMinCoordinate:proposedMin ofSubviewAt:offset]; + + // Min coordinate depends on min of subview offset and the max of subview offset + 1 + CGFloat newMinFromThisSubview = proposedMin; + CGFloat newMaxFromNextSubview = proposedMin; + + // Min from this subview + CGFloat minValue = [self subviewMinimumSize:offset]; + if (minValue != 0) + { + NSView *subview = [[self subviews] objectAtIndex:offset]; + CGFloat originCoord = [self isVertical] ? [subview frame].origin.x : [subview frame].origin.y; + + newMinFromThisSubview = originCoord + minValue; + } + + // Min from the next subview + int nextOffset = offset + 1; + if ([[self subviews] count] > nextOffset) + { + CGFloat maxValue = [self subviewMaximumSize:nextOffset]; + if (maxValue != FLT_MAX) + { + NSView *subview = [[self subviews] objectAtIndex:nextOffset]; + CGFloat endCoord = [self isVertical] ? [subview frame].origin.x + [subview frame].size.width : [subview frame].origin.y + [subview frame].size.height; + + newMaxFromNextSubview = endCoord - maxValue - [self dividerThickness]; + // This could cause trouble when over constrained (TODO) + } + } + + CGFloat newMin = fmaxf(newMinFromThisSubview, newMaxFromNextSubview); + + if (newMin > proposedMin) + return newMin; + + return proposedMin; +} + +- (CGFloat)splitView:(NSSplitView *)sender constrainSplitPosition:(CGFloat)proposedPosition ofSubviewAt:(NSInteger)offset +{ + [self clearPreferredProportionsAndSizes]; + + if ([self respondsToSelector:@selector(ibDidAddToDesignableDocument:)]) + return proposedPosition; + + if ([secondaryDelegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)] && + [secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]] == NO) + return [secondaryDelegate splitView:sender constrainSplitPosition:proposedPosition ofSubviewAt:offset]; + + return proposedPosition; +} + +- (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect ofDividerAtIndex:(NSInteger)dividerIndex +{ + if ([secondaryDelegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)]) + return [secondaryDelegate splitView:splitView effectiveRect:proposedEffectiveRect forDrawnRect:drawnRect ofDividerAtIndex:dividerIndex]; + + return proposedEffectiveRect; +} + +- (void)splitViewDidResizeSubviews:(NSNotification *)aNotification +{ + if (collapsibleSubviewCollapsed && ([self isVertical] ? [[self collapsibleSubview] frame].size.width > 0 : [[self collapsibleSubview] frame].size.height > 0)) + { + [self setCollapsibleSubviewCollapsed:NO]; + + [self resizeAndAdjustSubviews]; + } + else if (!collapsibleSubviewCollapsed && ([self isVertical] ? [[self collapsibleSubview] frame].size.width < 0.1 : [[self collapsibleSubview] frame].size.height < 0.1)) + { + [self setCollapsibleSubviewCollapsed:YES]; + + [self resizeAndAdjustSubviews]; + } + else if ([self collapsibleSubviewIsCollapsed]) + { + [self resizeAndAdjustSubviews]; + } + + [self setNeedsDisplay:YES]; + + if ([secondaryDelegate respondsToSelector:@selector(splitViewDidResizeSubviews:)]) + [secondaryDelegate splitViewDidResizeSubviews:aNotification]; +} + +- (void)splitViewWillResizeSubviews:(NSNotification *)aNotification +{ + if ([secondaryDelegate respondsToSelector:@selector(splitViewWillResizeSubviews:)]) + [secondaryDelegate splitViewWillResizeSubviews:aNotification]; +} + +- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview +{ + if ([secondaryDelegate respondsToSelector:_cmd]) + return [secondaryDelegate splitView:splitView shouldAdjustSizeOfSubview:subview]; + return YES; +} + +#pragma mark - Resize Subviews Delegate Method and Helper Methods + +- (int)resizableSubviews +{ + int resizableSubviews = 0; + + for (NSView *subview in [self subviews]) + { + if ([self subviewIsResizable:subview]) + resizableSubviews++; + } + + return resizableSubviews; +} + +- (BOOL)subviewIsResizable:(NSView *)subview +{ + if ([self isVertical] && [subview autoresizingMask] & NSViewWidthSizable) + return YES; + + if (![self isVertical] && [subview autoresizingMask] & NSViewHeightSizable) + return YES; + + return NO; +} + +- (CGFloat)subviewMinimumSize:(int)subviewIndex; +{ + NSNumber *minNum = [minValues objectForKey:[NSNumber numberWithInt:subviewIndex]]; + if (!minNum) + return 0; + + int units = 0; + NSNumber *unitsNum = [minUnits objectForKey:[NSNumber numberWithInt:subviewIndex]]; + if (unitsNum) + units = [unitsNum intValue]; + + CGFloat min = [minNum floatValue]; + + switch (units) + { + case 1: + { + // Percent + CGFloat dividerThicknessTotal = [self dividerThickness] * ([[self subviews] count] - 1); + CGFloat totalSize = [self isVertical] ? [self frame].size.width : [self frame].size.height; + totalSize -= dividerThicknessTotal; + + return roundf((min / 100.0) * totalSize); + break; + } + case 0: + default: + { + // Points + return min; + break; + } + } +} + +- (CGFloat)subviewMaximumSize:(int)subviewIndex; +{ + NSNumber *maxNum = [maxValues objectForKey:[NSNumber numberWithInt:subviewIndex]]; + if (!maxNum) + return FLT_MAX; + + int units = 0; + NSNumber *unitsNum = [maxUnits objectForKey:[NSNumber numberWithInt:subviewIndex]]; + if (unitsNum) + units = [unitsNum intValue]; + + CGFloat max = [maxNum floatValue]; + + switch (units) + { + case 1: + { + // Percent + CGFloat dividerThicknessTotal = [self dividerThickness] * ([[self subviews] count] - 1); + CGFloat totalSize = [self isVertical] ? [self frame].size.width : [self frame].size.height; + totalSize -= dividerThicknessTotal; + + return roundf((max / 100.0) * totalSize); + break; + } + case 0: + default: + { + // Points + return max; + break; + } + } +} + +// PREFERRED PROPORTIONS AND SIZES +// +// Preferred proportions (for resizable) +// Need to store resizable subviews preferred proportions for calculating new sizes +// +// Preferred sizes (for non-resizable) +// If a non-resizable subview is ever forced larger or smaller than it prefers, we need to know it's preferred size +// +// Need to recalculate both of the above whenever a divider is moved, or a subview is added/removed or changed between resizable/non-resizable + +- (void)recalculatePreferredProportionsAndSizes; +{ + NSMutableArray *stateArray = [NSMutableArray arrayWithCapacity:[[self subviews] count]]; + + NSMutableDictionary *preferredProportions = [NSMutableDictionary dictionary]; + NSMutableDictionary *preferredSizes = [NSMutableDictionary dictionary]; + + // Total is only the sum of resizable subviews + CGFloat resizableTotal = 0; + + // Calculate resizable total + for (NSView *subview in [self subviews]) + { + if ([self subviewIsResizable:subview]) + resizableTotal += [self isVertical] ? [subview frame].size.width : [subview frame].size.height; + } + + // Calculate resizable preferred propotions and set non-resizable preferred sizes + for (NSView *subview in [self subviews]) + { + int index = [[self subviews] indexOfObject:subview]; + + if ([self subviewIsResizable:subview]) + { + CGFloat size = [self isVertical] ? [subview frame].size.width : [subview frame].size.height; + CGFloat proportion = (resizableTotal > 0) ? (size / resizableTotal) : 0; + + [preferredProportions setObject:[NSNumber numberWithFloat:proportion] + forKey:[NSNumber numberWithInt:index]]; + + [stateArray addObject:[NSNumber numberWithBool:YES]]; + } + else + { + CGFloat size = [self isVertical] ? [subview frame].size.width : [subview frame].size.height; + + [preferredSizes setObject:[NSNumber numberWithFloat:size] + forKey:[NSNumber numberWithInt:index]]; + + [stateArray addObject:[NSNumber numberWithBool:NO]]; + } + } + + [self setResizableSubviewPreferredProportion:preferredProportions]; + [self setNonresizableSubviewPreferredSize:preferredSizes]; + + if (RESIZE_DEBUG_LOGS) NSLog(@"resizableSubviewPreferredProportion: %@", resizableSubviewPreferredProportion); + if (RESIZE_DEBUG_LOGS) NSLog(@"nonresizableSubviewPreferredSize: %@", nonresizableSubviewPreferredSize); + + // Remember state to know when to recalculate + [self setStateForLastPreferredCalculations:stateArray]; + if (RESIZE_DEBUG_LOGS) NSLog(@"stateForLastPreferredCalculations: %@", stateForLastPreferredCalculations); +} + +// Checks if the number or type of subviews has changed since we last recalculated +- (BOOL)validatePreferredProportionsAndSizes; +{ + if (RESIZE_DEBUG_LOGS) NSLog(@"validating preferred proportions and sizes"); + + // Check if we even have saved proportions and sizes + if (![self resizableSubviewPreferredProportion] || ![self nonresizableSubviewPreferredSize]) + return NO; + + // Check if number of items has changed + if ([[self subviews] count] != [[self stateForLastPreferredCalculations] count]) + return NO; + + // Check if any of the subviews have changed between resizable and non-resizable + for (NSView *subview in [self subviews]) + { + int index = [[self subviews] indexOfObject:subview]; + + if ([self subviewIsResizable:subview] != [[[self stateForLastPreferredCalculations] objectAtIndex:index] boolValue]) + return NO; + } + + return YES; +} + +- (void)correctCollapsiblePreferredProportionOrSize; +{ + // TODO: Assuming that the collapsible subview does not change between resizable and non-resizable while collapsed + + if (![self hasCollapsibleSubview]) + return; + + NSMutableDictionary *preferredProportions = [[[self resizableSubviewPreferredProportion] mutableCopy] autorelease]; + NSMutableDictionary *preferredSizes = [[[self nonresizableSubviewPreferredSize] mutableCopy] autorelease]; + + NSNumber *key = [NSNumber numberWithInt:[self collapsibleSubviewIndex]]; + NSView *subview = [self collapsibleSubview]; + + // If the collapsible subview is collapsed, we put aside its preferred propotion/size + if ([self subviewIsCollapsed:subview]) + { + BOOL resizable = [self subviewIsResizable:subview]; + + if (!resizable) + { + NSNumber *sizeNum = [preferredSizes objectForKey:key]; + if (sizeNum) + { + if (RESIZE_DEBUG_LOGS) NSLog(@"removing collapsible view from preferred sizes"); + + // TODO: Save the size for later + + // Remove from preferred sizes + [preferredSizes removeObjectForKey:key]; + } + } + else + { + NSNumber *proportionNum = [preferredProportions objectForKey:key]; + if (proportionNum) + { + if (RESIZE_DEBUG_LOGS) NSLog(@"removing collapsible view from preferred proportions"); + + CGFloat proportion = [proportionNum floatValue]; + + // TODO: Save the proportion for later + + // Remove from preferred proportions + [preferredProportions removeObjectForKey:key]; + + // Recalculate other proportions + CGFloat proportionTotal = 1.0 - proportion; + if (proportionTotal > 0) + { + for (NSNumber *pkey in [preferredProportions allKeys]) + { + CGFloat oldProportion = [[preferredProportions objectForKey:pkey] floatValue]; + CGFloat newPropotion = oldProportion / proportionTotal; + + [preferredProportions setObject:[NSNumber numberWithFloat:newPropotion] forKey:pkey]; + } + } + } + } + + [self setResizableSubviewPreferredProportion:preferredProportions]; + [self setNonresizableSubviewPreferredSize:preferredSizes]; + } + else // Otherwise, we reintegrate its preferred proportion/size + { + [self clearPreferredProportionsAndSizes]; + [self recalculatePreferredProportionsAndSizes]; + } +} + +- (void)validateAndCalculatePreferredProportionsAndSizes; +{ + if (![self validatePreferredProportionsAndSizes]) + [self recalculatePreferredProportionsAndSizes]; + + // Need to make sure the collapsed subviews preferred size/proportion is in the right place + [self correctCollapsiblePreferredProportionOrSize]; +} + + +- (void)clearPreferredProportionsAndSizes; +{ + if (RESIZE_DEBUG_LOGS) NSLog(@"clearing preferred proportions and sizes"); + + [self setResizableSubviewPreferredProportion:nil]; + [self setNonresizableSubviewPreferredSize:nil]; +} + +// RESIZING ALGORITHM + +// non-resizable subviews are given preferred size +// overall remaining size is calculated +// resizable subviews are calculated based on remaining size and preferred proportions +// resizable subviews are checked for min/max constraint violations +// if violating constraint, set to valid size and remove from resizable subviews +// recalculate other resizable subviews and repeat +// if all resizable subviews reached constraints without meeting target size, need to resize non-resizable views +// non-resizable subviews are adjusted proportionally to meet target size +// non-resizable subviews are checked for min/max constraint violations +// if violating constraint, set to valid size and remove from non-resizable subviews +// recalculate other non-resizable subviews and repeat +// if all subviews reached constraints without meeting target size, need to adjust all views to fit +// proportionally resize all subviews to fit in target size, ignoring min/max constraints + +- (void)resizeAndAdjustSubviews; +{ + // Temporary: for now, we will just remember the proportions the first time subviews are resized + // we should be remember them in the user defaults so they save across quits (TODO) + + [self validateAndCalculatePreferredProportionsAndSizes]; + + if (RESIZE_DEBUG_LOGS) NSLog(@"resizeSubviews begins -----------------------------------------------------"); + + NSMutableDictionary *newSubviewSizes = [NSMutableDictionary dictionaryWithCapacity:[[self subviews] count]]; + + // Get new total size + CGFloat totalAvailableSize = [self isVertical] ? [self frame].size.width : [self frame].size.height; + if (RESIZE_DEBUG_LOGS) NSLog(@"totalAvailableSize: %f", totalAvailableSize); + + // Calculate non-resizable subviews total + CGFloat nonresizableSubviewsTotalPreferredSize = 0; + for (NSNumber *size in [nonresizableSubviewPreferredSize allValues]) + nonresizableSubviewsTotalPreferredSize += [size floatValue]; + if (RESIZE_DEBUG_LOGS) NSLog(@"nonresizableSubviewsTotalPreferredSize: %f", nonresizableSubviewsTotalPreferredSize); + + // Calculate divider thickness total + int dividerCount = [[self subviews] count] - 1; + if ([self collapsibleSubviewIsCollapsed] && dividerCanCollapse) dividerCount--; + CGFloat dividerThicknessTotal = [self dividerThickness] * dividerCount; + if (RESIZE_DEBUG_LOGS) NSLog(@"dividerThicknessTotal: %f", dividerThicknessTotal); + + // Calculate overall remaining size (could be negative) + CGFloat resizableSubviewsTotalAvailableSize = totalAvailableSize - nonresizableSubviewsTotalPreferredSize - dividerThicknessTotal; + if (RESIZE_DEBUG_LOGS) NSLog(@"resizableSubviewsTotalAvailableSize: %f", resizableSubviewsTotalAvailableSize); + + // Special case for the collapsible subview + if ([self collapsibleSubviewIsCollapsed]) + { + [newSubviewSizes setObject:[NSNumber numberWithFloat:0.0] + forKey:[NSNumber numberWithInt:[self collapsibleSubviewIndex]]]; + } + + // Set non-resizable subviews to preferred size + [newSubviewSizes addEntriesFromDictionary:nonresizableSubviewPreferredSize]; + + // Set sizes of resizable views based on proportions (could be negative) + CGFloat resizableSubviewAvailableSizeUsed = 0; + int resizableSubviewCounter = 0; + int resizableSubviewCount = [resizableSubviewPreferredProportion count]; + for (NSNumber *key in [resizableSubviewPreferredProportion allKeys]) + { + resizableSubviewCounter++; + + CGFloat proportion = [[resizableSubviewPreferredProportion objectForKey:key] floatValue]; + CGFloat size = roundf(proportion * resizableSubviewsTotalAvailableSize); + resizableSubviewAvailableSizeUsed += size; + + if (resizableSubviewCounter == resizableSubviewCount) + { + // Make adjustment if necessary + size += (resizableSubviewsTotalAvailableSize - resizableSubviewAvailableSizeUsed); + } + + [newSubviewSizes setObject:[NSNumber numberWithFloat:size] forKey:key]; + } + if (RESIZE_DEBUG_LOGS) NSLog(@"newSubviewSizes after resizable proportional resizing: %@", newSubviewSizes); + + // TODO: Could add a special case for resizableSubviewsTotalAvailableSize <= 0 : just set all resizable subviews to minimum size + + // Make array of all the resizable subviews indexes + NSMutableArray *resizableSubviewIndexes = [[[resizableSubviewPreferredProportion allKeys] mutableCopy] autorelease]; + [resizableSubviewIndexes sortUsingDescriptors:[NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES] autorelease]]]; + + // Loop until none of the resizable subviews' constraints are violated + CGFloat proportionTotal = 1; + CGFloat resizableSubviewsRemainingAvailableSize = resizableSubviewsTotalAvailableSize; + int i; + for (i = 0; i < [resizableSubviewIndexes count]; i++) + { + NSNumber *key = [resizableSubviewIndexes objectAtIndex:i]; + CGFloat size = [[newSubviewSizes objectForKey:key] floatValue]; + CGFloat minSize = [self subviewMinimumSize:[key intValue]]; + CGFloat maxSize = [self subviewMaximumSize:[key intValue]]; + + BOOL overMax = size > maxSize; + BOOL underMin = size < minSize; + + // Check if current item in array violates constraints + if (underMin || overMax) + { + CGFloat constrainedSize = underMin ? minSize : maxSize; + + if (RESIZE_DEBUG_LOGS) NSLog(@"resizable subview %@ was %@, set to %f", key, (underMin ? @"under min" : @"over max"), constrainedSize); + + // Give subview constrained size and remove from array + [newSubviewSizes setObject:[NSNumber numberWithFloat:constrainedSize] forKey:key]; + [resizableSubviewIndexes removeObject:key]; + + // Adjust total proportion and remaining available size + proportionTotal -= [[resizableSubviewPreferredProportion objectForKey:key] floatValue]; + resizableSubviewsRemainingAvailableSize -= underMin ? minSize : maxSize; + + // Recalculate remaining subview sizes + CGFloat resizableSubviewRemainingSizeUsed = 0; + int j; + for (j = 0; j < [resizableSubviewIndexes count]; j++) + { + NSNumber *jKey = [resizableSubviewIndexes objectAtIndex:j]; + + CGFloat proportion = 0; + if (proportionTotal > 0) + proportion = [[resizableSubviewPreferredProportion objectForKey:jKey] floatValue] / proportionTotal; + else + proportion = 1.0 / [resizableSubviewIndexes count]; + + CGFloat size = roundf(proportion * resizableSubviewsRemainingAvailableSize); + resizableSubviewRemainingSizeUsed += size; + + if (j == [resizableSubviewIndexes count] - 1) + { + // Make adjustment if necessary + size += (resizableSubviewsRemainingAvailableSize - resizableSubviewRemainingSizeUsed); + } + + [newSubviewSizes setObject:[NSNumber numberWithFloat:size] forKey:jKey]; + + // Reset outer loop to start from beginning + i = -1; + } + } + } + if (RESIZE_DEBUG_LOGS) NSLog(@"newSubviewSizes after resizable constraint fulfilling: %@", newSubviewSizes); + + if ([resizableSubviewIndexes count] == 0 && resizableSubviewsRemainingAvailableSize != 0) + { + if (RESIZE_DEBUG_LOGS) NSLog(@"entering nonresizable adjustment stage"); + + // All resizable subviews have reached constraints without reaching the target size + + // First try to adjust non-resizable subviews, with resizableSubviewsRemainingAvailableSize being the amount of adjustment needed + + // Make array of non-resizable preferred proportions (normally go by preferred sizes) + NSMutableDictionary *nonresizableSubviewPreferredProportion = [NSMutableDictionary dictionary]; + for (NSNumber *key in [nonresizableSubviewPreferredSize allKeys]) + { + CGFloat proportion = [[nonresizableSubviewPreferredSize objectForKey:key] floatValue] / nonresizableSubviewsTotalPreferredSize; + + [nonresizableSubviewPreferredProportion setObject:[NSNumber numberWithFloat:proportion] forKey:key]; + } + + // ResizableSubviewsRemainingAvailableSize is the amount of adjustment needed + CGFloat nonresizableSubviewsRemainingAvailableSize = nonresizableSubviewsTotalPreferredSize + resizableSubviewsRemainingAvailableSize; + + // Set sizes of nonresizable views based on proportions (could be negative) + CGFloat nonresizableSubviewAvailableSizeUsed = 0; + int nonresizableSubviewCounter = 0; + int nonresizableSubviewCount = [nonresizableSubviewPreferredProportion count]; + for (NSNumber *key in [nonresizableSubviewPreferredProportion allKeys]) + { + nonresizableSubviewCounter++; + + CGFloat proportion = [[nonresizableSubviewPreferredProportion objectForKey:key] floatValue]; + CGFloat size = roundf(proportion * nonresizableSubviewsRemainingAvailableSize); + nonresizableSubviewAvailableSizeUsed += size; + + if (nonresizableSubviewCounter == nonresizableSubviewCount) + { + // Make adjustment if necessary + size += (nonresizableSubviewsRemainingAvailableSize - nonresizableSubviewAvailableSizeUsed); + } + + [newSubviewSizes setObject:[NSNumber numberWithFloat:size] forKey:key]; + } + if (RESIZE_DEBUG_LOGS) NSLog(@"newSubviewSizes after nonresizable proportional resizing: %@", newSubviewSizes); + + // Make array of all the non-resizable subviews indexes + NSMutableArray *nonresizableSubviewIndexes = [[[nonresizableSubviewPreferredSize allKeys] mutableCopy] autorelease]; + [nonresizableSubviewIndexes sortUsingDescriptors:[NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES] autorelease]]]; + + // Loop until none of the non-resizable subviews' constraints are violated + CGFloat proportionTotal = 1; + int i; + for (i = 0; i < [nonresizableSubviewIndexes count]; i++) + { + NSNumber *key = [nonresizableSubviewIndexes objectAtIndex:i]; + CGFloat size = [[newSubviewSizes objectForKey:key] floatValue]; + CGFloat minSize = [self subviewMinimumSize:[key intValue]]; + CGFloat maxSize = [self subviewMaximumSize:[key intValue]]; + + BOOL overMax = size > maxSize; + BOOL underMin = size < minSize; + + // Check if current item in array violates constraints + if (underMin || overMax) + { + CGFloat constrainedSize = underMin ? minSize : maxSize; + + if (RESIZE_DEBUG_LOGS) NSLog(@"nonresizable subview %@ was %@, set to %f", key, (underMin ? @"under min" : @"over max"), constrainedSize); + + // Give subview constrained size and remove from array + [newSubviewSizes setObject:[NSNumber numberWithFloat:constrainedSize] forKey:key]; + [nonresizableSubviewIndexes removeObject:key]; + + // Adjust total proportion and remaining available size + proportionTotal -= [[nonresizableSubviewPreferredProportion objectForKey:key] floatValue]; + nonresizableSubviewsRemainingAvailableSize -= underMin ? minSize : maxSize; + + // Recalculate remaining subview sizes + CGFloat nonresizableSubviewRemainingSizeUsed = 0; + int j; + for (j = 0; j < [nonresizableSubviewIndexes count]; j++) + { + NSNumber *jKey = [nonresizableSubviewIndexes objectAtIndex:j]; + + CGFloat proportion = 0; + if (proportionTotal > 0) + proportion = [[nonresizableSubviewPreferredProportion objectForKey:jKey] floatValue] / proportionTotal; + else + proportion = 1.0 / [nonresizableSubviewIndexes count]; + + CGFloat size = roundf(proportion * nonresizableSubviewsRemainingAvailableSize); + nonresizableSubviewRemainingSizeUsed += size; + + if (j == [nonresizableSubviewIndexes count] - 1) + { + // Make adjustment if necessary + size += (nonresizableSubviewsRemainingAvailableSize - nonresizableSubviewRemainingSizeUsed); + } + + [newSubviewSizes setObject:[NSNumber numberWithFloat:size] forKey:jKey]; + + // Reset outer loop to start from beginning + i = -1; + } + } + } + if (RESIZE_DEBUG_LOGS) NSLog(@"newSubviewSizes after nonresizable constraint fulfilling: %@", newSubviewSizes); + + // If there is still overall violation, resize everything proportionally to make up the difference + + if ([resizableSubviewIndexes count] == 0 && nonresizableSubviewsRemainingAvailableSize != 0) + { + if (RESIZE_DEBUG_LOGS) NSLog(@"entering all subviews forced adjustment stage"); + + // Calculate current proportions and use to calculate new size + + CGFloat allSubviewTotalCurrentSize = 0; + for (NSNumber *size in [newSubviewSizes allValues]) + allSubviewTotalCurrentSize += [size floatValue]; + + CGFloat allSubviewRemainingSizeUsed = 0; + CGFloat allSubviewTotalSize = totalAvailableSize - dividerThicknessTotal; + // TODO: What to do if even the dividers don't fit? + + int k; + for (k = 0; k < [newSubviewSizes count]; k++) + { + NSNumber *key = [NSNumber numberWithInt:k]; + + CGFloat currentSize = [[newSubviewSizes objectForKey:key] floatValue]; + + CGFloat proportion = currentSize / allSubviewTotalCurrentSize; + CGFloat size = roundf(proportion * allSubviewTotalSize); + allSubviewRemainingSizeUsed += size; + + if (k == [newSubviewSizes count] - 1) + { + // Make adjustment if necessary + size += allSubviewTotalSize - allSubviewRemainingSizeUsed; + } + + [newSubviewSizes setObject:[NSNumber numberWithFloat:size] forKey:key]; + } + if (RESIZE_DEBUG_LOGS) NSLog(@"newSubviewSizes after all subviews forced adjustment: %@", newSubviewSizes); + } + + // Otherwise there is still flexibiliy in the non-resizable views, so we are done + } + + // Otherwise there is still flexibility in the resizable views, so we are done + + // Set subview frames + CGFloat position = 0; + for (i = 0; i < [[self subviews] count]; i++) + { + NSView *subview = [[self subviews] objectAtIndex:i]; + CGFloat size = [[newSubviewSizes objectForKey:[NSNumber numberWithInt:i]] floatValue]; + + NSRect subviewFrame = NSZeroRect; + + if ([self isVertical]) + { + subviewFrame.size.height = [self frame].size.height; + subviewFrame.size.width = size; + subviewFrame.origin.y = [subview frame].origin.y; + subviewFrame.origin.x = position; + } + else + { + subviewFrame.size.height = size; + subviewFrame.size.width = [self frame].size.width; + subviewFrame.origin.y = position; + subviewFrame.origin.x = [subview frame].origin.x; + } + + [subview setFrame:subviewFrame]; + + position += size; + + if (dividerCanCollapse && [self subviewIsCollapsed:subview]) + { + // Do nothing + } + else + { + position += [self dividerThickness]; + } + } +} + +- (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize +{ + if ([secondaryDelegate isKindOfClass:[BWAnchoredButtonBar class]]) + { + [self resizeAndAdjustSubviews]; + } + else if ([secondaryDelegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)]) + { + [secondaryDelegate splitView:sender resizeSubviewsWithOldSize:oldSize]; + } + else if (sender == self) + { + [self resizeAndAdjustSubviews]; + } + else + { + [sender adjustSubviews]; + } +} + +- (void)setDividerStyle:(NSSplitViewDividerStyle)aStyle +{ + [super setDividerStyle:aStyle]; + + // There can be sizing issues during design-time if we don't call this + [self adjustSubviews]; +} + +#pragma mark IB Inspector Support Methods + +- (BOOL)checkboxIsEnabled +{ + if (![self isVertical] && [super dividerThickness] > 1.01) + return NO; + + return YES; +} + +- (void)setColorIsEnabled:(BOOL)flag +{ + colorIsEnabled = flag; + + [self setNeedsDisplay:YES]; +} + +- (void)setColor:(NSColor *)aColor +{ + if (color != aColor) + { + [color release]; + color = [aColor copy]; + } + + [self setNeedsDisplay:YES]; +} + +- (NSColor *)color +{ + if (color == nil) + color = [[NSColor blackColor] retain]; + + return [[color retain] autorelease]; +} + +- (NSMutableDictionary *)minValues +{ + if (minValues == nil) + minValues = [NSMutableDictionary new]; + + return [[minValues retain] autorelease]; +} + +- (NSMutableDictionary *)maxValues +{ + if (maxValues == nil) + maxValues = [NSMutableDictionary new]; + + return [[maxValues retain] autorelease]; +} + +- (NSMutableDictionary *)minUnits +{ + if (minUnits == nil) + minUnits = [NSMutableDictionary new]; + + return [[minUnits retain] autorelease]; +} + +- (NSMutableDictionary *)maxUnits +{ + if (maxUnits == nil) + maxUnits = [NSMutableDictionary new]; + + return [[maxUnits retain] autorelease]; +} + +- (void)dealloc +{ + [color release]; + [minValues release]; + [maxValues release]; + [minUnits release]; + [maxUnits release]; + [resizableSubviewPreferredProportion release]; + [nonresizableSubviewPreferredSize release]; + [toggleCollapseButton release]; + [stateForLastPreferredCalculations release]; + + [super dealloc]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/TemplateIcon.icns b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/TemplateIcon.icns new file mode 100644 index 000000000..8ba575586 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/TemplateIcon.icns differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/project.pbxproj b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/project.pbxproj new file mode 100644 index 000000000..63d951212 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/project.pbxproj @@ -0,0 +1,782 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 53DF6901067E5B8E0090B5B0 /* All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C056398708A954F8003078D8 /* Build configuration list for PBXAggregateTarget "All" */; + buildPhases = ( + ); + dependencies = ( + 53DF6905067E5B930090B5B0 /* PBXTargetDependency */, + ); + name = All; + productName = All; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 13F8B89007B43554008AE28D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD92D38A0106425D02CA0E72 /* Cocoa.framework */; }; + CA325B4F0DCAE25A001446BB /* BWAnchoredButtonBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CA325B4D0DCAE25A001446BB /* BWAnchoredButtonBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA325B500DCAE25A001446BB /* BWAnchoredButtonBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CA325B4E0DCAE25A001446BB /* BWAnchoredButtonBar.m */; }; + CA325F040DCD91EF001446BB /* BWAnchoredButton.h in Headers */ = {isa = PBXBuildFile; fileRef = CA325F020DCD91EF001446BB /* BWAnchoredButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA325F050DCD91EF001446BB /* BWAnchoredButton.m in Sources */ = {isa = PBXBuildFile; fileRef = CA325F030DCD91EF001446BB /* BWAnchoredButton.m */; }; + CA325F080DCD9268001446BB /* BWAnchoredButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = CA325F060DCD9268001446BB /* BWAnchoredButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA325F090DCD9268001446BB /* BWAnchoredButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CA325F070DCD9268001446BB /* BWAnchoredButtonCell.m */; }; + CA4071390E0B985300B56AB7 /* BWUnanchoredButton.h in Headers */ = {isa = PBXBuildFile; fileRef = CA4071370E0B985300B56AB7 /* BWUnanchoredButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA40713A0E0B985300B56AB7 /* BWUnanchoredButton.m in Sources */ = {isa = PBXBuildFile; fileRef = CA4071380E0B985300B56AB7 /* BWUnanchoredButton.m */; }; + CA40713D0E0B986000B56AB7 /* BWUnanchoredButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = CA40713B0E0B986000B56AB7 /* BWUnanchoredButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA40713E0E0B986000B56AB7 /* BWUnanchoredButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CA40713C0E0B986000B56AB7 /* BWUnanchoredButtonCell.m */; }; + CA4071CD0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = CA4071CB0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.h */; }; + CA4071CE0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = CA4071CC0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.m */; }; + CA630A6F0DC7F6FC00AD7F9E /* TexturedSliderTrackRight.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A680DC7F6FC00AD7F9E /* TexturedSliderTrackRight.tiff */; }; + CA630A700DC7F6FC00AD7F9E /* TexturedSliderTrackFill.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A690DC7F6FC00AD7F9E /* TexturedSliderTrackFill.tiff */; }; + CA630A710DC7F6FC00AD7F9E /* TexturedSliderTrackLeft.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A6A0DC7F6FC00AD7F9E /* TexturedSliderTrackLeft.tiff */; }; + CA630A720DC7F6FC00AD7F9E /* TexturedSliderThumbP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A6B0DC7F6FC00AD7F9E /* TexturedSliderThumbP.tiff */; }; + CA630A730DC7F6FC00AD7F9E /* TexturedSliderThumbN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A6C0DC7F6FC00AD7F9E /* TexturedSliderThumbN.tiff */; }; + CA630A780DC7F74400AD7F9E /* GradientSplitViewDimpleBitmap.tif in Resources */ = {isa = PBXBuildFile; fileRef = CA630A760DC7F74400AD7F9E /* GradientSplitViewDimpleBitmap.tif */; }; + CA630A790DC7F74400AD7F9E /* GradientSplitViewDimpleVector.pdf in Resources */ = {isa = PBXBuildFile; fileRef = CA630A770DC7F74400AD7F9E /* GradientSplitViewDimpleVector.pdf */; }; + CA630A880DC7F83A00AD7F9E /* TransparentSliderThumbP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A830DC7F83A00AD7F9E /* TransparentSliderThumbP.tiff */; }; + CA630A890DC7F83A00AD7F9E /* TransparentSliderThumbN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A840DC7F83A00AD7F9E /* TransparentSliderThumbN.tiff */; }; + CA630A8A0DC7F83A00AD7F9E /* TransparentSliderTrackFill.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A850DC7F83A00AD7F9E /* TransparentSliderTrackFill.tiff */; }; + CA630A8B0DC7F83A00AD7F9E /* TransparentSliderTrackLeft.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A860DC7F83A00AD7F9E /* TransparentSliderTrackLeft.tiff */; }; + CA630A8C0DC7F83A00AD7F9E /* TransparentSliderTrackRight.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A870DC7F83A00AD7F9E /* TransparentSliderTrackRight.tiff */; }; + CA630A930DC7F84700AD7F9E /* TransparentButtonRightN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A8D0DC7F84700AD7F9E /* TransparentButtonRightN.tiff */; }; + CA630A940DC7F84700AD7F9E /* TransparentButtonFillN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A8E0DC7F84700AD7F9E /* TransparentButtonFillN.tiff */; }; + CA630A950DC7F84700AD7F9E /* TransparentButtonLeftN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A8F0DC7F84700AD7F9E /* TransparentButtonLeftN.tiff */; }; + CA630A960DC7F84700AD7F9E /* TransparentButtonRightP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A900DC7F84700AD7F9E /* TransparentButtonRightP.tiff */; }; + CA630A970DC7F84700AD7F9E /* TransparentButtonFillP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A910DC7F84700AD7F9E /* TransparentButtonFillP.tiff */; }; + CA630A980DC7F84700AD7F9E /* TransparentButtonLeftP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A920DC7F84700AD7F9E /* TransparentButtonLeftP.tiff */; }; + CA630A9D0DC7F87B00AD7F9E /* TransparentCheckboxOffN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A990DC7F87B00AD7F9E /* TransparentCheckboxOffN.tiff */; }; + CA630A9E0DC7F87B00AD7F9E /* TransparentCheckboxOffP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A9A0DC7F87B00AD7F9E /* TransparentCheckboxOffP.tiff */; }; + CA630A9F0DC7F87B00AD7F9E /* TransparentCheckboxOnN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A9B0DC7F87B00AD7F9E /* TransparentCheckboxOnN.tiff */; }; + CA630AA00DC7F87B00AD7F9E /* TransparentCheckboxOnP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630A9C0DC7F87B00AD7F9E /* TransparentCheckboxOnP.tiff */; }; + CA630AA70DC7F88A00AD7F9E /* TransparentPopUpFillN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630AA10DC7F88A00AD7F9E /* TransparentPopUpFillN.tiff */; }; + CA630AA80DC7F88A00AD7F9E /* TransparentPopUpFillP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630AA20DC7F88A00AD7F9E /* TransparentPopUpFillP.tiff */; }; + CA630AA90DC7F88A00AD7F9E /* TransparentPopUpLeftN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630AA30DC7F88A00AD7F9E /* TransparentPopUpLeftN.tiff */; }; + CA630AAA0DC7F88A00AD7F9E /* TransparentPopUpLeftP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630AA40DC7F88A00AD7F9E /* TransparentPopUpLeftP.tiff */; }; + CA630AAB0DC7F88A00AD7F9E /* TransparentPopUpRightN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630AA50DC7F88A00AD7F9E /* TransparentPopUpRightN.tiff */; }; + CA630AAC0DC7F88A00AD7F9E /* TransparentPopUpRightP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA630AA60DC7F88A00AD7F9E /* TransparentPopUpRightP.tiff */; }; + CA630AF00DC7FF0800AD7F9E /* BWAddRegularBottomBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CA630AEC0DC7FF0800AD7F9E /* BWAddRegularBottomBar.h */; }; + CA630AF10DC7FF0800AD7F9E /* BWAddRegularBottomBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CA630AED0DC7FF0800AD7F9E /* BWAddRegularBottomBar.m */; }; + CA630AF20DC7FF0800AD7F9E /* BWRemoveBottomBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CA630AEE0DC7FF0800AD7F9E /* BWRemoveBottomBar.h */; }; + CA630AF30DC7FF0800AD7F9E /* BWRemoveBottomBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CA630AEF0DC7FF0800AD7F9E /* BWRemoveBottomBar.m */; }; + CA630B1E0DC82DD600AD7F9E /* BWSplitView.h in Headers */ = {isa = PBXBuildFile; fileRef = CA630B1C0DC82DD600AD7F9E /* BWSplitView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA630B1F0DC82DD600AD7F9E /* BWSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = CA630B1D0DC82DD600AD7F9E /* BWSplitView.m */; }; + CA630CFA0DC843DD00AD7F9E /* BWAddSmallBottomBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CA630CF80DC843DD00AD7F9E /* BWAddSmallBottomBar.h */; }; + CA630CFB0DC843DD00AD7F9E /* BWAddSmallBottomBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CA630CF90DC843DD00AD7F9E /* BWAddSmallBottomBar.m */; }; + CA66C0F60EF79AC0005EE9A5 /* NSString+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CA66C0F40EF79AC0005EE9A5 /* NSString+BWAdditions.m */; }; + CA66C0F70EF79AC0005EE9A5 /* NSString+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CA66C0F50EF79AC0005EE9A5 /* NSString+BWAdditions.h */; }; + CA685EFF0E68C6CB0003D937 /* BWAddMiniBottomBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CA685EFD0E68C6CB0003D937 /* BWAddMiniBottomBar.h */; }; + CA685F000E68C6CB0003D937 /* BWAddMiniBottomBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CA685EFE0E68C6CB0003D937 /* BWAddMiniBottomBar.m */; }; + CA685F210E68C8290003D937 /* BWAddSheetBottomBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CA685F1F0E68C8290003D937 /* BWAddSheetBottomBar.h */; }; + CA685F220E68C8290003D937 /* BWAddSheetBottomBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CA685F200E68C8290003D937 /* BWAddSheetBottomBar.m */; }; + CA875ADA0DD165A500764511 /* NSColor+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CA875AD80DD165A500764511 /* NSColor+BWAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA875ADB0DD165A500764511 /* NSColor+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CA875AD90DD165A500764511 /* NSColor+BWAdditions.m */; }; + CA875CC70DD7EA3900764511 /* NSImage+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CA875CC50DD7EA3900764511 /* NSImage+BWAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA875CC80DD7EA3900764511 /* NSImage+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CA875CC60DD7EA3900764511 /* NSImage+BWAdditions.m */; }; + CA944DDA0DDF800D00F103BC /* NSWindow+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CA944DD80DDF800D00F103BC /* NSWindow+BWAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA944DDB0DDF800D00F103BC /* NSWindow+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CA944DD90DDF800D00F103BC /* NSWindow+BWAdditions.m */; }; + CA944F080DE00CC000F103BC /* NSView+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CA944F060DE00CC000F103BC /* NSView+BWAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA944F090DE00CC000F103BC /* NSView+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CA944F070DE00CC000F103BC /* NSView+BWAdditions.m */; }; + CA94521C0DE17A1A00F103BC /* TransparentSliderTriangleThumbN.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA94521A0DE17A1A00F103BC /* TransparentSliderTriangleThumbN.tiff */; }; + CA94521D0DE17A1A00F103BC /* TransparentSliderTriangleThumbP.tiff in Resources */ = {isa = PBXBuildFile; fileRef = CA94521B0DE17A1A00F103BC /* TransparentSliderTriangleThumbP.tiff */; }; + CA9453DD0DE293BC00F103BC /* BWAnchoredPopUpButton.h in Headers */ = {isa = PBXBuildFile; fileRef = CA9453DB0DE293BC00F103BC /* BWAnchoredPopUpButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA9453DE0DE293BC00F103BC /* BWAnchoredPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9453DC0DE293BC00F103BC /* BWAnchoredPopUpButton.m */; }; + CA9453E10DE293C800F103BC /* BWAnchoredPopUpButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = CA9453DF0DE293C800F103BC /* BWAnchoredPopUpButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA9453E20DE293C800F103BC /* BWAnchoredPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9453E00DE293C800F103BC /* BWAnchoredPopUpButtonCell.m */; }; + CA9919660DF9F81600FE0577 /* BWCustomView.h in Headers */ = {isa = PBXBuildFile; fileRef = CA9919640DF9F81600FE0577 /* BWCustomView.h */; }; + CA9919670DF9F81600FE0577 /* BWCustomView.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9919650DF9F81600FE0577 /* BWCustomView.m */; }; + CA991BD10DFA8B3D00FE0577 /* TexturedSliderPhotoSmall.tif in Resources */ = {isa = PBXBuildFile; fileRef = CA991BCD0DFA8B3D00FE0577 /* TexturedSliderPhotoSmall.tif */; }; + CA991BD20DFA8B3D00FE0577 /* TexturedSliderPhotoLarge.tif in Resources */ = {isa = PBXBuildFile; fileRef = CA991BCE0DFA8B3D00FE0577 /* TexturedSliderPhotoLarge.tif */; }; + CA991BD30DFA8B3D00FE0577 /* TexturedSliderSpeakerQuiet.png in Resources */ = {isa = PBXBuildFile; fileRef = CA991BCF0DFA8B3D00FE0577 /* TexturedSliderSpeakerQuiet.png */; }; + CA991BD40DFA8B3D00FE0577 /* TexturedSliderSpeakerLoud.png in Resources */ = {isa = PBXBuildFile; fileRef = CA991BD00DFA8B3D00FE0577 /* TexturedSliderSpeakerLoud.png */; }; + CA9995D90E2DE8B20001808E /* TransparentPopUpPullDownRightN.tif in Resources */ = {isa = PBXBuildFile; fileRef = CA9995D80E2DE8B20001808E /* TransparentPopUpPullDownRightN.tif */; }; + CA9995E80E2DE9C60001808E /* TransparentPopUpPullDownRightP.tif in Resources */ = {isa = PBXBuildFile; fileRef = CA9995E70E2DE9C60001808E /* TransparentPopUpPullDownRightP.tif */; }; + CAAC333A0FE5DA5700C66575 /* NSApplication+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAAC33380FE5DA5700C66575 /* NSApplication+BWAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CAAC333B0FE5DA5700C66575 /* NSApplication+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CAAC33390FE5DA5700C66575 /* NSApplication+BWAdditions.m */; }; + CAB82ED40F514F39006519E3 /* NSEvent+BWAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAB82ED20F514F39006519E3 /* NSEvent+BWAdditions.h */; }; + CAB82ED50F514F39006519E3 /* NSEvent+BWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB82ED30F514F39006519E3 /* NSEvent+BWAdditions.m */; }; + CACEBC7B0E178524003E3CB2 /* NSCustomView.h in Headers */ = {isa = PBXBuildFile; fileRef = CACEBC7A0E178524003E3CB2 /* NSCustomView.h */; }; + CAEB146B0F4A534300E57E67 /* BWToolkitFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = CAEB146A0F4A534300E57E67 /* BWToolkitFramework.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CAEB14750F4A538100E57E67 /* License.rtf in Resources */ = {isa = PBXBuildFile; fileRef = CAEB14740F4A538100E57E67 /* License.rtf */; }; + CAEB14770F4A538A00E57E67 /* Release Notes.rtf in Resources */ = {isa = PBXBuildFile; fileRef = CAEB14760F4A538A00E57E67 /* Release Notes.rtf */; }; + CAF6B8450E049A6500CA1768 /* ButtonBarPullDownArrow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = CAF6B8440E049A6500CA1768 /* ButtonBarPullDownArrow.pdf */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 53DF6904067E5B930090B5B0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0259C573FE90428111CA0C5A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 53DF68FC067E5B5A0090B5B0; + remoteInfo = BWToolkitFramework; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 13F8B88807B434F6008AE28D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 13F8B88907B434F6008AE28D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + 13F8B88A07B434F6008AE28D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 53DF68FD067E5B5A0090B5B0 /* BWToolkitFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BWToolkitFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 53DF68FE067E5B5A0090B5B0 /* BWToolkitFramework-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BWToolkitFramework-Info.plist"; sourceTree = ""; }; + 8D1AC9730486D14A00FE50C9 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8D1AC97B0486D23100FE50C9 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + C0D069550A49DF9100C95564 /* InterfaceBuilderKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InterfaceBuilderKit.framework; path = /Developer/Library/Frameworks/InterfaceBuilderKit.framework; sourceTree = ""; }; + CA325B4D0DCAE25A001446BB /* BWAnchoredButtonBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAnchoredButtonBar.h; sourceTree = ""; }; + CA325B4E0DCAE25A001446BB /* BWAnchoredButtonBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAnchoredButtonBar.m; sourceTree = ""; }; + CA325F020DCD91EF001446BB /* BWAnchoredButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAnchoredButton.h; sourceTree = ""; }; + CA325F030DCD91EF001446BB /* BWAnchoredButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAnchoredButton.m; sourceTree = ""; }; + CA325F060DCD9268001446BB /* BWAnchoredButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAnchoredButtonCell.h; sourceTree = ""; }; + CA325F070DCD9268001446BB /* BWAnchoredButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAnchoredButtonCell.m; sourceTree = ""; }; + CA4071370E0B985300B56AB7 /* BWUnanchoredButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWUnanchoredButton.h; sourceTree = ""; }; + CA4071380E0B985300B56AB7 /* BWUnanchoredButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWUnanchoredButton.m; sourceTree = ""; }; + CA40713B0E0B986000B56AB7 /* BWUnanchoredButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWUnanchoredButtonCell.h; sourceTree = ""; }; + CA40713C0E0B986000B56AB7 /* BWUnanchoredButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWUnanchoredButtonCell.m; sourceTree = ""; }; + CA4071CB0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWUnanchoredButtonContainer.h; sourceTree = ""; }; + CA4071CC0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWUnanchoredButtonContainer.m; sourceTree = ""; }; + CA630A680DC7F6FC00AD7F9E /* TexturedSliderTrackRight.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderTrackRight.tiff; sourceTree = ""; }; + CA630A690DC7F6FC00AD7F9E /* TexturedSliderTrackFill.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderTrackFill.tiff; sourceTree = ""; }; + CA630A6A0DC7F6FC00AD7F9E /* TexturedSliderTrackLeft.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderTrackLeft.tiff; sourceTree = ""; }; + CA630A6B0DC7F6FC00AD7F9E /* TexturedSliderThumbP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderThumbP.tiff; sourceTree = ""; }; + CA630A6C0DC7F6FC00AD7F9E /* TexturedSliderThumbN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderThumbN.tiff; sourceTree = ""; }; + CA630A760DC7F74400AD7F9E /* GradientSplitViewDimpleBitmap.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GradientSplitViewDimpleBitmap.tif; sourceTree = ""; }; + CA630A770DC7F74400AD7F9E /* GradientSplitViewDimpleVector.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = GradientSplitViewDimpleVector.pdf; sourceTree = ""; }; + CA630A830DC7F83A00AD7F9E /* TransparentSliderThumbP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderThumbP.tiff; sourceTree = ""; }; + CA630A840DC7F83A00AD7F9E /* TransparentSliderThumbN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderThumbN.tiff; sourceTree = ""; }; + CA630A850DC7F83A00AD7F9E /* TransparentSliderTrackFill.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderTrackFill.tiff; sourceTree = ""; }; + CA630A860DC7F83A00AD7F9E /* TransparentSliderTrackLeft.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderTrackLeft.tiff; sourceTree = ""; }; + CA630A870DC7F83A00AD7F9E /* TransparentSliderTrackRight.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderTrackRight.tiff; sourceTree = ""; }; + CA630A8D0DC7F84700AD7F9E /* TransparentButtonRightN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentButtonRightN.tiff; sourceTree = ""; }; + CA630A8E0DC7F84700AD7F9E /* TransparentButtonFillN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentButtonFillN.tiff; sourceTree = ""; }; + CA630A8F0DC7F84700AD7F9E /* TransparentButtonLeftN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentButtonLeftN.tiff; sourceTree = ""; }; + CA630A900DC7F84700AD7F9E /* TransparentButtonRightP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentButtonRightP.tiff; sourceTree = ""; }; + CA630A910DC7F84700AD7F9E /* TransparentButtonFillP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentButtonFillP.tiff; sourceTree = ""; }; + CA630A920DC7F84700AD7F9E /* TransparentButtonLeftP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentButtonLeftP.tiff; sourceTree = ""; }; + CA630A990DC7F87B00AD7F9E /* TransparentCheckboxOffN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentCheckboxOffN.tiff; sourceTree = ""; }; + CA630A9A0DC7F87B00AD7F9E /* TransparentCheckboxOffP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentCheckboxOffP.tiff; sourceTree = ""; }; + CA630A9B0DC7F87B00AD7F9E /* TransparentCheckboxOnN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentCheckboxOnN.tiff; sourceTree = ""; }; + CA630A9C0DC7F87B00AD7F9E /* TransparentCheckboxOnP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentCheckboxOnP.tiff; sourceTree = ""; }; + CA630AA10DC7F88A00AD7F9E /* TransparentPopUpFillN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpFillN.tiff; sourceTree = ""; }; + CA630AA20DC7F88A00AD7F9E /* TransparentPopUpFillP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpFillP.tiff; sourceTree = ""; }; + CA630AA30DC7F88A00AD7F9E /* TransparentPopUpLeftN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpLeftN.tiff; sourceTree = ""; }; + CA630AA40DC7F88A00AD7F9E /* TransparentPopUpLeftP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpLeftP.tiff; sourceTree = ""; }; + CA630AA50DC7F88A00AD7F9E /* TransparentPopUpRightN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpRightN.tiff; sourceTree = ""; }; + CA630AA60DC7F88A00AD7F9E /* TransparentPopUpRightP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpRightP.tiff; sourceTree = ""; }; + CA630AEC0DC7FF0800AD7F9E /* BWAddRegularBottomBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAddRegularBottomBar.h; sourceTree = ""; }; + CA630AED0DC7FF0800AD7F9E /* BWAddRegularBottomBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAddRegularBottomBar.m; sourceTree = ""; }; + CA630AEE0DC7FF0800AD7F9E /* BWRemoveBottomBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWRemoveBottomBar.h; sourceTree = ""; }; + CA630AEF0DC7FF0800AD7F9E /* BWRemoveBottomBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWRemoveBottomBar.m; sourceTree = ""; }; + CA630B1C0DC82DD600AD7F9E /* BWSplitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWSplitView.h; sourceTree = ""; }; + CA630B1D0DC82DD600AD7F9E /* BWSplitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWSplitView.m; sourceTree = ""; }; + CA630CF80DC843DD00AD7F9E /* BWAddSmallBottomBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAddSmallBottomBar.h; sourceTree = ""; }; + CA630CF90DC843DD00AD7F9E /* BWAddSmallBottomBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAddSmallBottomBar.m; sourceTree = ""; }; + CA66C0F40EF79AC0005EE9A5 /* NSString+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+BWAdditions.m"; sourceTree = ""; }; + CA66C0F50EF79AC0005EE9A5 /* NSString+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+BWAdditions.h"; sourceTree = ""; }; + CA685EFD0E68C6CB0003D937 /* BWAddMiniBottomBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAddMiniBottomBar.h; sourceTree = ""; }; + CA685EFE0E68C6CB0003D937 /* BWAddMiniBottomBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAddMiniBottomBar.m; sourceTree = ""; }; + CA685F1F0E68C8290003D937 /* BWAddSheetBottomBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAddSheetBottomBar.h; sourceTree = ""; }; + CA685F200E68C8290003D937 /* BWAddSheetBottomBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAddSheetBottomBar.m; sourceTree = ""; }; + CA875AD80DD165A500764511 /* NSColor+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSColor+BWAdditions.h"; sourceTree = ""; }; + CA875AD90DD165A500764511 /* NSColor+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSColor+BWAdditions.m"; sourceTree = ""; }; + CA875CC50DD7EA3900764511 /* NSImage+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage+BWAdditions.h"; sourceTree = ""; }; + CA875CC60DD7EA3900764511 /* NSImage+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSImage+BWAdditions.m"; sourceTree = ""; }; + CA944DD80DDF800D00F103BC /* NSWindow+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSWindow+BWAdditions.h"; sourceTree = ""; }; + CA944DD90DDF800D00F103BC /* NSWindow+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSWindow+BWAdditions.m"; sourceTree = ""; }; + CA944F060DE00CC000F103BC /* NSView+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+BWAdditions.h"; sourceTree = ""; }; + CA944F070DE00CC000F103BC /* NSView+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+BWAdditions.m"; sourceTree = ""; }; + CA94521A0DE17A1A00F103BC /* TransparentSliderTriangleThumbN.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderTriangleThumbN.tiff; sourceTree = ""; }; + CA94521B0DE17A1A00F103BC /* TransparentSliderTriangleThumbP.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentSliderTriangleThumbP.tiff; sourceTree = ""; }; + CA9453DB0DE293BC00F103BC /* BWAnchoredPopUpButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAnchoredPopUpButton.h; sourceTree = ""; }; + CA9453DC0DE293BC00F103BC /* BWAnchoredPopUpButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAnchoredPopUpButton.m; sourceTree = ""; }; + CA9453DF0DE293C800F103BC /* BWAnchoredPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAnchoredPopUpButtonCell.h; sourceTree = ""; }; + CA9453E00DE293C800F103BC /* BWAnchoredPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAnchoredPopUpButtonCell.m; sourceTree = ""; }; + CA9919640DF9F81600FE0577 /* BWCustomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWCustomView.h; sourceTree = ""; }; + CA9919650DF9F81600FE0577 /* BWCustomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWCustomView.m; sourceTree = ""; }; + CA991BCD0DFA8B3D00FE0577 /* TexturedSliderPhotoSmall.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderPhotoSmall.tif; sourceTree = ""; }; + CA991BCE0DFA8B3D00FE0577 /* TexturedSliderPhotoLarge.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TexturedSliderPhotoLarge.tif; sourceTree = ""; }; + CA991BCF0DFA8B3D00FE0577 /* TexturedSliderSpeakerQuiet.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TexturedSliderSpeakerQuiet.png; sourceTree = ""; }; + CA991BD00DFA8B3D00FE0577 /* TexturedSliderSpeakerLoud.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TexturedSliderSpeakerLoud.png; sourceTree = ""; }; + CA9995D80E2DE8B20001808E /* TransparentPopUpPullDownRightN.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpPullDownRightN.tif; sourceTree = ""; }; + CA9995E70E2DE9C60001808E /* TransparentPopUpPullDownRightP.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TransparentPopUpPullDownRightP.tif; sourceTree = ""; }; + CAAC33380FE5DA5700C66575 /* NSApplication+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSApplication+BWAdditions.h"; sourceTree = ""; }; + CAAC33390FE5DA5700C66575 /* NSApplication+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSApplication+BWAdditions.m"; sourceTree = ""; }; + CAB82ED20F514F39006519E3 /* NSEvent+BWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSEvent+BWAdditions.h"; sourceTree = ""; }; + CAB82ED30F514F39006519E3 /* NSEvent+BWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSEvent+BWAdditions.m"; sourceTree = ""; }; + CACEBC7A0E178524003E3CB2 /* NSCustomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCustomView.h; sourceTree = ""; }; + CAEB146A0F4A534300E57E67 /* BWToolkitFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWToolkitFramework.h; sourceTree = ""; }; + CAEB14740F4A538100E57E67 /* License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = License.rtf; sourceTree = ""; }; + CAEB14760F4A538A00E57E67 /* Release Notes.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Release Notes.rtf"; sourceTree = ""; }; + CAF6B8440E049A6500CA1768 /* ButtonBarPullDownArrow.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ButtonBarPullDownArrow.pdf; sourceTree = ""; }; + DD92D38A0106425D02CA0E72 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 53DF68FB067E5B5A0090B5B0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 13F8B89007B43554008AE28D /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0259C574FE90428111CA0C5A /* BWToolkit */ = { + isa = PBXGroup; + children = ( + 54D33B2C06778E4400C9C163 /* Framework */, + 0259C582FE90428111CA0C5A /* Resources */, + 1ED78706FE9D4A0611CA0C5A /* Products */, + 2E58F364FFB232C311CA0CBA /* Frameworks */, + ); + name = BWToolkit; + sourceTree = ""; + }; + 0259C582FE90428111CA0C5A /* Resources */ = { + isa = PBXGroup; + children = ( + CAEB14760F4A538A00E57E67 /* Release Notes.rtf */, + CAEB14740F4A538100E57E67 /* License.rtf */, + 8D1AC9730486D14A00FE50C9 /* Info.plist */, + 53DF68FE067E5B5A0090B5B0 /* BWToolkitFramework-Info.plist */, + 8D1AC97F0486D23B00FE50C9 /* InfoPlist.strings */, + ); + name = Resources; + sourceTree = ""; + }; + 13F8B6FD07B43410008AE28D /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + DD92D38A0106425D02CA0E72 /* Cocoa.framework */, + C0D069550A49DF9100C95564 /* InterfaceBuilderKit.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 13F8B70407B43425008AE28D /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 13F8B88807B434F6008AE28D /* AppKit.framework */, + 13F8B88907B434F6008AE28D /* CoreData.framework */, + 13F8B88A07B434F6008AE28D /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 1ED78706FE9D4A0611CA0C5A /* Products */ = { + isa = PBXGroup; + children = ( + 53DF68FD067E5B5A0090B5B0 /* BWToolkitFramework.framework */, + ); + name = Products; + sourceTree = ""; + }; + 2E58F364FFB232C311CA0CBA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 13F8B6FD07B43410008AE28D /* Linked Frameworks */, + 13F8B70407B43425008AE28D /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 54D33B2C06778E4400C9C163 /* Framework */ = { + isa = PBXGroup; + children = ( + CA630A630DC7F67F00AD7F9E /* Graphics */, + CA630AAD0DC7F8ED00AD7F9E /* Classes */, + C0894DA40C32F4C100401507 /* Categories */, + CACEBC780E17759C003E3CB2 /* Private Cocoa Headers */, + ); + name = Framework; + sourceTree = ""; + }; + C0894DA40C32F4C100401507 /* Categories */ = { + isa = PBXGroup; + children = ( + CA875AD80DD165A500764511 /* NSColor+BWAdditions.h */, + CA875AD90DD165A500764511 /* NSColor+BWAdditions.m */, + CA875CC50DD7EA3900764511 /* NSImage+BWAdditions.h */, + CA875CC60DD7EA3900764511 /* NSImage+BWAdditions.m */, + CA944DD80DDF800D00F103BC /* NSWindow+BWAdditions.h */, + CA944DD90DDF800D00F103BC /* NSWindow+BWAdditions.m */, + CA944F060DE00CC000F103BC /* NSView+BWAdditions.h */, + CA944F070DE00CC000F103BC /* NSView+BWAdditions.m */, + CAB82ED20F514F39006519E3 /* NSEvent+BWAdditions.h */, + CAB82ED30F514F39006519E3 /* NSEvent+BWAdditions.m */, + CA66C0F50EF79AC0005EE9A5 /* NSString+BWAdditions.h */, + CA66C0F40EF79AC0005EE9A5 /* NSString+BWAdditions.m */, + CAAC33380FE5DA5700C66575 /* NSApplication+BWAdditions.h */, + CAAC33390FE5DA5700C66575 /* NSApplication+BWAdditions.m */, + ); + name = Categories; + sourceTree = ""; + }; + CA325ABD0DCAB76C001446BB /* Button Bar */ = { + isa = PBXGroup; + children = ( + CA325B4D0DCAE25A001446BB /* BWAnchoredButtonBar.h */, + CA325B4E0DCAE25A001446BB /* BWAnchoredButtonBar.m */, + CA325F020DCD91EF001446BB /* BWAnchoredButton.h */, + CA325F030DCD91EF001446BB /* BWAnchoredButton.m */, + CA325F060DCD9268001446BB /* BWAnchoredButtonCell.h */, + CA325F070DCD9268001446BB /* BWAnchoredButtonCell.m */, + CA9453DB0DE293BC00F103BC /* BWAnchoredPopUpButton.h */, + CA9453DC0DE293BC00F103BC /* BWAnchoredPopUpButton.m */, + CA9453DF0DE293C800F103BC /* BWAnchoredPopUpButtonCell.h */, + CA9453E00DE293C800F103BC /* BWAnchoredPopUpButtonCell.m */, + CA4071CB0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.h */, + CA4071CC0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.m */, + CA4071370E0B985300B56AB7 /* BWUnanchoredButton.h */, + CA4071380E0B985300B56AB7 /* BWUnanchoredButton.m */, + CA40713B0E0B986000B56AB7 /* BWUnanchoredButtonCell.h */, + CA40713C0E0B986000B56AB7 /* BWUnanchoredButtonCell.m */, + ); + name = "Button Bar"; + sourceTree = ""; + }; + CA630A630DC7F67F00AD7F9E /* Graphics */ = { + isa = PBXGroup; + children = ( + CAF6B8060E049A3100CA1768 /* Button Bar */, + CA630A670DC7F6E300AD7F9E /* Textured Slider */, + CA630A660DC7F6D300AD7F9E /* Split View */, + CA630A640DC7F6BA00AD7F9E /* Toolbar Items */, + CA630A650DC7F6C300AD7F9E /* Transparent Controls */, + ); + name = Graphics; + sourceTree = ""; + }; + CA630A640DC7F6BA00AD7F9E /* Toolbar Items */ = { + isa = PBXGroup; + children = ( + ); + name = "Toolbar Items"; + sourceTree = ""; + }; + CA630A650DC7F6C300AD7F9E /* Transparent Controls */ = { + isa = PBXGroup; + children = ( + CA630A820DC7F80900AD7F9E /* Slider */, + CA630A810DC7F80400AD7F9E /* Button */, + CA630A800DC7F7FD00AD7F9E /* Check Box */, + CA630A7F0DC7F7F700AD7F9E /* Pop Up */, + ); + name = "Transparent Controls"; + sourceTree = ""; + }; + CA630A660DC7F6D300AD7F9E /* Split View */ = { + isa = PBXGroup; + children = ( + CA630A760DC7F74400AD7F9E /* GradientSplitViewDimpleBitmap.tif */, + CA630A770DC7F74400AD7F9E /* GradientSplitViewDimpleVector.pdf */, + ); + name = "Split View"; + sourceTree = ""; + }; + CA630A670DC7F6E300AD7F9E /* Textured Slider */ = { + isa = PBXGroup; + children = ( + CA991BCD0DFA8B3D00FE0577 /* TexturedSliderPhotoSmall.tif */, + CA991BCE0DFA8B3D00FE0577 /* TexturedSliderPhotoLarge.tif */, + CA991BCF0DFA8B3D00FE0577 /* TexturedSliderSpeakerQuiet.png */, + CA991BD00DFA8B3D00FE0577 /* TexturedSliderSpeakerLoud.png */, + CA630A680DC7F6FC00AD7F9E /* TexturedSliderTrackRight.tiff */, + CA630A690DC7F6FC00AD7F9E /* TexturedSliderTrackFill.tiff */, + CA630A6A0DC7F6FC00AD7F9E /* TexturedSliderTrackLeft.tiff */, + CA630A6B0DC7F6FC00AD7F9E /* TexturedSliderThumbP.tiff */, + CA630A6C0DC7F6FC00AD7F9E /* TexturedSliderThumbN.tiff */, + ); + name = "Textured Slider"; + sourceTree = ""; + }; + CA630A7F0DC7F7F700AD7F9E /* Pop Up */ = { + isa = PBXGroup; + children = ( + CA630AA10DC7F88A00AD7F9E /* TransparentPopUpFillN.tiff */, + CA630AA20DC7F88A00AD7F9E /* TransparentPopUpFillP.tiff */, + CA630AA30DC7F88A00AD7F9E /* TransparentPopUpLeftN.tiff */, + CA630AA40DC7F88A00AD7F9E /* TransparentPopUpLeftP.tiff */, + CA630AA50DC7F88A00AD7F9E /* TransparentPopUpRightN.tiff */, + CA630AA60DC7F88A00AD7F9E /* TransparentPopUpRightP.tiff */, + CA9995D80E2DE8B20001808E /* TransparentPopUpPullDownRightN.tif */, + CA9995E70E2DE9C60001808E /* TransparentPopUpPullDownRightP.tif */, + ); + name = "Pop Up"; + sourceTree = ""; + }; + CA630A800DC7F7FD00AD7F9E /* Check Box */ = { + isa = PBXGroup; + children = ( + CA630A990DC7F87B00AD7F9E /* TransparentCheckboxOffN.tiff */, + CA630A9A0DC7F87B00AD7F9E /* TransparentCheckboxOffP.tiff */, + CA630A9B0DC7F87B00AD7F9E /* TransparentCheckboxOnN.tiff */, + CA630A9C0DC7F87B00AD7F9E /* TransparentCheckboxOnP.tiff */, + ); + name = "Check Box"; + sourceTree = ""; + }; + CA630A810DC7F80400AD7F9E /* Button */ = { + isa = PBXGroup; + children = ( + CA630A8D0DC7F84700AD7F9E /* TransparentButtonRightN.tiff */, + CA630A8E0DC7F84700AD7F9E /* TransparentButtonFillN.tiff */, + CA630A8F0DC7F84700AD7F9E /* TransparentButtonLeftN.tiff */, + CA630A900DC7F84700AD7F9E /* TransparentButtonRightP.tiff */, + CA630A910DC7F84700AD7F9E /* TransparentButtonFillP.tiff */, + CA630A920DC7F84700AD7F9E /* TransparentButtonLeftP.tiff */, + ); + name = Button; + sourceTree = ""; + }; + CA630A820DC7F80900AD7F9E /* Slider */ = { + isa = PBXGroup; + children = ( + CA94521A0DE17A1A00F103BC /* TransparentSliderTriangleThumbN.tiff */, + CA94521B0DE17A1A00F103BC /* TransparentSliderTriangleThumbP.tiff */, + CA630A830DC7F83A00AD7F9E /* TransparentSliderThumbP.tiff */, + CA630A840DC7F83A00AD7F9E /* TransparentSliderThumbN.tiff */, + CA630A850DC7F83A00AD7F9E /* TransparentSliderTrackFill.tiff */, + CA630A860DC7F83A00AD7F9E /* TransparentSliderTrackLeft.tiff */, + CA630A870DC7F83A00AD7F9E /* TransparentSliderTrackRight.tiff */, + ); + name = Slider; + sourceTree = ""; + }; + CA630AAD0DC7F8ED00AD7F9E /* Classes */ = { + isa = PBXGroup; + children = ( + CAEB146A0F4A534300E57E67 /* BWToolkitFramework.h */, + CA325ABD0DCAB76C001446BB /* Button Bar */, + CA630ABA0DC7F97C00AD7F9E /* Bottom Bar */, + CA630AB70DC7F95D00AD7F9E /* Split View */, + ); + name = Classes; + sourceTree = ""; + }; + CA630AB70DC7F95D00AD7F9E /* Split View */ = { + isa = PBXGroup; + children = ( + CA630B1C0DC82DD600AD7F9E /* BWSplitView.h */, + CA630B1D0DC82DD600AD7F9E /* BWSplitView.m */, + CA9919640DF9F81600FE0577 /* BWCustomView.h */, + CA9919650DF9F81600FE0577 /* BWCustomView.m */, + ); + name = "Split View"; + sourceTree = ""; + }; + CA630ABA0DC7F97C00AD7F9E /* Bottom Bar */ = { + isa = PBXGroup; + children = ( + CA630AEC0DC7FF0800AD7F9E /* BWAddRegularBottomBar.h */, + CA630AED0DC7FF0800AD7F9E /* BWAddRegularBottomBar.m */, + CA630CF80DC843DD00AD7F9E /* BWAddSmallBottomBar.h */, + CA630CF90DC843DD00AD7F9E /* BWAddSmallBottomBar.m */, + CA685EFD0E68C6CB0003D937 /* BWAddMiniBottomBar.h */, + CA685EFE0E68C6CB0003D937 /* BWAddMiniBottomBar.m */, + CA685F1F0E68C8290003D937 /* BWAddSheetBottomBar.h */, + CA685F200E68C8290003D937 /* BWAddSheetBottomBar.m */, + CA630AEE0DC7FF0800AD7F9E /* BWRemoveBottomBar.h */, + CA630AEF0DC7FF0800AD7F9E /* BWRemoveBottomBar.m */, + ); + name = "Bottom Bar"; + sourceTree = ""; + }; + CACEBC780E17759C003E3CB2 /* Private Cocoa Headers */ = { + isa = PBXGroup; + children = ( + CACEBC7A0E178524003E3CB2 /* NSCustomView.h */, + ); + name = "Private Cocoa Headers"; + sourceTree = ""; + }; + CAF6B8060E049A3100CA1768 /* Button Bar */ = { + isa = PBXGroup; + children = ( + CAF6B8440E049A6500CA1768 /* ButtonBarPullDownArrow.pdf */, + ); + name = "Button Bar"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 53DF68F8067E5B5A0090B5B0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CA630AF00DC7FF0800AD7F9E /* BWAddRegularBottomBar.h in Headers */, + CA630AF20DC7FF0800AD7F9E /* BWRemoveBottomBar.h in Headers */, + CA630B1E0DC82DD600AD7F9E /* BWSplitView.h in Headers */, + CA630CFA0DC843DD00AD7F9E /* BWAddSmallBottomBar.h in Headers */, + CA325B4F0DCAE25A001446BB /* BWAnchoredButtonBar.h in Headers */, + CA325F040DCD91EF001446BB /* BWAnchoredButton.h in Headers */, + CA325F080DCD9268001446BB /* BWAnchoredButtonCell.h in Headers */, + CA875ADA0DD165A500764511 /* NSColor+BWAdditions.h in Headers */, + CA875CC70DD7EA3900764511 /* NSImage+BWAdditions.h in Headers */, + CA944DDA0DDF800D00F103BC /* NSWindow+BWAdditions.h in Headers */, + CA944F080DE00CC000F103BC /* NSView+BWAdditions.h in Headers */, + CA9453DD0DE293BC00F103BC /* BWAnchoredPopUpButton.h in Headers */, + CA9453E10DE293C800F103BC /* BWAnchoredPopUpButtonCell.h in Headers */, + CA9919660DF9F81600FE0577 /* BWCustomView.h in Headers */, + CA4071390E0B985300B56AB7 /* BWUnanchoredButton.h in Headers */, + CA40713D0E0B986000B56AB7 /* BWUnanchoredButtonCell.h in Headers */, + CA4071CD0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.h in Headers */, + CACEBC7B0E178524003E3CB2 /* NSCustomView.h in Headers */, + CA685EFF0E68C6CB0003D937 /* BWAddMiniBottomBar.h in Headers */, + CA685F210E68C8290003D937 /* BWAddSheetBottomBar.h in Headers */, + CA66C0F70EF79AC0005EE9A5 /* NSString+BWAdditions.h in Headers */, + CAEB146B0F4A534300E57E67 /* BWToolkitFramework.h in Headers */, + CAB82ED40F514F39006519E3 /* NSEvent+BWAdditions.h in Headers */, + CAAC333A0FE5DA5700C66575 /* NSApplication+BWAdditions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 53DF68FC067E5B5A0090B5B0 /* BWToolkitFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = C056397F08A954F8003078D8 /* Build configuration list for PBXNativeTarget "BWToolkitFramework" */; + buildPhases = ( + 53DF68F8067E5B5A0090B5B0 /* Headers */, + 53DF68F9067E5B5A0090B5B0 /* Resources */, + 53DF68FA067E5B5A0090B5B0 /* Sources */, + 53DF68FB067E5B5A0090B5B0 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BWToolkitFramework; + productName = BWToolkitFramework; + productReference = 53DF68FD067E5B5A0090B5B0 /* BWToolkitFramework.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0259C573FE90428111CA0C5A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = C056398B08A954F8003078D8 /* Build configuration list for PBXProject "BWToolkit" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 0259C574FE90428111CA0C5A /* BWToolkit */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 53DF6901067E5B8E0090B5B0 /* All */, + 53DF68FC067E5B5A0090B5B0 /* BWToolkitFramework */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 53DF68F9067E5B5A0090B5B0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CA630A6F0DC7F6FC00AD7F9E /* TexturedSliderTrackRight.tiff in Resources */, + CA630A700DC7F6FC00AD7F9E /* TexturedSliderTrackFill.tiff in Resources */, + CA630A710DC7F6FC00AD7F9E /* TexturedSliderTrackLeft.tiff in Resources */, + CA630A720DC7F6FC00AD7F9E /* TexturedSliderThumbP.tiff in Resources */, + CA630A730DC7F6FC00AD7F9E /* TexturedSliderThumbN.tiff in Resources */, + CA630A780DC7F74400AD7F9E /* GradientSplitViewDimpleBitmap.tif in Resources */, + CA630A790DC7F74400AD7F9E /* GradientSplitViewDimpleVector.pdf in Resources */, + CA630A880DC7F83A00AD7F9E /* TransparentSliderThumbP.tiff in Resources */, + CA630A890DC7F83A00AD7F9E /* TransparentSliderThumbN.tiff in Resources */, + CA630A8A0DC7F83A00AD7F9E /* TransparentSliderTrackFill.tiff in Resources */, + CA630A8B0DC7F83A00AD7F9E /* TransparentSliderTrackLeft.tiff in Resources */, + CA630A8C0DC7F83A00AD7F9E /* TransparentSliderTrackRight.tiff in Resources */, + CA630A930DC7F84700AD7F9E /* TransparentButtonRightN.tiff in Resources */, + CA630A940DC7F84700AD7F9E /* TransparentButtonFillN.tiff in Resources */, + CA630A950DC7F84700AD7F9E /* TransparentButtonLeftN.tiff in Resources */, + CA630A960DC7F84700AD7F9E /* TransparentButtonRightP.tiff in Resources */, + CA630A970DC7F84700AD7F9E /* TransparentButtonFillP.tiff in Resources */, + CA630A980DC7F84700AD7F9E /* TransparentButtonLeftP.tiff in Resources */, + CA630A9D0DC7F87B00AD7F9E /* TransparentCheckboxOffN.tiff in Resources */, + CA630A9E0DC7F87B00AD7F9E /* TransparentCheckboxOffP.tiff in Resources */, + CA630A9F0DC7F87B00AD7F9E /* TransparentCheckboxOnN.tiff in Resources */, + CA630AA00DC7F87B00AD7F9E /* TransparentCheckboxOnP.tiff in Resources */, + CA630AA70DC7F88A00AD7F9E /* TransparentPopUpFillN.tiff in Resources */, + CA630AA80DC7F88A00AD7F9E /* TransparentPopUpFillP.tiff in Resources */, + CA630AA90DC7F88A00AD7F9E /* TransparentPopUpLeftN.tiff in Resources */, + CA630AAA0DC7F88A00AD7F9E /* TransparentPopUpLeftP.tiff in Resources */, + CA630AAB0DC7F88A00AD7F9E /* TransparentPopUpRightN.tiff in Resources */, + CA630AAC0DC7F88A00AD7F9E /* TransparentPopUpRightP.tiff in Resources */, + CA94521C0DE17A1A00F103BC /* TransparentSliderTriangleThumbN.tiff in Resources */, + CA94521D0DE17A1A00F103BC /* TransparentSliderTriangleThumbP.tiff in Resources */, + CA991BD10DFA8B3D00FE0577 /* TexturedSliderPhotoSmall.tif in Resources */, + CA991BD20DFA8B3D00FE0577 /* TexturedSliderPhotoLarge.tif in Resources */, + CA991BD30DFA8B3D00FE0577 /* TexturedSliderSpeakerQuiet.png in Resources */, + CA991BD40DFA8B3D00FE0577 /* TexturedSliderSpeakerLoud.png in Resources */, + CAF6B8450E049A6500CA1768 /* ButtonBarPullDownArrow.pdf in Resources */, + CA9995D90E2DE8B20001808E /* TransparentPopUpPullDownRightN.tif in Resources */, + CA9995E80E2DE9C60001808E /* TransparentPopUpPullDownRightP.tif in Resources */, + CAEB14750F4A538100E57E67 /* License.rtf in Resources */, + CAEB14770F4A538A00E57E67 /* Release Notes.rtf in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 53DF68FA067E5B5A0090B5B0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CA630AF10DC7FF0800AD7F9E /* BWAddRegularBottomBar.m in Sources */, + CA630AF30DC7FF0800AD7F9E /* BWRemoveBottomBar.m in Sources */, + CA630B1F0DC82DD600AD7F9E /* BWSplitView.m in Sources */, + CA630CFB0DC843DD00AD7F9E /* BWAddSmallBottomBar.m in Sources */, + CA325B500DCAE25A001446BB /* BWAnchoredButtonBar.m in Sources */, + CA325F050DCD91EF001446BB /* BWAnchoredButton.m in Sources */, + CA325F090DCD9268001446BB /* BWAnchoredButtonCell.m in Sources */, + CA875ADB0DD165A500764511 /* NSColor+BWAdditions.m in Sources */, + CA875CC80DD7EA3900764511 /* NSImage+BWAdditions.m in Sources */, + CA944DDB0DDF800D00F103BC /* NSWindow+BWAdditions.m in Sources */, + CA944F090DE00CC000F103BC /* NSView+BWAdditions.m in Sources */, + CA9453DE0DE293BC00F103BC /* BWAnchoredPopUpButton.m in Sources */, + CA9453E20DE293C800F103BC /* BWAnchoredPopUpButtonCell.m in Sources */, + CA9919670DF9F81600FE0577 /* BWCustomView.m in Sources */, + CA40713A0E0B985300B56AB7 /* BWUnanchoredButton.m in Sources */, + CA40713E0E0B986000B56AB7 /* BWUnanchoredButtonCell.m in Sources */, + CA4071CE0E0ED32300B56AB7 /* BWUnanchoredButtonContainer.m in Sources */, + CA685F000E68C6CB0003D937 /* BWAddMiniBottomBar.m in Sources */, + CA685F220E68C8290003D937 /* BWAddSheetBottomBar.m in Sources */, + CA66C0F60EF79AC0005EE9A5 /* NSString+BWAdditions.m in Sources */, + CAB82ED50F514F39006519E3 /* NSEvent+BWAdditions.m in Sources */, + CAAC333B0FE5DA5700C66575 /* NSApplication+BWAdditions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 53DF6905067E5B930090B5B0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 53DF68FC067E5B5A0090B5B0 /* BWToolkitFramework */; + targetProxy = 53DF6904067E5B930090B5B0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 8D1AC97F0486D23B00FE50C9 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 8D1AC97B0486D23100FE50C9 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + C056398008A954F8003078D8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "BWToolkitFramework-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = BWToolkitFramework; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C056398108A954F8003078D8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "BWToolkitFramework-Info.plist"; + INSTALL_MODE_FLAG = "go-w,a+rX"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = BWToolkitFramework; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C056398808A954F8003078D8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C056398908A954F8003078D8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C056398C08A954F8003078D8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + C056398D08A954F8003078D8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C056397F08A954F8003078D8 /* Build configuration list for PBXNativeTarget "BWToolkitFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C056398008A954F8003078D8 /* Debug */, + C056398108A954F8003078D8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C056398708A954F8003078D8 /* Build configuration list for PBXAggregateTarget "All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C056398808A954F8003078D8 /* Debug */, + C056398908A954F8003078D8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C056398B08A954F8003078D8 /* Build configuration list for PBXProject "BWToolkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C056398C08A954F8003078D8 /* Debug */, + C056398D08A954F8003078D8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0259C573FE90428111CA0C5A /* Project object */; +} diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..30c232ca0 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkit.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkitFramework-Info.plist b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkitFramework-Info.plist new file mode 100644 index 000000000..3f250ff7f --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkitFramework-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + BWToolkitFramework + CFBundleIdentifier + com.brandonwalkin.BWToolkitFramework + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.2.5 + NSPrincipalClass + BWToolkit + + diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkitFramework.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkitFramework.h new file mode 100644 index 000000000..6d2088e88 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWToolkitFramework.h @@ -0,0 +1,18 @@ +// +// BWToolkitFramework.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +// This is a convenience header for importing the BWToolkit framework into your classes. + +#import "BWAnchoredButton.h" +#import "BWAnchoredButtonBar.h" +#import "BWAnchoredButtonCell.h" +#import "BWAnchoredPopUpButton.h" +#import "BWAnchoredPopUpButtonCell.h" +#import "BWSplitView.h" +#import "BWUnanchoredButton.h" +#import "BWUnanchoredButtonCell.h" diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButton.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButton.h new file mode 100644 index 000000000..03ab62116 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButton.h @@ -0,0 +1,16 @@ +// +// BWUnanchoredButton.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWUnanchoredButton : NSButton +{ + NSPoint topAndLeftInset; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButton.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButton.m new file mode 100644 index 000000000..baa59462c --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButton.m @@ -0,0 +1,40 @@ +// +// BWUnanchoredButton.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWUnanchoredButton.h" +#import "BWAnchoredButtonBar.h" +#import "NSView+BWAdditions.h" + +@implementation BWUnanchoredButton + +- (id)initWithCoder:(NSCoder *)decoder; +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([BWAnchoredButtonBar wasBorderedBar]) + topAndLeftInset = NSMakePoint(0, 0); + else + topAndLeftInset = NSMakePoint(1, 1); + } + return self; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + [self bwBringToFront]; + [super mouseDown:theEvent]; +} + +- (NSRect)frame +{ + NSRect frame = [super frame]; + frame.size.height = 22; + return frame; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonCell.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonCell.h new file mode 100644 index 000000000..8204cb0dd --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonCell.h @@ -0,0 +1,17 @@ +// +// BWUnanchoredButtonCell.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import +#import "BWAnchoredButtonCell.h" + +@interface BWUnanchoredButtonCell : BWAnchoredButtonCell +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonCell.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonCell.m new file mode 100644 index 000000000..7e5199736 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonCell.m @@ -0,0 +1,60 @@ +// +// BWUnanchoredButtonCell.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "BWUnanchoredButtonCell.h" +#import "BWUnanchoredButton.h" +#import "NSColor+BWAdditions.h" + +static NSColor *fillStop1, *fillStop2, *fillStop3, *fillStop4; +static NSColor *borderColor, *topBorderColor, *bottomInsetColor, *topInsetColor, *pressedColor; +static NSGradient *fillGradient; + +@implementation BWUnanchoredButtonCell + ++ (void)initialize; +{ + fillStop1 = [[NSColor colorWithCalibratedWhite:(251.0f / 255.0f) alpha:1] retain]; + fillStop2 = [[NSColor colorWithCalibratedWhite:(251.0f / 255.0f) alpha:1] retain]; + fillStop3 = [[NSColor colorWithCalibratedWhite:(236.0f / 255.0f) alpha:1] retain]; + fillStop4 = [[NSColor colorWithCalibratedWhite:(243.0f / 255.0f) alpha:1] retain]; + + fillGradient = [[NSGradient alloc] initWithColorsAndLocations: + fillStop1, (CGFloat)0.0, + fillStop2, (CGFloat)0.5, + fillStop3, (CGFloat)0.5, + fillStop4, (CGFloat)1.0, + nil]; + + topBorderColor = [[NSColor colorWithCalibratedWhite:(126.0f / 255.0f) alpha:1] retain]; + borderColor = [[NSColor colorWithCalibratedWhite:(151.0f / 255.0f) alpha:1] retain]; + + topInsetColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.08] retain]; + bottomInsetColor = [[NSColor colorWithCalibratedWhite:(255.0f / 255.0f) alpha:0.54] retain]; + + pressedColor = [[NSColor colorWithCalibratedWhite:(0.0f / 255.0f) alpha:0.3] retain]; +} + +- (void)drawBezelWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + [fillGradient drawInRect:NSInsetRect(cellFrame, 0, 2) angle:90]; + + [topInsetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:NO]; + [topBorderColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:NO]; + [borderColor bwDrawPixelThickLineAtPosition:1 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:YES]; + [bottomInsetColor bwDrawPixelThickLineAtPosition:0 withInset:0 inRect:cellFrame inView:[self controlView] horizontal:YES flip:YES]; + + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:2 inRect:cellFrame inView:[self controlView] horizontal:NO flip:YES]; + [borderColor bwDrawPixelThickLineAtPosition:0 withInset:2 inRect:cellFrame inView:[self controlView] horizontal:NO flip:NO]; +} + +- (NSRect)highlightRectForBounds:(NSRect)bounds +{ + return NSInsetRect(bounds, 0, 1); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonContainer.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonContainer.h new file mode 100644 index 000000000..73f1aa557 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonContainer.h @@ -0,0 +1,16 @@ +// +// BWUnanchoredButtonContainer.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface BWUnanchoredButtonContainer : NSView +{ + +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonContainer.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonContainer.m new file mode 100644 index 000000000..2900e2dac --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/BWUnanchoredButtonContainer.m @@ -0,0 +1,23 @@ +// +// BWUnanchoredButtonContainer.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +// See the integration class + +#import "BWUnanchoredButtonContainer.h" + +@implementation BWUnanchoredButtonContainer + +- (void)awakeFromNib +{ + for (NSView *subview in [self subviews]) + { + [subview setFrameSize:NSMakeSize(subview.frame.size.width, 22)]; + } +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/ButtonBarPullDownArrow.pdf b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/ButtonBarPullDownArrow.pdf new file mode 100644 index 000000000..79350a272 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/ButtonBarPullDownArrow.pdf differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/English.lproj/InfoPlist.strings b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/English.lproj/InfoPlist.strings new file mode 100644 index 000000000..06b1f5377 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/English.lproj/InfoPlist.strings differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/GradientSplitViewDimpleBitmap.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/GradientSplitViewDimpleBitmap.tif new file mode 100644 index 000000000..52c9d8181 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/GradientSplitViewDimpleBitmap.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/GradientSplitViewDimpleVector.pdf b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/GradientSplitViewDimpleVector.pdf new file mode 100644 index 000000000..2f430e3e6 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/GradientSplitViewDimpleVector.pdf differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Info.plist b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Info.plist new file mode 100644 index 000000000..36ae53f46 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.brandonwalkin.BWToolkit + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.2.5 + CFBundleSignature + ???? + CFBundleVersion + 1.2.5 + NSPrincipalClass + BWToolkit + + diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Library-CustomView.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Library-CustomView.tif new file mode 100644 index 000000000..e093fac39 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Library-CustomView.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/License.rtf b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/License.rtf new file mode 100644 index 000000000..1b1e793bf --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/License.rtf @@ -0,0 +1,18 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf250 +{\fonttbl\f0\fnil\fcharset0 Verdana;\f1\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red73\green73\blue73;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} +\deftab720 +\pard\pardeftab720\sl400\sa280\ql\qnatural + +\f0\fs24 \cf2 Copyright (c) 2010, Brandon Walkin +\f1 \uc0\u8232 +\f0 All rights reserved.\ +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl400\sa20\ql\qnatural +\ls1\ilvl0\cf2 {\listtext \'95 }Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\ +{\listtext \'95 }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.\ +{\listtext \'95 }Neither the name of the Brandon Walkin nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\ +\pard\pardeftab720\sl400\sa280\ql\qnatural +\cf2 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.} \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSApplication+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSApplication+BWAdditions.h new file mode 100644 index 000000000..502804906 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSApplication+BWAdditions.h @@ -0,0 +1,15 @@ +// +// NSApplication+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSApplication (BWAdditions) + ++ (BOOL)bwIsOnLeopard; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSApplication+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSApplication+BWAdditions.m new file mode 100644 index 000000000..471fa2da4 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSApplication+BWAdditions.m @@ -0,0 +1,21 @@ +// +// NSApplication+BWAdditions.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSApplication+BWAdditions.h" + +@implementation NSApplication (BWAdditions) + ++ (BOOL)bwIsOnLeopard +{ + SInt32 minorVersion, majorVersion; + Gestalt(gestaltSystemVersionMajor, &majorVersion); + Gestalt(gestaltSystemVersionMinor, &minorVersion); + return majorVersion == 10 && minorVersion == 5; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSColor+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSColor+BWAdditions.h new file mode 100644 index 000000000..06a0bc257 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSColor+BWAdditions.h @@ -0,0 +1,16 @@ +// +// NSColor+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSColor (BWAdditions) + +// Use this method to draw 1 px wide lines independent of scale factor. Handy for resolution independent drawing. Still needs some work - there are issues with drawing at the edges of views. +- (void)bwDrawPixelThickLineAtPosition:(int)posInPixels withInset:(int)insetInPixels inRect:(NSRect)aRect inView:(NSView *)view horizontal:(BOOL)isHorizontal flip:(BOOL)shouldFlip; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSColor+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSColor+BWAdditions.m new file mode 100644 index 000000000..1b628e973 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSColor+BWAdditions.m @@ -0,0 +1,79 @@ +// +// NSColor+PixelWideLines.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSColor+BWAdditions.h" + +@implementation NSColor (BWAdditions) + +// Use this method to draw 1 px wide lines independent of scale factor. Handy for resolution independent drawing. Still needs some work - there are issues with drawing at the edges of views. +- (void)bwDrawPixelThickLineAtPosition:(int)posInPixels withInset:(int)insetInPixels inRect:(NSRect)aRect inView:(NSView *)view horizontal:(BOOL)isHorizontal flip:(BOOL)shouldFlip +{ + // Convert the given rectangle from points to pixels + aRect = [view convertRectToBase:aRect]; + + // Round up the rect's values to integers + aRect = NSIntegralRect(aRect); + + // Add or subtract 0.5 so the lines are drawn within pixel bounds + if (isHorizontal) + { + if ([view isFlipped]) + aRect.origin.y -= 0.5; + else + aRect.origin.y += 0.5; + } + else + { + aRect.origin.x += 0.5; + } + + NSSize sizeInPixels = aRect.size; + + // Convert the rect back to points for drawing + aRect = [view convertRectFromBase:aRect]; + + // Flip the position so it's at the other side of the rect + if (shouldFlip) + { + if (isHorizontal) + posInPixels = sizeInPixels.height - posInPixels - 1; + else + posInPixels = sizeInPixels.width - posInPixels - 1; + } + + float posInPoints = posInPixels / [[NSScreen mainScreen] userSpaceScaleFactor]; + float insetInPoints = insetInPixels / [[NSScreen mainScreen] userSpaceScaleFactor]; + + // Calculate line start and end points + float startX, startY, endX, endY; + + if (isHorizontal) + { + startX = aRect.origin.x + insetInPoints; + startY = aRect.origin.y + posInPoints; + endX = aRect.origin.x + aRect.size.width - insetInPoints; + endY = aRect.origin.y + posInPoints; + } + else + { + startX = aRect.origin.x + posInPoints; + startY = aRect.origin.y + insetInPoints; + endX = aRect.origin.x + posInPoints; + endY = aRect.origin.y + aRect.size.height - insetInPoints; + } + + // Draw line + NSBezierPath *path = [NSBezierPath bezierPath]; + [path setLineWidth:0.0f]; + [path moveToPoint:NSMakePoint(startX,startY)]; + [path lineToPoint:NSMakePoint(endX,endY)]; + [self set]; + [path stroke]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSCustomView.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSCustomView.h new file mode 100644 index 000000000..7e7eec19f --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSCustomView.h @@ -0,0 +1,27 @@ +/* + * Generated by class-dump 3.1.2. + * + * class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2007 by Steve Nygard. + */ + +#import + +@class NSString; + +@interface NSCustomView : NSView +{ + NSString *className; + NSView *view; + id extension; +} + ++ (void)initialize; +- (id)initWithFrame:(NSRect)fp8; +- (void)dealloc; +- (void)finalize; +- (id)nibInstantiate; +- (void)encodeWithCoder:(id)fp8; +- (id)initWithCoder:(id)fp8; + +@end + diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSEvent+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSEvent+BWAdditions.h new file mode 100644 index 000000000..f16ee4cbb --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSEvent+BWAdditions.h @@ -0,0 +1,19 @@ +// +// NSEvent+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSEvent (BWAdditions) + ++ (BOOL)bwShiftKeyIsDown; ++ (BOOL)bwCommandKeyIsDown; ++ (BOOL)bwOptionKeyIsDown; ++ (BOOL)bwControlKeyIsDown; ++ (BOOL)bwCapsLockKeyIsDown; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSEvent+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSEvent+BWAdditions.m new file mode 100644 index 000000000..b8c38bad2 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSEvent+BWAdditions.m @@ -0,0 +1,53 @@ +// +// NSEvent+BWAdditions.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSEvent+BWAdditions.h" + +@implementation NSEvent (BWAdditions) + ++ (BOOL)bwShiftKeyIsDown +{ + if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) + return YES; + + return NO; +} + ++ (BOOL)bwCommandKeyIsDown +{ + if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) + return YES; + + return NO; +} + ++ (BOOL)bwOptionKeyIsDown +{ + if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) + return YES; + + return NO; +} + ++ (BOOL)bwControlKeyIsDown +{ + if ([[NSApp currentEvent] modifierFlags] & NSControlKeyMask) + return YES; + + return NO; +} + ++ (BOOL)bwCapsLockKeyIsDown +{ + if ([[NSApp currentEvent] modifierFlags] & NSAlphaShiftKeyMask) + return YES; + + return NO; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSImage+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSImage+BWAdditions.h new file mode 100644 index 000000000..b876023e2 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSImage+BWAdditions.h @@ -0,0 +1,19 @@ +// +// NSImage+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSImage (BWAdditions) + +// Draw a solid color over an image - taking into account alpha. Useful for coloring template images. +- (NSImage *)bwTintedImageWithColor:(NSColor *)tint; + +// Rotate an image 90 degrees clockwise or counterclockwise +- (NSImage *)bwRotateImage90DegreesClockwise:(BOOL)clockwise; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSImage+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSImage+BWAdditions.m new file mode 100644 index 000000000..ca82bc47a --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSImage+BWAdditions.m @@ -0,0 +1,83 @@ +// +// NSImage+BWAdditions.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSImage+BWAdditions.h" + +@implementation NSImage (BWAdditions) + +// Draw a solid color over an image - taking into account alpha. Useful for coloring template images. + +- (NSImage *)bwTintedImageWithColor:(NSColor *)tint +{ + NSSize size = [self size]; + NSRect imageBounds = NSMakeRect(0, 0, size.width, size.height); + + NSImage *copiedImage = [self copy]; + + [copiedImage lockFocus]; + + [tint set]; + NSRectFillUsingOperation(imageBounds, NSCompositeSourceAtop); + + [copiedImage unlockFocus]; + + return [copiedImage autorelease]; +} + +// Rotate an image 90 degrees clockwise or counterclockwise +// Code from http://swik.net/User:marc/Chipmunk+Ninja+Technical+Articles/Rotating+an+NSImage+object+in+Cocoa/zgha + +- (NSImage *)bwRotateImage90DegreesClockwise:(BOOL)clockwise +{ + NSImage *existingImage = self; + NSSize existingSize; + + /** + * Get the size of the original image in its raw bitmap format. + * The bestRepresentationForDevice: nil tells the NSImage to just + * give us the raw image instead of it's wacky DPI-translated version. + */ + existingSize.width = [[existingImage bestRepresentationForDevice:nil] pixelsWide]; + existingSize.height = [[existingImage bestRepresentationForDevice:nil] pixelsHigh]; + + NSSize newSize = NSMakeSize(existingSize.height, existingSize.width); + NSImage *rotatedImage = [[[NSImage alloc] initWithSize:newSize] autorelease]; + + [rotatedImage lockFocus]; + + /** + * Apply the following transformations: + * + * - bring the rotation point to the centre of the image instead of + * the default lower, left corner (0,0). + * - rotate it by 90 degrees, either clock or counter clockwise. + * - re-translate the rotated image back down to the lower left corner + * so that it appears in the right place. + */ + NSAffineTransform *rotateTF = [NSAffineTransform transform]; + NSPoint centerPoint = NSMakePoint(newSize.width / 2, newSize.height / 2); + + [rotateTF translateXBy: centerPoint.x yBy: centerPoint.y]; + [rotateTF rotateByDegrees: (clockwise) ? - 90 : 90]; + [rotateTF translateXBy: -centerPoint.y yBy: -centerPoint.x]; + [rotateTF concat]; + + /** + * We have to get the image representation to do its drawing directly, + * because otherwise the stupid NSImage DPI thingie bites us in the butt + * again. + */ + NSRect r1 = NSMakeRect(0, 0, newSize.height, newSize.width); + [[existingImage bestRepresentationForDevice:nil] drawInRect:r1]; + + [rotatedImage unlockFocus]; + + return rotatedImage; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSString+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSString+BWAdditions.h new file mode 100644 index 000000000..3a9545d45 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSString+BWAdditions.h @@ -0,0 +1,15 @@ +// +// NSString+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSString (BWAdditions) + ++ (NSString *)bwRandomUUID; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSString+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSString+BWAdditions.m new file mode 100644 index 000000000..e517637ef --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSString+BWAdditions.m @@ -0,0 +1,22 @@ +// +// NSString+BWAdditions.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSString+BWAdditions.h" + +@implementation NSString (BWAdditions) + ++ (NSString *)bwRandomUUID +{ + CFUUIDRef uuidObj = CFUUIDCreate(nil); + NSString *newUUID = (NSString*)CFMakeCollectable(CFUUIDCreateString(nil, uuidObj)); + CFRelease(uuidObj); + + return [newUUID autorelease]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSView+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSView+BWAdditions.h new file mode 100644 index 000000000..21a4c7008 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSView+BWAdditions.h @@ -0,0 +1,18 @@ +// +// NSView+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSView (BWAdditions) + +- (void)bwBringToFront; + +// Returns animator proxy and calls setWantsLayer:NO on the view when the animation completes +- (id)bwAnimator; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSView+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSView+BWAdditions.m new file mode 100644 index 000000000..3a990cf7d --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSView+BWAdditions.m @@ -0,0 +1,48 @@ +// +// NSView+BWAdditions.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSView+BWAdditions.h" + +NSComparisonResult compareViews(id firstView, id secondView, id context); +NSComparisonResult compareViews(id firstView, id secondView, id context) +{ + if (firstView != context && secondView != context) {return NSOrderedSame;} + else + { + if (firstView == context) {return NSOrderedDescending;} + else {return NSOrderedAscending;} + } +} + +@interface NSView (BWPrivateAdditions) +- (void)bwTurnOffLayer; +@end + +@implementation NSView (BWAdditions) + +- (void)bwBringToFront +{ + [[self superview] sortSubviewsUsingFunction:(NSComparisonResult (*)(id, id, void *))compareViews context:self]; +} + +- (id)bwAnimator +{ + float duration = [[NSAnimationContext currentContext] duration]; + [self performSelector:@selector(bwTurnOffLayer) withObject:nil afterDelay:duration]; + + return [self animator]; +} + +- (void)bwTurnOffLayer +{ + [self setWantsLayer:NO]; +} + +@end + + diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSWindow+BWAdditions.h b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSWindow+BWAdditions.h new file mode 100644 index 000000000..ed86396e4 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSWindow+BWAdditions.h @@ -0,0 +1,16 @@ +// +// NSWindow+BWAdditions.h +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import + +@interface NSWindow (BWAdditions) + +- (void)bwResizeToSize:(NSSize)newSize animate:(BOOL)animateFlag; +- (BOOL)bwIsTextured; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSWindow+BWAdditions.m b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSWindow+BWAdditions.m new file mode 100644 index 000000000..9fa3d61b2 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/NSWindow+BWAdditions.m @@ -0,0 +1,41 @@ +// +// NSWindow+BWAdditions.m +// BWToolkit +// +// Created by Brandon Walkin (www.brandonwalkin.com) +// All code is provided under the New BSD license. +// + +#import "NSWindow+BWAdditions.h" + +@implementation NSWindow (BWAdditions) + +- (void)bwResizeToSize:(NSSize)newSize animate:(BOOL)animateFlag +{ + NSRect windowFrame; + windowFrame.origin.x = [self frame].origin.x; + + if ([self isSheet]) + { + float oldWidth = [self frame].size.width; + float newWidth = newSize.width; + + float difference = oldWidth - newWidth; + + windowFrame.origin.x += difference / 2; + } + + windowFrame.origin.y = [self frame].origin.y + [self frame].size.height - newSize.height; + windowFrame.size.width = newSize.width; + windowFrame.size.height = newSize.height; + + if (!NSIsEmptyRect(windowFrame)) + [self setFrame:windowFrame display:YES animate:animateFlag]; +} + +- (BOOL)bwIsTextured +{ + return (([self styleMask] & NSTexturedBackgroundWindowMask) != 0); +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Release Notes.rtf b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Release Notes.rtf new file mode 100644 index 000000000..b32304cb8 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/Release Notes.rtf @@ -0,0 +1,65 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf250 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;} +{\colortbl;\red255\green255\blue255;\red100\green56\blue32;\red196\green26\blue22;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2} +{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}} +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\b\fs54 \cf0 BWToolkit +\fs36 \ + +\b0 Plugin for Interface Builder 3\ + +\b \ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 Version 1.2.5\ +January 20, 2010\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\fs32 \cf0 \ +\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\b\fs36 \cf0 Installation +\b0\fs28 \ +\ +Note: If you're building on 10.5, you'll need to build BWToolkit from source.\ +\ +Step 1. Double click the BWToolkit.ibplugin file to load the plugin into Interface Builder\ +\ +Note: Interface Builder will reference this file rather than copy it to another location. Keep the .ibplugin file in a location where it won't be deleted.\ +\ +Step 2. In the Xcode project you want to use the plugin in:\ +\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural +\ls1\ilvl0\cf0 {\listtext \'95 }Right click the Linked Frameworks folder and click Add -> Existing Frameworks. Select the BWToolkitFramework.framework directory.\ +\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural +\ls2\ilvl0\cf0 {\listtext \'95 }Right click your target and click Add -> New Build Phase -> New Copy Files Build Phase. For destination, select Frameworks, leave the path field blank, and close the window.\ +\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural +\ls3\ilvl0\cf0 {\listtext \'95 }Drag the BWToolkit framework from Linked Frameworks to the Copy Files build phase you just added.\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural +\cf0 \ +Note: You'll have to repeat step 2 for each project you want to use BWToolkit in.\ +\ +If you need to reference BWToolkit objects in your classes, you can import the main header like so:\ +\ +\pard\tx560\pardeftab560\ql\qnatural\pardirnatural + +\f1\fs24 \cf2 \CocoaLigature0 #import \cf3 +\f0\fs28 \cf0 \CocoaLigature1 \ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\fs32 \cf0 \ +\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\b\fs36 \cf0 License\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\b0\fs28 \cf0 \ +All source code is provided under the three clause BSD license. Attribution is appreciated but by no means required.\ +\ +\ +} \ No newline at end of file diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderPhotoLarge.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderPhotoLarge.tif new file mode 100644 index 000000000..69c38f919 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderPhotoLarge.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderPhotoSmall.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderPhotoSmall.tif new file mode 100644 index 000000000..f5f644b32 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderPhotoSmall.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderSpeakerLoud.png b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderSpeakerLoud.png new file mode 100644 index 000000000..d7e87f776 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderSpeakerLoud.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderSpeakerQuiet.png b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderSpeakerQuiet.png new file mode 100644 index 000000000..5836a7af8 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderSpeakerQuiet.png differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderThumbN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderThumbN.tiff new file mode 100644 index 000000000..064db7aca Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderThumbN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderThumbP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderThumbP.tiff new file mode 100644 index 000000000..a62dc01e6 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderThumbP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackFill.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackFill.tiff new file mode 100644 index 000000000..fe3105ad1 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackFill.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackLeft.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackLeft.tiff new file mode 100644 index 000000000..0250746f9 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackLeft.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackRight.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackRight.tiff new file mode 100644 index 000000000..4ac757349 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TexturedSliderTrackRight.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TokenFieldArrow.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TokenFieldArrow.tif new file mode 100644 index 000000000..6a6db9acc Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TokenFieldArrow.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TokenFieldHighlightedArrow.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TokenFieldHighlightedArrow.tif new file mode 100644 index 000000000..cb5d30d77 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TokenFieldHighlightedArrow.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/ToolbarItemFonts.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/ToolbarItemFonts.tiff new file mode 100644 index 000000000..eeda1835f Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/ToolbarItemFonts.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonFillN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonFillN.tiff new file mode 100644 index 000000000..d5dda9f61 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonFillN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonFillP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonFillP.tiff new file mode 100644 index 000000000..31237382a Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonFillP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonLeftN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonLeftN.tiff new file mode 100644 index 000000000..f346e2a93 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonLeftN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonLeftP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonLeftP.tiff new file mode 100644 index 000000000..7d764aa28 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonLeftP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonRightN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonRightN.tiff new file mode 100644 index 000000000..8fd41997b Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonRightN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonRightP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonRightP.tiff new file mode 100644 index 000000000..d000b4f2a Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentButtonRightP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOffN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOffN.tiff new file mode 100644 index 000000000..611379276 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOffN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOffP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOffP.tiff new file mode 100644 index 000000000..2eebeed00 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOffP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOnN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOnN.tiff new file mode 100644 index 000000000..5642a4985 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOnN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOnP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOnP.tiff new file mode 100644 index 000000000..71f11e25d Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentCheckboxOnP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpFillN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpFillN.tiff new file mode 100644 index 000000000..26e948e77 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpFillN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpFillP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpFillP.tiff new file mode 100644 index 000000000..31237382a Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpFillP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpLeftN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpLeftN.tiff new file mode 100644 index 000000000..fa4cb8a63 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpLeftN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpLeftP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpLeftP.tiff new file mode 100644 index 000000000..f402d79e3 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpLeftP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpPullDownRightN.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpPullDownRightN.tif new file mode 100644 index 000000000..e280e2f5a Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpPullDownRightN.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpPullDownRightP.tif b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpPullDownRightP.tif new file mode 100644 index 000000000..029d05ae4 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpPullDownRightP.tif differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpRightN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpRightN.tiff new file mode 100644 index 000000000..9b9bcf583 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpRightN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpRightP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpRightP.tiff new file mode 100644 index 000000000..dbc14743e Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentPopUpRightP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderThumbN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderThumbN.tiff new file mode 100644 index 000000000..99d067856 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderThumbN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderThumbP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderThumbP.tiff new file mode 100644 index 000000000..0ede44a44 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderThumbP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackFill.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackFill.tiff new file mode 100644 index 000000000..79fdd98b4 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackFill.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackLeft.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackLeft.tiff new file mode 100644 index 000000000..e8a393826 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackLeft.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackRight.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackRight.tiff new file mode 100644 index 000000000..58c2b17d9 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTrackRight.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTriangleThumbN.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTriangleThumbN.tiff new file mode 100644 index 000000000..14bad9e87 Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTriangleThumbN.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTriangleThumbP.tiff b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTriangleThumbP.tiff new file mode 100644 index 000000000..c1e5d2a8f Binary files /dev/null and b/External Source/NSLogger/Desktop Viewer/Third Party/BWToolkit/TransparentSliderTriangleThumbP.tiff differ diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/README b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/README new file mode 100644 index 000000000..680fd840c --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/README @@ -0,0 +1,58 @@ +SSSelectable Toolbar +-------------------- + +Copyright (c) 2011 Steve Streeting + +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. + +Why? +---- + +I needed a preference-pane style selectable toolbar which switched views easily, +allowing different sizes per pane, and not requiring a lot of manual code. I +wanted to do most of the work in Interface Builder still. + +I liked the selectable toolbar in BWToolkit, but it had a few issues such as +crashing Interface Builder, getting the vertical position wrong at times, and +also that in XCode 4, Interface Builder plugins are no longer supported. So I +needed a selectable toolbar that worked in IB without any plugins. + +How to use +---------- + +1) Add all the source files in the 'toolbar' subfolder to your XCode project +2) In Interface Builder, drag & drop an NSToolbar on to your window +3) Change the type to 'SSSelectableToolbar' +4) Connect the 'window' outlet of the toolbar to the parent window +5) Drag & drop NSToolbarItem instances on to the toolbar and check the + 'Selectable' option +6) Change the type of each one to 'SSSelectableToolbarItem' +7) Create a Custom View instance at the root of the document (not in the window) + for each pane and populate them how you like +8) Connect the 'linkedView' outlet of each toolbar item to the corresponding + pane view +9) Connect the 'nextKeyView' outlet of each custom view to the control that + should become the first responder when switching to that tab (Optional) + +And you're ready to go. Each toolbar item will switch to its corresponding pane, +resizing the window as necessary. You can make the window resizable if you like, +and the user size will be remembered when switching back and forth. + + + + diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbar.h b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbar.h new file mode 100644 index 000000000..c8538a4a5 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbar.h @@ -0,0 +1,27 @@ +// +// SSToolbar.h +// SelectableToolbarHelper +// +// Created by Steven Streeting on 19/06/2011. +// Copyright 2011 Torus Knot Software Ltd. All rights reserved. +// + +#import + +@interface SSSelectableToolbar : NSToolbar +{ + NSWindow* window; + NSView* blankView; + NSInteger defaultItemIndex; +} +@property (nonatomic, retain) IBOutlet NSWindow* window; +@property (nonatomic, assign) NSInteger defaultItemIndex; + +-(NSToolbarItem*)itemWithIdentifier:(NSString*)identifier; +// select the item with the given index, ordered as per the palette and ignoring +// all types of buttons except SSSelectableToolbarItem +-(void)selectItemWithIndex:(NSInteger)idx; +// Convert a selectable item index (ignoring all except selectable items in palette) +// to a main index which can be used for other purposes +-(NSInteger)selectableItemIndexToMainIndex:(NSInteger)idx; +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbar.m b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbar.m new file mode 100644 index 000000000..6d0ceefef --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbar.m @@ -0,0 +1,157 @@ +// +// SSToolbar.m +// SelectableToolbarHelper +// +// Created by Steven Streeting on 19/06/2011. +// Copyright 2011 Torus Knot Software Ltd. All rights reserved. +// + +#import "SSSelectableToolbar.h" +#import "SSSelectableToolbarItem.h" + + +@implementation SSSelectableToolbar +@synthesize window; +@synthesize defaultItemIndex; + +- (id) initWithIdentifier:(NSString *)identifier +{ + if (self = [super initWithIdentifier:identifier]) + { + blankView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]; + } + return self; +} + +- (void) dealloc +{ + [blankView release]; + [window release]; + [super dealloc]; + +} +-(IBAction)toolbarItemClicked:sender +{ + // this is really only here so I can set up a target / action which makes button clickable +} + +-(void)selectDefaultItem:sender +{ + // select the default item first time becomes key + [self selectItemWithIndex:defaultItemIndex]; + // Don't tell us again + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:window]; + +} + +-(void) awakeFromNib +{ + // Set target / action on all buttons to make them clickable + NSArray* items = [self visibleItems]; + for (NSToolbarItem* item in items) + { + if ([item isKindOfClass:[SSSelectableToolbarItem class]]) + { + [item setTarget:self]; + [item setAction:@selector(toolbarItemClicked:)]; + } + } + + // Wait until window displayed before sizing (important for displaying in sheets) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(selectDefaultItem:) + name:NSWindowDidBecomeKeyNotification + object:window]; + + +} + +-(NSToolbarItem*)itemWithIdentifier:(NSString*)identifier +{ + for (NSToolbarItem* item in [self items]) + { + if ([[item itemIdentifier] isEqual:identifier]) + return item; + } + return nil; +} + +- (void)setSelectedItemIdentifier:(NSString *)itemIdentifier +{ + [super setSelectedItemIdentifier:itemIdentifier]; + + NSToolbarItem* item = [self itemWithIdentifier:itemIdentifier]; + if ([item isKindOfClass:[SSSelectableToolbarItem class]]) + { + SSSelectableToolbarItem* ssitem = (SSSelectableToolbarItem*)item; + + NSView* view = [ssitem linkedView]; + if (view && window) + { + NSView* oldView = [window contentView]; + NSRect oldFrame = [oldView frame]; + NSRect newFrame = [view frame]; + NSRect oldWinFrame = [window frame]; + NSRect winFrame = oldWinFrame; + float toolbarHeight = NSHeight(oldWinFrame) - NSHeight(oldFrame); + + // resize + winFrame.size.width = newFrame.size.width; + winFrame.size.height = newFrame.size.height + toolbarHeight; + winFrame.origin.y -= NSHeight(winFrame) - NSHeight(oldWinFrame); + [window setContentView:blankView]; + [window setFrame:winFrame display:YES animate:YES]; + [window setContentView:view]; + + // change title + [window setTitle:[ssitem label]]; + + // tab to first control (if nextKeyView connected) + NSView* keyView = [view nextKeyView]; + if (keyView) + [window makeFirstResponder:keyView]; + + + } + } +} + +-(void)selectItemWithIndex:(NSInteger)idx +{ + NSInteger currIdx = 0; + for (NSToolbarItem* item in [self items]) + { + if ([item isKindOfClass:[SSSelectableToolbarItem class]]) + { + if (currIdx == idx) + { + [self setSelectedItemIdentifier:[item itemIdentifier]]; + return; + } + // We're only counting these types, ignore spacing and other default items + ++currIdx; + } + } + +} + +-(NSInteger)selectableItemIndexToMainIndex:(NSInteger)idx +{ + NSInteger selIdx = 0; + NSInteger mainIdx = 0; + for (NSToolbarItem* item in [self items]) + { + if ([item isKindOfClass:[SSSelectableToolbarItem class]]) + { + if (selIdx == idx) + { + return mainIdx; + } + ++selIdx; + } + ++mainIdx; + } + + return -1; +} +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbarItem.h b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbarItem.h new file mode 100644 index 000000000..716ac4a64 --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbarItem.h @@ -0,0 +1,19 @@ +// +// SSToolbarItem.h +// SelectableToolbarHelper +// +// Created by Steven Streeting on 19/06/2011. +// Copyright 2011 Torus Knot Software Ltd. All rights reserved. +// + +#import + + +@interface SSSelectableToolbarItem : NSToolbarItem +{ + NSView* linkedView; +} + +@property (nonatomic, retain) IBOutlet NSView* linkedView; + +@end diff --git a/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbarItem.m b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbarItem.m new file mode 100644 index 000000000..87bfd82fa --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/Third Party/SSSelectableToolbar/SSSelectableToolbarItem.m @@ -0,0 +1,22 @@ +// +// SSToolbarItem.m +// SelectableToolbarHelper +// +// Created by Steven Streeting on 19/06/2011. +// Copyright 2011 Torus Knot Software Ltd. All rights reserved. +// + +#import "SSSelectableToolbarItem.h" + + +@implementation SSSelectableToolbarItem + +@synthesize linkedView; + +-(void) dealloc +{ + [linkedView release]; + [super dealloc]; +} + +@end diff --git a/External Source/NSLogger/Desktop Viewer/main.m b/External Source/NSLogger/Desktop Viewer/main.m new file mode 100644 index 000000000..7cfae24bd --- /dev/null +++ b/External Source/NSLogger/Desktop Viewer/main.m @@ -0,0 +1,36 @@ +/* + * main.m + * + * BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2010-2011 Florent Pillet All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of Florent + * Pillet nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/External Source/NSLogger/Docs/Cocoaheads_Paris_Presentation_EN.key.zip b/External Source/NSLogger/Docs/Cocoaheads_Paris_Presentation_EN.key.zip new file mode 100644 index 000000000..1f946e875 Binary files /dev/null and b/External Source/NSLogger/Docs/Cocoaheads_Paris_Presentation_EN.key.zip differ diff --git a/External Source/NSLogger/Docs/Cocoaheads_Paris_Presentation_FR.key.zip b/External Source/NSLogger/Docs/Cocoaheads_Paris_Presentation_FR.key.zip new file mode 100644 index 000000000..f75ddaa32 Binary files /dev/null and b/External Source/NSLogger/Docs/Cocoaheads_Paris_Presentation_FR.key.zip differ diff --git a/Source/Quincy/Quincy-Info.plist b/External Source/NSLogger/Info.plist similarity index 78% rename from Source/Quincy/Quincy-Info.plist rename to External Source/NSLogger/Info.plist index de7d488e4..d62082895 100644 --- a/Source/Quincy/Quincy-Info.plist +++ b/External Source/NSLogger/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - Dustin-Rue.${PRODUCT_NAME:rfc1034identifier} + com.florentpillet.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -17,13 +17,13 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + ${CURRENT_MARKETING_VERSION} CFBundleSignature ???? CFBundleVersion - 1 + ${CURRENT_PROJECT_VERSION} NSHumanReadableCopyright - Copyright © 2011 __MyCompanyName__. All rights reserved. + Copyright © 2011. All rights reserved. NSPrincipalClass diff --git a/External Source/NSLogger/LICENSE.txt b/External Source/NSLogger/LICENSE.txt new file mode 100644 index 000000000..b703a11d9 --- /dev/null +++ b/External Source/NSLogger/LICENSE.txt @@ -0,0 +1,23 @@ +BSD license follows (http://www.opensource.org/licenses/bsd-license.php) + +Copyright (c) 2010-2011, Florent Pillet All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must +reproduce the above copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided with the +distribution. Neither the name of Florent Pillet nor the names of its +contributors may be used to endorse or promote products derived from this software +without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT +HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/External Source/NSLogger/README.markdown b/External Source/NSLogger/README.markdown new file mode 100644 index 000000000..9c9fb67f7 --- /dev/null +++ b/External Source/NSLogger/README.markdown @@ -0,0 +1,73 @@ +# NSLogger # +![Icon](https://github.com/fpillet/NSLogger/raw/master/Screenshots/icon_small.png "Icon") + +*NSLogger* is a high perfomance logging utility which displays traces emitted by client applications running on **Mac OS X** or **iOS (iPhone OS)**. It replaces your usual *NSLog()*-based traces and provides powerful additions like display filtering, image and binary logging, traces buffering, timing information, etc. + +*NSLogger* feature summary: + + * View logs using the Mac OS X desktop viewer, accept connections from local network clients (using Bonjour) or remote clients connecting directly over the internet + * Online (application running and connected to _NSLogger_) and offline (saved logs) log viewing + * Buffer all traces in memory or in a file, send them over to viewer when a connection is acquired + * Secure logging (connections use SSL by default) + * Advanced log filtering options + * Save viewer logs to share them and/or review them later + * Export logs to text files + * Open raw buffered traces files that you brought back from client applications not directly connected to the log viewer + +**You'll find instructions for use in the [NSLogger wiki](https://github.com/fpillet/NSLogger/wiki/).** + +Your application emits traces using the *NSLogger* [trace APIs](https://github.com/fpillet/NSLogger/wiki/NSLogger-API). The desktop viewer application (running on **Mac OS X 10.6 or later**) displays them. + +Clients automatically find the logger application running on Mac OS X via Bonjour networking, and can optionally connect to a specific remote host/port. You have no setup to do: just start the logger on your Mac, launch your iOS or Mac OS X application then when your app emits traces, they will automatically show up in *NSLogger* if the viewer is running locally on your network. Until a logger is found, logs are buffered on the client so you don't lose anything. + +![Desktop Viewer (main window)](https://github.com/fpillet/NSLogger/raw/master/Screenshots/mainwindow.png "Desktop Viewer") + +# One-step setup # +All you have to do is add `LoggerClient.h`, `LoggerClient.m` and `LoggerCommon.h` (as well as add the `CFNetwork.framework` and `SystemConfiguration.framework` frameworks) to your iOS or Mac OS X application, then replace your *NSLog()* calls with *LogMessageCompat()* calls. We recommend using a macro, so you can turn off logs when building the distribution version of your application. + +# Using the desktop logger # +Start the NSLogger application on Mac OS X. Your client app must run on a device that is on the same network as your Mac. When it starts logging traces, it will automatically (by default) look for the desktop NSLogger using Bonjour. As soon as traces start coming, a new window will open on your Mac. Advanced users can setup a Remote Host / Port to log from a client to a specific host). + +You can create custom filters to quickly switch between different views of your logs. + +# Evolved logging facility # +It's very easy to log binary data or images using *NSLogger*. Use the *LogData()* and *LogImage()* calls in your application, and you're done. Advanced users can also enable remote logging to have logs sent directly from remote devices running at distant locations, or have logs be directed to a file that can later be sent to a remote server. + +# Powerful desktop viewer # +The desktop viewer application provides tools like: + + * Filters (with [regular expression matching](https://github.com/fpillet/NSLogger/wiki/Tips-and-tricks)) that let your perform data mining in your logs + * Timing information: each message displays the time elapsed since the previous message in the filtered display, so you can get a sense of time between events in your application. + * Image and binary data display directly in the log window + * [Markers](https://github.com/fpillet/NSLogger/wiki/Tips-and-tricks) (when a client is connected, place a marker at the end of a log to clearly see what happens afterwards, for example place a marker before pressing a button in your application) + * Fast navigation in your logs + * Display and export all your logs as text + * Optional display of file, line and function for uncluttered display + + +Your logs can be saved to a `.nsloggerdata` file, and reloaded later. When logging to a file, name your log file with extension `.rawnsloggerdata` so NSLogger can reopen and process it. You can have clients remotely generating raw logger data files, then send them to you so you can investigate post-mortem. + +Note that the NSLogger Mac OS X viewer requires **Mac OS X 10.6 or later**. + +![Filter Editor](https://github.com/fpillet/NSLogger/raw/master/Screenshots/filtereditor.png "Filter Editor") + +# High performance, low overhead # +*NSLogger* runs in its own thread in your application. It tries hard to consume as few CPU and memory as possible. If the desktop viewer has not been found yet, your traces can be buffered in memory until a connection is acquired. This allows for tracing in difficult situations, for example device wakeup times when the network connection is not up and running. + +*NSLogger* can be used for low-level code in situations where only CoreFoundation can be called. Disable the **ALLOW_COCOA** flag in *LoggerClient.h* to prevent any use of Cocoa code. + +# Work in progress - Current status # +This tool comes from a personal need for a more powerful logger. There are more features planned for inclusion, here is a quick list of what I'm thinking of. Requests and suggestions are welcome. + + * Log entry colorization + * Search and search term highlight in Details window + * Support time-based filtering (filter clause based on the time lapse between a previous trace) + * Pause (buffer logs) and resume sending logs to the logger, in order to eliminate NSLogger's network load from the equation when testing networking code + + +You'll find documentation in the [NSLogger Wiki](https://github.com/fpillet/NSLogger/wiki/) + +NSLogger uses parts of [Brandon Walkin's BWToolkit](http://www.brandonwalkin.com/bwtoolkit/), for which source code is included with NSLogger. + +NSLogger is Copyright (c) 2010-2011 Florent Pillet, All Rights Reserved, All Wrongs Revenged. Released under the [New BSD Licence](http://www.opensource.org/licenses/bsd-license.php). +The NSLogger icon is Copyright (c) [Louis Harboe](http://www.graphicpeel.com) diff --git a/External Source/NSLogger/Screenshots/Logger Status.jpg b/External Source/NSLogger/Screenshots/Logger Status.jpg new file mode 100644 index 000000000..edf574ab2 Binary files /dev/null and b/External Source/NSLogger/Screenshots/Logger Status.jpg differ diff --git a/External Source/NSLogger/Screenshots/filtereditor.png b/External Source/NSLogger/Screenshots/filtereditor.png new file mode 100644 index 000000000..bc6056070 Binary files /dev/null and b/External Source/NSLogger/Screenshots/filtereditor.png differ diff --git a/External Source/NSLogger/Screenshots/icon_small.png b/External Source/NSLogger/Screenshots/icon_small.png new file mode 100644 index 000000000..2e2b4e0e9 Binary files /dev/null and b/External Source/NSLogger/Screenshots/icon_small.png differ diff --git a/External Source/NSLogger/Screenshots/mainwindow.png b/External Source/NSLogger/Screenshots/mainwindow.png new file mode 100644 index 000000000..6e22240a1 Binary files /dev/null and b/External Source/NSLogger/Screenshots/mainwindow.png differ diff --git a/External Source/NSLogger/Screenshots/marks.png b/External Source/NSLogger/Screenshots/marks.png new file mode 100644 index 000000000..a666c8761 Binary files /dev/null and b/External Source/NSLogger/Screenshots/marks.png differ diff --git a/External Source/NSLogger/Screenshots/regex.png b/External Source/NSLogger/Screenshots/regex.png new file mode 100644 index 000000000..de4f7ea72 Binary files /dev/null and b/External Source/NSLogger/Screenshots/regex.png differ diff --git a/External Source/QuincyKit/.gitignore b/External Source/QuincyKit/.gitignore new file mode 100644 index 000000000..0f668c373 --- /dev/null +++ b/External Source/QuincyKit/.gitignore @@ -0,0 +1,45 @@ +# XCode (and ancestors) per-user config (very noisy, and not relevant) +*.mode1 +*.mode?v3 +!default.mode?v3 +*.perspective +*.perspectivev3 +!default.perspectivev3 +*.pbxuser +!default.pbxuser + +*.xcworkspace +!default.xcworkspace +xcuserdata + +profile +*.moved-aside + +# Generated files +VersionX-revision.h + +# build products +build/ +*.[oa] + +# Other source repository archive directories (protects when importing) +.hg +.svn +CVS + +# automatic backup files +*~.nib +*.swp +*~ +*(Autosaved).rtfd/ +Backup[ ]of[ ]*.pages/ +Backup[ ]of[ ]*.key/ +Backup[ ]of[ ]*.numbers/ + +# osx noise +.DS_Store +*.ipa +*.swp +*~.nib +profile + diff --git a/External Source/QuincyKit/LICENSE.txt b/External Source/QuincyKit/LICENSE.txt new file mode 100755 index 000000000..adda9dce1 --- /dev/null +++ b/External Source/QuincyKit/LICENSE.txt @@ -0,0 +1,25 @@ +QuincyKit is provided under the following license: + + The MIT License + Copyright (c) 2011 Andreas Linde. 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. \ No newline at end of file diff --git a/External Source/QuincyKit/README.markdown b/External Source/QuincyKit/README.markdown new file mode 100644 index 000000000..e6ae7f06d --- /dev/null +++ b/External Source/QuincyKit/README.markdown @@ -0,0 +1,259 @@ + Author: Andreas Linde + + Copyright (c) 2009-2011 Andreas Linde. + 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. + + +# Main features of QuincyKit + +- (Automatically) send crash reports to a developers database +- Let the user decide per crash to (not) send data or always send +- The user has the option to provide additional information in the settings, like email address for contacting the user +- Give the user immediate feedback if the crash is known and will be fixed in the next update, or if the update is already waiting at Apple for approval, or if the update is already available to install + + +# Main features on backend side for the developer + +- Admin interface to manage the incoming crash log data +- Script to symbolicate crash logs on the database, needs to be run on a mac with access to the DSYM files +- Automatic grouping of crash files for most likely same kind of crashes +- Maintain crash reports and sort them by using simple patterns. Automatically know how many times a bug has occured and easily filter the new ones in the DB +- Assign bugfix versions for each crash group and define a status for each version, which can be used to provide some feedback for the user + like: Bug already fixed, new version with bugfix already available, etc. + + +## Server side files + +- `/server/database_schema.sql` contains all the default tables +- `/server/crash_v200.php` is the file that is invoked by the iPhone app +- `/server/config.php` contains database access information +- `/server/test_setup.php` simple script that checks if everything required on the server is available +- `/server/admin/` contains all administration scripts +- `/server/admin/symbolicate.php` needs to be copied to a local mac, and the url has to be adjusted to access the scripts on your server + + +# SERVER INSTALLATION + +The server requires at least PHP 5.2 and a MySQL server installation! + +- Copy the server scripts to your web server: + All files inside /server except the content of the `/server/local` directory +- Execute the SQL statements from `database_schema.sql` in your MySQL database on the web server + + +## SERVER DATABASE CONFIGURATION + +- Adjust settings in `/server/CONFIG.PHP`: + + $server = 'your.server.com'; // database server hostname + $loginsql = 'database_username'; // username to access the database + $passsql = 'database_password'; // password for the above username + $base = 'database_name'; // database name which contains the below listed tables + +- Adjust `$default_amount_crashes`, this defines the amount of crashes listed right away per pattern, if there are more, those are shown after clicking on a link at the end of the shortened list +- Adjust your local timezone in the last line: `date_default_timezone_set('Europe/Berlin')` (see [http://de3.php.net/manual/en/timezones.php](http://de3.php.net/manual/en/timezones.php "PHP: List of Supported Timezones - Manual")) +- If you DO NOT want to limit the server to accept only data for your applications: + - set `$acceptallapps` to true +- Otherwise: + - start the web interface + - add the bundle identifiers of the permitted apps, e.g. `"de.buzzworks.crashreporterdemo"` (this is the same bundle identifier string as used in the `info.plist` of your app!) +- Invoke `test_setup.php` via the browser to check if everything is setup correctly and Push can be used or not + +- If you are upgrading a previous edition, invoke 'migrate.php' first to update the database setup + + +## UPDATE TO QUINCYKIT 2.0 + +- Add the new database fields to the following tables: + + **apps** + + `hockeyappidentifier` text default NULL + + **crash** + + `jailbreak` int(11) unsigned default '0' + +- If you are upgrading from an early version, please make sure the database follows the schema defined in *database_schema.sql*. + + +## SERVER ENABLE PUSH NOTIFICATIONS + +- **NOTICE**: Push Notification requires the Server PHP installation to have curl addon installed! +- **NOTICE**: Push Notifications are implemented using Prowl iPhone app and web service, you need the app and an Prowl API key! +- Adjust settings in `/server/CONFIG.PHP`: + - set `$push_activated` to true + - if you don't want a push message for every new pattern, set `$push_newtype` to false + - adjust `$notify_amount_group` to the amount of crash occurences of a pattern when a push message should be sent + - add up to 5 comma separated prowl api keys into $push_prowlids to receive the push messages on the device + - adjust `$notify_default_version`, defines if you want to receive pushes for automatically created new versions for your apps +- If push is activated, check the web interface for push settings per app version + + +# SETUP LOCAL SYMBOLIFICATION + +- **NOTICE**: These are the instructions when using Mac OS X 10.6.2 +- Copy the files inside of `/server/local` onto a local directory on your Intel Mac running at least Mac OS X 10.6.2 having the iPhone SDK 3.x installed +- Adjust settings in `local/serverconfig.php` + - set `$hostname` to the server hostname running the server side part, e.g. `www.crashreporterdemo.com` + - if the `/admin/` directory on the server is access restricted, set the required username into `$webuser` and password into `$webpwd` + - adjust the path to access the scripts (will be appended to `$hostname`): + - `$downloadtodosurl = '/admin/actionapi.php?action=getsymbolicationtodo';` // the path to the script delivering the todo list + - `$getcrashdataurl = '/admin/actionapi.php?action=getlogcrashid&id=';` // the path to the script delivering the crashlog + - `$updatecrashdataurl = '/admin/crash_update.php';` // the path to the script updating the crashlog +- Make the modified symbolicatecrash.pl file from the `/server/local/` directory executable: `chmod + x symbolicatecrash.pl` +- Copy the `.app` package and `.app.dSYM` package of each version into any directory of your Mac + Best is to add the version number to the directory of each version, so multiple versions of the same app can be symbolicated. + Example: + + QuincyDemo_1_0/QuincyDemo.app + QuincyDemo_1_0/QuincyDemo.app.dSYM + QuincyDemoBeta_1_1/QuincyDemoBeta.app + QuincyDemoBeta_1_1/QuincyDemoBeta.app.dSYM + +- Test symbolification: + - Download a crash report into the local directory from above + - run `symbolicatecrash nameofthecrashlogfile .` + - if the output shows function names and line numbers for your code and apples code, everything is fine and ready to go, otherwise there is a problem :( +- If test was successful, try to execute `php symbolicate.php` + This will print some error message which can be ignored +- Open the web interface and check the crashlogs if they are now symbolicated +- If everything went fine, setup a cron job +- IMPORTANT: Don't forget to add new builds with `.app` and `.app.dSYM` packages to the directory, so symbolification will be done correctly + There is currently no checking if a package is found in the directory before symbolification is started, no matter if it was or not, the result will be uploaded to the server + + +# IPHONE PROJECT INSTALLATION + +- Include `BWQuincyManager.h`, `BWQuincyManager.m` and `Quincy.bundle` into your project +- Include `CrashReporter.framework` into your project +- Add the "-all_load" flag to your projects build configurations "Other Linker Flags" +- Add the Apple framework `SystemConfiguration.framework` to your project +- In your `appDelegate.h` include + + #import "BWQuincyManager.h" + + and let your appDelegate implement the protocol `BWQuincyManagerDelegate` +- In your appDelegate applicationDidFinishLaunching function include + + [[BWQuincyManager sharedQuincyManager] setSubmissionURL:@"http://yourserver.com/crash_v200.php"]; + +- Done. +- When testing the connection and a server side error appears after sending a crash log, the error code is printed in the console. Error code values are listed in `BWQuincyManager.h` + + +# MAC PROJECT INSTALLATION + +- Include `Quincy.framework` into your project +- In your `appDelegate.h` include + + #import + +- In your appDelegate.h add the BWQuincyManagerDelegate protocol to your appDelegate + + @interface DemoAppDelegate : NSObject {} + +- In your `appDelegate` change the invocation of the main window to the following structure + + // this delegate method is required + - (void) showMainApplicationWindow + { + // launch the main app window + // remember not to automatically show the main window if using NIBs + [window makeFirstResponder: nil]; + [window makeKeyAndOrderFront:nil]; + } + + + - (void)applicationDidFinishLaunching:(NSNotification *)note + { + // Launch the crash reporter task + [[BWQuincyManager sharedQuincyManager] setSubmissionURL:@"http://yourserver.com/crash_v200.php"]; + [[BWQuincyManager sharedQuincyManager] setDelegate:self]; + } + +- When using the client in a Sandbox, add the following temporary exception entitlement + com.apple.security.temporary-exception.files.home-relative-path.read-only /Library/Logs + +- Done. + + +# BRANCHES: +The branching structure follows the git flow concept, defined by Vincent Driessen: http://nvie.com/posts/a-successful-git-branching-model/ + +* Master branch: + + The main branch where the source code of HEAD always reflects a production-ready state. + +* Develop branch: + + Consider this to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the “integration branchâ€. + +* Feature branches: + + These are used to develop new features for the upcoming or a distant future release. The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop (to definitely add the new feature to the upcoming release) or discarded (in case of a disappointing experiment). + +* Release branches: + + These branches support preparation of a new production release. By using this, the develop branch is cleared to receive features for the next big release. + +* Hotfix branches: + + Hotfix branches are very much like release branches in that they are also meant to prepare for a new production release, albeit unplanned. + + +# Dependencies + +## Server + +Web server supporting PHP 5.0+ and MySQL. + +## Mac OS X + +Requires Max OS X 10.5+ + +## iOS + +Requires iOS 3.0+ + +## ARC Support + +If you are including QuincyKit in a project with Automatic Reference Counting (ARC) enabled, you will need to set the `-fno-objc-arc` compiler flag on all of the QuincyKit source files. To do this in Xcode, go to your active target and select the "Build Phases" tab. In the "Compiler Flags" column, set `-fno-objc-arc` for each of the QuincyKit source files. + + +# ACKNOWLEDGMENTS + +**The following 3rd party open source libraries have been used:** + +- PLCrashReporter by Landon Fuller (http://code.google.com/p/plcrashreporter/) +- bluescreen css framework (http://blueprintcss.org/) + + +Feel free to add enhancements, fixes, changes and provide them back to the community! + +Thanks +Andreas Linde +http://www.andreaslinde.com/ +http://www.buzzworks.de/ +http://www.hockeyapp.net/ diff --git a/External Source/QuincyKit/client/Mac/BWQuincyMain.nib/designable.nib b/External Source/QuincyKit/client/Mac/BWQuincyMain.nib/designable.nib new file mode 100644 index 000000000..125a5570e --- /dev/null +++ b/External Source/QuincyKit/client/Mac/BWQuincyMain.nib/designable.nib @@ -0,0 +1,1399 @@ + + + + 1060 + 11C74 + 1938 + 1138.23 + 567.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1938 + + + YES + NSScroller + NSButton + NSTextFieldCell + NSButtonCell + NSImageView + NSBox + NSImageCell + NSScrollView + NSCustomObject + NSTextView + NSView + NSWindowTemplate + NSTextField + NSUserDefaultsController + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + BWQuincyUI + + + FirstResponder + + + NSApplication + + + 1 + 2 + {{602, 592}, {571, 587}} + 1886912512 + Crash Reporter + NSWindow + + View + + + {213, 107} + + + 256 + + YES + + + 288 + + YES + + + 274 + + YES + + + 290 + {{0, 263}, {442, 24}} + + + + YES + + 67239424 + 272629760 + Problem details and system configuration + + LucidaGrande + 13 + 1044 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 290 + + YES + + + 2304 + + YES + + + 2322 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + NeXT font pasteboard type + NeXT ruler pasteboard type + WebURLsWithTitlesPboardType + public.url + + + {{0, -14}, {437, 14}} + + + + + + + + + + + + + YES + + + 6 + + + + 437 + 1 + + + 67112931 + 0 + + + 3 + MQA + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 0 + + 6 + {876, 10000000} + {114, 0} + + + + {{1, 1}, {437, 253}} + + + + + + + {4, 5} + + 12582912 + + YES + + YES + + + + TU0AKgAAAHCAFUqgBVKsAAAAwdVQUqwaEQeIRGJRGFlYqwWLQ+JxuOQpVRmEx2RROKwOQyOUQSPyaUym +SxqWyKXyeYxyZzWbSuJTScRCbz2Nz+gRKhUOfTqeUai0OSxiWTiBQSHSGFquGwekxyAgAAAOAQAAAwAA +AAEAEAAAAQEAAwAAAAEAEAAAAQIAAwAAAAIACAAIAQMAAwAAAAEABQAAAQYAAwAAAAEAAQAAAREABAAA +AAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAgAAARYAAwAAAAEAEAAAARcABAAAAAEAAABnARwAAwAA +AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA + + + + + + 3 + MCAwAA + + + + 4 + + + + -2147483392 + {{-30, 1}, {15, 90}} + + + + + _doScroller: + 1 + + + + -2147483392 + {{-100, -100}, {87, 18}} + + + + 1 + + _doScroller: + 1 + 0.94565220000000005 + + + {{0, 8}, {439, 255}} + + + + 133650 + + + + + + {439, 285} + + + + + + {{112, 75}, {439, 285}} + + + + {0, 0} + + 67239424 + 0 + Title + + LucidaGrande + 11 + 16 + + + 6 + System + textBackgroundColor + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 0 + 3 + 0 + NO + + + + 264 + {{112, 368}, {439, 105}} + + + + YES + + -1805517311 + 272629760 + + + Placeholder + + YES + + + 6 + System + textColor + + + + + + + 264 + {{109, 508}, {445, 59}} + + + + YES + + 67239424 + 272629760 + %@ unexpectedly quit the last time it was run. Would you like to send a crash report to %@? + + + + + + + + + 292 + {{106, 35}, {119, 32}} + + + + YES + + 67239424 + 134217728 + Show Details + + + -2038284033 + 1 + + + + 200 + 25 + + + + + -2147483356 + {{106, 35}, {119, 32}} + + + + YES + + 67239424 + 134217728 + Hide Details + + + -2038284033 + 1 + + + + 200 + 25 + + + + + 289 + {{393, 35}, {82, 32}} + + + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 289 + {{475, 35}, {82, 32}} + + + + YES + + 67239424 + 134217728 + Send + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 268 + {{112, 481}, {13, 13}} + + + + YES + + 67239424 + 0 + + + + -1198636801 + 5 + + + + + + 200 + 25 + + + + + 268 + {{130, 479}, {115, 18}} + + + + YES + + 67239424 + 272629760 + Comments + + + + + + + + + 268 + + YES + + YES + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + NSFilenamesPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT TIFF v4.0 pasteboard type + + + {{20, 503}, {64, 64}} + + + + YES + + 130560 + 33554432 + + NSImage + NSApplicationIcon + + 0 + 0 + 0 + NO + + YES + + + + 290 + {{109, 20}, {445, 11}} + + + + YES + + -1541276159 + 272629760 + + + LucidaGrande + 9 + 16 + + Note + + + 4 + MQA + + + + + + {571, 587} + + + + + {{0, 0}, {2560, 1418}} + {213, 129} + {10000000000000, 10000000000000} + YES + + + YES + + + + + YES + + + submitReport: + + + + 398 + + + + window + + + + 401 + + + + submitButton + + + + 402 + + + + cancelButton + + + + 406 + + + + crashLogTextView + + + + 408 + + + + hideButton + + + + 413 + + + + showButton + + + + 414 + + + + hideDetails: + + + + 415 + + + + showDetails: + + + + 416 + + + + showComments: + + + + 417 + + + + cancelReport: + + + + 454 + + + + descriptionTextField + + + + 458 + + + + noteText + + + + 479 + + + + initialFirstResponder + + + + 395 + + + + delegate + + + + 399 + + + + hidden: showDetails + + + + + + hidden: showDetails + hidden + showDetails + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 444 + + + + value: showComments + + + + + + value: showComments + value + showComments + 2 + + + 438 + + + + displayPatternValue1: applicationName + + + + + + displayPatternValue1: applicationName + displayPatternValue1 + applicationName + + NSDisplayPattern + %{value1}@ has unexpectedly quit last time it was run. Would you like to send a crash report to %{value2}@? + + 2 + + + 480 + + + + displayPatternValue2: companyName + + + + + + displayPatternValue2: companyName + displayPatternValue2 + companyName + + NSDisplayPattern + %{value1}@ has unexpectedly quit last time it was run. Would you like to send a crash report to %{value2}@? + + + 2 + + + 481 + + + + value: self + + + + + + value: self + value + self + 2 + + + 419 + + + + hidden: showDetails + + + + + + hidden: showDetails + hidden + showDetails + 2 + + + 453 + + + + hidden: showDetails + + + + + + hidden: showDetails + hidden + showDetails + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 452 + + + + hidden: showComments + + + + + + hidden: showComments + hidden + showComments + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 485 + + + + delegate + + + + 486 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 361 + + + YES + + + + Window + + + 362 + + + YES + + + + + + + + + + + + + + + + 364 + + + YES + + + + + + + 365 + + + YES + + + + + + 366 + + + YES + + + + + + 367 + + + YES + + + + + + 369 + + + YES + + + + + + 370 + + + YES + + + + + + 371 + + + + + 372 + + + + + 374 + + + + + 375 + + + + + 376 + + + + + 396 + + + YES + + + + + + 397 + + + + + 411 + + + YES + + + + + + 412 + + + + + 440 + + + + + 455 + + + YES + + + + + + 456 + + + + + 477 + + + YES + + + + + + 478 + + + + + 368 + + + YES + + + + + + 373 + + + + + 377 + + + YES + + + + + + 394 + + + + + 378 + + + YES + + + + + + + + 393 + + + + + 392 + + + + + 391 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 361.IBPluginDependency + 361.IBWindowTemplateEditedContentRect + 362.IBPluginDependency + 364.IBPluginDependency + 365.IBPluginDependency + 366.IBPluginDependency + 367.IBPluginDependency + 368.IBPluginDependency + 369.IBPluginDependency + 370.IBPluginDependency + 371.IBPluginDependency + 372.IBPluginDependency + 373.IBPluginDependency + 374.IBPluginDependency + 375.IBPluginDependency + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 391.IBAttributePlaceholdersKey + 391.IBPluginDependency + 392.IBPluginDependency + 392.IBShouldRemoveOnLegacySave + 393.IBPluginDependency + 393.IBShouldRemoveOnLegacySave + 394.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 440.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 477.IBPluginDependency + 478.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{406, 702}, {571, 294}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + YES + + YES + AccessibilityDescription + AccessibilityHelp + ToolTip + + + YES + + AccessibilityDescription + + Please describe any steps needed to trigger the problem + + + AccessibilityHelp + + Please describe any steps needed to trigger the problem + + + ToolTip + + Please describe any steps needed to trigger the problem + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + + + + YES + + + + + 486 + + + + YES + + BWQuincyUI + NSWindowController + + YES + + YES + cancelReport: + hideDetails: + showComments: + showDetails: + submitReport: + + + YES + id + id + id + id + id + + + + YES + + YES + cancelReport: + hideDetails: + showComments: + showDetails: + submitReport: + + + YES + + cancelReport: + id + + + hideDetails: + id + + + showComments: + id + + + showDetails: + id + + + submitReport: + id + + + + + YES + + YES + cancelButton + crashLogTextView + descriptionTextField + hideButton + noteText + showButton + submitButton + + + YES + NSButton + NSTextView + NSTextField + NSButton + NSTextField + NSButton + NSButton + + + + YES + + YES + cancelButton + crashLogTextView + descriptionTextField + hideButton + noteText + showButton + submitButton + + + YES + + cancelButton + NSButton + + + crashLogTextView + NSTextView + + + descriptionTextField + NSTextField + + + hideButton + NSButton + + + noteText + NSTextField + + + showButton + NSButton + + + submitButton + NSButton + + + + + IBProjectSource + ./Classes/BWQuincyUI.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + NSApplicationIcon + {128, 128} + + + diff --git a/External Source/QuincyKit/client/Mac/BWQuincyMain.nib/keyedobjects.nib b/External Source/QuincyKit/client/Mac/BWQuincyMain.nib/keyedobjects.nib new file mode 100644 index 000000000..c3b6a17e1 Binary files /dev/null and b/External Source/QuincyKit/client/Mac/BWQuincyMain.nib/keyedobjects.nib differ diff --git a/External Source/QuincyKit/client/Mac/BWQuincyManager.h b/External Source/QuincyKit/client/Mac/BWQuincyManager.h new file mode 100644 index 000000000..b66340cc6 --- /dev/null +++ b/External Source/QuincyKit/client/Mac/BWQuincyManager.h @@ -0,0 +1,219 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +#import + +#define CRASHREPORTSENDER_MAX_CONSOLE_SIZE 50000 + +typedef enum CrashAlertType { + CrashAlertTypeSend = 0, + CrashAlertTypeFeedback = 1, +} CrashAlertType; + +typedef enum CrashReportStatus { + // This app version is set to discontinued, no new crash reports accepted by the server + CrashReportStatusFailureVersionDiscontinued = -30, + + // XML: Sender ersion string contains not allowed characters, only alphanumberical including space and . are allowed + CrashReportStatusFailureXMLSenderVersionNotAllowed = -21, + + // XML: Version string contains not allowed characters, only alphanumberical including space and . are allowed + CrashReportStatusFailureXMLVersionNotAllowed = -20, + + // SQL for adding a symoblicate todo entry in the database failed + CrashReportStatusFailureSQLAddSymbolicateTodo = -18, + + // SQL for adding crash log in the database failed + CrashReportStatusFailureSQLAddCrashlog = -17, + + // SQL for adding a new version in the database failed + CrashReportStatusFailureSQLAddVersion = -16, + + // SQL for checking if the version is already added in the database failed + CrashReportStatusFailureSQLCheckVersionExists = -15, + + // SQL for creating a new pattern for this bug and set amount of occurrances to 1 in the database failed + CrashReportStatusFailureSQLAddPattern = -14, + + // SQL for checking the status of the bugfix version in the database failed + CrashReportStatusFailureSQLCheckBugfixStatus = -13, + + // SQL for updating the occurances of this pattern in the database failed + CrashReportStatusFailureSQLUpdatePatternOccurances = -12, + + // SQL for getting all the known bug patterns for the current app version in the database failed + CrashReportStatusFailureSQLFindKnownPatterns = -11, + + // SQL for finding the bundle identifier in the database failed + CrashReportStatusFailureSQLSearchAppName = -10, + + // the post request didn't contain valid data + CrashReportStatusFailureInvalidPostData = -3, + + // incoming data may not be added, because e.g. bundle identifier wasn't found + CrashReportStatusFailureInvalidIncomingData = -2, + + // database cannot be accessed, check hostname, username, password and database name settings in config.php + CrashReportStatusFailureDatabaseNotAvailable = -1, + + CrashReportStatusUnknown = 0, + + CrashReportStatusAssigned = 1, + + CrashReportStatusSubmitted = 2, + + CrashReportStatusAvailable = 3, +} CrashReportStatus; + + +@class BWQuincyUI; + +// This protocol is used to send the image updates +@protocol BWQuincyManagerDelegate + +@required + +// Invoked once the modal sheets are gone +- (void) showMainApplicationWindow; + +@optional + +// Return the description the crashreport should contain, empty by default. The string will automatically be wrapped into <[DATA[ ]]>, so make sure you don't do that in your string. +-(NSString *) crashReportDescription; + +@optional + +// Return the userid the crashreport should contain, empty by default +-(NSString *) crashReportUserID; + +// Return the contact value (e.g. email) the crashreport should contain, empty by default +-(NSString *) crashReportContact; +@end + +@interface BWQuincyManager : NSObject +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + +#endif +{ + CrashReportStatus _serverResult; + + NSInteger _statusCode; + + NSMutableString *_contentOfProperty; + + id _delegate; + + NSString *_submissionURL; + NSString *_companyName; + NSString *_appIdentifier; + BOOL _autoSubmitCrashReport; + + NSString *_crashFile; + + BWQuincyUI *_quincyUI; +} + +- (NSString*) modelVersion; + ++ (BWQuincyManager *)sharedQuincyManager; + +// submission URL defines where to send the crash reports to (required) +@property (nonatomic, retain) NSString *submissionURL; + +// defines the company name to be shown in the crash reporting dialog +@property (nonatomic, retain) NSString *companyName; + +// delegate is required +@property (nonatomic, assign) id delegate; + +// if YES, the crash report will be submitted without asking the user +// if NO, the user will be asked if the crash report can be submitted (default) +@property (nonatomic, assign, getter=isAutoSubmitCrashReport) BOOL autoSubmitCrashReport; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// settings + +// If you want to use HockeyApp instead of your own server, this is required +@property (nonatomic, retain) NSString *appIdentifier; + + +- (void) cancelReport; +- (void) sendReportCrash:(NSString*)crashContent + description:(NSString*)description; + +- (NSString *) applicationName; +- (NSString *) applicationVersionString; +- (NSString *) applicationVersion; + +@end + + +@interface BWQuincyUI : NSWindowController { + IBOutlet NSTextField *descriptionTextField; + IBOutlet NSTextView *crashLogTextView; + + IBOutlet NSTextField *noteText; + + IBOutlet NSButton *showButton; + IBOutlet NSButton *hideButton; + IBOutlet NSButton *cancelButton; + IBOutlet NSButton *submitButton; + + BWQuincyManager *_delegate; + + NSString *_xml; + + NSString *_crashFile; + NSString *_companyName; + NSString *_applicationName; + + NSMutableString *_consoleContent; + NSString *_crashLogContent; + + BOOL showComments; + BOOL showDetails; +} + +- (id)init:(id)delegate crashFile:(NSString *)crashFile companyName:(NSString *)companyName applicationName:(NSString *)applicationName; + +- (void) askCrashReportDetails; + +- (IBAction) cancelReport:(id)sender; +- (IBAction) submitReport:(id)sender; +- (IBAction) showDetails:(id)sender; +- (IBAction) hideDetails:(id)sender; +- (IBAction) showComments:(id)sender; + +- (BOOL)showComments; +- (void)setShowComments:(BOOL)value; + +- (BOOL)showDetails; +- (void)setShowDetails:(BOOL)value; + +@end diff --git a/External Source/QuincyKit/client/Mac/BWQuincyManager.m b/External Source/QuincyKit/client/Mac/BWQuincyManager.m new file mode 100644 index 000000000..7a5747f5b --- /dev/null +++ b/External Source/QuincyKit/client/Mac/BWQuincyManager.m @@ -0,0 +1,628 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +#import "BWQuincyManager.h" +#import + +@interface BWQuincyManager(private) +- (void) startManager; + +- (void) _postXML:(NSString*)xml toURL:(NSURL*)url; +- (void) searchCrashLogFile:(NSString *)path; +- (BOOL) hasPendingCrashReport; +- (void) returnToMainApplication; +@end + +@interface BWQuincyUI(private) +- (void) askCrashReportDetails; +- (void) endCrashReporter; +@end + +const CGFloat kCommentsHeight = 105; +const CGFloat kDetailsHeight = 285; + +@implementation BWQuincyManager + +@synthesize delegate = _delegate; +@synthesize submissionURL = _submissionURL; +@synthesize companyName = _companyName; +@synthesize appIdentifier = _appIdentifier; +@synthesize autoSubmitCrashReport = _autoSubmitCrashReport; + ++ (BWQuincyManager *)sharedQuincyManager { + static BWQuincyManager *quincyManager = nil; + + if (quincyManager == nil) { + quincyManager = [[BWQuincyManager alloc] init]; + } + + return quincyManager; +} + +- (id) init { + if ((self = [super init])) { + _serverResult = CrashReportStatusFailureDatabaseNotAvailable; + _quincyUI = nil; + + _submissionURL = nil; + _appIdentifier = nil; + + _crashFile = nil; + + self.delegate = nil; + self.companyName = @""; + } + return self; +} + +- (void)dealloc { + _companyName = nil; + _delegate = nil; + _submissionURL = nil; + _appIdentifier = nil; + + [_crashFile release]; + [_quincyUI release]; + + [super dealloc]; +} + +- (void) searchCrashLogFile:(NSString *)path { + NSFileManager* fman = [NSFileManager defaultManager]; + + NSError* error; + NSMutableArray* filesWithModificationDate = [NSMutableArray array]; + NSArray* crashLogFiles = [fman contentsOfDirectoryAtPath:path error:&error]; + NSEnumerator* filesEnumerator = [crashLogFiles objectEnumerator]; + NSString* crashFile; + while((crashFile = [filesEnumerator nextObject])) { + NSString* crashLogPath = [path stringByAppendingPathComponent:crashFile]; + NSDate* modDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:crashLogPath error:&error] fileModificationDate]; + [filesWithModificationDate addObject:[NSDictionary dictionaryWithObjectsAndKeys:crashFile,@"name",crashLogPath,@"path",modDate,@"modDate",nil]]; + } + + NSSortDescriptor* dateSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"modDate" ascending:YES] autorelease]; + NSArray* sortedFiles = [filesWithModificationDate sortedArrayUsingDescriptors:[NSArray arrayWithObject:dateSortDescriptor]]; + + NSPredicate* filterPredicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@", [self applicationName]]; + NSArray* filteredFiles = [sortedFiles filteredArrayUsingPredicate:filterPredicate]; + + _crashFile = [[[filteredFiles valueForKeyPath:@"path"] lastObject] copy]; +} + +#pragma mark - +#pragma mark setter +- (void)setSubmissionURL:(NSString *)anSubmissionURL { + if (_submissionURL != anSubmissionURL) { + [_submissionURL release]; + _submissionURL = [anSubmissionURL copy]; + } + + [self performSelector:@selector(startManager) withObject:nil afterDelay:0.1f]; +} + +- (void)setAppIdentifier:(NSString *)anAppIdentifier { + if (_appIdentifier != anAppIdentifier) { + [_appIdentifier release]; + _appIdentifier = [anAppIdentifier copy]; + } + + [self setSubmissionURL:@"https://rink.hockeyapp.net/"]; +} + +- (void)storeLastCrashDate:(NSDate *) date { + [[NSUserDefaults standardUserDefaults] setValue:date forKey:@"CrashReportSender.lastCrashDate"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (NSDate *)loadLastCrashDate { + NSDate *date = [[NSUserDefaults standardUserDefaults] valueForKey:@"CrashReportSender.lastCrashDate"]; + return date ?: [NSDate distantPast]; +} + +- (void)storeAppVersion:(NSString *) version { + [[NSUserDefaults standardUserDefaults] setValue:version forKey:@"CrashReportSender.appVersion"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (NSString *)loadAppVersion { + NSString *appVersion = [[NSUserDefaults standardUserDefaults] valueForKey:@"CrashReportSender.appVersion"]; + return appVersion ?: nil; +} + +#pragma mark - +#pragma mark GetCrashData + +- (BOOL) hasPendingCrashReport { + BOOL returnValue = NO; + + NSString *appVersion = [self loadAppVersion]; + NSDate *lastCrashDate = [self loadLastCrashDate]; + + if (!appVersion || ![appVersion isEqualToString:[self applicationVersion]] || [lastCrashDate isEqualToDate:[NSDate distantPast]]) { + [self storeAppVersion:[self applicationVersion]]; + [self storeLastCrashDate:[NSDate date]]; + return NO; + } + + NSArray* libraryDirectories = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, TRUE); + // Snow Leopard is having the log files in another location + [self searchCrashLogFile:[[libraryDirectories lastObject] stringByAppendingPathComponent:@"Logs/DiagnosticReports"]]; + if (_crashFile == nil) { + [self searchCrashLogFile:[[libraryDirectories lastObject] stringByAppendingPathComponent:@"Logs/CrashReporter"]]; + if (_crashFile == nil) { + NSString *sandboxFolder = [NSString stringWithFormat:@"/Containers/%@/Data/Library", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]]; + if ([[libraryDirectories lastObject] rangeOfString:sandboxFolder].location != NSNotFound) { + NSString *libFolderName = [[libraryDirectories lastObject] stringByReplacingOccurrencesOfString:sandboxFolder withString:@""]; + [self searchCrashLogFile:[libFolderName stringByAppendingPathComponent:@"Logs/DiagnosticReports"]]; + } + } + } + + if (_crashFile) { + NSError* error; + + NSDate *crashLogModificationDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:_crashFile error:&error] fileModificationDate]; + unsigned long long crashLogFileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:_crashFile error:&error] fileSize]; + if ([crashLogModificationDate compare: lastCrashDate] == NSOrderedDescending && crashLogFileSize > 0) { + [self storeLastCrashDate:crashLogModificationDate]; + returnValue = YES; + } + } + + return returnValue; +} + +- (void) returnToMainApplication { + if ( self.delegate != nil && [self.delegate respondsToSelector:@selector(showMainApplicationWindow)]) + [self.delegate showMainApplicationWindow]; +} + +- (void) startManager { + if ([self hasPendingCrashReport]) { + if (!self.autoSubmitCrashReport) { + _quincyUI = [[BWQuincyUI alloc] init:self crashFile:_crashFile companyName:_companyName applicationName:[self applicationName]]; + [_quincyUI askCrashReportDetails]; + } else { + NSError* error = nil; + NSString *crashLogs = [NSString stringWithContentsOfFile:_crashFile encoding:NSUTF8StringEncoding error:&error]; + if (!error) { + NSString *lastCrash = [[crashLogs componentsSeparatedByString: @"**********\n\n"] lastObject]; + + NSString* description = @""; + + if (_delegate && [_delegate respondsToSelector:@selector(crashReportDescription)]) { + description = [_delegate crashReportDescription]; + } + + [self sendReportCrash:lastCrash description:description]; + } + } + } else { + [self returnToMainApplication]; + } +} + +- (NSString*) modelVersion { + NSString * modelString = nil; + int modelInfo[2] = { CTL_HW, HW_MODEL }; + size_t modelSize; + + if (sysctl(modelInfo, + 2, + NULL, + &modelSize, + NULL, 0) == 0) { + void * modelData = malloc(modelSize); + + if (modelData) { + if (sysctl(modelInfo, + 2, + modelData, + &modelSize, + NULL, 0) == 0) { + modelString = [NSString stringWithUTF8String:modelData]; + } + + free(modelData); + } + } + + return modelString; +} + + + +- (void) cancelReport { + [self returnToMainApplication]; +} + + +- (void) sendReportCrash:(NSString*)crashContent + description:(NSString*)notes +{ + NSString *userid = @""; + NSString *contact = @""; + + SInt32 versionMajor, versionMinor, versionBugFix; + if (Gestalt(gestaltSystemVersionMajor, &versionMajor) != noErr) versionMajor = 0; + if (Gestalt(gestaltSystemVersionMinor, &versionMinor) != noErr) versionMinor= 0; + if (Gestalt(gestaltSystemVersionBugFix, &versionBugFix) != noErr) versionBugFix = 0; + + NSString* xml = [NSString stringWithFormat:@"%s%s%@%@%@%@%@%@", + [[self applicationName] UTF8String], + [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"] UTF8String], + [NSString stringWithFormat:@"%i.%i.%i", versionMajor, versionMinor, versionBugFix], + [self applicationVersion], + [self applicationVersion], + [self modelVersion], + userid, + contact, + notes, + crashContent + ]; + + + [self returnToMainApplication]; + + [self _postXML:[NSString stringWithFormat:@"%@", xml] toURL:[NSURL URLWithString:self.submissionURL]]; +} + +- (void)_postXML:(NSString*)xml toURL:(NSURL*)url { + NSMutableURLRequest *request = nil; + NSString *boundary = @"----FOO"; + + if (self.appIdentifier) { + request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes", + self.submissionURL, + [self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + ] + ]]; + } else { + request = [NSMutableURLRequest requestWithURL:url]; + } + + [request setValue:@"Quincy/Mac" forHTTPHeaderField:@"User-Agent"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setTimeoutInterval: 15]; + [request setHTTPMethod:@"POST"]; + NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; + [request setValue:contentType forHTTPHeaderField:@"Content-type"]; + + NSMutableData *postBody = [NSMutableData data]; + [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; + if (self.appIdentifier) { + [postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; + [postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; + } else { + [postBody appendData:[@"Content-Disposition: form-data; name=\"xmlstring\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; + } + [postBody appendData:[xml dataUsingEncoding:NSUTF8StringEncoding]]; + [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; + [request setHTTPBody:postBody]; + + _serverResult = CrashReportStatusUnknown; + _statusCode = 200; + + NSHTTPURLResponse *response = nil; + NSError *error = nil; + + NSData *responseData = nil; + responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; + _statusCode = [response statusCode]; + + if (responseData != nil) { + if (_statusCode >= 200 && _statusCode < 400) { + NSXMLParser *parser = [[NSXMLParser alloc] initWithData:responseData]; + // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks. + [parser setDelegate:self]; + // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser. + [parser setShouldProcessNamespaces:NO]; + [parser setShouldReportNamespacePrefixes:NO]; + [parser setShouldResolveExternalEntities:NO]; + + [parser parse]; + + [parser release]; + } + } +} + + +#pragma mark NSXMLParser + +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { + if (qName) { + elementName = qName; + } + + if ([elementName isEqualToString:@"result"]) { + _contentOfProperty = [NSMutableString string]; + } +} + +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { + if (qName) { + elementName = qName; + } + + if ([elementName isEqualToString:@"result"]) { + if ([_contentOfProperty intValue] > _serverResult) { + _serverResult = [_contentOfProperty intValue]; + } + } +} + + +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { + if (_contentOfProperty) { + // If the current element is one whose content we care about, append 'string' + // to the property that holds the content of the current element. + if (string != nil) { + [_contentOfProperty appendString:string]; + } + } +} + + +#pragma mark GetterSetter + +- (NSString *) applicationName { + NSString *applicationName = [[[NSBundle mainBundle] localizedInfoDictionary] valueForKey: @"CFBundleExecutable"]; + + if (!applicationName) + applicationName = [[[NSBundle mainBundle] infoDictionary] valueForKey: @"CFBundleExecutable"]; + + return applicationName; +} + + +- (NSString*) applicationVersionString { + NSString* string = [[[NSBundle mainBundle] localizedInfoDictionary] valueForKey: @"CFBundleShortVersionString"]; + + if (!string) + string = [[[NSBundle mainBundle] infoDictionary] valueForKey: @"CFBundleShortVersionString"]; + + return string; +} + +- (NSString *) applicationVersion { + NSString* string = [[[NSBundle mainBundle] localizedInfoDictionary] valueForKey: @"CFBundleVersion"]; + + if (!string) + string = [[[NSBundle mainBundle] infoDictionary] valueForKey: @"CFBundleVersion"]; + + return string; +} + +@end + + + + +@implementation BWQuincyUI + +- (id)init:(id)delegate crashFile:(NSString *)crashFile companyName:(NSString *)companyName applicationName:(NSString *)applicationName { + + self = [super initWithWindowNibName: @"BWQuincyMain"]; + + if ( self != nil) { + _xml = nil; + _delegate = delegate; + _crashFile = crashFile; + _companyName = companyName; + _applicationName = applicationName; + [self setShowComments: YES]; + [self setShowDetails: NO]; + + NSRect windowFrame = [[self window] frame]; + windowFrame.size = NSMakeSize(windowFrame.size.width, windowFrame.size.height - kDetailsHeight); + windowFrame.origin.y -= kDetailsHeight; + [[self window] setFrame: windowFrame + display: YES + animate: NO]; + + } + return self; +} + + +- (void) endCrashReporter { + [self close]; +} + + +- (IBAction) showComments: (id) sender { + NSRect windowFrame = [[self window] frame]; + + if ([sender intValue]) { + [self setShowComments: NO]; + + windowFrame.size = NSMakeSize(windowFrame.size.width, windowFrame.size.height + kCommentsHeight); + windowFrame.origin.y -= kCommentsHeight; + [[self window] setFrame: windowFrame + display: YES + animate: YES]; + + [self setShowComments: YES]; + } else { + [self setShowComments: NO]; + + windowFrame.size = NSMakeSize(windowFrame.size.width, windowFrame.size.height - kCommentsHeight); + windowFrame.origin.y += kCommentsHeight; + [[self window] setFrame: windowFrame + display: YES + animate: YES]; + } +} + + +- (IBAction) showDetails:(id)sender { + NSRect windowFrame = [[self window] frame]; + + windowFrame.size = NSMakeSize(windowFrame.size.width, windowFrame.size.height + kDetailsHeight); + windowFrame.origin.y -= kDetailsHeight; + [[self window] setFrame: windowFrame + display: YES + animate: YES]; + + [self setShowDetails:YES]; + +} + + +- (IBAction) hideDetails:(id)sender { + NSRect windowFrame = [[self window] frame]; + + [self setShowDetails:NO]; + + windowFrame.size = NSMakeSize(windowFrame.size.width, windowFrame.size.height - kDetailsHeight); + windowFrame.origin.y += kDetailsHeight; + [[self window] setFrame: windowFrame + display: YES + animate: YES]; +} + + +- (IBAction) cancelReport:(id)sender { + [self endCrashReporter]; + [NSApp stopModal]; + + if ( _delegate != nil && [_delegate respondsToSelector:@selector(cancelReport)]) + [_delegate cancelReport]; +} + +- (void) _sendReportAfterDelay { + if ( _delegate != nil && [_delegate respondsToSelector:@selector(sendReport:)]) { + NSString *notes = [NSString stringWithFormat:@"Comments:\n%@\n\nConsole:\n%@", [descriptionTextField stringValue], _consoleContent]; + + [_delegate sendReportCrash:_crashLogContent description:notes]; + } +} + +- (IBAction) submitReport:(id)sender { + [submitButton setEnabled:NO]; + + [[self window] makeFirstResponder: nil]; + + [self performSelector:@selector(_sendReportAfterDelay) withObject:nil afterDelay:0.01]; + + [self endCrashReporter]; + [NSApp stopModal]; +} + + +- (void) askCrashReportDetails { + NSError *error; + + [[self window] setTitle:[NSString stringWithFormat:NSLocalizedString(@"Problem Report for %@", @"Window title"), _applicationName]]; + + [[descriptionTextField cell] setPlaceholderString:NSLocalizedString(@"Please describe any steps needed to trigger the problem", @"User description placeholder")]; + [noteText setStringValue:NSLocalizedString(@"No personal information will be sent with this report.", @"Note text")]; + + // get the crash log + NSString *crashLogs = [NSString stringWithContentsOfFile:_crashFile encoding:NSUTF8StringEncoding error:&error]; + NSString *lastCrash = [[crashLogs componentsSeparatedByString: @"**********\n\n"] lastObject]; + + _crashLogContent = lastCrash; + + // get the console log + NSEnumerator *theEnum = [[[NSString stringWithContentsOfFile:@"/private/var/log/system.log" encoding:NSUTF8StringEncoding error:&error] componentsSeparatedByString: @"\n"] objectEnumerator]; + NSString* currentObject; + NSMutableArray* applicationStrings = [NSMutableArray array]; + + NSString* searchString = [[_delegate applicationName] stringByAppendingString:@"["]; + while ( (currentObject = [theEnum nextObject]) ) { + if ([currentObject rangeOfString:searchString].location != NSNotFound) + [applicationStrings addObject: currentObject]; + } + + _consoleContent = [NSMutableString string]; + + NSInteger i; + for(i = ((NSInteger)[applicationStrings count])-1; (i>=0 && i>((NSInteger)[applicationStrings count])-100); i--) { + [_consoleContent appendString:[applicationStrings objectAtIndex:i]]; + [_consoleContent appendString:@"\n"]; + } + + // Now limit the content to CRASHREPORTSENDER_MAX_CONSOLE_SIZE (default: 50kByte) + if ([_consoleContent length] > CRASHREPORTSENDER_MAX_CONSOLE_SIZE) { + _consoleContent = (NSMutableString *)[_consoleContent substringWithRange:NSMakeRange([_consoleContent length]-CRASHREPORTSENDER_MAX_CONSOLE_SIZE-1, CRASHREPORTSENDER_MAX_CONSOLE_SIZE)]; + } + + [crashLogTextView setString:[NSString stringWithFormat:@"%@\n\n%@", _crashLogContent, _consoleContent]]; + + + NSBeep(); + [NSApp runModalForWindow:[self window]]; +} + + +- (void)dealloc { + _companyName = nil; + _delegate = nil; + + [super dealloc]; +} + + +- (BOOL)showComments { + return showComments; +} + + +- (void)setShowComments:(BOOL)value { + showComments = value; +} + + +- (BOOL)showDetails { + return showDetails; +} + + +- (void)setShowDetails:(BOOL)value { + showDetails = value; +} + +#pragma mark NSTextField Delegate + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector { + BOOL commandHandled = NO; + + if (commandSelector == @selector(insertNewline:)) { + [textView insertNewlineIgnoringFieldEditor:self]; + commandHandled = YES; + } + + return commandHandled; +} + +@end + diff --git a/External Source/QuincyKit/client/iOS/BWQuincyManager.h b/External Source/QuincyKit/client/iOS/BWQuincyManager.h new file mode 100644 index 000000000..e4accd406 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/BWQuincyManager.h @@ -0,0 +1,228 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +#import + +#define BWQuincyLog(fmt, ...) do { if([BWQuincyManager sharedQuincyManager].isLoggingEnabled) { NSLog((@"[QuincyLib] %s/%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); }} while(0) + +#define kQuincyBundleName @"Quincy.bundle" + +NSBundle *quincyBundle(void); +NSString *BWQuincyLocalize(NSString *stringToken); + +//#define BWQuincyLocalize(StringToken) NSLocalizedStringFromTableInBundle(StringToken, @"Quincy", quincyBundle(), @"") + +// flags if the crashlog analyzer is started. since this may theoretically crash we need to track it +#define kQuincyKitAnalyzerStarted @"QuincyKitAnalyzerStarted" + +// flags if the QuincyKit is activated at all +#define kQuincyKitActivated @"QuincyKitActivated" + +// flags if the crashreporter should automatically send crashes without asking the user again +#define kAutomaticallySendCrashReports @"AutomaticallySendCrashReports" + +// stores the set of crashreports that have been approved but aren't sent yet +#define kApprovedCrashReports @"ApprovedCrashReports" + +// Notification message which QuincyManager is listening to, to retry sending pending crash reports to the server +#define BWQuincyNetworkBecomeReachable @"NetworkDidBecomeReachable" + +typedef enum QuincyKitAlertType { + QuincyKitAlertTypeSend = 0, + QuincyKitAlertTypeFeedback = 1, +} CrashAlertType; + +typedef enum CrashReportStatus { + // The status of the crash is queued, need to check later (HockeyApp) + CrashReportStatusQueued = -80, + + // This app version is set to discontinued, no new crash reports accepted by the server + CrashReportStatusFailureVersionDiscontinued = -30, + + // XML: Sender version string contains not allowed characters, only alphanumberical including space and . are allowed + CrashReportStatusFailureXMLSenderVersionNotAllowed = -21, + + // XML: Version string contains not allowed characters, only alphanumberical including space and . are allowed + CrashReportStatusFailureXMLVersionNotAllowed = -20, + + // SQL for adding a symoblicate todo entry in the database failed + CrashReportStatusFailureSQLAddSymbolicateTodo = -18, + + // SQL for adding crash log in the database failed + CrashReportStatusFailureSQLAddCrashlog = -17, + + // SQL for adding a new version in the database failed + CrashReportStatusFailureSQLAddVersion = -16, + + // SQL for checking if the version is already added in the database failed + CrashReportStatusFailureSQLCheckVersionExists = -15, + + // SQL for creating a new pattern for this bug and set amount of occurrances to 1 in the database failed + CrashReportStatusFailureSQLAddPattern = -14, + + // SQL for checking the status of the bugfix version in the database failed + CrashReportStatusFailureSQLCheckBugfixStatus = -13, + + // SQL for updating the occurances of this pattern in the database failed + CrashReportStatusFailureSQLUpdatePatternOccurances = -12, + + // SQL for getting all the known bug patterns for the current app version in the database failed + CrashReportStatusFailureSQLFindKnownPatterns = -11, + + // SQL for finding the bundle identifier in the database failed + CrashReportStatusFailureSQLSearchAppName = -10, + + // the post request didn't contain valid data + CrashReportStatusFailureInvalidPostData = -3, + + // incoming data may not be added, because e.g. bundle identifier wasn't found + CrashReportStatusFailureInvalidIncomingData = -2, + + // database cannot be accessed, check hostname, username, password and database name settings in config.php + CrashReportStatusFailureDatabaseNotAvailable = -1, + + CrashReportStatusUnknown = 0, + + CrashReportStatusAssigned = 1, + + CrashReportStatusSubmitted = 2, + + CrashReportStatusAvailable = 3, +} CrashReportStatus; + +// This protocol is used to send the image updates +@protocol BWQuincyManagerDelegate + +@optional + +// Return the userid the crashreport should contain, empty by default +-(NSString *) crashReportUserID; + +// Return the contact value (e.g. email) the crashreport should contain, empty by default +-(NSString *) crashReportContact; + +// Return the description the crashreport should contain, empty by default. The string will automatically be wrapped into <[DATA[ ]]>, so make sure you don't do that in your string. +-(NSString *) crashReportDescription; + +// Invoked when the internet connection is started, to let the app enable the activity indicator +-(void) connectionOpened; + +// Invoked when the internet connection is closed, to let the app disable the activity indicator +-(void) connectionClosed; + +// Invoked before the user is asked to send a crash report, so you can do additional actions. E.g. to make sure not to ask the user for an app rating :) +-(void) willShowSubmitCrashReportAlert; + +// Invoked after the user did choose to send crashes always in the alert +-(void) userDidChooseSendAlways; + +@end + +@interface BWQuincyManager : NSObject { + NSString *_submissionURL; + + id _delegate; + + BOOL _loggingEnabled; + BOOL _showAlwaysButton; + BOOL _feedbackActivated; + BOOL _autoSubmitCrashReport; + BOOL _autoSubmitDeviceUDID; + + BOOL _didCrashInLastSession; + + NSString *_appIdentifier; + + NSString *_feedbackRequestID; + float _feedbackDelayInterval; + + NSMutableString *_contentOfProperty; + CrashReportStatus _serverResult; + + int _analyzerStarted; + NSString *_crashesDir; + + BOOL _crashIdenticalCurrentVersion; + BOOL _crashReportActivated; + + NSMutableArray *_crashFiles; + + NSMutableData *_responseData; + NSInteger _statusCode; + + NSURLConnection *_urlConnection; + + NSData *_crashData; + + NSString *_languageStyle; + BOOL _sendingInProgress; +} + ++ (BWQuincyManager *)sharedQuincyManager; + +// submission URL defines where to send the crash reports to (required) +@property (nonatomic, retain) NSString *submissionURL; + +// delegate is optional +@property (nonatomic, assign) id delegate; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// settings + +// if YES, states will be logged using NSLog. Only enable this for debugging! +// if NO, nothing will be logged. (default) +@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled; + +// nil, using the default localization files (Default) +// set to another string which will be appended to the Quincy localization file name, "Alternate" is another provided text set +@property (nonatomic, retain) NSString *languageStyle; + +// if YES, the user will get the option to choose "Always" for sending crash reports. This will cause the dialog not to show the alert description text landscape mode! (default) +// if NO, the dialog will not show a "Always" button +@property (nonatomic, assign, getter=isShowingAlwaysButton) BOOL showAlwaysButton; + +// if YES, the user will be presented with a status of the crash, if known +// if NO, the user will not see any feedback information (default) +@property (nonatomic, assign, getter=isFeedbackActivated) BOOL feedbackActivated; + +// if YES, the crash report will be submitted without asking the user +// if NO, the user will be asked if the crash report can be submitted (default) +@property (nonatomic, assign, getter=isAutoSubmitCrashReport) BOOL autoSubmitCrashReport; + +// if YES, the device UDID will be submitted as the user id, without the need to define it in the crashReportUserID delegate (meant for beta versions!) +// if NO, the crashReportUserID delegate defines what to be sent as user id (default) +@property (nonatomic, assign, getter=isAutoSubmitDeviceUDID) BOOL autoSubmitDeviceUDID; + +// will return if the last session crashed, to e.g. make sure a "rate my app" alert will not show up +@property (nonatomic, readonly) BOOL didCrashInLastSession; + +// If you want to use HockeyApp instead of your own server, this is required +@property (nonatomic, retain) NSString *appIdentifier; + +@end diff --git a/External Source/QuincyKit/client/iOS/BWQuincyManager.m b/External Source/QuincyKit/client/iOS/BWQuincyManager.m new file mode 100644 index 000000000..67e94dda8 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/BWQuincyManager.m @@ -0,0 +1,794 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +#import +#import +#import +#import "BWQuincyManager.h" + +#include +#include //needed for PRIx64 macro + +NSBundle *quincyBundle(void) { + static NSBundle* bundle = nil; + if (!bundle) { + NSString* path = [[[NSBundle mainBundle] resourcePath] + stringByAppendingPathComponent:kQuincyBundleName]; + bundle = [[NSBundle bundleWithPath:path] retain]; + } + return bundle; +} + +NSString *BWQuincyLocalize(NSString *stringToken) { + if ([BWQuincyManager sharedQuincyManager].languageStyle == nil) + return NSLocalizedStringFromTableInBundle(stringToken, @"Quincy", quincyBundle(), @""); + else { + NSString *alternate = [NSString stringWithFormat:@"Quincy%@", [BWQuincyManager sharedQuincyManager].languageStyle]; + return NSLocalizedStringFromTableInBundle(stringToken, alternate, quincyBundle(), @""); + } +} + + +@interface BWQuincyManager () + +- (void)startManager; + +- (void)showCrashStatusMessage; + +- (void)handleCrashReport; +- (void)_cleanCrashReports; + +- (void)_checkForFeedbackStatus; + +- (void)_performSendingCrashReports; +- (void)_sendCrashReports; + +- (void)_postXML:(NSString*)xml toURL:(NSURL*)url; +- (NSString *)_getDevicePlatform; + +- (BOOL)hasNonApprovedCrashReports; +- (BOOL)hasPendingCrashReport; + +@end + +@implementation BWQuincyManager + +@synthesize delegate = _delegate; +@synthesize submissionURL = _submissionURL; +@synthesize showAlwaysButton = _showAlwaysButton; +@synthesize feedbackActivated = _feedbackActivated; +@synthesize autoSubmitCrashReport = _autoSubmitCrashReport; +@synthesize autoSubmitDeviceUDID = _autoSubmitDeviceUDID; +@synthesize languageStyle = _languageStyle; +@synthesize didCrashInLastSession = _didCrashInLastSession; +@synthesize loggingEnabled = _loggingEnabled; + +@synthesize appIdentifier = _appIdentifier; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 ++(BWQuincyManager *)sharedQuincyManager { + static BWQuincyManager *sharedInstance = nil; + static dispatch_once_t pred; + + dispatch_once(&pred, ^{ + sharedInstance = [BWQuincyManager alloc]; + sharedInstance = [sharedInstance init]; + }); + + return sharedInstance; +} +#else ++ (BWQuincyManager *)sharedQuincyManager { + static BWQuincyManager *quincyManager = nil; + + if (quincyManager == nil) { + quincyManager = [[BWQuincyManager alloc] init]; + } + + return quincyManager; +} +#endif + +- (id) init { + if ((self = [super init])) { + _serverResult = CrashReportStatusUnknown; + _crashIdenticalCurrentVersion = YES; + _crashData = nil; + _urlConnection = nil; + _submissionURL = nil; + _responseData = nil; + _appIdentifier = nil; + _sendingInProgress = NO; + _languageStyle = nil; + _didCrashInLastSession = NO; + _loggingEnabled = NO; + + self.delegate = nil; + self.feedbackActivated = NO; + self.showAlwaysButton = NO; + self.autoSubmitCrashReport = NO; + self.autoSubmitDeviceUDID = NO; + + NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitAnalyzerStarted]; + if (testValue) { + _analyzerStarted = [[NSUserDefaults standardUserDefaults] integerForKey:kQuincyKitAnalyzerStarted]; + } else { + _analyzerStarted = 0; + } + + testValue = nil; + testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitActivated]; + if (testValue) { + _crashReportActivated = [[NSUserDefaults standardUserDefaults] boolForKey:kQuincyKitActivated]; + } else { + _crashReportActivated = YES; + [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kQuincyKitActivated]; + } + + if (_crashReportActivated) { + _crashFiles = [[NSMutableArray alloc] init]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + _crashesDir = [[NSString stringWithFormat:@"%@", [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/crashes/"]] retain]; + + NSFileManager *fm = [NSFileManager defaultManager]; + + if (![fm fileExistsAtPath:_crashesDir]) { + NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions]; + NSError *theError = NULL; + + [fm createDirectoryAtPath:_crashesDir withIntermediateDirectories: YES attributes: attributes error: &theError]; + } + + PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; + NSError *error = NULL; + + // Check if we previously crashed + if ([crashReporter hasPendingCrashReport]) { + _didCrashInLastSession = YES; + [self handleCrashReport]; + } + + // Enable the Crash Reporter + if (![crashReporter enableCrashReporterAndReturnError: &error]) + NSLog(@"WARNING: Could not enable crash reporter: %@", error); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startManager) name:BWQuincyNetworkBecomeReachable object:nil]; + } + + if (!quincyBundle()) { + NSLog(@"WARNING: Quincy.bundle is missing, will send reports automatically!"); + } + } + return self; +} + + +- (void) dealloc { + self.delegate = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self name:BWQuincyNetworkBecomeReachable object:nil]; + + [_languageStyle release]; + + [_submissionURL release]; + _submissionURL = nil; + + [_appIdentifier release]; + _appIdentifier = nil; + + [_urlConnection cancel]; + [_urlConnection release]; + _urlConnection = nil; + + [_crashData release]; + + [_crashesDir release]; + [_crashFiles release]; + + [super dealloc]; +} + + +#pragma mark - +#pragma mark setter +- (void)setSubmissionURL:(NSString *)anSubmissionURL { + if (_submissionURL != anSubmissionURL) { + [_submissionURL release]; + _submissionURL = [anSubmissionURL copy]; + } + + [self performSelector:@selector(startManager) withObject:nil afterDelay:1.0f]; +} + +- (void)setAppIdentifier:(NSString *)anAppIdentifier { + if (_appIdentifier != anAppIdentifier) { + [_appIdentifier release]; + _appIdentifier = [anAppIdentifier copy]; + } + + [self setSubmissionURL:@"https://rink.hockeyapp.net/"]; +} + + +#pragma mark - +#pragma mark private methods + +- (BOOL)autoSendCrashReports { + BOOL result = NO; + + if (!self.autoSubmitCrashReport) { + if (self.isShowingAlwaysButton && [[NSUserDefaults standardUserDefaults] boolForKey: kAutomaticallySendCrashReports]) { + result = YES; + } + } else { + result = YES; + } + + return result; +} + +// begin the startup process +- (void)startManager { + if (!_sendingInProgress && [self hasPendingCrashReport]) { + _sendingInProgress = YES; + if (!quincyBundle()) { + NSLog(@"WARNING: Quincy.bundle is missing, sending reports automatically!"); + [self _sendCrashReports]; + } else if (![self autoSendCrashReports] && [self hasNonApprovedCrashReports]) { + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(willShowSubmitCrashReportAlert)]) { + [self.delegate willShowSubmitCrashReportAlert]; + } + + NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BWQuincyLocalize(@"CrashDataFoundTitle"), appName] + message:[NSString stringWithFormat:BWQuincyLocalize(@"CrashDataFoundDescription"), appName] + delegate:self + cancelButtonTitle:BWQuincyLocalize(@"CrashDontSendReport") + otherButtonTitles:BWQuincyLocalize(@"CrashSendReport"), nil]; + + if ([self isShowingAlwaysButton]) { + [alertView addButtonWithTitle:BWQuincyLocalize(@"CrashSendReportAlways")]; + } + + [alertView setTag: QuincyKitAlertTypeSend]; + [alertView show]; + [alertView release]; + } else { + [self _sendCrashReports]; + } + } +} + +- (BOOL)hasNonApprovedCrashReports { + NSDictionary *approvedCrashReports = [[NSUserDefaults standardUserDefaults] dictionaryForKey: kApprovedCrashReports]; + + if (!approvedCrashReports || [approvedCrashReports count] == 0) return YES; + + for (NSUInteger i=0; i < [_crashFiles count]; i++) { + NSString *filename = [_crashFiles objectAtIndex:i]; + + if (![approvedCrashReports objectForKey:filename]) return YES; + } + + return NO; +} + +- (BOOL)hasPendingCrashReport { + if (_crashReportActivated) { + NSFileManager *fm = [NSFileManager defaultManager]; + + if ([_crashFiles count] == 0 && [fm fileExistsAtPath:_crashesDir]) { + NSString *file = nil; + NSError *error = NULL; + + NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath: _crashesDir]; + + while ((file = [dirEnum nextObject])) { + NSDictionary *fileAttributes = [fm attributesOfItemAtPath:[_crashesDir stringByAppendingPathComponent:file] error:&error]; + if ([[fileAttributes objectForKey:NSFileSize] intValue] > 0) { + [_crashFiles addObject:file]; + } + } + } + + if ([_crashFiles count] > 0) { + BWQuincyLog(@"Pending crash reports found."); + return YES; + } else + return NO; + } else + return NO; +} + + +- (void) showCrashStatusMessage { + UIAlertView *alertView = nil; + + if (_serverResult >= CrashReportStatusAssigned && + _crashIdenticalCurrentVersion && + quincyBundle()) { + // show some feedback to the user about the crash status + NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + switch (_serverResult) { + case CrashReportStatusAssigned: + alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ] + message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseNextRelease"), appName] + delegate: self + cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK") + otherButtonTitles: nil]; + break; + case CrashReportStatusSubmitted: + alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ] + message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseWaitingApple"), appName] + delegate: self + cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK") + otherButtonTitles: nil]; + break; + case CrashReportStatusAvailable: + alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ] + message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseAvailable"), appName] + delegate: self + cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK") + otherButtonTitles: nil]; + break; + default: + alertView = nil; + break; + } + + if (alertView) { + [alertView setTag: QuincyKitAlertTypeFeedback]; + [alertView show]; + [alertView release]; + } + } +} + + +#pragma mark - +#pragma mark UIAlertView Delegate + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + if ([alertView tag] == QuincyKitAlertTypeSend) { + switch (buttonIndex) { + case 0: + _sendingInProgress = NO; + [self _cleanCrashReports]; + break; + case 1: + [self _sendCrashReports]; + break; + case 2: { + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAutomaticallySendCrashReports]; + [[NSUserDefaults standardUserDefaults] synchronize]; + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(userDidChooseSendAlways)]) { + [self.delegate userDidChooseSendAlways]; + } + + [self _sendCrashReports]; + break; + } + default: + _sendingInProgress = NO; + [self _cleanCrashReports]; + break; + } + } +} + +#pragma mark - +#pragma mark NSXMLParser Delegate + +#pragma mark NSXMLParser + +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { + if (qName) { + elementName = qName; + } + + if ([elementName isEqualToString:@"result"]) { + _contentOfProperty = [NSMutableString string]; + } +} + +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { + if (qName) { + elementName = qName; + } + + // open source implementation + if ([elementName isEqualToString: @"result"]) { + if ([_contentOfProperty intValue] > _serverResult) { + _serverResult = (CrashReportStatus)[_contentOfProperty intValue]; + } else { + CrashReportStatus errorcode = (CrashReportStatus)[_contentOfProperty intValue]; + NSLog(@"CrashReporter ended in error code: %i", errorcode); + } + } +} + + +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { + if (_contentOfProperty) { + // If the current element is one whose content we care about, append 'string' + // to the property that holds the content of the current element. + if (string != nil) { + [_contentOfProperty appendString:string]; + } + } +} + +#pragma mark - +#pragma mark Private + + +- (NSString *)_getDevicePlatform { + size_t size = 0; + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char *answer = (char*)malloc(size); + sysctlbyname("hw.machine", answer, &size, NULL, 0); + NSString *platform = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding]; + free(answer); + return platform; +} + +- (NSString *)deviceIdentifier { + if ([[UIDevice currentDevice] respondsToSelector:@selector(uniqueIdentifier)]) { + return [[UIDevice currentDevice] performSelector:@selector(uniqueIdentifier)]; + } + else { + return @"invalid"; + } +} + +- (void)_performSendingCrashReports { + NSMutableDictionary *approvedCrashReports = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey: kApprovedCrashReports]]; + + NSFileManager *fm = [NSFileManager defaultManager]; + NSError *error = NULL; + + NSString *userid = @""; + NSString *contact = @""; + NSString *description = @""; + + if (self.autoSubmitDeviceUDID && [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]) { + userid = [self deviceIdentifier]; + } else if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportUserID)]) { + userid = [self.delegate crashReportUserID] ?: @""; + } + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportContact)]) { + contact = [self.delegate crashReportContact] ?: @""; + } + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportDescription)]) { + description = [self.delegate crashReportDescription] ?: @""; + } + + NSMutableString *crashes = nil; + _crashIdenticalCurrentVersion = NO; + + for (NSUInteger i=0; i < [_crashFiles count]; i++) { + NSString *filename = [_crashesDir stringByAppendingPathComponent:[_crashFiles objectAtIndex:i]]; + NSData *crashData = [NSData dataWithContentsOfFile:filename]; + + if ([crashData length] > 0) { + PLCrashReport *report = [[[PLCrashReport alloc] initWithData:crashData error:&error] autorelease]; + + if (report == nil) { + NSLog(@"Could not parse crash report"); + continue; + } + + NSString *crashLogString = [PLCrashReportTextFormatter stringValueForCrashReport:report withTextFormat:PLCrashReportTextFormatiOS]; + + if ([report.applicationInfo.applicationVersion compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) { + _crashIdenticalCurrentVersion = YES; + } + + if (crashes == nil) { + crashes = [NSMutableString string]; + } + + [crashes appendFormat:@"%s%@%@%@%@%@%@%@", + [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"] UTF8String], + report.applicationInfo.applicationIdentifier, + report.systemInfo.operatingSystemVersion, + [self _getDevicePlatform], + [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"], + report.applicationInfo.applicationVersion, + [crashLogString stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]>" options:NSLiteralSearch range:NSMakeRange(0,crashLogString.length)], + userid, + contact, + [description stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]>" options:NSLiteralSearch range:NSMakeRange(0,description.length)]]; + + + // store this crash report as user approved, so if it fails it will retry automatically + [approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:[_crashFiles objectAtIndex:i]]; + } else { + // we cannot do anything with this report, so delete it + [fm removeItemAtPath:filename error:&error]; + } + } + + [[NSUserDefaults standardUserDefaults] setObject:approvedCrashReports forKey:kApprovedCrashReports]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + if (crashes != nil) { + BWQuincyLog(@"Sending crash reports:\n%@", crashes); + [self _postXML:[NSString stringWithFormat:@"%@", crashes] + toURL:[NSURL URLWithString:self.submissionURL]]; + + } +} + +- (void)_cleanCrashReports { + NSError *error = NULL; + + NSFileManager *fm = [NSFileManager defaultManager]; + + for (NSUInteger i=0; i < [_crashFiles count]; i++) { + [fm removeItemAtPath:[_crashesDir stringByAppendingPathComponent:[_crashFiles objectAtIndex:i]] error:&error]; + } + [_crashFiles removeAllObjects]; + + [[NSUserDefaults standardUserDefaults] setObject:nil forKey:kApprovedCrashReports]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (void)_sendCrashReports { + // send it to the next runloop + [self performSelector:@selector(_performSendingCrashReports) withObject:nil afterDelay:0.0f]; +} + +- (void)_checkForFeedbackStatus { + NSMutableURLRequest *request = nil; + + request = [NSMutableURLRequest requestWithURL: + [NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes/%@", + self.submissionURL, + [self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + _feedbackRequestID + ] + ]]; + + [request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData]; + [request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setTimeoutInterval: 15]; + [request setHTTPMethod:@"GET"]; + + _serverResult = CrashReportStatusUnknown; + _statusCode = 200; + + // Release when done in the delegate method + _responseData = [[NSMutableData alloc] init]; + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) { + [self.delegate connectionOpened]; + } + + _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; + + BWQuincyLog(@"Requesting feedback status."); +} + +- (void)_postXML:(NSString*)xml toURL:(NSURL*)url { + NSMutableURLRequest *request = nil; + NSString *boundary = @"----FOO"; + + if (self.appIdentifier) { + request = [NSMutableURLRequest requestWithURL: + [NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes", + self.submissionURL, + [self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + ] + ]]; + } else { + request = [NSMutableURLRequest requestWithURL:url]; + } + + [request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData]; + [request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setTimeoutInterval: 15]; + [request setHTTPMethod:@"POST"]; + NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; + [request setValue:contentType forHTTPHeaderField:@"Content-type"]; + + NSMutableData *postBody = [NSMutableData data]; + [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; + if (self.appIdentifier) { + [postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; + [postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; + } else { + [postBody appendData:[@"Content-Disposition: form-data; name=\"xmlstring\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; + } + [postBody appendData:[xml dataUsingEncoding:NSUTF8StringEncoding]]; + [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; + + [request setHTTPBody:postBody]; + + _serverResult = CrashReportStatusUnknown; + _statusCode = 200; + + //Release when done in the delegate method + _responseData = [[NSMutableData alloc] init]; + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) { + [self.delegate connectionOpened]; + } + + _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; + + if (!_urlConnection) { + BWQuincyLog(@"Sending crash reports could not start!"); + _sendingInProgress = NO; + } else { + BWQuincyLog(@"Sending crash reports started."); + } +} + +#pragma mark NSURLConnection Delegate + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + _statusCode = [(NSHTTPURLResponse *)response statusCode]; + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + [_responseData appendData:data]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + [_responseData release]; + _responseData = nil; + _urlConnection = nil; + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) { + [self.delegate connectionClosed]; + } + + BWQuincyLog(@"ERROR: %@", [error localizedDescription]); + + _sendingInProgress = NO; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + if (_statusCode >= 200 && _statusCode < 400 && _responseData != nil && [_responseData length] > 0) { + [self _cleanCrashReports]; + + _feedbackRequestID = nil; + if (self.appIdentifier) { + // HockeyApp uses PList XML format + NSMutableDictionary *response = [NSPropertyListSerialization propertyListFromData:_responseData + mutabilityOption:NSPropertyListMutableContainersAndLeaves + format:nil + errorDescription:NULL]; + BWQuincyLog(@"Received API response: %@", response); + + _serverResult = (CrashReportStatus)[[response objectForKey:@"status"] intValue]; + if ([response objectForKey:@"id"]) { + _feedbackRequestID = [[NSString alloc] initWithString:[response objectForKey:@"id"]]; + _feedbackDelayInterval = [[response objectForKey:@"delay"] floatValue]; + if (_feedbackDelayInterval > 0) + _feedbackDelayInterval *= 0.01; + } + } else { + BWQuincyLog(@"Received API response: %@", [[[NSString alloc] initWithBytes:[_responseData bytes] length:[_responseData length] encoding: NSUTF8StringEncoding] autorelease]); + + NSXMLParser *parser = [[NSXMLParser alloc] initWithData:_responseData]; + // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks. + [parser setDelegate:self]; + // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser. + [parser setShouldProcessNamespaces:NO]; + [parser setShouldReportNamespacePrefixes:NO]; + [parser setShouldResolveExternalEntities:NO]; + + [parser parse]; + + [parser release]; + } + + if ([self isFeedbackActivated]) { + // only proceed if the server did not report any problem + if ((self.appIdentifier) && (_serverResult == CrashReportStatusQueued)) { + // the report is still in the queue + if (_feedbackRequestID) { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_checkForFeedbackStatus) object:nil]; + [self performSelector:@selector(_checkForFeedbackStatus) withObject:nil afterDelay:_feedbackDelayInterval]; + } + } else { + [self showCrashStatusMessage]; + } + } + } else if (_statusCode == 400 && self.appIdentifier) { + [self _cleanCrashReports]; + BWQuincyLog(@"ERROR: The server rejected receiving crash reports for this app version!"); + } else { + if (_responseData == nil || [_responseData length] == 0) { + BWQuincyLog(@"ERROR: Sending failed with an empty response!"); + } else { + BWQuincyLog(@"ERROR: Sending failed with status code: %i", _statusCode); + } + } + + [_responseData release]; + _responseData = nil; + _urlConnection = nil; + + if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) { + [self.delegate connectionClosed]; + } + + _sendingInProgress = NO; +} + +#pragma mark PLCrashReporter + +// +// Called to handle a pending crash report. +// +- (void) handleCrashReport { + PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; + NSError *error = NULL; + + // check if the next call ran successfully the last time + if (_analyzerStarted == 0) { + // mark the start of the routine + _analyzerStarted = 1; + [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + // Try loading the crash report + _crashData = [[NSData alloc] initWithData:[crashReporter loadPendingCrashReportDataAndReturnError: &error]]; + + NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]]; + + if (_crashData == nil) { + NSLog(@"Could not load crash report: %@", error); + } else { + [_crashData writeToFile:[_crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES]; + } + } + + // Purge the report + // mark the end of the routine + _analyzerStarted = 0; + [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + [crashReporter purgePendingCrashReport]; + return; +} + + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/CrashReporter b/External Source/QuincyKit/client/iOS/CrashReporter.framework/CrashReporter new file mode 120000 index 000000000..92b400e68 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/CrashReporter @@ -0,0 +1 @@ +Versions/Current/CrashReporter \ No newline at end of file diff --git a/Frameworks/MapKit.framework/Headers b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Headers similarity index 100% rename from Frameworks/MapKit.framework/Headers rename to External Source/QuincyKit/client/iOS/CrashReporter.framework/Headers diff --git a/Frameworks/MapKit.framework/Resources b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Resources similarity index 100% rename from Frameworks/MapKit.framework/Resources rename to External Source/QuincyKit/client/iOS/CrashReporter.framework/Resources diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/CrashReporter b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/CrashReporter new file mode 100644 index 000000000..31b0171b3 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/CrashReporter differ diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/CrashReporter.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/CrashReporter.h new file mode 100644 index 000000000..7239d6d9e --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/CrashReporter.h @@ -0,0 +1,229 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +#ifdef __APPLE__ +#import +#endif + +#import "PLCrashReporter.h" +#import "PLCrashReport.h" +#import "PLCrashReportTextFormatter.h" + +/** + * @defgroup functions Crash Reporter Functions Reference + */ + +/** + * @defgroup types Crash Reporter Data Types Reference + */ + +/** + * @defgroup constants Crash Reporter Constants Reference + */ + +/** + * @internal + * @defgroup plcrash_internal Crash Reporter Internal Documentation + */ + +/** + * @defgroup enums Enumerations + * @ingroup constants + */ + +/** + * @defgroup globals Global Variables + * @ingroup constants + */ + +/** + * @defgroup exceptions Exceptions + * @ingroup constants + */ + +/* Exceptions */ +extern NSString *PLCrashReporterException; + +/* Error Domain and Codes */ +extern NSString *PLCrashReporterErrorDomain; + +/** + * NSError codes in the Plausible Crash Reporter error domain. + * @ingroup enums + */ +typedef enum { + /** An unknown error has occured. If this + * code is received, it is a bug, and should be reported. */ + PLCrashReporterErrorUnknown = 0, + + /** An Mach or POSIX operating system error has occured. The underlying NSError cause may be fetched from the userInfo + * dictionary using the NSUnderlyingErrorKey key. */ + PLCrashReporterErrorOperatingSystem = 1, + + /** The crash report log file is corrupt or invalid */ + PLCrashReporterErrorCrashReportInvalid = 2, +} PLCrashReporterError; + + +/* Library Imports */ +#import "PLCrashReporter.h" +#import "PLCrashReport.h" +#import "PLCrashReportTextFormatter.h" + +/** + * @mainpage Plausible Crash Reporter + * + * @section intro_sec Introduction + * + * Plausile CrashReporter implements in-process crash reporting on the iPhone and Mac OS X. + * + * The following features are supported: + * + * - Implemented as an in-process signal handler. + * - Does not interfer with debugging in gdb.. + * - Handles both uncaught Objective-C exceptions and fatal signals (SIGSEGV, SIGBUS, etc). + * - Full thread state for all active threads (backtraces, register dumps) is provided. + * + * If your application crashes, a crash report will be written. When the application is next run, you may check for a + * pending crash report, and submit the report to your own HTTP server, send an e-mail, or even introspect the + * report locally. + * + * @section intro_encoding Crash Report Format + * + * Crash logs are encoded using google protobuf, and may be decoded + * using the provided PLCrashReport API. Additionally, the include plcrashutil handles conversion of binary crash reports to the + * symbolicate-compatible iPhone text format. + * + * @section doc_sections Documentation Sections + * - @subpage example_usage_iphone + * - @subpage error_handling + * - @subpage async_safety + */ + +/** + * @page example_usage_iphone Example iPhone Usage + * + * @code + * // + * // Called to handle a pending crash report. + * // + * - (void) handleCrashReport { + * PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; + * NSData *crashData; + * NSError *error; + * + * // Try loading the crash report + * crashData = [crashReporter loadPendingCrashReportDataAndReturnError: &error]; + * if (crashData == nil) { + * NSLog(@"Could not load crash report: %@", error); + * goto finish; + * } + * + * // We could send the report from here, but we'll just print out + * // some debugging info instead + * PLCrashReport *report = [[[PLCrashReport alloc] initWithData: crashData error: &error] autorelease]; + * if (report == nil) { + * NSLog(@"Could not parse crash report"); + * goto finish; + * } + * + * NSLog(@"Crashed on %@", report.systemInfo.timestamp); + * NSLog(@"Crashed with signal %@ (code %@, address=0x%" PRIx64 ")", report.signalInfo.name, + * report.signalInfo.code, report.signalInfo.address); + * + * // Purge the report + * finish: + * [crashReporter purgePendingCrashReport]; + * return; + * } + * + * // from UIApplicationDelegate protocol + * - (void) applicationDidFinishLaunching: (UIApplication *) application { + * PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; + * NSError *error; + * + * // Check if we previously crashed + * if ([crashReporter hasPendingCrashReport]) + * [self handleCrashReport]; + + * // Enable the Crash Reporter + * if (![crashReporter enableCrashReporterAndReturnError: &error]) + * NSLog(@"Warning: Could not enable crash reporter: %@", error); + * + * } + * @endcode + * + */ + +/** + * @page error_handling Error Handling Programming Guide + * + * Where a method may return an error, Plausible Crash Reporter provides access to the underlying + * cause via an optional NSError argument. + * + * All returned errors will be a member of one of the below defined domains, however, new domains and + * error codes may be added at any time. If you do not wish to report on the error cause, many methods + * support a simple form that requires no NSError argument. + * + * @section error_domains Error Domains, Codes, and User Info + * + * @subsection crashreporter_errors Crash Reporter Errors + * + * Any errors in Plausible Crash Reporter use the #PLCrashReporterErrorDomain error domain, and and one + * of the error codes defined in #PLCrashReporterError. + */ + +/** + * @page async_safety Async-Safe Programming Guide + * + * Plausible CrashReporter provides support for executing an application specified function in the context of the + * crash reporter's signal handler, after the crash report has been written to disk. This was a regularly requested + * feature, and provides the ability to implement application finalization in the event of a crash. However, writing + * code intended for execution inside of a signal handler is exceptionally difficult, and is not recommended. + * + * @section program_flow Program Flow and Signal Handlers + * + * When the signal handler is called the normal flow of the program is interrupted, and your program is an unknown + * state. Locks may be held, the heap may be corrupt (or in the process of being updated), and your signal + * handler may invoke a function that was being executed at the time of the signal. This may result in deadlocks, + * data corruption, and program termination. + * + * @section functions Async-Safe Functions + * + * A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If + * you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions + * and additional information is available from the + * CERT programming guide - SIG30-C + * + * Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal + * handler. + * + * @sa PLCrashReporter::setCrashCallbacks: + */ \ No newline at end of file diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReport.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReport.h new file mode 100644 index 000000000..f229fd03f --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReport.h @@ -0,0 +1,169 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2010 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import +#import "PLCrashReportSystemInfo.h" +#import "PLCrashReportMachineInfo.h" +#import "PLCrashReportApplicationInfo.h" +#import "PLCrashReportProcessInfo.h" +#import "PLCrashReportSignalInfo.h" +#import "PLCrashReportThreadInfo.h" +#import "PLCrashReportBinaryImageInfo.h" +#import "PLCrashReportExceptionInfo.h" + +/** + * @ingroup constants + * Crash file magic identifier */ +#define PLCRASH_REPORT_FILE_MAGIC "plcrash" + +/** + * @ingroup constants + * Crash format version byte identifier. Will not change outside of the introduction of + * an entirely new crash log format. */ +#define PLCRASH_REPORT_FILE_VERSION 1 + +/** + * @ingroup types + * Crash log file header format. + * + * Crash log files start with 7 byte magic identifier (#PLCRASH_REPORT_FILE_MAGIC), + * followed by a single unsigned byte version number (#PLCRASH_REPORT_FILE_VERSION). + * The crash log message format itself is extensible, so this version number will only + * be incremented in the event of an incompatible encoding or format change. + */ +struct PLCrashReportFileHeader { + /** Crash log magic identifier, not NULL terminated */ + const char magic[7]; + + /** Crash log encoding/format version */ + const uint8_t version; + + /** File data */ + const uint8_t data[]; +} __attribute__((packed)); + + +/** + * @internal + * Private decoder instance variables (used to hide the underlying protobuf parser). + */ +typedef struct _PLCrashReportDecoder _PLCrashReportDecoder; + +@interface PLCrashReport : NSObject { +@private + /** Private implementation variables (used to hide the underlying protobuf parser) */ + _PLCrashReportDecoder *_decoder; + + /** System info */ + PLCrashReportSystemInfo *_systemInfo; + + /** Machine info */ + PLCrashReportMachineInfo *_machineInfo; + + /** Application info */ + PLCrashReportApplicationInfo *_applicationInfo; + + /** Process info */ + PLCrashReportProcessInfo *_processInfo; + + /** Signal info */ + PLCrashReportSignalInfo *_signalInfo; + + /** Thread info (PLCrashReportThreadInfo instances) */ + NSArray *_threads; + + /** Binary images (PLCrashReportBinaryImageInfo instances */ + NSArray *_images; + + /** Exception information (may be nil) */ + PLCrashReportExceptionInfo *_exceptionInfo; +} + +- (id) initWithData: (NSData *) encodedData error: (NSError **) outError; + +- (PLCrashReportBinaryImageInfo *) imageForAddress: (uint64_t) address; + +/** + * System information. + */ +@property(nonatomic, readonly) PLCrashReportSystemInfo *systemInfo; + +/** + * YES if machine information is available. + */ +@property(nonatomic, readonly) BOOL hasMachineInfo; + +/** + * Machine information. Only available in later (v1.1+) crash report format versions. If not available, + * will be nil. + */ +@property(nonatomic, readonly) PLCrashReportMachineInfo *machineInfo; + +/** + * Application information. + */ +@property(nonatomic, readonly) PLCrashReportApplicationInfo *applicationInfo; + +/** + * YES if process information is available. + */ +@property(nonatomic, readonly) BOOL hasProcessInfo; + +/** + * Process information. Only available in later (v1.1+) crash report format versions. If not available, + * will be nil. + */ +@property(nonatomic, readonly) PLCrashReportProcessInfo *processInfo; + +/** + * Signal information. This provides the signal and signal code of the fatal signal. + */ +@property(nonatomic, readonly) PLCrashReportSignalInfo *signalInfo; + +/** + * Thread information. Returns a list of PLCrashReportThreadInfo instances. + */ +@property(nonatomic, readonly) NSArray *threads; + +/** + * Binary image information. Returns a list of PLCrashReportBinaryImageInfo instances. + */ +@property(nonatomic, readonly) NSArray *images; + +/** + * YES if exception information is available. + */ +@property(nonatomic, readonly) BOOL hasExceptionInfo; + +/** + * Exception information. Only available if a crash was caused by an uncaught exception, + * otherwise nil. + */ +@property(nonatomic, readonly) PLCrashReportExceptionInfo *exceptionInfo; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportApplicationInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportApplicationInfo.h new file mode 100644 index 000000000..2c2ab9708 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportApplicationInfo.h @@ -0,0 +1,53 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +@interface PLCrashReportApplicationInfo : NSObject { +@private + /** Application identifier */ + NSString *_applicationIdentifier; + + /** Application version */ + NSString *_applicationVersion; +} + +- (id) initWithApplicationIdentifier: (NSString *) applicationIdentifier + applicationVersion: (NSString *) applicationVersion; + +/** + * The application identifier. This is usually the application's CFBundleIdentifier value. + */ +@property(nonatomic, readonly) NSString *applicationIdentifier; + +/** + * The application version. This is usually the application's CFBundleVersion value. + */ +@property(nonatomic, readonly) NSString *applicationVersion; + +@end \ No newline at end of file diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportBinaryImageInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportBinaryImageInfo.h new file mode 100644 index 000000000..339fdbb08 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportBinaryImageInfo.h @@ -0,0 +1,90 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import +#import "PLCrashReportProcessorInfo.h" + +@interface PLCrashReportBinaryImageInfo : NSObject { +@private + /** Code type */ + PLCrashReportProcessorInfo *_processorInfo; + + /** Base image address */ + uint64_t _baseAddress; + + /** Image segment size */ + uint64_t _imageSize; + + /** Name of binary image */ + NSString *_imageName; + + /** If the UUID is available */ + BOOL _hasImageUUID; + + /** 128-bit object UUID. May be nil. */ + NSString *_imageUUID; +} + +- (id) initWithCodeType: (PLCrashReportProcessorInfo *) processorInfo + baseAddress: (uint64_t) baseAddress + size: (uint64_t) imageSize + name: (NSString *) imageName + uuid: (NSData *) uuid; + +/** + * Image code type, or nil if unavailable. + */ +@property(nonatomic, readonly) PLCrashReportProcessorInfo *codeType; + +/** + * Image base address. + */ +@property(nonatomic, readonly) uint64_t imageBaseAddress; + +/** + * Segment size. + */ +@property(nonatomic, readonly) uint64_t imageSize; + +/** + * Image name (absolute path) + */ +@property(nonatomic, readonly) NSString *imageName; + + +/** + * YES if this image has an associated UUID. + */ +@property(nonatomic, readonly) BOOL hasImageUUID; + +/** + * 128-bit object UUID (matches Mach-O DWARF dSYM files). May be nil if unavailable. + */ +@property(nonatomic, readonly) NSString *imageUUID; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportExceptionInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportExceptionInfo.h new file mode 100644 index 000000000..623b1d4e1 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportExceptionInfo.h @@ -0,0 +1,65 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import +#import "PLCrashReportThreadInfo.h" + + +@interface PLCrashReportExceptionInfo : NSObject { +@private + /** Name */ + NSString *_name; + + /** Reason */ + NSString *_reason; + + /** Ordered list of PLCrashReportStackFrame instances, or nil if unavailable. */ + NSArray *_stackFrames; +} + +- (id) initWithExceptionName: (NSString *) name reason: (NSString *) reason; + +- (id) initWithExceptionName: (NSString *) name + reason: (NSString *) reason + stackFrames: (NSArray *) stackFrames; + +/** + * The exception name. + */ +@property(nonatomic, readonly) NSString *exceptionName; + +/** + * The exception reason. + */ +@property(nonatomic, readonly) NSString *exceptionReason; + +/* The exception's original call stack, as an array of PLCrashReportStackFrameInfo instances, or nil if unavailable. + * This may be preserved across rethrow of an exception, and can be used to determine the original call stack. */ +@property(nonatomic, readonly) NSArray *stackFrames; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportFormatter.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportFormatter.h new file mode 100644 index 000000000..a32a243f6 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportFormatter.h @@ -0,0 +1,51 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2010 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +#import "PLCrashReport.h" + +/** + * A crash report formatter accepts a PLCrashReport instance, formats it according to implementation-specified rules, + * (such as implementing text output support), and returns the result. + */ +@protocol PLCrashReportFormatter + +/** + * Format the provided @a report. + * + * @param report Report to be formatted. + * @param outError A pointer to an NSError object variable. If an error occurs, this pointer will contain an error + * object indicating why the pending crash report could not be formatted. If no error occurs, this parameter will + * be left unmodified. You may specify nil for this parameter, and no error information will be provided. + * + * @return Returns the formatted report data on success, or nil on failure. + */ +- (NSData *) formatReport: (PLCrashReport *) report error: (NSError **) outError; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportMachineInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportMachineInfo.h new file mode 100644 index 000000000..58c4baa5f --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportMachineInfo.h @@ -0,0 +1,73 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +#import "PLCrashReportProcessorInfo.h" + +@interface PLCrashReportMachineInfo : NSObject { +@private + /** The hardware model name (eg, MacBookPro6,1). This may be unavailable, and this property will be nil. */ + NSString *_modelName; + + /** The processor type. */ + PLCrashReportProcessorInfo *_processorInfo; + + /* The number of actual physical processor cores. */ + NSUInteger _processorCount; + + /* The number of logical processors. */ + NSUInteger _logicalProcessorCount; +} + +- (id) initWithModelName: (NSString *) modelName + processorInfo: (PLCrashReportProcessorInfo *) processorInfo + processorCount: (NSUInteger) processorCount + logicalProcessorCount: (NSUInteger) logicalProcessorCount; + +/** The hardware model name (eg, MacBookPro6,1). This may be unavailable, and this property will be nil. */ +@property(nonatomic, readonly) NSString *modelName; + +/** The processor type. */ +@property(nonatomic, readonly) PLCrashReportProcessorInfo *processorInfo; + +/* + * The number of actual physical processor cores. Note that the number of active processors may be managed by the + * operating system's power management system, and this value may not reflect the number of active + * processors at the time of the crash. + */ +@property(nonatomic, readonly) NSUInteger processorCount; + +/* + * The number of logical processors. Note that the number of active processors may be managed by the + * operating system's power management system, and this value may not reflect the number of active + * processors at the time of the crash. + */ +@property(nonatomic, readonly) NSUInteger logicalProcessorCount; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessInfo.h new file mode 100644 index 000000000..ffc81ed9c --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessInfo.h @@ -0,0 +1,92 @@ +/* + * Author: Damian Morris + * + * Copyright (c) 2010 MOSO Corporation, Pty Ltd. + * Copyright (c) 2010 Plausible Labs Cooperative, Inc. + * + * 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. + */ + +#import + +@interface PLCrashReportProcessInfo : NSObject { +@private + /** Process name */ + NSString *_processName; + + /** Process ID */ + NSUInteger _processID; + + /** Process path */ + NSString* _processPath; + + /** Parent process name */ + NSString *_parentProcessName; + + /** Parent process ID */ + NSUInteger _parentProcessID; + + /** If false, the process is being run via process-level CPU emulation (such as Rosetta). */ + BOOL _native; +} + +- (id) initWithProcessName: (NSString *) processName + processID: (NSUInteger) processID + processPath: (NSString *) processPath + parentProcessName: (NSString *) parentProcessName + parentProcessID: (NSUInteger) parentProcessID + native: (BOOL) native; + +/** + * The process name. This value may not be included in the crash report, in which case this property + * will be nil. + */ +@property(nonatomic, readonly) NSString *processName; + +/** + * The process ID. + */ +@property(nonatomic, readonly) NSUInteger processID; + +/** + * The path to the process executable. This value may not be included in the crash report, in which case this property + * will be nil. + */ +@property(nonatomic, readonly) NSString *processPath; + +/** + * The parent process name. This value may not be included in the crash report, in which case this property + * will be nil. + */ +@property(nonatomic, readonly) NSString *parentProcessName; + +/** + * The parent process ID. + */ +@property(nonatomic, readonly) NSUInteger parentProcessID; + +/** The process' native execution status. If false, the process is being run via process-level CPU emulation (such as Rosetta). */ +@property(nonatomic, readonly) BOOL native; + +@end \ No newline at end of file diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessorInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessorInfo.h new file mode 100644 index 000000000..af027bea5 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessorInfo.h @@ -0,0 +1,74 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import +#import + +/** + * @ingroup constants + * + * The type encodings supported for CPU types and subtypes. Currently only Apple + * Mach-O defined encodings are supported. + * + * @internal + * These enum values match the protobuf values. Keep them synchronized. + */ +typedef enum { + /** Unknown cpu type encoding. */ + PLCrashReportProcessorTypeEncodingUnknown = 0, + + /** Apple Mach-defined processor types. */ + PLCrashReportProcessorTypeEncodingMach = 1 +} PLCrashReportProcessorTypeEncoding; + +@interface PLCrashReportProcessorInfo : NSObject { +@private + /** Type encoding */ + PLCrashReportProcessorTypeEncoding _typeEncoding; + + /** CPU type */ + uint64_t _type; + + /** CPU subtype */ + uint64_t _subtype; +} + +- (id) initWithTypeEncoding: (PLCrashReportProcessorTypeEncoding) typeEncoding + type: (uint64_t) type + subtype: (uint64_t) subtype; + +/** The CPU type encoding. */ +@property(nonatomic, readonly) PLCrashReportProcessorTypeEncoding typeEncoding; + +/** The CPU type. */ +@property(nonatomic, readonly) uint64_t type; + +/** The CPU subtype. */ +@property(nonatomic, readonly) uint64_t subtype; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportSignalInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportSignalInfo.h new file mode 100644 index 000000000..2c5c5fe23 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportSignalInfo.h @@ -0,0 +1,60 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +@interface PLCrashReportSignalInfo : NSObject { +@private + /** Signal name */ + NSString *_name; + + /** Signal code */ + NSString *_code; + + /** Fauling instruction or address */ + uint64_t _address; +} + +- (id) initWithSignalName: (NSString *) name code: (NSString *) code address: (uint64_t) address; + +/** + * The signal name. + */ +@property(nonatomic, readonly) NSString *name; + +/** + * The signal code. + */ +@property(nonatomic, readonly) NSString *code; + +/** + * The faulting instruction or address. + */ +@property(nonatomic, readonly) uint64_t address; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportSystemInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportSystemInfo.h new file mode 100644 index 000000000..70167dfcf --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportSystemInfo.h @@ -0,0 +1,142 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +/** + * @ingroup constants + * + * Indicates the Operating System under which a Crash Log was generated. + * + * @internal + * These enum values match the protobuf values. Keep them synchronized. + */ +typedef enum { + /** Mac OS X. */ + PLCrashReportOperatingSystemMacOSX = 0, + + /** iPhone OS */ + PLCrashReportOperatingSystemiPhoneOS = 1, + + /** iPhone Simulator (Mac OS X with additional simulator-specific runtime libraries) */ + PLCrashReportOperatingSystemiPhoneSimulator = 2, + + /** Unknown operating system */ + PLCrashReportOperatingSystemUnknown = 3, +} PLCrashReportOperatingSystem; + +/** + * @ingroup constants + * + * Indicates the architecture under which a Crash Log was generated. + * + * @deprecated The architecture value has been deprecated in v1.1 and later crash reports. All new reports + * will make use of the new PLCrashReportProcessorInfo CPU type encodings. + * + * @internal + * These enum values match the protobuf values. Keep them synchronized. + */ +typedef enum { + /** x86-32. */ + PLCrashReportArchitectureX86_32 = 0, + + /** x86-64 */ + PLCrashReportArchitectureX86_64 = 1, + + /** ARMv6 */ + PLCrashReportArchitectureARMv6 = 2, + + /** + * ARMv6 + * @deprecated + * @sa PLCrashReportArchitectureARMv6 + */ + PLCrashReportArchitectureARM = PLCrashReportArchitectureARMv6, + + /** PPC */ + PLCrashReportArchitecturePPC = 3, + + /** PPC64 */ + PLCrashReportArchitecturePPC64 = 4, + + /** ARMv7 */ + PLCrashReportArchitectureARMv7 = 5, + + /** Unknown */ + PLCrashReportArchitectureUnknown = 6 +} PLCrashReportArchitecture; + + +extern PLCrashReportOperatingSystem PLCrashReportHostOperatingSystem; +extern PLCrashReportArchitecture PLCrashReportHostArchitecture; + +@interface PLCrashReportSystemInfo : NSObject { +@private + /** Operating system */ + PLCrashReportOperatingSystem _operatingSystem; + + /** Operating system version */ + NSString *_osVersion; + + /** OS build. May be nil. */ + NSString *_osBuild; + + /** Architecture */ + PLCrashReportArchitecture _architecture; + + /** Date crash report was generated. May be nil if the date is unknown. */ + NSDate *_timestamp; +} + +- (id) initWithOperatingSystem: (PLCrashReportOperatingSystem) operatingSystem + operatingSystemVersion: (NSString *) operatingSystemVersion + architecture: (PLCrashReportArchitecture) architecture + timestamp: (NSDate *) timestamp; + +- (id) initWithOperatingSystem: (PLCrashReportOperatingSystem) operatingSystem + operatingSystemVersion: (NSString *) operatingSystemVersion + operatingSystemBuild: (NSString *) operatingSystemBuild + architecture: (PLCrashReportArchitecture) architecture + timestamp: (NSDate *) timestamp; + +/** The operating system. */ +@property(nonatomic, readonly) PLCrashReportOperatingSystem operatingSystem; + +/** The operating system's release version. */ +@property(nonatomic, readonly) NSString *operatingSystemVersion; + +/** The operating system's build identifier (eg, 10J869). This may be unavailable, and this property will be nil. */ +@property(nonatomic, readonly) NSString *operatingSystemBuild; + +/** Architecture. */ +@property(nonatomic, readonly) PLCrashReportArchitecture architecture; + +/** Date and time that the crash report was generated. This may be unavailable, and this property will be nil. */ +@property(nonatomic, readonly) NSDate *timestamp; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportTextFormatter.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportTextFormatter.h new file mode 100644 index 000000000..61e6689f7 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportTextFormatter.h @@ -0,0 +1,62 @@ +/* + * Authors: + * Landon Fuller + * Damian Morris + * + * Copyright (c) 2008-2010 Plausible Labs Cooperative, Inc. + * Copyright (c) 2010 MOSO Corporation, Pty Ltd. + * 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. + */ + + +#import + +#import "PLCrashReportFormatter.h" + +/** + * Supported text output formats. + * + * @ingroup enums + */ +typedef enum { + /** An iOS-compatible crash log text format. Compatible with the crash logs generated by the device and available + * through iTunes Connect. */ + PLCrashReportTextFormatiOS = 0 +} PLCrashReportTextFormat; + + +@interface PLCrashReportTextFormatter : NSObject { +@private + /** Text output format. */ + PLCrashReportTextFormat _textFormat; + + /** Encoding to use for string output. */ + NSStringEncoding _stringEncoding; +} + ++ (NSString *) stringValueForCrashReport: (PLCrashReport *) report withTextFormat: (PLCrashReportTextFormat) textFormat; + +- (id) initWithTextFormat: (PLCrashReportTextFormat) textFormat stringEncoding: (NSStringEncoding) stringEncoding; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportThreadInfo.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportThreadInfo.h new file mode 100644 index 000000000..7ea39b259 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReportThreadInfo.h @@ -0,0 +1,114 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +@interface PLCrashReportStackFrameInfo : NSObject { +@private + /** Frame instruction pointer. */ + uint64_t _instructionPointer; +} + +- (id) initWithInstructionPointer: (uint64_t) instructionPointer; + +/** + * Frame's instruction pointer. + */ +@property(nonatomic, readonly) uint64_t instructionPointer; + +@end + + +@interface PLCrashReportRegisterInfo : NSObject { +@private + /** Register name */ + NSString *_registerName; + + /** Register value */ + uint64_t _registerValue; +} + +- (id) initWithRegisterName: (NSString *) registerName registerValue: (uint64_t) registerValue; + +/** + * Register name. + */ +@property(nonatomic, readonly) NSString *registerName; + +/** + * Register value. + */ +@property(nonatomic, readonly) uint64_t registerValue; + +@end + + +@interface PLCrashReportThreadInfo : NSObject { +@private + /** The thread number. Should be unique within a given crash log. */ + NSInteger _threadNumber; + + /** Ordered list of PLCrashReportStackFrame instances */ + NSArray *_stackFrames; + + /** YES if this thread crashed. */ + BOOL _crashed; + + /** List of PLCrashReportRegister instances. Will be empty if _crashed is NO. */ + NSArray *_registers; +} + +- (id) initWithThreadNumber: (NSInteger) threadNumber + stackFrames: (NSArray *) stackFrames + crashed: (BOOL) crashed + registers: (NSArray *) registers; + +/** + * Application thread number. + */ +@property(nonatomic, readonly) NSInteger threadNumber; + +/** + * Thread backtrace. Provides an array of PLCrashReportStackFrameInfo instances. + * The array is ordered, last callee to first. + */ +@property(nonatomic, readonly) NSArray *stackFrames; + +/** + * If this thread crashed, set to YES. + */ +@property(nonatomic, readonly) BOOL crashed; + +/** + * State of the general purpose and related registers, as a list of + * PLCrashReportRegister instances. If this thead did not crash (crashed returns NO), + * this list will be empty. + */ +@property(nonatomic, readonly) NSArray *registers; + +@end diff --git a/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReporter.h b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReporter.h new file mode 100644 index 000000000..8ea5e46e6 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Headers/PLCrashReporter.h @@ -0,0 +1,97 @@ +/* + * Author: Landon Fuller + * + * Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc. + * 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. + */ + +#import + +/** + * @ingroup functions + * + * Prototype of a callback function used to execute additional user code with signal information as provided + * by PLCrashReporter. Called upon completion of crash handling, after the crash report has been written to disk. + * + * @param info The signal info. + * @param uap The crash's threads context. + * @param context The API client's supplied context value. + * + * @sa @ref async_safety + * @sa PLCrashReporter::setPostCrashCallbacks: + */ +typedef void (*PLCrashReporterPostCrashSignalCallback)(siginfo_t *info, ucontext_t *uap, void *context); + +/** + * @ingroup types + * + * This structure contains callbacks supported by PLCrashReporter to allow the host application to perform + * additional tasks prior to program termination after a crash has occured. + * + * @sa @ref async_safety + */ +typedef struct PLCrashReporterCallbacks { + /** The version number of this structure. If not one of the defined version numbers for this type, the behavior + * is undefined. The current version of this structure is 0. */ + uint16_t version; + + /** An arbitrary user-supplied context value. This value may be NULL. */ + void *context; + + /** The callback used to report caught signal information. In version 0 of this structure, all crashes will be + * reported via this function. */ + PLCrashReporterPostCrashSignalCallback handleSignal; +} PLCrashReporterCallbacks; + +@interface PLCrashReporter : NSObject { +@private + /** YES if the crash reporter has been enabled */ + BOOL _enabled; + + /** Application identifier */ + NSString *_applicationIdentifier; + + /** Application version */ + NSString *_applicationVersion; + + /** Path to the crash reporter internal data directory */ + NSString *_crashReportDirectory; +} + ++ (PLCrashReporter *) sharedReporter; + +- (BOOL) hasPendingCrashReport; + +- (NSData *) loadPendingCrashReportData; +- (NSData *) loadPendingCrashReportDataAndReturnError: (NSError **) outError; + +- (BOOL) purgePendingCrashReport; +- (BOOL) purgePendingCrashReportAndReturnError: (NSError **) outError; + +- (BOOL) enableCrashReporter; +- (BOOL) enableCrashReporterAndReturnError: (NSError **) outError; + +- (void) setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks; + +@end \ No newline at end of file diff --git a/Frameworks/Sparkle.framework/Versions/A/Resources/Info.plist b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Resources/Info.plist similarity index 70% rename from Frameworks/Sparkle.framework/Versions/A/Resources/Info.plist rename to External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Resources/Info.plist index f9c22c01c..02c411c14 100644 --- a/Frameworks/Sparkle.framework/Versions/A/Resources/Info.plist +++ b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/A/Resources/Info.plist @@ -3,35 +3,33 @@ BuildMachineOSBuild - 11C74 + 11D50 CFBundleDevelopmentRegion - en + English CFBundleExecutable - Sparkle + CrashReporter CFBundleIdentifier - org.andymatuschak.Sparkle + com.yourcompany.CrashReporter CFBundleInfoDictionaryVersion 6.0 CFBundleName - Sparkle + CrashReporter CFBundlePackageType FMWK - CFBundleShortVersionString - 1.5 Beta (git) CFBundleSignature ???? CFBundleVersion - 290f64f + 1.0 DTCompiler - com.apple.compilers.llvm.clang.1_0 + com.apple.compilers.llvmgcc42 DTPlatformBuild 4D502 DTPlatformVersion GM DTSDKBuild - 10K549 + 11C63 DTSDKName - macosx10.6 + macosx10.7 DTXcode 0421 DTXcodeBuild diff --git a/Frameworks/MapKit.framework/Versions/Current b/External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/Current similarity index 100% rename from Frameworks/MapKit.framework/Versions/Current rename to External Source/QuincyKit/client/iOS/CrashReporter.framework/Versions/Current diff --git a/External Source/QuincyKit/client/iOS/LICENSE.txt b/External Source/QuincyKit/client/iOS/LICENSE.txt new file mode 100755 index 000000000..b803b6966 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/LICENSE.txt @@ -0,0 +1,68 @@ +QuincyKit is provided under the following license: + + The MIT License + Copyright (c) 2011 Andreas Linde. 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. + +Except as noted below, PLCrashReporter +is provided under the following license: + + Copyright (c) 2008 - 2009 Plausible Labs Cooperative, Inc. + 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. + +The protobuf-c library, as well as the PLCrashLogWriterEncoding.c +file are licensed as follows: + + Copyright 2008, Dave Benson. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with + the License. You may obtain a copy of the License + at http://www.apache.org/licenses/LICENSE-2.0 Unless + required by applicable law or agreed to in writing, + software distributed under the License is distributed on + an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/de.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/de.lproj/Quincy.strings new file mode 100755 index 000000000..3f63136e9 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/de.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/de.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/de.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..8a1a0ed15 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/de.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/en.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/en.lproj/Quincy.strings new file mode 100755 index 000000000..4137ba40f Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/en.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/en.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/en.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..dbe56b739 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/en.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/es.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/es.lproj/Quincy.strings new file mode 100755 index 000000000..54b6137f5 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/es.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/es.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/es.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..4736dca12 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/es.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/fr.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/fr.lproj/Quincy.strings new file mode 100755 index 000000000..53713d16c Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/fr.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/fr.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/fr.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..39340c652 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/fr.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/it.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/it.lproj/Quincy.strings new file mode 100755 index 000000000..e91fb7c67 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/it.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/it.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/it.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..640149ab0 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/it.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/ja.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/ja.lproj/Quincy.strings new file mode 100755 index 000000000..b27f1e955 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/ja.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/ja.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/ja.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..b8d010e15 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/ja.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/nl.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/nl.lproj/Quincy.strings new file mode 100755 index 000000000..ea18175fd Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/nl.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/nl.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/nl.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..71c99c777 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/nl.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/pt-PT.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt-PT.lproj/Quincy.strings new file mode 100755 index 000000000..0d5912c03 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt-PT.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/pt-PT.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt-PT.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..32acabf12 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt-PT.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/pt.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt.lproj/Quincy.strings new file mode 100755 index 000000000..c99da648e Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/pt.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..2712ccfff Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/pt.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/ru.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/ru.lproj/Quincy.strings new file mode 100755 index 000000000..139aa9ce1 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/ru.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/ru.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/ru.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..139aa9ce1 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/ru.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/sv.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/sv.lproj/Quincy.strings new file mode 100755 index 000000000..f36df14e2 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/sv.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/sv.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/sv.lproj/QuincyAlternate.strings new file mode 100755 index 000000000..d3cbe2a08 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/sv.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/tr.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/tr.lproj/Quincy.strings new file mode 100644 index 000000000..246e757ed Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/tr.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/tr.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/tr.lproj/QuincyAlternate.strings new file mode 100644 index 000000000..2594040b0 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/tr.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_CN.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_CN.lproj/Quincy.strings new file mode 100644 index 000000000..f83511d1b Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_CN.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_CN.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_CN.lproj/QuincyAlternate.strings new file mode 100644 index 000000000..23aed4c96 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_CN.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_TW.lproj/Quincy.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_TW.lproj/Quincy.strings new file mode 100644 index 000000000..347f9df0d Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_TW.lproj/Quincy.strings differ diff --git a/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_TW.lproj/QuincyAlternate.strings b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_TW.lproj/QuincyAlternate.strings new file mode 100644 index 000000000..e6a0d9bd1 Binary files /dev/null and b/External Source/QuincyKit/client/iOS/Quincy.bundle/zh_TW.lproj/QuincyAlternate.strings differ diff --git a/External Source/QuincyKit/client/iOS/QuincyLib/QuincyLib.xcodeproj/project.pbxproj b/External Source/QuincyKit/client/iOS/QuincyLib/QuincyLib.xcodeproj/project.pbxproj new file mode 100644 index 000000000..cd7fa79b2 --- /dev/null +++ b/External Source/QuincyKit/client/iOS/QuincyLib/QuincyLib.xcodeproj/project.pbxproj @@ -0,0 +1,247 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 36892BF0145EC96A0036932D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36892BEF145EC96A0036932D /* Foundation.framework */; }; + 36908F20145ECB090070379E /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36908F1F145ECB090070379E /* CrashReporter.framework */; }; + 36908F23145ECB2E0070379E /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 36908F22145ECB2E0070379E /* BWQuincyManager.m */; }; + 36908F25145ECB370070379E /* BWQuincyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 36908F24145ECB370070379E /* BWQuincyManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 36892BEC145EC96A0036932D /* libQuincyLib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libQuincyLib.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 36892BEF145EC96A0036932D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 36908F1F145ECB090070379E /* CrashReporter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CrashReporter.framework; path = ../CrashReporter.framework; sourceTree = ""; }; + 36908F22145ECB2E0070379E /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BWQuincyManager.m; path = ../BWQuincyManager.m; sourceTree = ""; }; + 36908F24145ECB370070379E /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BWQuincyManager.h; path = ../BWQuincyManager.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 36892BE9145EC96A0036932D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 36908F20145ECB090070379E /* CrashReporter.framework in Frameworks */, + 36892BF0145EC96A0036932D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 36892BE1145EC96A0036932D = { + isa = PBXGroup; + children = ( + 36908F21145ECB220070379E /* Classes */, + 36892BEE145EC96A0036932D /* Frameworks */, + 36892BED145EC96A0036932D /* Products */, + ); + sourceTree = ""; + }; + 36892BED145EC96A0036932D /* Products */ = { + isa = PBXGroup; + children = ( + 36892BEC145EC96A0036932D /* libQuincyLib.a */, + ); + name = Products; + sourceTree = ""; + }; + 36892BEE145EC96A0036932D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 36908F1F145ECB090070379E /* CrashReporter.framework */, + 36892BEF145EC96A0036932D /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 36908F21145ECB220070379E /* Classes */ = { + isa = PBXGroup; + children = ( + 36908F24145ECB370070379E /* BWQuincyManager.h */, + 36908F22145ECB2E0070379E /* BWQuincyManager.m */, + ); + name = Classes; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 36892BEA145EC96A0036932D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 36908F25145ECB370070379E /* BWQuincyManager.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 36892BEB145EC96A0036932D /* QuincyLib */ = { + isa = PBXNativeTarget; + buildConfigurationList = 36892BF9145EC96B0036932D /* Build configuration list for PBXNativeTarget "QuincyLib" */; + buildPhases = ( + 36892BE8145EC96A0036932D /* Sources */, + 36892BE9145EC96A0036932D /* Frameworks */, + 36892BEA145EC96A0036932D /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = QuincyLib; + productName = QuincyLib; + productReference = 36892BEC145EC96A0036932D /* libQuincyLib.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 36892BE3145EC96A0036932D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + ORGANIZATIONNAME = "litl, LLC"; + }; + buildConfigurationList = 36892BE6145EC96A0036932D /* Build configuration list for PBXProject "QuincyLib" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 36892BE1145EC96A0036932D; + productRefGroup = 36892BED145EC96A0036932D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 36892BEB145EC96A0036932D /* QuincyLib */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 36892BE8145EC96A0036932D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 36908F23145ECB2E0070379E /* BWQuincyManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 36892BF7145EC96B0036932D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = ( + armv7, + armv6, + ); + COPY_PHASE_STRIP = NO; + 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_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PUBLIC_HEADERS_FOLDER_PATH = /include/Quincy; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 36892BF8145EC96B0036932D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = ( + armv7, + armv6, + ); + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PUBLIC_HEADERS_FOLDER_PATH = /include/Quincy; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 36892BFA145EC96B0036932D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/QuincyLib.dst; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../..\"", + "\"$(SRCROOT)/..\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ""; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 36892BFB145EC96B0036932D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/QuincyLib.dst; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../..\"", + "\"$(SRCROOT)/..\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ""; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 36892BE6145EC96A0036932D /* Build configuration list for PBXProject "QuincyLib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 36892BF7145EC96B0036932D /* Debug */, + 36892BF8145EC96B0036932D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 36892BF9145EC96B0036932D /* Build configuration list for PBXNativeTarget "QuincyLib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 36892BFA145EC96B0036932D /* Debug */, + 36892BFB145EC96B0036932D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 36892BE3145EC96A0036932D /* Project object */; +} diff --git a/External Source/QuincyKit/demo/Mac/Info.plist b/External Source/QuincyKit/demo/Mac/Info.plist new file mode 100644 index 000000000..daaad48e1 --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Quincy + CFBundleIdentifier + de.buzzworks.Quincy + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + + diff --git a/External Source/QuincyKit/demo/Mac/MainMenu.xib b/External Source/QuincyKit/demo/Mac/MainMenu.xib new file mode 100644 index 000000000..fb22aad0c --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/MainMenu.xib @@ -0,0 +1,1051 @@ + + + + 1050 + 10J869 + 851 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 851 + + + YES + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{335, 390}, {480, 360}} + 1946157056 + Window + NSWindow + + {1.79769e+308, 1.79769e+308} + + + 256 + + YES + + + 268 + {{184, 184}, {104, 32}} + + YES + + 67239424 + 134217728 + Crash me! + + LucidaGrande + 13 + 1044 + + + -2038284033 + 129 + + + 200 + 25 + + + + {{7, 11}, {480, 360}} + + + {{0, 0}, {1440, 878}} + {1.79769e+308, 1.79769e+308} + + + QuincyDemoAppDelegate + + + AMainMenu + + YES + + + QuincyDemo + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + QuincyDemo + + YES + + + About QuincyDemo + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide NewApplication + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit QuincyDemo + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + _NSMainMenu + + + + + YES + + + delegate + + + + 451 + + + + doCrash: + + + + 454 + + + + terminate: + + + + 581 + + + + hide: + + + + 590 + + + + hideOtherApplications: + + + + 591 + + + + unhideAllApplications: + + + + 592 + + + + window + + + + 593 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 371 + + + YES + + + + + + 372 + + + YES + + + + + + 450 + + + Quincy Demo App Delegate + + + 452 + + + YES + + + + + + 453 + + + + + 460 + + + YES + + + + Main Menu + + + 466 + + + YES + + + + + + 473 + + + YES + + + + + + + + + + + + + + + + 474 + + + + + 475 + + + + + 476 + + + YES + + + + + + 477 + + + + + 478 + + + + + 479 + + + + + 480 + + + + + 481 + + + + + 482 + + + + + 483 + + + + + 484 + + + + + 485 + + + + + + + YES + + YES + -3.IBPluginDependency + 371.IBEditorWindowLastContentRect + 371.IBPluginDependency + 371.IBWindowTemplateEditedContentRect + 371.NSWindowTemplate.visibleAtLaunch + 371.editorWindowContentRectSynchronizationRect + 372.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 460.IBEditorWindowLastContentRect + 460.IBPluginDependency + 460.ImportedFromIB2 + 460.WindowOrigin + 460.editorWindowContentRectSynchronizationRect + 466.IBPluginDependency + 466.ImportedFromIB2 + 473.IBEditorWindowLastContentRect + 473.IBPluginDependency + 473.ImportedFromIB2 + 473.editorWindowContentRectSynchronizationRect + 474.IBPluginDependency + 474.ImportedFromIB2 + 475.IBPluginDependency + 475.ImportedFromIB2 + 476.IBPluginDependency + 476.ImportedFromIB2 + 477.IBPluginDependency + 477.ImportedFromIB2 + 478.IBPluginDependency + 478.ImportedFromIB2 + 479.IBPluginDependency + 479.ImportedFromIB2 + 480.IBPluginDependency + 480.ImportedFromIB2 + 481.IBPluginDependency + 481.ImportedFromIB2 + 482.IBPluginDependency + 482.ImportedFromIB2 + 483.IBPluginDependency + 483.ImportedFromIB2 + 484.IBPluginDependency + 484.ImportedFromIB2 + 485.IBEditorWindowLastContentRect + 485.IBPluginDependency + 485.ImportedFromIB2 + 485.editorWindowContentRectSynchronizationRect + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + {{492, 451}, {480, 360}} + com.apple.InterfaceBuilder.CocoaPlugin + {{492, 451}, {480, 360}} + + {{33, 99}, {480, 360}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{101, 746}, {189, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{113, 563}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{531, 606}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + + + + YES + + + YES + + + + + YES + + + YES + + + + 593 + + + + YES + + QuincyDemoAppDelegate + NSObject + + doCrash: + id + + + doCrash: + + doCrash: + id + + + + window + NSWindow + + + window + + window + NSWindow + + + + IBProjectSource + QuincyDemoAppDelegate.h + + + + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/External Source/QuincyKit/demo/Mac/QuincyDemo-Info.plist b/External Source/QuincyKit/demo/Mac/QuincyDemo-Info.plist new file mode 100644 index 000000000..84800c6e6 --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/QuincyDemo-Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + de.buzzworks.QuincyMacDemo + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleURLTypes + + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + NSServices + + UTExportedTypeDeclarations + + UTImportedTypeDeclarations + + + diff --git a/External Source/QuincyKit/demo/Mac/QuincyDemo.xcodeproj/project.pbxproj b/External Source/QuincyKit/demo/Mac/QuincyDemo.xcodeproj/project.pbxproj new file mode 100644 index 000000000..9238d26dc --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/QuincyDemo.xcodeproj/project.pbxproj @@ -0,0 +1,445 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1E360774135A618B00A79125 /* Quincy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E360773135A618B00A79125 /* Quincy.framework */; }; + 1E542D88135A4F31001D7981 /* BWQuincyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E542D84135A4F31001D7981 /* BWQuincyManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1E542D89135A4F31001D7981 /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E542D85135A4F31001D7981 /* BWQuincyManager.m */; }; + 1E542D8B135A4F31001D7981 /* BWQuincyMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = 1E542D87135A4F31001D7981 /* BWQuincyMain.nib */; }; + 1EB61278102B784900B206A7 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1EB61277102B784900B206A7 /* MainMenu.xib */; }; + 1EB6127B102B785E00B206A7 /* QuincyDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB6127A102B785E00B206A7 /* QuincyDemoAppDelegate.m */; }; + 1EB6127D102B787100B206A7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB6127C102B787100B206A7 /* main.m */; }; + 1EB612E4102B815A00B206A7 /* Quincy.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Quincy.framework */; }; + 1EB61442102B8BEE00B206A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + 1EB61462102B8C4400B206A7 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + 1EB614AE102B927900B206A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXBuildRule section */ + 9DB46B601001FCD700D7F5F2 /* PBXBuildRule */ = { + isa = PBXBuildRule; + compilerSpec = com.apple.compilers.proxy.script; + filePatterns = "*.app"; + fileType = pattern.proxy; + isEditable = 1; + outputFiles = ( + "$(DERIVED_FILES_DIR)/$(INPUT_FILE_BASE).h", + ); + script = "sdef \"$INPUT_FILE_PATH\" | sdp -fh -o \"$DERIVED_FILES_DIR\" --basename \"$INPUT_FILE_BASE\" --bundleid `defaults read \"$INPUT_FILE_PATH/Contents/Info\" CFBundleIdentifier`"; + }; +/* End PBXBuildRule section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 1EB612EB102B817100B206A7 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 1EB612E4102B815A00B206A7 /* Quincy.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 1E360773135A618B00A79125 /* Quincy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quincy.framework; path = build/Debug/Quincy.framework; sourceTree = ""; }; + 1E542D84135A4F31001D7981 /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BWQuincyManager.h; path = ../../client/Mac/BWQuincyManager.h; sourceTree = ""; }; + 1E542D85135A4F31001D7981 /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BWQuincyManager.m; path = ../../client/Mac/BWQuincyManager.m; sourceTree = ""; }; + 1E542D87135A4F31001D7981 /* BWQuincyMain.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = BWQuincyMain.nib; path = ../../client/Mac/BWQuincyMain.nib; sourceTree = ""; }; + 1E542D94135A535D001D7981 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1EB61267102B779200B206A7 /* QuincyDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuincyDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1EB61269102B779200B206A7 /* QuincyDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "QuincyDemo-Info.plist"; sourceTree = ""; }; + 1EB61277102B784900B206A7 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + 1EB61279102B785E00B206A7 /* QuincyDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemoAppDelegate.h; sourceTree = ""; }; + 1EB6127A102B785E00B206A7 /* QuincyDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuincyDemoAppDelegate.m; sourceTree = ""; }; + 1EB6127C102B787100B206A7 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 1EB6127E102B787B00B206A7 /* QuincyDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemo_Prefix.pch; sourceTree = ""; }; + 8DC2EF5B0486A6940098B216 /* Quincy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quincy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1EB61265102B779200B206A7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB61442102B8BEE00B206A7 /* Foundation.framework in Frameworks */, + 1EB61462102B8C4400B206A7 /* AppKit.framework in Frameworks */, + 1E360774135A618B00A79125 /* Quincy.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */, + 1EB614AE102B927900B206A7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* Quincy.framework */, + 1EB61267102B779200B206A7 /* QuincyDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* crashReporter */ = { + isa = PBXGroup; + children = ( + 1E542D83135A4F12001D7981 /* Mac */, + 08FB77AEFE84172EC02AAC07 /* Classes */, + 32C88DFF0371C24200C91783 /* Other Sources */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = crashReporter; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 1EB61277102B784900B206A7 /* MainMenu.xib */, + 1E542D94135A535D001D7981 /* Info.plist */, + 1EB61269102B779200B206A7 /* QuincyDemo-Info.plist */, + 1E360773135A618B00A79125 /* Quincy.framework */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* Classes */ = { + isa = PBXGroup; + children = ( + 1EB61279102B785E00B206A7 /* QuincyDemoAppDelegate.h */, + 1EB6127A102B785E00B206A7 /* QuincyDemoAppDelegate.m */, + ); + name = Classes; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 1E542D83135A4F12001D7981 /* Mac */ = { + isa = PBXGroup; + children = ( + 1E542D84135A4F31001D7981 /* BWQuincyManager.h */, + 1E542D85135A4F31001D7981 /* BWQuincyManager.m */, + 1E542D87135A4F31001D7981 /* BWQuincyMain.nib */, + ); + name = Mac; + sourceTree = ""; + }; + 32C88DFF0371C24200C91783 /* Other Sources */ = { + isa = PBXGroup; + children = ( + 1EB6127E102B787B00B206A7 /* QuincyDemo_Prefix.pch */, + 1EB6127C102B787100B206A7 /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1E542D88135A4F31001D7981 /* BWQuincyManager.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1EB61266102B779200B206A7 /* QuincyDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1EB6126C102B779300B206A7 /* Build configuration list for PBXNativeTarget "QuincyDemo" */; + buildPhases = ( + 1EB612EB102B817100B206A7 /* CopyFiles */, + 1EB61263102B779200B206A7 /* Resources */, + 1EB61264102B779200B206A7 /* Sources */, + 1EB61265102B779200B206A7 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = QuincyDemo; + productName = QuincyDemo; + productReference = 1EB61267102B779200B206A7 /* QuincyDemo.app */; + productType = "com.apple.product-type.application"; + }; + 8DC2EF4F0486A6940098B216 /* Quincy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Quincy" */; + buildPhases = ( + 8DC2EF500486A6940098B216 /* Headers */, + 8DC2EF520486A6940098B216 /* Resources */, + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + ); + buildRules = ( + 9DB46B601001FCD700D7F5F2 /* PBXBuildRule */, + ); + dependencies = ( + ); + name = Quincy; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = Quincy; + productReference = 8DC2EF5B0486A6940098B216 /* Quincy.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "QuincyDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + Italian, + ); + mainGroup = 0867D691FE84028FC02AAC07 /* crashReporter */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* Quincy */, + 1EB61266102B779200B206A7 /* QuincyDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1EB61263102B779200B206A7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB61278102B784900B206A7 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DC2EF520486A6940098B216 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1E542D8B135A4F31001D7981 /* BWQuincyMain.nib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1EB61264102B779200B206A7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB6127B102B785E00B206A7 /* QuincyDemoAppDelegate.m in Sources */, + 1EB6127D102B787100B206A7 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1E542D89135A4F31001D7981 /* BWQuincyManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.5; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.5; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_PREFIX_HEADER = Quincy_Prefix.pch; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.4; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = Quincy; + SDKROOT = macosx; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_PREFIX_HEADER = Quincy_Prefix.pch; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = Quincy; + SDKROOT = macosx; + }; + name = Release; + }; + 1EB6126A102B779300B206A7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "QuincyDemo-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = QuincyDemo; + }; + name = Debug; + }; + 1EB6126B102B779300B206A7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "QuincyDemo-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = QuincyDemo; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Quincy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "QuincyDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1EB6126C102B779300B206A7 /* Build configuration list for PBXNativeTarget "QuincyDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1EB6126A102B779300B206A7 /* Debug */, + 1EB6126B102B779300B206A7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/External Source/QuincyKit/demo/Mac/QuincyDemoAppDelegate.h b/External Source/QuincyKit/demo/Mac/QuincyDemoAppDelegate.h new file mode 100644 index 000000000..825c0b02b --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/QuincyDemoAppDelegate.h @@ -0,0 +1,39 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2011 Andreas Linde & Kent Sutherland. All rights reserved. + * 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. + */ + +#import +#import + +@interface QuincyDemoAppDelegate : NSObject { + IBOutlet NSWindow *window; +} + +- (IBAction)doCrash:(id)sender; + +@end diff --git a/External Source/QuincyKit/demo/Mac/QuincyDemoAppDelegate.m b/External Source/QuincyKit/demo/Mac/QuincyDemoAppDelegate.m new file mode 100644 index 000000000..85914b43f --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/QuincyDemoAppDelegate.m @@ -0,0 +1,66 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2011 Andreas Linde & Kent Sutherland. All rights reserved. + * 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. + */ + +#import "QuincyDemoAppDelegate.h" + +@implementation QuincyDemoAppDelegate + +// set the main nibs window to hidden on startup +// this delegate method is required to be implemented! +- (void) showMainApplicationWindow { + [window makeFirstResponder: nil]; + [window makeKeyAndOrderFront:nil]; +} + + +- (void)applicationDidFinishLaunching:(NSNotification *)note { + // Launch the crash reporter task + + // setSubmissionURL for self hosted Example: http://yourserver.com/crash_v200.php + // setAppIdentifier for HockeyApp Example: 658b693ff4c164e65168fe0f43112ac0 + // [[BWQuincyManager sharedQuincyManager] setAppIdentifier:@"658b693ff4c164e65168fe0f43112ac0"]; + // [[BWQuincyManager sharedQuincyManager] setSubmissionURL:@"http://yourserver.com/crash_v200.php"]; + + [[BWQuincyManager sharedQuincyManager] setCompanyName:@"My company"]; + [[BWQuincyManager sharedQuincyManager] setDelegate:self]; +} + + +- (void)bam { + signal(SIGBUS, SIG_DFL); + + *(long*)0 = 0xDEADBEEF; +} + + +- (IBAction)doCrash:(id)sender { + [self bam]; +} + +@end diff --git a/External Source/QuincyKit/demo/Mac/QuincyDemoFatPPC.xcodeproj/project.pbxproj b/External Source/QuincyKit/demo/Mac/QuincyDemoFatPPC.xcodeproj/project.pbxproj new file mode 100644 index 000000000..30575e75e --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/QuincyDemoFatPPC.xcodeproj/project.pbxproj @@ -0,0 +1,482 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1E360774135A618B00A79125 /* Quincy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E360773135A618B00A79125 /* Quincy.framework */; }; + 1E542D88135A4F31001D7981 /* BWQuincyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E542D84135A4F31001D7981 /* BWQuincyManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1E542D89135A4F31001D7981 /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E542D85135A4F31001D7981 /* BWQuincyManager.m */; }; + 1E542D8B135A4F31001D7981 /* BWQuincyMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = 1E542D87135A4F31001D7981 /* BWQuincyMain.nib */; }; + 1EB61278102B784900B206A7 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1EB61277102B784900B206A7 /* MainMenu.xib */; }; + 1EB6127B102B785E00B206A7 /* QuincyDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB6127A102B785E00B206A7 /* QuincyDemoAppDelegate.m */; }; + 1EB6127D102B787100B206A7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB6127C102B787100B206A7 /* main.m */; }; + 1EB612E4102B815A00B206A7 /* Quincy.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Quincy.framework */; }; + 1EB61442102B8BEE00B206A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + 1EB61462102B8C4400B206A7 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + 1EB614AE102B927900B206A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXBuildRule section */ + 9DB46B601001FCD700D7F5F2 /* PBXBuildRule */ = { + isa = PBXBuildRule; + compilerSpec = com.apple.compilers.proxy.script; + filePatterns = "*.app"; + fileType = pattern.proxy; + isEditable = 1; + outputFiles = ( + "$(DERIVED_FILES_DIR)/$(INPUT_FILE_BASE).h", + ); + script = "sdef \"$INPUT_FILE_PATH\" | sdp -fh -o \"$DERIVED_FILES_DIR\" --basename \"$INPUT_FILE_BASE\" --bundleid `defaults read \"$INPUT_FILE_PATH/Contents/Info\" CFBundleIdentifier`"; + }; +/* End PBXBuildRule section */ + +/* Begin PBXContainerItemProxy section */ + 4AE7E0D613BB2E0A007E6D8E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = Quincy; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 1EB612EB102B817100B206A7 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 1EB612E4102B815A00B206A7 /* Quincy.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 1E360773135A618B00A79125 /* Quincy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quincy.framework; path = build/Debug/Quincy.framework; sourceTree = ""; }; + 1E542D84135A4F31001D7981 /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BWQuincyManager.h; path = ../../client/Mac/BWQuincyManager.h; sourceTree = ""; }; + 1E542D85135A4F31001D7981 /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BWQuincyManager.m; path = ../../client/Mac/BWQuincyManager.m; sourceTree = ""; }; + 1E542D87135A4F31001D7981 /* BWQuincyMain.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = BWQuincyMain.nib; path = ../../client/Mac/BWQuincyMain.nib; sourceTree = ""; }; + 1E542D94135A535D001D7981 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1EB61267102B779200B206A7 /* QuincyDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuincyDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1EB61269102B779200B206A7 /* QuincyDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "QuincyDemo-Info.plist"; sourceTree = ""; }; + 1EB61277102B784900B206A7 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + 1EB61279102B785E00B206A7 /* QuincyDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemoAppDelegate.h; sourceTree = ""; }; + 1EB6127A102B785E00B206A7 /* QuincyDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuincyDemoAppDelegate.m; sourceTree = ""; }; + 1EB6127C102B787100B206A7 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 1EB6127E102B787B00B206A7 /* QuincyDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemo_Prefix.pch; sourceTree = ""; }; + 8DC2EF5B0486A6940098B216 /* Quincy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quincy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1EB61265102B779200B206A7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB61442102B8BEE00B206A7 /* Foundation.framework in Frameworks */, + 1EB61462102B8C4400B206A7 /* AppKit.framework in Frameworks */, + 1E360774135A618B00A79125 /* Quincy.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */, + 1EB614AE102B927900B206A7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* Quincy.framework */, + 1EB61267102B779200B206A7 /* QuincyDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* crashReporter */ = { + isa = PBXGroup; + children = ( + 1E542D83135A4F12001D7981 /* Mac */, + 08FB77AEFE84172EC02AAC07 /* Classes */, + 32C88DFF0371C24200C91783 /* Other Sources */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = crashReporter; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 1EB61277102B784900B206A7 /* MainMenu.xib */, + 1E542D94135A535D001D7981 /* Info.plist */, + 1EB61269102B779200B206A7 /* QuincyDemo-Info.plist */, + 1E360773135A618B00A79125 /* Quincy.framework */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* Classes */ = { + isa = PBXGroup; + children = ( + 1EB61279102B785E00B206A7 /* QuincyDemoAppDelegate.h */, + 1EB6127A102B785E00B206A7 /* QuincyDemoAppDelegate.m */, + ); + name = Classes; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 1E542D83135A4F12001D7981 /* Mac */ = { + isa = PBXGroup; + children = ( + 1E542D84135A4F31001D7981 /* BWQuincyManager.h */, + 1E542D85135A4F31001D7981 /* BWQuincyManager.m */, + 1E542D87135A4F31001D7981 /* BWQuincyMain.nib */, + ); + name = Mac; + sourceTree = ""; + }; + 32C88DFF0371C24200C91783 /* Other Sources */ = { + isa = PBXGroup; + children = ( + 1EB6127E102B787B00B206A7 /* QuincyDemo_Prefix.pch */, + 1EB6127C102B787100B206A7 /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1E542D88135A4F31001D7981 /* BWQuincyManager.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1EB61266102B779200B206A7 /* QuincyDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1EB6126C102B779300B206A7 /* Build configuration list for PBXNativeTarget "QuincyDemo" */; + buildPhases = ( + 1EB612EB102B817100B206A7 /* CopyFiles */, + 1EB61263102B779200B206A7 /* Resources */, + 1EB61264102B779200B206A7 /* Sources */, + 1EB61265102B779200B206A7 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 4AE7E0D713BB2E0A007E6D8E /* PBXTargetDependency */, + ); + name = QuincyDemo; + productName = QuincyDemo; + productReference = 1EB61267102B779200B206A7 /* QuincyDemo.app */; + productType = "com.apple.product-type.application"; + }; + 8DC2EF4F0486A6940098B216 /* Quincy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Quincy" */; + buildPhases = ( + 8DC2EF500486A6940098B216 /* Headers */, + 8DC2EF520486A6940098B216 /* Resources */, + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + ); + buildRules = ( + 9DB46B601001FCD700D7F5F2 /* PBXBuildRule */, + ); + dependencies = ( + ); + name = Quincy; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = Quincy; + productReference = 8DC2EF5B0486A6940098B216 /* Quincy.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "QuincyDemoFatPPC" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + Italian, + ); + mainGroup = 0867D691FE84028FC02AAC07 /* crashReporter */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* Quincy */, + 1EB61266102B779200B206A7 /* QuincyDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1EB61263102B779200B206A7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB61278102B784900B206A7 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DC2EF520486A6940098B216 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1E542D8B135A4F31001D7981 /* BWQuincyMain.nib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1EB61264102B779200B206A7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB6127B102B785E00B206A7 /* QuincyDemoAppDelegate.m in Sources */, + 1EB6127D102B787100B206A7 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1E542D89135A4F31001D7981 /* BWQuincyManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4AE7E0D713BB2E0A007E6D8E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* Quincy */; + targetProxy = 4AE7E0D613BB2E0A007E6D8E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + x86_64, + i386, + ppc, + ); + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_PREFIX_HEADER = Quincy_Prefix.pch; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.5; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + PRODUCT_NAME = Quincy; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + x86_64, + i386, + ppc, + ); + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_PREFIX_HEADER = Quincy_Prefix.pch; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.5; + PREBINDING = NO; + PRODUCT_NAME = Quincy; + SDKROOT = macosx10.6; + }; + name = Release; + }; + 1EB6126A102B779300B206A7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/build/Debug\"", + ); + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "QuincyDemo-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = QuincyDemo; + }; + name = Debug; + }; + 1EB6126B102B779300B206A7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/build/Debug\"", + ); + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "QuincyDemo-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = QuincyDemo; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Quincy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "QuincyDemoFatPPC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1EB6126C102B779300B206A7 /* Build configuration list for PBXNativeTarget "QuincyDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1EB6126A102B779300B206A7 /* Debug */, + 1EB6126B102B779300B206A7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/External Source/QuincyKit/demo/Mac/QuincyDemo_Prefix.pch b/External Source/QuincyKit/demo/Mac/QuincyDemo_Prefix.pch new file mode 100644 index 000000000..75809b11c --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/QuincyDemo_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'HDCrashReporter' target in the 'HDCrashReporter' project. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/External Source/QuincyKit/demo/Mac/Quincy_Prefix.pch b/External Source/QuincyKit/demo/Mac/Quincy_Prefix.pch new file mode 100644 index 000000000..75809b11c --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/Quincy_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'HDCrashReporter' target in the 'HDCrashReporter' project. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/External Source/QuincyKit/demo/Mac/main.m b/External Source/QuincyKit/demo/Mac/main.m new file mode 100644 index 000000000..6868274c7 --- /dev/null +++ b/External Source/QuincyKit/demo/Mac/main.m @@ -0,0 +1,35 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2009 Andreas Linde & Kent Sutherland. All rights reserved. + * 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. + */ + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoAppDelegate.h b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoAppDelegate.h new file mode 100644 index 000000000..9f1e8007f --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoAppDelegate.h @@ -0,0 +1,46 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +#import +#import "BWQuincyManager.h" + +@class QuincyDemoViewController; + +@interface QuincyDemoAppDelegate : NSObject { + UIApplication *_application; + + IBOutlet UIWindow *window; + IBOutlet QuincyDemoViewController *viewController; +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet QuincyDemoViewController *viewController; + +@end + diff --git a/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoAppDelegate.m b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoAppDelegate.m new file mode 100644 index 000000000..569f900ac --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoAppDelegate.m @@ -0,0 +1,73 @@ +/* + * Author: Andreas Linde + * Kent Sutherland + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +#import "QuincyDemoAppDelegate.h" +#import "QuincyDemoViewController.h" + +@implementation QuincyDemoAppDelegate + +@synthesize window; +@synthesize viewController; + +- (void)applicationDidFinishLaunching:(UIApplication *)application { + _application = application; + + // Override point for customization after app launch + [window addSubview:viewController.view]; + [window makeKeyAndVisible]; + + // setSubmissionURL for self hosted Example: http://yourserver.com/crash_v200.php + // setAppIdentifier for HockeyApp Example: 6463991af4a2da3f9cb320533c83b156 + // [[BWQuincyManager sharedQuincyManager] setSubmissionURL:@"http://yourserver.com/crash_v200.php"]; + // [[BWQuincyManager sharedQuincyManager] setAppIdentifier:@"6463991af4a2da3f9cb320533c83b156"]; + + [[BWQuincyManager sharedQuincyManager] setDelegate:self]; +} + + +- (void)dealloc { + [viewController release]; + [window release]; + [super dealloc]; +} + + +#pragma mark BWQuincyManagerDelegate + +-(void)connectionOpened { + _application.networkActivityIndicatorVisible = YES; +} + + +-(void)connectionClosed { + _application.networkActivityIndicatorVisible = NO; +} + + +@end \ No newline at end of file diff --git a/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoViewController.h b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoViewController.h new file mode 100644 index 000000000..3acfc3418 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoViewController.h @@ -0,0 +1,42 @@ +/* + * Author: Andreas Linde + * + * Copyright (c) 2009-2011 Andreas Linde. + * 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. + */ + +#import + +@interface QuincyDemoViewController : UIViewController { + IBOutlet UIButton *triggerButtonCrash; + IBOutlet UIButton *triggerButtonExceptionCrash; +} + +@property (nonatomic, retain) IBOutlet UIButton *triggerButtonCrash; + +- (IBAction) triggerCrash; +- (IBAction) triggerExceptionCrash; + +@end + diff --git a/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoViewController.m b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoViewController.m new file mode 100644 index 000000000..4f56d3d89 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Classes/QuincyDemoViewController.m @@ -0,0 +1,69 @@ +/* + * Author: Andreas Linde + * + * Copyright (c) 2009-2011 Andreas Linde. + * 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. + */ + +#import "QuincyDemoViewController.h" + +@implementation QuincyDemoViewController + +@synthesize triggerButtonCrash; + + +- (IBAction) triggerCrash { + /* Trigger a crash */ + CFRelease(NULL); +} + + +- (IBAction) triggerExceptionCrash { + /* Trigger a crash */ + NSArray *array = [NSArray array]; + [array objectAtIndex:23]; +} + + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview + // Release anything that's not essential, such as cached data +} + + +- (void)dealloc { + [super dealloc]; +} + +#pragma mark - +#pragma mark Rotation + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return (interfaceOrientation == UIInterfaceOrientationPortrait) || + (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) || + (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || + (interfaceOrientation == UIInterfaceOrientationLandscapeRight); +} + +@end diff --git a/External Source/QuincyKit/demo/iOS/Info.plist b/External Source/QuincyKit/demo/iOS/Info.plist new file mode 100644 index 000000000..2888a11e0 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + de.buzzworks.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 2.1 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + NSMainNibFile~ipad + MainWindow-iPad + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/External Source/QuincyKit/demo/iOS/MainWindow-iPad.xib b/External Source/QuincyKit/demo/iOS/MainWindow-iPad.xib new file mode 100644 index 000000000..9cec9939d --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/MainWindow-iPad.xib @@ -0,0 +1,327 @@ + + + + 768 + 10J869 + 1306 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 301 + + + YES + IBUICustomObject + IBUIWindow + IBUIViewController + IBProxyObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + + + YES + + IBFilesOwner + IBIPadFramework + + + IBFirstResponder + IBIPadFramework + + + IBIPadFramework + + + QuincyDemoViewController + + 2 + + + 1 + 1 + + IBIPadFramework + NO + + + + 292 + {768, 1024} + + + + + 1 + MSAxIDEAA + + NO + NO + + IBIPadFramework + YES + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + QuincyDemo App Delegate + + + -2 + + + + + 10 + + + QuincyDemo View Controller + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBLastUsedUIStatusBarStylesToTargetRuntimesMap + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBLastUsedUIStatusBarStylesToTargetRuntimesMap + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + QuincyDemoViewController + {{512, 351}, {320, 480}} + + IBCocoaTouchFramework + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + + IBCocoaTouchFramework + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + QuincyDemoAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 26 + + + + YES + + QuincyDemoAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + QuincyDemoViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + QuincyDemoViewController + + + window + UIWindow + + + + + IBProjectSource + ./Classes/QuincyDemoAppDelegate.h + + + + QuincyDemoViewController + UIViewController + + YES + + YES + triggerCrash + triggerMemoryLeak + + + YES + id + id + + + + YES + + YES + triggerCrash + triggerMemoryLeak + + + YES + + triggerCrash + id + + + triggerMemoryLeak + id + + + + + YES + + YES + triggerButtonCrash + triggerButtonMemoryLeak + + + YES + UIButton + UIButton + + + + YES + + YES + triggerButtonCrash + triggerButtonMemoryLeak + + + YES + + triggerButtonCrash + UIButton + + + triggerButtonMemoryLeak + UIButton + + + + + IBProjectSource + ./Classes/QuincyDemoViewController.h + + + + + 0 + IBIPadFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 301 + + diff --git a/External Source/QuincyKit/demo/iOS/MainWindow.xib b/External Source/QuincyKit/demo/iOS/MainWindow.xib new file mode 100644 index 000000000..8fcaa9443 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/MainWindow.xib @@ -0,0 +1,307 @@ + + + + 768 + 10J869 + 1306 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 301 + + + YES + IBUICustomObject + IBUIWindow + IBUIViewController + IBProxyObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + QuincyDemoViewController + + + 1 + 1 + + IBCocoaTouchFramework + NO + + + + 292 + {320, 480} + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + QuincyDemo App Delegate + + + -2 + + + + + 10 + + + QuincyDemo View Controller + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + QuincyDemoViewController + {{512, 351}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + QuincyDemoAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 26 + + + + YES + + QuincyDemoAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + QuincyDemoViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + QuincyDemoViewController + + + window + UIWindow + + + + + IBProjectSource + ./Classes/QuincyDemoAppDelegate.h + + + + QuincyDemoViewController + UIViewController + + YES + + YES + triggerCrash + triggerMemoryLeak + + + YES + id + id + + + + YES + + YES + triggerCrash + triggerMemoryLeak + + + YES + + triggerCrash + id + + + triggerMemoryLeak + id + + + + + YES + + YES + triggerButtonCrash + triggerButtonMemoryLeak + + + YES + UIButton + UIButton + + + + YES + + YES + triggerButtonCrash + triggerButtonMemoryLeak + + + YES + + triggerButtonCrash + UIButton + + + triggerButtonMemoryLeak + UIButton + + + + + IBProjectSource + ./Classes/QuincyDemoViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 301 + + diff --git a/External Source/QuincyKit/demo/iOS/QuincyDemo.xcodeproj/project.pbxproj b/External Source/QuincyKit/demo/iOS/QuincyDemo.xcodeproj/project.pbxproj new file mode 100755 index 000000000..bbcb292cc --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/QuincyDemo.xcodeproj/project.pbxproj @@ -0,0 +1,327 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1D3623260D0F684500981E51 /* QuincyDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* QuincyDemoAppDelegate.m */; }; + 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 1E542D41135A2D6E001D7981 /* QuincyDemoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E542D40135A2D6E001D7981 /* QuincyDemoViewController.xib */; }; + 1E542D51135A2F84001D7981 /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E542D50135A2F84001D7981 /* BWQuincyManager.m */; }; + 1E542D5E135A2FFA001D7981 /* Quincy.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1E542D5D135A2FFA001D7981 /* Quincy.bundle */; }; + 1E542D75135A3075001D7981 /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E542D74135A3075001D7981 /* MainWindow-iPad.xib */; }; + 1E542D77135A343F001D7981 /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E542D76135A343F001D7981 /* CrashReporter.framework */; }; + 1E94B4850F5F229D002D4D2C /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1E94B4840F5F229D002D4D2C /* Settings.bundle */; }; + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 28D7ACF80DDB3853001CB0EB /* QuincyDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* QuincyDemoViewController.m */; }; + 37DD8C46100A4A5700461FA4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37DD8C45100A4A5700461FA4 /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D3623240D0F684500981E51 /* QuincyDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemoAppDelegate.h; sourceTree = ""; }; + 1D3623250D0F684500981E51 /* QuincyDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuincyDemoAppDelegate.m; sourceTree = ""; }; + 1D6058910D05DD3D006BFB54 /* QuincyDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuincyDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 1E542D40135A2D6E001D7981 /* QuincyDemoViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = QuincyDemoViewController.xib; sourceTree = ""; }; + 1E542D4F135A2F84001D7981 /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWQuincyManager.h; sourceTree = ""; }; + 1E542D50135A2F84001D7981 /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWQuincyManager.m; sourceTree = ""; }; + 1E542D5D135A2FFA001D7981 /* Quincy.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Quincy.bundle; sourceTree = ""; }; + 1E542D74135A3075001D7981 /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = "MainWindow-iPad.xib"; sourceTree = ""; }; + 1E542D76135A343F001D7981 /* CrashReporter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CrashReporter.framework; sourceTree = ""; }; + 1E94B4840F5F229D002D4D2C /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; + 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; + 28D7ACF60DDB3853001CB0EB /* QuincyDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemoViewController.h; sourceTree = ""; }; + 28D7ACF70DDB3853001CB0EB /* QuincyDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuincyDemoViewController.m; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* QuincyDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuincyDemo_Prefix.pch; sourceTree = ""; }; + 37DD8C45100A4A5700461FA4 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + 37DD8C46100A4A5700461FA4 /* SystemConfiguration.framework in Frameworks */, + 1E542D77135A343F001D7981 /* CrashReporter.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 1D3623240D0F684500981E51 /* QuincyDemoAppDelegate.h */, + 1D3623250D0F684500981E51 /* QuincyDemoAppDelegate.m */, + 28D7ACF60DDB3853001CB0EB /* QuincyDemoViewController.h */, + 28D7ACF70DDB3853001CB0EB /* QuincyDemoViewController.m */, + ); + path = Classes; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* QuincyDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 1E542D4E135A2F5E001D7981 /* iOS */ = { + isa = PBXGroup; + children = ( + 1E542D4F135A2F84001D7981 /* BWQuincyManager.h */, + 1E542D50135A2F84001D7981 /* BWQuincyManager.m */, + 1E542D5D135A2FFA001D7981 /* Quincy.bundle */, + 1E542D76135A343F001D7981 /* CrashReporter.framework */, + ); + name = iOS; + path = ../../client/iOS; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 1E542D4E135A2F5E001D7981 /* iOS */, + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* QuincyDemo_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 1E94B4840F5F229D002D4D2C /* Settings.bundle */, + 1E542D40135A2D6E001D7981 /* QuincyDemoViewController.xib */, + 28AD733E0D9D9553002E5188 /* MainWindow.xib */, + 1E542D74135A3075001D7981 /* MainWindow-iPad.xib */, + 8D1107310486CEB800E47090 /* Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + 37DD8C45100A4A5700461FA4 /* SystemConfiguration.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* QuincyDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "QuincyDemo" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = QuincyDemo; + productName = QuincyDemo; + productReference = 1D6058910D05DD3D006BFB54 /* QuincyDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "QuincyDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + fi, + es, + pt, + ru, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* QuincyDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, + 1E94B4850F5F229D002D4D2C /* Settings.bundle in Resources */, + 1E542D41135A2D6E001D7981 /* QuincyDemoViewController.xib in Resources */, + 1E542D5E135A2FFA001D7981 /* Quincy.bundle in Resources */, + 1E542D75135A3075001D7981 /* MainWindow-iPad.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 1D3623260D0F684500981E51 /* QuincyDemoAppDelegate.m in Sources */, + 28D7ACF80DDB3853001CB0EB /* QuincyDemoViewController.m in Sources */, + 1E542D51135A2F84001D7981 /* BWQuincyManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = ( + armv6, + armv7, + ); + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + "\"$(SRCROOT)/../../client/iOS\"", + ); + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = QuincyDemo_Prefix.pch; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + PRODUCT_NAME = QuincyDemo; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = ( + armv6, + armv7, + ); + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + "\"$(SRCROOT)/../../client/iOS\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = QuincyDemo_Prefix.pch; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + PRODUCT_NAME = QuincyDemo; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + OTHER_LDFLAGS = "-all_load"; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "QuincyDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "QuincyDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/External Source/QuincyKit/demo/iOS/QuincyDemoViewController.xib b/External Source/QuincyKit/demo/iOS/QuincyDemoViewController.xib new file mode 100644 index 000000000..9eb3edea1 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/QuincyDemoViewController.xib @@ -0,0 +1,345 @@ + + + + 768 + 11C74 + 1938 + 1138.23 + 567.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 933 + + + YES + IBProxyObject + IBUIView + IBUIButton + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 292 + {{72, 205}, {176, 37}} + + + + NO + NO + IBCocoaTouchFramework + 0 + 0 + 1 + Trigger Crash + Trigger Crash + Trigger Crash + Trigger Crash + + 1 + MSAxIDEAA + + + 1 + MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA + + + 3 + MAA + + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + + + + + 292 + {{61, 285}, {199, 37}} + + + + NO + NO + IBCocoaTouchFramework + 0 + 0 + 1 + Trigger Exception Crash + + + 1 + MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA + + + + + + + {{0, 20}, {320, 460}} + + + + + 3 + MC43NQA + + 2 + + + NO + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 19 + + + + triggerButtonCrash + + + + 20 + + + + triggerButtonExceptionCrash + + + + 25 + + + + triggerCrash + + + 7 + + 21 + + + + triggerExceptionCrash + + + 7 + + 24 + + + + + YES + + 0 + + YES + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + + + 9 + + + + + 22 + + + + + + + YES + + YES + -1.CustomClassName + -1.IBPluginDependency + -2.CustomClassName + -2.IBPluginDependency + 22.IBPluginDependency + 6.IBPluginDependency + 9.IBPluginDependency + + + YES + QuincyDemoViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 25 + + + + YES + + QuincyDemoViewController + UIViewController + + YES + + YES + triggerCrash + triggerExceptionCrash + + + YES + id + id + + + + YES + + YES + triggerCrash + triggerExceptionCrash + + + YES + + triggerCrash + id + + + triggerExceptionCrash + id + + + + + YES + + YES + triggerButtonCrash + triggerButtonExceptionCrash + + + YES + UIButton + UIButton + + + + YES + + YES + triggerButtonCrash + triggerButtonExceptionCrash + + + YES + + triggerButtonCrash + UIButton + + + triggerButtonExceptionCrash + UIButton + + + + + IBProjectSource + ./Classes/QuincyDemoViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 933 + + diff --git a/External Source/QuincyKit/demo/iOS/QuincyDemo_Prefix.pch b/External Source/QuincyKit/demo/iOS/QuincyDemo_Prefix.pch new file mode 100644 index 000000000..03ffd7798 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/QuincyDemo_Prefix.pch @@ -0,0 +1,8 @@ +// +// Prefix header for all source files of the 'CrashReporterDemo' target in the 'CrashReporterDemo' project +// + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/Root.plist b/External Source/QuincyKit/demo/iOS/Settings.bundle/Root.plist new file mode 100755 index 000000000..5453b843f --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/Root.plist @@ -0,0 +1,27 @@ + + + + + PreferenceSpecifiers + + + Type + PSGroupSpecifier + Title + + + + Type + PSChildPaneSpecifier + Title + SettingsCrashTitle + File + bugdata + + + StringsTable + Root + Title + Crash Reporter Demo + + diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/bugdata.plist b/External Source/QuincyKit/demo/iOS/Settings.bundle/bugdata.plist new file mode 100644 index 000000000..763a91388 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/bugdata.plist @@ -0,0 +1,73 @@ + + + + + PreferenceSpecifiers + + + DefaultValue + + Key + CrashReportActivated + Title + SettingsActivateCrashReporter + Type + PSToggleSwitchSpecifier + + + Title + SettingsActivateCrashReporterDescription + Type + PSGroupSpecifier + + + DefaultValue + + Key + AutomaticallySendCrashReports + Title + SettingsAutoSendCrash + Type + PSToggleSwitchSpecifier + + + Title + SettingsAutoSendCrashDescription + Type + PSGroupSpecifier + + + DefaultValue + + Key + CrashDataContactAllowKey + Title + SettingsAllowContact + Type + PSToggleSwitchSpecifier + + + Key + CrashDataContactEmailKey + KeyboardType + EmailAddress + AutocapitalizationType + None + Title + SettingsContactEmail + Type + PSTextFieldSpecifier + + + Title + SettingsContactDescription + Type + PSGroupSpecifier + + + StringsTable + bugdata + Title + Bug data + + diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/de.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/de.lproj/Root.strings new file mode 100644 index 000000000..4e4cbc549 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/de.lproj/Root.strings @@ -0,0 +1,5 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Fehlerbericht"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/de.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/de.lproj/bugdata.strings new file mode 100644 index 000000000..74f139b86 Binary files /dev/null and b/External Source/QuincyKit/demo/iOS/Settings.bundle/de.lproj/bugdata.strings differ diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/en.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/en.lproj/Root.strings new file mode 100644 index 000000000..1626f40ec --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/en.lproj/Root.strings @@ -0,0 +1,5 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Bug report"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/en.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/en.lproj/bugdata.strings new file mode 100644 index 000000000..23170262d --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/en.lproj/bugdata.strings @@ -0,0 +1,21 @@ + +/* Settings title if collecting crash data is activated */ +"SettingsActivateCrashReporter" = "Collect crash data"; + +/* Description text for automatic sending of crash data */ +"SettingsActivateCrashReporterDescription" = "If a crash happens, data which can help the developer to correct the problem will be collected automatically."; + +/* Settings title if crash data might be sent to the developer automatically */ +"SettingsAutoSendCrash" = "Automatic report"; + +/* Description text for automatic sending of crash data */ +"SettingsAutoSendCrashDescription" = "If a crash happens, the data would be sent to the developer automatically without asking the users."; + +/* Allow the developer to contact the user via email */ +"SettingsAllowContact" = "Allow contact"; + +/* Email address the developer might use */ +"SettingsContactEmail" = "EMail address"; + +/* Description text for email contact usage */ +"SettingsContactDescription" = "The email address would only be used to contact the user if there might be more clarifications needed about the problem"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/es.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/es.lproj/Root.strings new file mode 100644 index 000000000..c9cd4ec1f --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/es.lproj/Root.strings @@ -0,0 +1,5 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Informe de error"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/es.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/es.lproj/bugdata.strings new file mode 100644 index 000000000..9e6579e18 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/es.lproj/bugdata.strings @@ -0,0 +1,21 @@ + +/* Settings title if collecting crash data is activated */ +"SettingsActivateCrashReporter" = "Collect crash data"; + +/* Description text for automatic sending of crash data */ +"SettingsActivateCrashReporterDescription" = "If a crash happens, data which can help the developer to correct the problem will be collected automatically."; + +/* Settings title if crash data might be sent to the developer automatically */ +"SettingsAutoSendCrash" = "Automática de informes"; + +/* Description text for automatic sending of crash data */ +"SettingsAutoSendCrashDescription" = "Si aparece un accidente, los datos serían enviados automáticamente a los desarrolladores sin pedir a los usuarios."; + +/* Allow the developer to contact the user via email */ +"SettingsAllowContact" = "Permitir el contacto"; + +/* Email address the developer might use */ +"SettingsContactEmail" = "EMail"; + +/* Description text for email contact usage */ +"SettingsContactDescription" = "La dirección de correo electrónico sólo se utiliza para ponerse en contacto con el usuario si puede haber más aclaraciones necesarias sobre el problema"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/fi.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/fi.lproj/Root.strings new file mode 100644 index 000000000..a836eb6f0 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/fi.lproj/Root.strings @@ -0,0 +1,7 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Virhetiedot"; + + diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/fi.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/fi.lproj/bugdata.strings new file mode 100644 index 000000000..39ab2c712 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/fi.lproj/bugdata.strings @@ -0,0 +1,21 @@ + +/* Settings title if collecting crash data is activated */ +"SettingsActivateCrashReporter" = "Collect crash data"; + +/* Description text for automatic sending of crash data */ +"SettingsActivateCrashReporterDescription" = "If a crash happens, data which can help the developer to correct the problem will be collected automatically."; + +/* Settings title if crash data might be sent to the developer automatically */ +"SettingsAutoSendCrash" = "Automaatt. ilmoitus"; + +/* Description text for automatic sending of crash data */ +"SettingsAutoSendCrashDescription" = "Jos ohjelma kaatuu, tiedot lähetetään kehittäjälle ilman luvan kysymistä käyttäjältä."; + +/* Allow the developer to contact the user via email */ +"SettingsAllowContact" = "Salli yhteyshenkilö"; + +/* Email address the developer might use */ +"SettingsContactEmail" = "Sähköp. osoite"; + +/* Description text for email contact usage */ +"SettingsContactDescription" = "Tätä sähköpostiosoitetta käytetään vain, jos kehittäjä tarvitsee lisää tietoja ongelmasta."; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/fr.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/fr.lproj/Root.strings new file mode 100644 index 000000000..8997379ce --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/fr.lproj/Root.strings @@ -0,0 +1,7 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Données de bogue"; + + diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/fr.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/fr.lproj/bugdata.strings new file mode 100644 index 000000000..a0ad13938 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/fr.lproj/bugdata.strings @@ -0,0 +1,21 @@ + +/* Settings title if collecting crash data is activated */ +"SettingsActivateCrashReporter" = "Collect crash data"; + +/* Description text for automatic sending of crash data */ +"SettingsActivateCrashReporterDescription" = "If a crash happens, data which can help the developer to correct the problem will be collected automatically."; + +/* Settings title if crash data might be sent to the developer automatically */ +"SettingsAutoSendCrash" = "Rapport automatique"; + +/* Description text for automatic sending of crash data */ +"SettingsAutoSendCrashDescription" = "Si une panne apparaît, les données seront envoyées automatiquement au développeur."; + +/* Allow the developer to contact the user via email */ +"SettingsAllowContact" = "Contact autorisé"; + +/* Email address the developer might use */ +"SettingsContactEmail" = "Adresse électronique"; + +/* Description text for email contact usage */ +"SettingsContactDescription" = "L'adresse mail ne sera utilisée que pour contacter l'utilisateur,en cas d'éclaircissements nécessaires sur le problème"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/pt.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/pt.lproj/Root.strings new file mode 100644 index 000000000..11a0e724d --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/pt.lproj/Root.strings @@ -0,0 +1,5 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Erro de dados"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/pt.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/pt.lproj/bugdata.strings new file mode 100644 index 000000000..f7c157c1c Binary files /dev/null and b/External Source/QuincyKit/demo/iOS/Settings.bundle/pt.lproj/bugdata.strings differ diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/ru.lproj/Root.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/ru.lproj/Root.strings new file mode 100644 index 000000000..7512ebd20 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/Settings.bundle/ru.lproj/Root.strings @@ -0,0 +1,5 @@ + +/* Settings */ + +/* What to do in case of crashes */ +"SettingsCrashTitle" = "Ошибки"; diff --git a/External Source/QuincyKit/demo/iOS/Settings.bundle/ru.lproj/bugdata.strings b/External Source/QuincyKit/demo/iOS/Settings.bundle/ru.lproj/bugdata.strings new file mode 100644 index 000000000..a6d9e2b97 Binary files /dev/null and b/External Source/QuincyKit/demo/iOS/Settings.bundle/ru.lproj/bugdata.strings differ diff --git a/External Source/QuincyKit/demo/iOS/main.m b/External Source/QuincyKit/demo/iOS/main.m new file mode 100644 index 000000000..eef3c1596 --- /dev/null +++ b/External Source/QuincyKit/demo/iOS/main.m @@ -0,0 +1,37 @@ +/* + * Author: Andreas Linde + * + * Copyright (c) 2009 Andreas Linde. All rights reserved. + * 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. + */ + +#import + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} diff --git a/External Source/QuincyKit/server/ProwlPHP.php b/External Source/QuincyKit/server/ProwlPHP.php new file mode 100755 index 000000000..074688f06 --- /dev/null +++ b/External Source/QuincyKit/server/ProwlPHP.php @@ -0,0 +1,198 @@ + maxsize] + 'apikey' => 204, // User API Key. + 'providerkey' => 40, // Provider key. + 'priority' => 2, // Range from -2 to 2. + 'application' => 254, // Name of the app. + 'event' => 1024, // Name of the event. + 'description' => 10000, // Description of the event. + ); + + public function __construct($apikey=null, $verify=false, $provkey=null, $proxy=null, $userpwd=null) + { + $curl_info = curl_version(); // Checks for cURL function and SSL version. Thanks Adrian Rollett! + if(!function_exists('curl_exec') || empty($curl_info['ssl_version'])) + { + die($this->getError(10000)); + } + + if(isset($proxy)) + $this->_setProxy($proxy, $userpwd); + + if(isset($apikey) && $verify) + $this->verify($apikey, $provkey); + + $this->_api_key = $apikey; + } + + public function verify($apikey, $provkey) + { + $return = $this->_execute(sprintf($this->_url_verify, $apikey, $provkey)); + return $this->_response($return); + } + + public function push($params, $is_post=false) + { + if($is_post) + $post_params = ''; + + $url = $is_post ? $this->_url_push : $this->_url_push . '?'; + $params = func_get_args(); + + if(isset($this->_api_key) && !isset($params[0]['apikey'])) + $params[0]['apikey'] = $this->_api_key; + + if(isset($this->_prov_key) && !isset($params[0]['providerkey'])) + $params[0]['providerkey'] = $this->_prov_key; + + foreach($params[0] as $k => $v) + { + $v = str_replace("\\n","\n",$v); // Fixes line break issue! Cheers Fr3d! + if(!isset($this->_params[$k])) + { + $this->_return_code = 400; + return false; + } + if(strlen($v) > $this->_params[$k]) + { + $this->_return_code = 10001; + return false; + } + + if($is_post) + $post_params .= $k . '=' . urlencode($v) . '&'; + else + $url .= $k . '=' . urlencode($v) . '&'; + } + + if($is_post) + $params = substr($post_params, 0, strlen($post_params)-1); + else + $url = substr($url, 0, strlen($url)-1); + + $return = $this->_execute($url, $is_post ? true : false, $params); + + return $this->_response($return); + } + + public function getError($code=null) + { + $code = (empty($code)) ? $this->_return_code : $code; + switch($code) + { + case 200: return 'Request Successful.'; break; + case 400: return 'Bad request, the parameters you provided did not validate.'; break; + case 401: return 'The API key given is not valid, and does not correspond to a user.'; break; + case 405: return 'Method not allowed, you attempted to use a non-SSL connection to Prowl.'; break; + case 406: return 'Your IP address has exceeded the API limit.'; break; + case 500: return 'Internal server error, something failed to execute properly on the Prowl side.'; break; + case 10000: return 'cURL library missing vital functions or does not support SSL. cURL w/SSL is required to execute ProwlPHP.'; break; + case 10001: return 'Parameter value exceeds the maximum byte size.'; break; + default: return false; break; + } + } + + public function getRemaining() + { + if(!isset($this->_remaining)) + return false; + + return $this->_remaining; + } + + public function getResetDate() + { + if(!isset($this->_resetdate)) + return false; + + return $this->_resetdate; + } + + private function _execute($url, $is_post=false, $params=null) + { + $this->_obj_curl = curl_init($this->_api_domain . $url); + curl_setopt($this->_obj_curl, CURLOPT_HEADER, 0); + curl_setopt($this->_obj_curl, CURLOPT_USERAGENT, "ProwlPHP/" . $this->_version); + curl_setopt($this->_obj_curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_setopt($this->_obj_curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($this->_obj_curl, CURLOPT_RETURNTRANSFER, 1); + + if($is_post) + { + curl_setopt($this->_obj_curl, CURLOPT_POST, 1); + curl_setopt($this->_obj_curl, CURLOPT_POSTFIELDS, $params); + } + + if($this->_use_proxy) + { + curl_setopt($this->_obj_curl, CURLOPT_HTTPPROXYTUNNEL, 1); + curl_setopt($this->_obj_curl, CURLOPT_PROXY, $this->_proxy); + curl_setopt($this->_obj_curl, CURLOPT_PROXYUSERPWD, $this->_proxy_userpwd); + } + + $return = curl_exec($this->_obj_curl); + curl_close($this->_obj_curl); + return $return; + } + + private function _response($return) + { + if($return===false) + { + $this->_return_code = 500; + return false; + } + + $response = new SimpleXMLElement($return); + + if(isset($response->success)) + { + $this->_return_code = (int)$response->success['code']; + $this->_remaining = (int)$response->success['remaining']; + $this->_resetdate = (int)$response->success['resetdate']; + } + else + { + $this->_return_code = $response->error['code']; + } + + switch($this->_return_code) + { + case 200: return true; break; + default: return false; break; + } + + unset($response); + } + + private function _setProxy($proxy, $userpwd=null) + { + if(strlen($proxy) > 0) + { + $this->_use_proxy = true; + $this->_proxy = $proxy; + $this->_proxy_userpwd = $userpwd; + } + } +} + +?> \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/actionapi.php b/External Source/QuincyKit/server/admin/actionapi.php new file mode 100644 index 000000000..2b591ad10 --- /dev/null +++ b/External Source/QuincyKit/server/admin/actionapi.php @@ -0,0 +1,212 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde. + * 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. + */ + +require_once('../config.php'); +require_once('common.inc'); + +init_database(); +parse_parameters(',action,id,groupid,bundleidentifier,version,fixversion,description,'); +parse_parameters_post(',action,id,groupid,bundleidentifier,version,fixversion,description,'); + +if (!isset($action)) $action = ""; +if (!isset($id)) $id = ""; +if (!isset($groupid)) $groupid = ""; +if (!isset($bundleidentifier)) $version = ""; +if (!isset($version)) $version = ""; +if (!isset($fixversion)) $fixversion = ""; +if (!isset($description)) $description = ""; + +if ($action == "") die('Wrong parameters'); + +if ($action == "deletecrashid" && $id != "") { + $query = "DELETE from " . $dbcrashtable . " WHERE id=" . $id; + $result = mysql_query($query) or die('Error in SQL '.$query); + + if ($groupid != "" && $groupid > -1) { + // adjust amount and timestamp + $query = "SELECT amount, latesttimestamp FROM ".$dbgrouptable." WHERE id = ".$groupid; + $result = mysql_query($query) or die('Error in SQL: '.$query); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) { + $amount = $row[0]; + $latest = $row[1]; + $lastupdate = 0; + + if ($amount > 0) { + $query2 = "SELECT max(UNIX_TIMESTAMP(timestamp)) FROM ".$dbcrashtable." WHERE groupid = '".$groupid."'"; + $result2 = mysql_query($query2) or die('Error in SQL '.$query2); + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) { + $row2 = mysql_fetch_row($result2); + $lastupdate = $row2[0]; + if ($lastupdate == "") $lastupdate = 0; + } + mysql_free_result($result2); + + $query2 = "UPDATE ".$dbgrouptable." SET latesttimestamp = ".$lastupdate." WHERE id = ".$groupid; + $result2 = mysql_query($query2) or die('Error in SQL '.$query2); + } + } + } + mysql_free_result($result); + + $query = "UPDATE ".$dbgrouptable." SET amount=amount-1 WHERE id=".$groupid; + $result = mysql_query($query) or die('Error in SQL '.$query); + } +} else if ($action == "deletegroupid" && $id != "") { + $query = "DELETE FROM ".$dbsymbolicatetable." WHERE crashid in (select id from ".$dbcrashtable." where groupid = ".$id.")"; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $query = "DELETE FROM ".$dbcrashtable." WHERE groupid = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $query = "DELETE FROM ".$dbgrouptable." WHERE id = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); +} else if ($action == "deletegroups" && $bundleidentifier != "" && $version != "") { + $query = "DELETE FROM ".$dbsymbolicatetable." WHERE crashid in (select id from ".$dbcrashtable." where bundleidentifier = '".$bundleidentifier."' and version = '".$version."')"; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $query = "DELETE FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' and version = '".$version."'"; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $query = "DELETE FROM ".$dbgrouptable." WHERE bundleidentifier = '".$bundleidentifier."' and affected = '".$version."'"; + $result = mysql_query($query) or die('Error in SQL '.$query); +} else if ($action == "updategroupid" && $id != "") { + $query = "UPDATE ".$dbgrouptable." SET fix = '".$fixversion."' WHERE id = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); + + if ($fixversion != "") { + // check if the fix version is already added, if not add it + $query = "SELECT id FROM ".$dbversiontable." WHERE bundleidentifier = '".$bundleidentifier."' and version = '".$fixversion."'"; + $result = mysql_query($query) or die('Error in SQL '.$query); + $numrows = mysql_num_rows($result); + mysql_free_result($result); + if ($numrows == 0) { + // version is not available, so add it with status VERSION_STATUS_AVAILABLE + $query = "INSERT INTO ".$dbversiontable." (bundleidentifier, version, status) values ('".$bundleidentifier."', '".$fixversion."', ".VERSION_STATUS_UNKNOWN.")"; + $result = mysql_query($query) or die('Error in SQL '.$query); + } + } + + $query = "UPDATE ".$dbgrouptable." SET description = '".mysql_real_escape_string($description)."' WHERE id = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); +} else if ($action == "symbolicatecrashid" && $id != "") { + $query = "SELECT id FROM ".$dbsymbolicatetable." WHERE crashid = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $numrows = mysql_num_rows($result); + mysql_free_result($result); + + if ($numrows > 0) + $query = "UPDATE ".$dbsymbolicatetable." SET done = 0 WHERE crashid = ".$id; + else + $query = "INSERT INTO ".$dbsymbolicatetable." (crashid, done) values (".$id.", 0)"; + + $result = mysql_query($query) or die('Error in SQL '.$query); +} else if ($action == "getsymbolicationtodo") { + $crashids = ""; + + $query = "SELECT crashid FROM ".$dbsymbolicatetable." WHERE done = 0"; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + while ($row = mysql_fetch_row($result)) + { + if ($crashids != '') + $crashids .= ','; + + $crashids .= $row[0]; + + } + mysql_free_result($result); + } + + echo $crashids; +} else if ($action == "getlogcrashid" && $id != "") { + $query = "SELECT log FROM ".$dbcrashtable." WHERE id = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + while ($row = mysql_fetch_row($result)) + { + echo $row[0]; + } + mysql_free_result($result); + } +} else if ($action == "getdescriptioncrashid" && $id != "") { + $query = "SELECT description FROM ".$dbcrashtable." WHERE id = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$query); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + while ($row = mysql_fetch_row($result)) + { + echo $row[0]; + } + mysql_free_result($result); + } +} else if ($action == "downloadcrashid" && ($id != "" || $groupid != "")) { + $query = ""; + if ($groupid != "") { + $query = "SELECT log FROM ".$dbcrashtable." WHERE groupid = '".$groupid."' ORDER BY systemversion desc, timestamp desc LIMIT 1"; + } else { + $query = "SELECT log FROM ".$dbcrashtable." WHERE id = '".$id."' ORDER BY systemversion desc, timestamp desc LIMIT 1"; + } + $result = mysql_query($query) or die('Error in SQL '.$query); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + // get the status + $row = mysql_fetch_row($result); + $log = $row[0]; + + // We'll be outputting a text file + header('Content-type: application/text'); + + // It will be called abc.txt + header('Content-Disposition: attachment; filename="'.$timestamp.'.crash"'); + echo $log; + + mysql_free_result($result); + } +} else { + die('Wrong parameters'); +} + + +mysql_close($link); + + +?> \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/app_name.php b/External Source/QuincyKit/server/admin/app_name.php new file mode 100755 index 000000000..afd8daccd --- /dev/null +++ b/External Source/QuincyKit/server/admin/app_name.php @@ -0,0 +1,182 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +// +// This is the main admin UI script +// +// You can add applications by adding their respective bundle identifiers +// and you can delete applications and define if external symbolification +// should be turned on or not +// + +require_once('../config.php'); +require_once('common.inc'); + +if ($acceptallapps) +{ + die(''); +} + +init_database(); +parse_parameters(',bundleidentifier,symbolicate,id,name,issuetrackerurl,hockeyappidentifier,pushids,emails,'); + +if (!isset($bundleidentifier)) $bundleidentifier = ""; +if (!isset($symbolicate)) $symbolicate = ""; +if (!isset($id)) $id = ""; +if (!isset($name)) $name = ""; +if (!isset($issuetrackerurl)) $issuetrackerurl = ""; +if (!isset($hockeyappidentifier)) $hockeyappidentifier = ""; +if (!isset($pushids)) $pushids = ""; +if (!isset($emails)) $emails = ""; + +$query = ""; +// update the app +if ($id != "" && $symbolicate != "") { + $query = "UPDATE ".$dbapptable." SET symbolicate = ".$symbolicate.", name = '".$name."', issuetrackerurl = '".$issuetrackerurl."', hockeyappidentifier = '".$hockeyappidentifier."', notifyemail = '".$emails."', notifypush = '".$pushids."' WHERE id = ".$id; +} else if ($bundleidentifier != "" && $id == "" && $symbolicate != "") { + // insert new app + // version is not available, so add it with status VERSION_STATUS_AVAILABLE + $query = "INSERT INTO ".$dbapptable." (bundleidentifier, name, symbolicate, issuetrackerurl, notifyemail, notifypush, hockeyappidentifier) values ('".$bundleidentifier."', '".$name."', ".$symbolicate.", '".$issuetrackerurl."', '".$emails."', '".$pushids."', '".$hockeyappidentifier."')"; +} else if ($symbolicate != "" && $id != "") { + $query = "UPDATE ".$dbapptable." SET symbolicate = ".$symbolicate." WHERE id = ".$id; +} else if ($id != "" && $symbolicate == "") { + // delete a version + $query = "DELETE FROM ".$dbapptable." WHERE id = ".$id; +} +if ($query != "") + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + +show_header('- Apps'); + +echo '

Apps

'; + +$cols = ''; +echo ''.$cols; +echo ""; +echo '
Bundle identifier / NameEmail - / Push NotificationsIssue Tracker / HockeyAppCrashesActions
'; + +if (!$acceptallapps) +{ + echo "
"; + echo ''.$cols; + + echo ""; + echo ""; + echo ""; + echo ""; + echo '
"; + echo ""; + if ($mail_activated) + echo "
"; + else + echo "Email notifications not activated!
"; + if ($push_activated) + echo ""; + else if ($boxcar_activated) + echo "Boxcar notifications set for $boxcar_uid
"; + else + echo "Push notifications not activated!"; + echo "

"; + echo ""; + echo "
"; + echo "
'; +} + +// get all applications and their symbolication status +$query = "SELECT bundleidentifier, symbolicate, id, name, issuetrackerurl, notifyemail, notifypush, hockeyappidentifier FROM ".$dbapptable." ORDER BY bundleidentifier asc, symbolicate desc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) + { + $bundleidentifier = $row[0]; + $symbolicate = $row[1]; + $id = $row[2]; + $name = $row[3]; + $issuetrackerurl = $row[4]; + $email = $row[5]; + $push = $row[6]; + $hockeyappidentifier = $row[7]; + + echo "
"; + echo ''.$cols; + + echo ""; + echo ""; + echo ""; + + echo ""; + + echo ""; + echo "
".$bundleidentifier."
"; + echo "
"; + if ($mail_activated) + echo "
"; + else + echo "Email notifications not activated!
"; + if ($push_activated) + echo ""; + else if ($boxcar_activated) + echo "Boxcar notifications set for $boxcar_uid
"; + else + echo "Push notifications not activated!"; + echo "

"; + echo "

"; + + // get the total number of crashes + $query2 = "SELECT count(*) FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."'"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + + $totalcrashes = 0; + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) { + $row2 = mysql_fetch_row($result2); + $totalcrashes = $row2[0]; + + mysql_free_result($result2); + } + + echo $totalcrashes . "
"; + echo " Delete
"; + } + + mysql_free_result($result); +} + +mysql_close($link); + +echo ''; + +?> diff --git a/External Source/QuincyKit/server/admin/app_versions.php b/External Source/QuincyKit/server/admin/app_versions.php new file mode 100755 index 000000000..ce1df0a80 --- /dev/null +++ b/External Source/QuincyKit/server/admin/app_versions.php @@ -0,0 +1,344 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +// +// This script shows all available versions for an application +// +// You can add versions, change the status of a version (which corresponds +// to the bugfix status), see how many crash groups are created for this +// version and how many crash reports in total are available +// If a version has no crash reports assigned, and no crash group +// has this version assigned as a bugfix version, this script also provides +// the possibility to delete the version +// + +require_once('../config.php'); +require_once('common.inc'); + +init_database(); +parse_parameters(',bundleidentifier,version,status,symbolicate,id,notify,deletecrashes,'); + +if (!isset($bundleidentifier)) $bundleidentifier = ""; +if (!isset($version)) $version = ""; +if (!isset($status)) $status = ""; +if (!isset($id)) $id = ""; +if (!isset($notify)) $notify = NOTIFY_OFF; +if (!isset($symbolicate)) $symbolicate = 0; +if (!isset($deletecrashes)) $deletecrashes = -1; + +// add the new app & version +if ($version != "" && $deletecrashes == "1") { + $query = "DELETE FROM ".$dbsymbolicatetable." WHERE crashid in (select id from ".$dbcrashtable." where bundleidentifier = '".$bundleidentifier."' and version = '".$version."')"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + + $query = "DELETE FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' and version = '".$version."'"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + + $query = "DELETE FROM ".$dbgrouptable." WHERE bundleidentifier = '".$bundleidentifier."' and affected = '".$version."'"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +} else if ($bundleidentifier != "" && $status != "" && $id == "" && $version != "") { + $query = "SELECT id FROM ".$dbversiontable." WHERE bundleidentifier = '".$bundleidentifier."' and version = '".$row[1]."'"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + + $numrows = mysql_num_rows($result); + if ($numrows == 1) + { + $row = mysql_fetch_row($result); + $query2 = "UPDATE ".$dbversiontable." SET status = ".$status." WHERE id = ".$row[0]; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + } else if ($numrows == 0) { + // version is not available, so add it with status VERSION_STATUS_AVAILABLE + $query2 = "INSERT INTO ".$dbversiontable." (bundleidentifier, version, status) values ('".$bundleidentifier."', '".$version."', ".$status.")"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + } + mysql_free_result($result); +} else if ($id != "" && ($status != "" || $notify != "")) { + $query = "UPDATE ".$dbversiontable." SET status = ".$status.", notify = ".$notify." WHERE id = ".$id; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +} else if ($id != "" && $status == "") { + // delete a version + $query = "DELETE FROM ".$dbversiontable." WHERE id = '".$id."'"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +} + +show_header('- App Versions'); + +if ($acceptallapps) + echo '

Versions

'; +else + echo '

Apps - '.create_link($bundleidentifier, 'app_versions.php', false, 'bundleidentifier').'

'; + +$osticks = ""; +$osvalues = ""; + +$crashvaluesarray = array(); +$crashvalues = ""; + +$cols2 = ''; +echo ''.$cols2.''; + +echo ""; +echo ""; +echo ""; + +// get the amount of crashes per system version +$crashestime = true; + +$query = "SELECT timestamp FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' ORDER BY timestamp desc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + while ($row = mysql_fetch_row($result)) { + $timestamp = $row[0]; + + if ($timestamp != "" && ($timestampvalue = strtotime($timestamp)) !== false) + { + $timeindex = substr($timestamp, 0, 10); + + if (!array_key_exists($timeindex, $crashvaluesarray)) { + $crashvaluesarray[$timeindex] = 0; + } + $crashvaluesarray[$timeindex]++; + } + } +} +mysql_free_result($result); + + +$osticks = ""; +$osvalues = ""; +$whereclause = ""; + +$query2 = "SELECT systemversion, COUNT(systemversion) FROM ".$dbcrashtable.$whereclause." WHERE bundleidentifier = '".$bundleidentifier."' group by systemversion order by systemversion desc"; +$result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); +$numrows2 = mysql_num_rows($result2); +if ($numrows2 > 0) { + // get the status + while ($row2 = mysql_fetch_row($result2)) { + if ($osticks != "") $osticks = $osticks.", "; + $osticks .= "'".$row2[0]."'"; + if ($osvalues != "") $osvalues = $osvalues.", "; + $osvalues .= $row2[1]; + } +} +mysql_free_result($result2); + +// get the amount of crashes per system version +$crashestime = true; + +$platformticks = ""; +$platformvalues = ""; +$query = "SELECT platform, COUNT(platform) FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' AND platform != \"\" group by platform order by platform desc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) { + if ($platformticks != "") $platformticks = $platformticks.", "; + $platformticks .= "'".mapPlatform($row[0])."'"; + if ($platformvalues != "") $platformvalues = $platformvalues.", "; + $platformvalues .= $row[1]; + } +} +mysql_free_result($result); + +echo '
Platform OverviewCrashes over timeSystem OS Overview
'; + +$cols2 = ''; +echo ''.$cols2.''; +echo '
Group Details
'; + +show_search("", -1, true, ""); + +echo '
'; + + +$cols = ''; +echo ''.$cols; +echo ""; +echo '
NameVersionStatusNotifyGroupsTotal CrashesActions
'; + +echo "
"; +if (!$acceptallapps) + echo ""; + +echo ''.$cols; + +echo ""; + +echo '
"; + +if ($acceptallapps) + echo ""; +else + echo $bundleidentifier; + +echo ""; + +if ($push_activated || $mail_activated) { + echo ""; +} else { + echo ""; +} + +echo "

'; + +// get all applications and their versions, amount of groups and amount of total bug reports +if ($acceptallapps) + $query = "SELECT bundleidentifier, version, status, notify, id FROM ".$dbversiontable." ORDER BY bundleidentifier asc, version desc, status desc"; +else + $query = "SELECT bundleidentifier, version, status, notify, id FROM ".$dbversiontable." WHERE bundleidentifier = '".$bundleidentifier."' ORDER BY bundleidentifier asc, version desc, status desc"; + +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) + { + $bundleidentifier = $row[0]; + $version = $row[1]; + $status = $row[2]; + $notify = $row[3]; + $id = $row[4]; + $groups = 0; + $totalcrashes = 0; + + // get the number of groups + $query2 = "SELECT count(*) FROM ".$dbgrouptable." WHERE bundleidentifier = '".$bundleidentifier."' and affected = '".$version."'"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$$query2)); + + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) { + $row2 = mysql_fetch_row($result2); + $groups = $row2[0]; + + mysql_free_result($result2); + } + + // get the total number of crashes + $query2 = "SELECT count(*) FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' and version = '".$version."'"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) { + $row2 = mysql_fetch_row($result2); + $totalcrashes = $row2[0]; + + mysql_free_result($result2); + } + + echo "
"; + echo ''.$cols; + + echo "
".$bundleidentifier.""; + + if ($groups > 0 || $totalcrashes > 0) + echo "".$version.""; + else + echo $version; + echo ""; + + echo ""; + if ($push_activated || $mail_activated) { + echo ""; + } else { + echo ""; + } + + echo "".$groups."".$totalcrashes.""; + + if ($totalcrashes == 0 && $groups == 0) + { + // only show delete button if this version is nowwhere assigned as fix version + $query2 = "SELECT count(*) FROM ".$dbgrouptable." WHERE bundleidentifier = '".$bundleidentifier."' and fix = '".$version."'"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + $numrows2 = mysql_num_rows($result2); + $showdelete = false; + if ($numrows2 > 0) { + $row2 = mysql_fetch_row($result2); + if ($row2[0] == 0) + { + $showdelete = true; + } + + mysql_free_result($result2); + } + + if ($showdelete == true || $version == "") + { + echo " Delete"; + } + } else { + echo "Delete Crashes"; + } + echo "
"; + } + + mysql_free_result($result); +} + +mysql_close($link); + +?> + + + + \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/LICENSE b/External Source/QuincyKit/server/admin/blueprint/LICENSE new file mode 100755 index 000000000..e1a863813 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/LICENSE @@ -0,0 +1,314 @@ +Blueprint CSS Framework License +---------------------------------------------------------------- + +Copyright (c) 2007-2009 blueprintcss.org + +The Blueprint CSS Framework is available for use in all personal or +commercial projects, under both the (modified) MIT and the GPL license. You +may choose the one that fits your project. + + +The (modified) MIT License +---------------------------------------------------------------- + +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, sub-license, 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 every other copyright notice found in this +software, and all the attributions in every file, 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 NON-INFRINGEMENT. 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. + + +The GPL License +---------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/External Source/QuincyKit/server/admin/blueprint/ie.css b/External Source/QuincyKit/server/admin/blueprint/ie.css new file mode 100755 index 000000000..f336f0edc --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/ie.css @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* ie.css */ +body {text-align:center;} +.container {text-align:left;} +* html .column, * html div.span-1, * html div.span-2, * html div.span-3, * html div.span-4, * html div.span-5, * html div.span-6, * html div.span-7, * html div.span-8, * html div.span-9, * html div.span-10, * html div.span-11, * html div.span-12, * html div.span-13, * html div.span-14, * html div.span-15, * html div.span-16, * html div.span-17, * html div.span-18, * html div.span-19, * html div.span-20, * html div.span-21, * html div.span-22, * html div.span-23, * html div.span-24 {display:inline;overflow-x:hidden;} +* html legend {margin:0px -8px 16px 0;padding:0;} +sup {vertical-align:text-top;} +sub {vertical-align:text-bottom;} +html>body p code {*white-space:normal;} +hr {margin:-8px auto 11px;} +img {-ms-interpolation-mode:bicubic;} +.clearfix, .container {display:inline-block;} +* html .clearfix, * html .container {height:1%;} +fieldset {padding-top:0;} +textarea {overflow:auto;} +input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;} +input.text:focus, input.title:focus {border-color:#666;} +input.text, input.title, textarea, select {margin:0.5em 0;} +input.checkbox, input.radio {position:relative;top:.25em;} +form.inline div, form.inline p {vertical-align:middle;} +form.inline label {position:relative;top:-0.25em;} +form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;} +button, input.button {position:relative;top:0.25em;} \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/cross.png b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/cross.png new file mode 100755 index 000000000..1514d51a3 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/cross.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/key.png b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/key.png new file mode 100755 index 000000000..a9d5e4f8c Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/key.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/tick.png b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/tick.png new file mode 100755 index 000000000..a9925a06a Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/icons/tick.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/readme.txt b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/readme.txt new file mode 100755 index 000000000..a8c2b5708 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/readme.txt @@ -0,0 +1,32 @@ +Buttons + +* Gives you great looking CSS buttons, for both and + + + Change Password + + + + Cancel + diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/screen.css b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/screen.css new file mode 100755 index 000000000..bb66b2154 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/buttons/screen.css @@ -0,0 +1,97 @@ +/* -------------------------------------------------------------- + + buttons.css + * Gives you some great CSS-only buttons. + + Created by Kevin Hale [particletree.com] + * particletree.com/features/rediscovering-the-button-element + + See Readme.txt in this folder for instructions. + +-------------------------------------------------------------- */ + +a.button, button { + display:block; + float:left; + margin: 0.7em 0.5em 0.7em 0; + padding:5px 10px 5px 7px; /* Links */ + + border:1px solid #dedede; + border-top:1px solid #eee; + border-left:1px solid #eee; + + background-color:#f5f5f5; + font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; + font-size:100%; + line-height:130%; + text-decoration:none; + font-weight:bold; + color:#565656; + cursor:pointer; +} +button { + width:auto; + overflow:visible; + padding:4px 10px 3px 7px; /* IE6 */ +} +button[type] { + padding:4px 10px 4px 7px; /* Firefox */ + line-height:17px; /* Safari */ +} +*:first-child+html button[type] { + padding:4px 10px 3px 7px; /* IE7 */ +} +button img, a.button img{ + margin:0 3px -3px 0 !important; + padding:0; + border:none; + width:16px; + height:16px; + float:none; +} + + +/* Button colors +-------------------------------------------------------------- */ + +/* Standard */ +button:hover, a.button:hover{ + background-color:#dff4ff; + border:1px solid #c2e1ef; + color:#336699; +} +a.button:active{ + background-color:#6299c5; + border:1px solid #6299c5; + color:#fff; +} + +/* Positive */ +body .positive { + color:#529214; +} +a.positive:hover, button.positive:hover { + background-color:#E6EFC2; + border:1px solid #C6D880; + color:#529214; +} +a.positive:active { + background-color:#529214; + border:1px solid #529214; + color:#fff; +} + +/* Negative */ +body .negative { + color:#d12f19; +} +a.negative:hover, button.negative:hover { + background-color:#fbe3e4; + border:1px solid #fbc2c4; + color:#d12f19; +} +a.negative:active { + background-color:#d12f19; + border:1px solid #d12f19; + color:#fff; +} diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/fancy-type/readme.txt b/External Source/QuincyKit/server/admin/blueprint/plugins/fancy-type/readme.txt new file mode 100755 index 000000000..85f249152 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/fancy-type/readme.txt @@ -0,0 +1,14 @@ +Fancy Type + +* Gives you classes to use if you'd like some + extra fancy typography. + +Credits and instructions are specified above each class +in the fancy-type.css file in this directory. + + +Usage +---------------------------------------------------------------- + +1) Add this plugin to lib/settings.yml. + See compress.rb for instructions. diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/fancy-type/screen.css b/External Source/QuincyKit/server/admin/blueprint/plugins/fancy-type/screen.css new file mode 100755 index 000000000..028e05bb6 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/fancy-type/screen.css @@ -0,0 +1,71 @@ +/* -------------------------------------------------------------- + + fancy-type.css + * Lots of pretty advanced classes for manipulating text. + + See the Readme file in this folder for additional instructions. + +-------------------------------------------------------------- */ + +/* Indentation instead of line shifts for sibling paragraphs. */ + p + p { text-indent:2em; margin-top:-1.5em; } + form p + p { text-indent: 0; } /* Don't want this in forms. */ + + +/* For great looking type, use this code instead of asdf: + asdf + Best used on prepositions and ampersands. */ + +.alt { + color: #666; + font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif; + font-style: italic; + font-weight: normal; +} + + +/* For great looking quote marks in titles, replace "asdf" with: + asdf” + (That is, when the title starts with a quote mark). + (You may have to change this value depending on your font size). */ + +.dquo { margin-left: -.5em; } + + +/* Reduced size type with incremental leading + (http://www.markboulton.co.uk/journal/comments/incremental_leading/) + + This could be used for side notes. For smaller type, you don't necessarily want to + follow the 1.5x vertical rhythm -- the line-height is too much. + + Using this class, it reduces your font size and line-height so that for + every four lines of normal sized type, there is five lines of the sidenote. eg: + + New type size in em's: + 10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems) + + New line-height value: + 12px x 1.5 = 18px (old line-height) + 18px x 4 = 72px + 72px / 5 = 14.4px (new line height) + 14.4px / 10px = 1.44 (new line height in em's) */ + +p.incr, .incr p { + font-size: 10px; + line-height: 1.44em; + margin-bottom: 1.5em; +} + + +/* Surround uppercase words and abbreviations with this class. + Based on work by Jørgen Arnor GÃ¥rdsø Lom [http://twistedintellect.com/] */ + +.caps { + font-variant: small-caps; + letter-spacing: 1px; + text-transform: lowercase; + font-size:1.2em; + line-height:1%; + font-weight:bold; + padding:0 2px; +} diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/doc.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/doc.png new file mode 100755 index 000000000..834cdfaf4 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/doc.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/email.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/email.png new file mode 100755 index 000000000..7348aed77 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/email.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/external.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/external.png new file mode 100755 index 000000000..cf1cfb426 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/external.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/feed.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/feed.png new file mode 100755 index 000000000..315c4f4fa Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/feed.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/im.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/im.png new file mode 100755 index 000000000..79f35ccbd Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/im.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/pdf.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/pdf.png new file mode 100755 index 000000000..8f8095e46 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/pdf.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/visited.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/visited.png new file mode 100755 index 000000000..ebf206def Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/visited.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/xls.png b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/xls.png new file mode 100755 index 000000000..b977d7e52 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/icons/xls.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/readme.txt b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/readme.txt new file mode 100755 index 000000000..3cb1b2ce6 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/readme.txt @@ -0,0 +1,18 @@ +Link Icons +* Icons for links based on protocol or file type. + +This is not supported in IE versions < 7. + + +Credits +---------------------------------------------------------------- + +* Marc Morgan +* Olav Bjorkoy [bjorkoy.com] + + +Usage +---------------------------------------------------------------- + +1) Add this line to your HTML: + \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/screen.css b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/screen.css new file mode 100755 index 000000000..6d3d47fad --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/link-icons/screen.css @@ -0,0 +1,40 @@ +/* -------------------------------------------------------------- + + link-icons.css + * Icons for links based on protocol or file type. + + See the Readme file in this folder for additional instructions. + +-------------------------------------------------------------- */ + +/* Use this class if a link gets an icon when it shouldn't. */ +body a.noicon { + background:transparent none !important; + padding:0 !important; + margin:0 !important; +} + +/* Make sure the icons are not cut */ +a[href^="http:"], a[href^="mailto:"], a[href^="http:"]:visited, +a[href$=".pdf"], a[href$=".doc"], a[href$=".xls"], a[href$=".rss"], +a[href$=".rdf"], a[href^="aim:"] { + padding:2px 22px 2px 0; + margin:-2px 0; + background-repeat: no-repeat; + background-position: right center; +} + +/* External links */ +a[href^="http:"] { background-image: url(icons/external.png); } +a[href^="mailto:"] { background-image: url(icons/email.png); } +a[href^="http:"]:visited { background-image: url(icons/visited.png); } + +/* Files */ +a[href$=".pdf"] { background-image: url(icons/pdf.png); } +a[href$=".doc"] { background-image: url(icons/doc.png); } +a[href$=".xls"] { background-image: url(icons/xls.png); } + +/* Misc */ +a[href$=".rss"], +a[href$=".rdf"] { background-image: url(icons/feed.png); } +a[href^="aim:"] { background-image: url(icons/im.png); } \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/rtl/readme.txt b/External Source/QuincyKit/server/admin/blueprint/plugins/rtl/readme.txt new file mode 100755 index 000000000..4c465352c --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/rtl/readme.txt @@ -0,0 +1,10 @@ +RTL +* Mirrors Blueprint, so it can be used with Right-to-Left languages. + +By Ran Yaniv Hartstein, ranh.co.il + +Usage +---------------------------------------------------------------- + +1) Add this line to your HTML: + \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/plugins/rtl/screen.css b/External Source/QuincyKit/server/admin/blueprint/plugins/rtl/screen.css new file mode 100755 index 000000000..7e7ccdb8c --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/plugins/rtl/screen.css @@ -0,0 +1,110 @@ +/* -------------------------------------------------------------- + + rtl.css + * Mirrors Blueprint for left-to-right languages + + By Ran Yaniv Hartstein [ranh.co.il] + +-------------------------------------------------------------- */ + +body .container { direction: rtl; } +body .column, body div.span-1, body div.span-2, body div.span-3, body div.span-4, body div.span-5, body div.span-6, body div.span-7, body div.span-8, body div.span-9, body div.span-10, body div.span-11, body div.span-12, body div.span-13, body div.span-14, body div.span-15, body div.span-16, body div.span-17, body div.span-18, body div.span-19, body div.span-20, body div.span-21, body div.span-22, body div.span-23, body div.span-24 { + float: right; + margin-right: 0; + margin-left: 10px; + text-align:right; +} + +body div.last { margin-left: 0; } +body table .last { padding-left: 0; } + +body .append-1 { padding-right: 0; padding-left: 40px; } +body .append-2 { padding-right: 0; padding-left: 80px; } +body .append-3 { padding-right: 0; padding-left: 120px; } +body .append-4 { padding-right: 0; padding-left: 160px; } +body .append-5 { padding-right: 0; padding-left: 200px; } +body .append-6 { padding-right: 0; padding-left: 240px; } +body .append-7 { padding-right: 0; padding-left: 280px; } +body .append-8 { padding-right: 0; padding-left: 320px; } +body .append-9 { padding-right: 0; padding-left: 360px; } +body .append-10 { padding-right: 0; padding-left: 400px; } +body .append-11 { padding-right: 0; padding-left: 440px; } +body .append-12 { padding-right: 0; padding-left: 480px; } +body .append-13 { padding-right: 0; padding-left: 520px; } +body .append-14 { padding-right: 0; padding-left: 560px; } +body .append-15 { padding-right: 0; padding-left: 600px; } +body .append-16 { padding-right: 0; padding-left: 640px; } +body .append-17 { padding-right: 0; padding-left: 680px; } +body .append-18 { padding-right: 0; padding-left: 720px; } +body .append-19 { padding-right: 0; padding-left: 760px; } +body .append-20 { padding-right: 0; padding-left: 800px; } +body .append-21 { padding-right: 0; padding-left: 840px; } +body .append-22 { padding-right: 0; padding-left: 880px; } +body .append-23 { padding-right: 0; padding-left: 920px; } + +body .prepend-1 { padding-left: 0; padding-right: 40px; } +body .prepend-2 { padding-left: 0; padding-right: 80px; } +body .prepend-3 { padding-left: 0; padding-right: 120px; } +body .prepend-4 { padding-left: 0; padding-right: 160px; } +body .prepend-5 { padding-left: 0; padding-right: 200px; } +body .prepend-6 { padding-left: 0; padding-right: 240px; } +body .prepend-7 { padding-left: 0; padding-right: 280px; } +body .prepend-8 { padding-left: 0; padding-right: 320px; } +body .prepend-9 { padding-left: 0; padding-right: 360px; } +body .prepend-10 { padding-left: 0; padding-right: 400px; } +body .prepend-11 { padding-left: 0; padding-right: 440px; } +body .prepend-12 { padding-left: 0; padding-right: 480px; } +body .prepend-13 { padding-left: 0; padding-right: 520px; } +body .prepend-14 { padding-left: 0; padding-right: 560px; } +body .prepend-15 { padding-left: 0; padding-right: 600px; } +body .prepend-16 { padding-left: 0; padding-right: 640px; } +body .prepend-17 { padding-left: 0; padding-right: 680px; } +body .prepend-18 { padding-left: 0; padding-right: 720px; } +body .prepend-19 { padding-left: 0; padding-right: 760px; } +body .prepend-20 { padding-left: 0; padding-right: 800px; } +body .prepend-21 { padding-left: 0; padding-right: 840px; } +body .prepend-22 { padding-left: 0; padding-right: 880px; } +body .prepend-23 { padding-left: 0; padding-right: 920px; } + +body .border { + padding-right: 0; + padding-left: 4px; + margin-right: 0; + margin-left: 5px; + border-right: none; + border-left: 1px solid #eee; +} + +body .colborder { + padding-right: 0; + padding-left: 24px; + margin-right: 0; + margin-left: 25px; + border-right: none; + border-left: 1px solid #eee; +} + +body .pull-1 { margin-left: 0; margin-right: -40px; } +body .pull-2 { margin-left: 0; margin-right: -80px; } +body .pull-3 { margin-left: 0; margin-right: -120px; } +body .pull-4 { margin-left: 0; margin-right: -160px; } + +body .push-0 { margin: 0 18px 0 0; } +body .push-1 { margin: 0 18px 0 -40px; } +body .push-2 { margin: 0 18px 0 -80px; } +body .push-3 { margin: 0 18px 0 -120px; } +body .push-4 { margin: 0 18px 0 -160px; } +body .push-0, body .push-1, body .push-2, +body .push-3, body .push-4 { float: left; } + + +/* Typography with RTL support */ +body h1,body h2,body h3, +body h4,body h5,body h6 { font-family: Arial, sans-serif; } +html body { font-family: Arial, sans-serif; } +body pre,body code,body tt { font-family: monospace; } + +/* Mirror floats and margins on typographic elements */ +body p img { float: right; margin: 1.5em 0 1.5em 1.5em; } +body dd, body ul, body ol { margin-left: 0; margin-right: 1.5em;} +body td, body th { text-align:right; } \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/print.css b/External Source/QuincyKit/server/admin/blueprint/print.css new file mode 100755 index 000000000..fdb82208e --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/print.css @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* print.css */ +body {line-height:1.5;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;color:#000;background:none;font-size:10pt;} +.container {background:none;} +hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;} +hr.space {background:#fff;color:#fff;visibility:hidden;} +h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;} +code {font:.9em "Courier New", Monaco, Courier, monospace;} +a img {border:none;} +p img.top {margin-top:0;} +blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;} +.small {font-size:.9em;} +.large {font-size:1.1em;} +.quiet {color:#999;} +.hide {display:none;} +a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;} +a:link:after, a:visited:after {content:" (" attr(href) ")";font-size:90%;} \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/screen.css b/External Source/QuincyKit/server/admin/blueprint/screen.css new file mode 100755 index 000000000..2c2b32834 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/screen.css @@ -0,0 +1,257 @@ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* reset.css */ +html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} +body {line-height:1.5;} +table {border-collapse:separate;border-spacing:0;} +caption, th, td {text-align:left;font-weight:normal;} +table, td, th {vertical-align:middle;} +blockquote:before, blockquote:after, q:before, q:after {content:"";} +blockquote, q {quotes:"" "";} +a img {border:none;} + +/* typography.css */ +html {font-size:100.01%;} +body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} +h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} +h2 {font-size:2em;margin-bottom:0.75em;} +h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} +h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} +h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} +h6 {font-size:1em;font-weight:bold;} +h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} +p {margin:0 0 1.5em;} +p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} +p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} +a:focus, a:hover {color:#000;} +a {color:#009;text-decoration:underline;} +blockquote {margin:1.5em;color:#666;font-style:italic;} +strong {font-weight:bold;} +em, dfn {font-style:italic;} +dfn {font-weight:bold;} +sup, sub {line-height:0;} +abbr, acronym {border-bottom:1px dotted #666;} +address {margin:0 0 1.5em;font-style:italic;} +del {color:#666;} +pre {margin:1.5em 0;white-space:pre;} +pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} +li ul, li ol {margin:0;} +ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;} +ul {list-style-type:disc;} +ol {list-style-type:decimal;} +dl {margin:0 0 1.5em 0;} +dl dt {font-weight:bold;} +dd {margin-left:1.5em;} +table {margin-bottom:1.4em;width:100%;} +th {font-weight:bold;} +thead th {background:#c3d9ff;} +th, td, caption {padding:4px 10px 4px 5px;} +tr.even td {background:#e5ecf9;} +tfoot {font-style:italic;} +caption {background:#eee;} +.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} +.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} +.hide {display:none;} +.quiet {color:#666;} +.loud {color:#000;} +.highlight {background:#ff0;} +.added {background:#060;color:#fff;} +.removed {background:#900;color:#fff;} +.first {margin-left:0;padding-left:0;} +.last {margin-right:0;padding-right:0;} +.top {margin-top:0;padding-top:0;} +.bottom {margin-bottom:0;padding-bottom:0;} + +/* forms.css */ +label {font-weight:bold;} +fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} +legend {font-weight:bold;font-size:1.2em;} +input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;} +input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;} +input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;} +input.text, input.title {width:300px;padding:5px;} +input.title {font-size:1.5em;} +textarea {width:390px;height:250px;padding:5px;} +input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;} +form.inline {line-height:3;} +form.inline p {margin-bottom:0;} +.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} +.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} +.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} +.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} +.error a {color:#8a1f11;} +.notice a {color:#514721;} +.success a {color:#264409;} + +/* grid.css */ +.container {width:950px;margin:0 auto;} +.showgrid {background:url(src/grid.png);} +.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;} +.last, div.last {margin-right:0;} +.span-1 {width:30px;} +.span-2 {width:70px;} +.span-3 {width:110px;} +.span-4 {width:150px;} +.span-5 {width:190px;} +.span-6 {width:230px;} +.span-7 {width:270px;} +.span-8 {width:310px;} +.span-9 {width:350px;} +.span-10 {width:390px;} +.span-11 {width:430px;} +.span-12 {width:470px;} +.span-13 {width:510px;} +.span-14 {width:550px;} +.span-15 {width:590px;} +.span-16 {width:630px;} +.span-17 {width:670px;} +.span-18 {width:710px;} +.span-19 {width:750px;} +.span-20 {width:790px;} +.span-21 {width:830px;} +.span-22 {width:870px;} +.span-23 {width:910px;} +.span-24, div.span-24 {width:950px;margin-right:0;} +input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {border-left-width:1px!important;border-right-width:1px!important;padding-left:5px!important;padding-right:5px!important;} +input.span-1, textarea.span-1 {width:18px!important;} +input.span-2, textarea.span-2 {width:58px!important;} +input.span-3, textarea.span-3 {width:98px!important;} +input.span-4, textarea.span-4 {width:138px!important;} +input.span-5, textarea.span-5 {width:178px!important;} +input.span-6, textarea.span-6 {width:218px!important;} +input.span-7, textarea.span-7 {width:258px!important;} +input.span-8, textarea.span-8 {width:298px!important;} +input.span-9, textarea.span-9 {width:338px!important;} +input.span-10, textarea.span-10 {width:378px!important;} +input.span-11, textarea.span-11 {width:418px!important;} +input.span-12, textarea.span-12 {width:458px!important;} +input.span-13, textarea.span-13 {width:498px!important;} +input.span-14, textarea.span-14 {width:538px!important;} +input.span-15, textarea.span-15 {width:578px!important;} +input.span-16, textarea.span-16 {width:618px!important;} +input.span-17, textarea.span-17 {width:658px!important;} +input.span-18, textarea.span-18 {width:698px!important;} +input.span-19, textarea.span-19 {width:738px!important;} +input.span-20, textarea.span-20 {width:778px!important;} +input.span-21, textarea.span-21 {width:818px!important;} +input.span-22, textarea.span-22 {width:858px!important;} +input.span-23, textarea.span-23 {width:898px!important;} +input.span-24, textarea.span-24 {width:938px!important;} +.append-1 {padding-right:40px;} +.append-2 {padding-right:80px;} +.append-3 {padding-right:120px;} +.append-4 {padding-right:160px;} +.append-5 {padding-right:200px;} +.append-6 {padding-right:240px;} +.append-7 {padding-right:280px;} +.append-8 {padding-right:320px;} +.append-9 {padding-right:360px;} +.append-10 {padding-right:400px;} +.append-11 {padding-right:440px;} +.append-12 {padding-right:480px;} +.append-13 {padding-right:520px;} +.append-14 {padding-right:560px;} +.append-15 {padding-right:600px;} +.append-16 {padding-right:640px;} +.append-17 {padding-right:680px;} +.append-18 {padding-right:720px;} +.append-19 {padding-right:760px;} +.append-20 {padding-right:800px;} +.append-21 {padding-right:840px;} +.append-22 {padding-right:880px;} +.append-23 {padding-right:920px;} +.prepend-1 {padding-left:40px;} +.prepend-2 {padding-left:80px;} +.prepend-3 {padding-left:120px;} +.prepend-4 {padding-left:160px;} +.prepend-5 {padding-left:200px;} +.prepend-6 {padding-left:240px;} +.prepend-7 {padding-left:280px;} +.prepend-8 {padding-left:320px;} +.prepend-9 {padding-left:360px;} +.prepend-10 {padding-left:400px;} +.prepend-11 {padding-left:440px;} +.prepend-12 {padding-left:480px;} +.prepend-13 {padding-left:520px;} +.prepend-14 {padding-left:560px;} +.prepend-15 {padding-left:600px;} +.prepend-16 {padding-left:640px;} +.prepend-17 {padding-left:680px;} +.prepend-18 {padding-left:720px;} +.prepend-19 {padding-left:760px;} +.prepend-20 {padding-left:800px;} +.prepend-21 {padding-left:840px;} +.prepend-22 {padding-left:880px;} +.prepend-23 {padding-left:920px;} +div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;} +div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;} +.pull-1 {margin-left:-40px;} +.pull-2 {margin-left:-80px;} +.pull-3 {margin-left:-120px;} +.pull-4 {margin-left:-160px;} +.pull-5 {margin-left:-200px;} +.pull-6 {margin-left:-240px;} +.pull-7 {margin-left:-280px;} +.pull-8 {margin-left:-320px;} +.pull-9 {margin-left:-360px;} +.pull-10 {margin-left:-400px;} +.pull-11 {margin-left:-440px;} +.pull-12 {margin-left:-480px;} +.pull-13 {margin-left:-520px;} +.pull-14 {margin-left:-560px;} +.pull-15 {margin-left:-600px;} +.pull-16 {margin-left:-640px;} +.pull-17 {margin-left:-680px;} +.pull-18 {margin-left:-720px;} +.pull-19 {margin-left:-760px;} +.pull-20 {margin-left:-800px;} +.pull-21 {margin-left:-840px;} +.pull-22 {margin-left:-880px;} +.pull-23 {margin-left:-920px;} +.pull-24 {margin-left:-960px;} +.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;} +.push-1 {margin:0 -40px 1.5em 40px;} +.push-2 {margin:0 -80px 1.5em 80px;} +.push-3 {margin:0 -120px 1.5em 120px;} +.push-4 {margin:0 -160px 1.5em 160px;} +.push-5 {margin:0 -200px 1.5em 200px;} +.push-6 {margin:0 -240px 1.5em 240px;} +.push-7 {margin:0 -280px 1.5em 280px;} +.push-8 {margin:0 -320px 1.5em 320px;} +.push-9 {margin:0 -360px 1.5em 360px;} +.push-10 {margin:0 -400px 1.5em 400px;} +.push-11 {margin:0 -440px 1.5em 440px;} +.push-12 {margin:0 -480px 1.5em 480px;} +.push-13 {margin:0 -520px 1.5em 520px;} +.push-14 {margin:0 -560px 1.5em 560px;} +.push-15 {margin:0 -600px 1.5em 600px;} +.push-16 {margin:0 -640px 1.5em 640px;} +.push-17 {margin:0 -680px 1.5em 680px;} +.push-18 {margin:0 -720px 1.5em 720px;} +.push-19 {margin:0 -760px 1.5em 760px;} +.push-20 {margin:0 -800px 1.5em 800px;} +.push-21 {margin:0 -840px 1.5em 840px;} +.push-22 {margin:0 -880px 1.5em 880px;} +.push-23 {margin:0 -920px 1.5em 920px;} +.push-24 {margin:0 -960px 1.5em 960px;} +.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;} +.prepend-top {margin-top:1.5em;} +.append-bottom {margin-bottom:1.5em;} +.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} +hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} +hr.space {background:#fff;color:#fff;visibility:hidden;} +.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} +.clearfix, .container {display:block;} +.clear {clear:both;} \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/src/forms.css b/External Source/QuincyKit/server/admin/blueprint/src/forms.css new file mode 100755 index 000000000..b49113407 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/src/forms.css @@ -0,0 +1,65 @@ +/* -------------------------------------------------------------- + + forms.css + * Sets up some default styling for forms + * Gives you classes to enhance your forms + + Usage: + * For text fields, use class .title or .text + * For inline forms, use .inline (even when using columns) + +-------------------------------------------------------------- */ + +label { font-weight: bold; } +fieldset { padding:1.4em; margin: 0 0 1.5em 0; border: 1px solid #ccc; } +legend { font-weight: bold; font-size:1.2em; } + + +/* Form fields +-------------------------------------------------------------- */ + +input[type=text], input[type=password], +input.text, input.title, +textarea, select { + background-color:#fff; + border:1px solid #bbb; +} +input[type=text]:focus, input[type=password]:focus, +input.text:focus, input.title:focus, +textarea:focus, select:focus { + border-color:#666; +} + +input[type=text], input[type=password], +input.text, input.title, +textarea, select { + margin:0.5em 0; +} + +input.text, +input.title { width: 300px; padding:5px; } +input.title { font-size:1.5em; } +textarea { width: 390px; height: 250px; padding:5px; } + +input[type=checkbox], input[type=radio], +input.checkbox, input.radio { + position:relative; top:.25em; +} + +form.inline { line-height:3; } +form.inline p { margin-bottom:0; } + + +/* Success, notice and error boxes +-------------------------------------------------------------- */ + +.error, +.notice, +.success { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd; } + +.error { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4; } +.notice { background: #FFF6BF; color: #514721; border-color: #FFD324; } +.success { background: #E6EFC2; color: #264409; border-color: #C6D880; } +.error a { color: #8a1f11; } +.notice a { color: #514721; } +.success a { color: #264409; } diff --git a/External Source/QuincyKit/server/admin/blueprint/src/grid.css b/External Source/QuincyKit/server/admin/blueprint/src/grid.css new file mode 100755 index 000000000..352e0e2a4 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/src/grid.css @@ -0,0 +1,281 @@ +/* -------------------------------------------------------------- + grid.css + * Sets up an easy-to-use grid of 24 columns. + + By default, the grid is 950px wide, with 24 columns + spanning 30px, and a 10px margin between columns. + + If you need fewer or more columns, namespaces or semantic + element names, use the compressor script (lib/compress.rb) + + Note: Changes made in this file will not be applied when + using the compressor: make changes in lib/blueprint/grid.css.rb +-------------------------------------------------------------- */ + +/* A container should group all your columns. */ +.container { + width: 950px; + margin: 0 auto; +} + +/* Use this class on any div.span / container to see the grid. */ +.showgrid { + background: url(src/grid.png); +} + + +/* Columns +-------------------------------------------------------------- */ + +/* Sets up basic grid floating and margin. */ +.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 { + float: left; + margin-right: 10px; +} + +/* The last column in a row needs this class. */ +.last, div.last { margin-right: 0; } + +/* Use these classes to set the width of a column. */ +.span-1 {width: 30px;} + +.span-2 {width: 70px;} +.span-3 {width: 110px;} +.span-4 {width: 150px;} +.span-5 {width: 190px;} +.span-6 {width: 230px;} +.span-7 {width: 270px;} +.span-8 {width: 310px;} +.span-9 {width: 350px;} +.span-10 {width: 390px;} +.span-11 {width: 430px;} +.span-12 {width: 470px;} +.span-13 {width: 510px;} +.span-14 {width: 550px;} +.span-15 {width: 590px;} +.span-16 {width: 630px;} +.span-17 {width: 670px;} +.span-18 {width: 710px;} +.span-19 {width: 750px;} +.span-20 {width: 790px;} +.span-21 {width: 830px;} +.span-22 {width: 870px;} +.span-23 {width: 910px;} +.span-24, div.span-24 { width:950px; margin-right:0; } + +/* Use these classes to set the width of an input. */ +input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 { + border-left-width: 1px!important; + border-right-width: 1px!important; + padding-left: 5px!important; + padding-right: 5px!important; +} + +input.span-1, textarea.span-1 { width: 18px!important; } +input.span-2, textarea.span-2 { width: 58px!important; } +input.span-3, textarea.span-3 { width: 98px!important; } +input.span-4, textarea.span-4 { width: 138px!important; } +input.span-5, textarea.span-5 { width: 178px!important; } +input.span-6, textarea.span-6 { width: 218px!important; } +input.span-7, textarea.span-7 { width: 258px!important; } +input.span-8, textarea.span-8 { width: 298px!important; } +input.span-9, textarea.span-9 { width: 338px!important; } +input.span-10, textarea.span-10 { width: 378px!important; } +input.span-11, textarea.span-11 { width: 418px!important; } +input.span-12, textarea.span-12 { width: 458px!important; } +input.span-13, textarea.span-13 { width: 498px!important; } +input.span-14, textarea.span-14 { width: 538px!important; } +input.span-15, textarea.span-15 { width: 578px!important; } +input.span-16, textarea.span-16 { width: 618px!important; } +input.span-17, textarea.span-17 { width: 658px!important; } +input.span-18, textarea.span-18 { width: 698px!important; } +input.span-19, textarea.span-19 { width: 738px!important; } +input.span-20, textarea.span-20 { width: 778px!important; } +input.span-21, textarea.span-21 { width: 818px!important; } +input.span-22, textarea.span-22 { width: 858px!important; } +input.span-23, textarea.span-23 { width: 898px!important; } +input.span-24, textarea.span-24 { width: 938px!important; } + +/* Add these to a column to append empty cols. */ + +.append-1 { padding-right: 40px;} +.append-2 { padding-right: 80px;} +.append-3 { padding-right: 120px;} +.append-4 { padding-right: 160px;} +.append-5 { padding-right: 200px;} +.append-6 { padding-right: 240px;} +.append-7 { padding-right: 280px;} +.append-8 { padding-right: 320px;} +.append-9 { padding-right: 360px;} +.append-10 { padding-right: 400px;} +.append-11 { padding-right: 440px;} +.append-12 { padding-right: 480px;} +.append-13 { padding-right: 520px;} +.append-14 { padding-right: 560px;} +.append-15 { padding-right: 600px;} +.append-16 { padding-right: 640px;} +.append-17 { padding-right: 680px;} +.append-18 { padding-right: 720px;} +.append-19 { padding-right: 760px;} +.append-20 { padding-right: 800px;} +.append-21 { padding-right: 840px;} +.append-22 { padding-right: 880px;} +.append-23 { padding-right: 920px;} + +/* Add these to a column to prepend empty cols. */ + +.prepend-1 { padding-left: 40px;} +.prepend-2 { padding-left: 80px;} +.prepend-3 { padding-left: 120px;} +.prepend-4 { padding-left: 160px;} +.prepend-5 { padding-left: 200px;} +.prepend-6 { padding-left: 240px;} +.prepend-7 { padding-left: 280px;} +.prepend-8 { padding-left: 320px;} +.prepend-9 { padding-left: 360px;} +.prepend-10 { padding-left: 400px;} +.prepend-11 { padding-left: 440px;} +.prepend-12 { padding-left: 480px;} +.prepend-13 { padding-left: 520px;} +.prepend-14 { padding-left: 560px;} +.prepend-15 { padding-left: 600px;} +.prepend-16 { padding-left: 640px;} +.prepend-17 { padding-left: 680px;} +.prepend-18 { padding-left: 720px;} +.prepend-19 { padding-left: 760px;} +.prepend-20 { padding-left: 800px;} +.prepend-21 { padding-left: 840px;} +.prepend-22 { padding-left: 880px;} +.prepend-23 { padding-left: 920px;} + + +/* Border on right hand side of a column. */ +div.border { + padding-right: 4px; + margin-right: 5px; + border-right: 1px solid #eee; +} + +/* Border with more whitespace, spans one column. */ +div.colborder { + padding-right: 24px; + margin-right: 25px; + border-right: 1px solid #eee; +} + + +/* Use these classes on an element to push it into the +next column, or to pull it into the previous column. */ + + +.pull-1 { margin-left: -40px; } +.pull-2 { margin-left: -80px; } +.pull-3 { margin-left: -120px; } +.pull-4 { margin-left: -160px; } +.pull-5 { margin-left: -200px; } +.pull-6 { margin-left: -240px; } +.pull-7 { margin-left: -280px; } +.pull-8 { margin-left: -320px; } +.pull-9 { margin-left: -360px; } +.pull-10 { margin-left: -400px; } +.pull-11 { margin-left: -440px; } +.pull-12 { margin-left: -480px; } +.pull-13 { margin-left: -520px; } +.pull-14 { margin-left: -560px; } +.pull-15 { margin-left: -600px; } +.pull-16 { margin-left: -640px; } +.pull-17 { margin-left: -680px; } +.pull-18 { margin-left: -720px; } +.pull-19 { margin-left: -760px; } +.pull-20 { margin-left: -800px; } +.pull-21 { margin-left: -840px; } +.pull-22 { margin-left: -880px; } +.pull-23 { margin-left: -920px; } +.pull-24 { margin-left: -960px; } + +.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float: left; position:relative;} + + +.push-1 { margin: 0 -40px 1.5em 40px; } +.push-2 { margin: 0 -80px 1.5em 80px; } +.push-3 { margin: 0 -120px 1.5em 120px; } +.push-4 { margin: 0 -160px 1.5em 160px; } +.push-5 { margin: 0 -200px 1.5em 200px; } +.push-6 { margin: 0 -240px 1.5em 240px; } +.push-7 { margin: 0 -280px 1.5em 280px; } +.push-8 { margin: 0 -320px 1.5em 320px; } +.push-9 { margin: 0 -360px 1.5em 360px; } +.push-10 { margin: 0 -400px 1.5em 400px; } +.push-11 { margin: 0 -440px 1.5em 440px; } +.push-12 { margin: 0 -480px 1.5em 480px; } +.push-13 { margin: 0 -520px 1.5em 520px; } +.push-14 { margin: 0 -560px 1.5em 560px; } +.push-15 { margin: 0 -600px 1.5em 600px; } +.push-16 { margin: 0 -640px 1.5em 640px; } +.push-17 { margin: 0 -680px 1.5em 680px; } +.push-18 { margin: 0 -720px 1.5em 720px; } +.push-19 { margin: 0 -760px 1.5em 760px; } +.push-20 { margin: 0 -800px 1.5em 800px; } +.push-21 { margin: 0 -840px 1.5em 840px; } +.push-22 { margin: 0 -880px 1.5em 880px; } +.push-23 { margin: 0 -920px 1.5em 920px; } +.push-24 { margin: 0 -960px 1.5em 960px; } + +.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float: right; position:relative;} + + +/* Misc classes and elements +-------------------------------------------------------------- */ + +/* In case you need to add a gutter above/below an element */ +.prepend-top { + margin-top:1.5em; +} +.append-bottom { + margin-bottom:1.5em; +} + +/* Use a .box to create a padded box inside a column. */ +.box { + padding: 1.5em; + margin-bottom: 1.5em; + background: #E5ECF9; +} + +/* Use this to create a horizontal ruler across a column. */ +hr { + background: #ddd; + color: #ddd; + clear: both; + float: none; + width: 100%; + height: .1em; + margin: 0 0 1.45em; + border: none; +} + +hr.space { + background: #fff; + color: #fff; + visibility: hidden; +} + + +/* Clearing floats without extra markup + Based on How To Clear Floats Without Structural Markup by PiE + [http://www.positioniseverything.net/easyclearing.html] */ + +.clearfix:after, .container:after { + content: "\0020"; + display: block; + height: 0; + clear: both; + visibility: hidden; + overflow:hidden; +} +.clearfix, .container {display: block;} + +/* Regular clearing + apply to column that should drop below previous ones. */ + +.clear { clear:both; } diff --git a/External Source/QuincyKit/server/admin/blueprint/src/grid.png b/External Source/QuincyKit/server/admin/blueprint/src/grid.png new file mode 100755 index 000000000..b7539f672 Binary files /dev/null and b/External Source/QuincyKit/server/admin/blueprint/src/grid.png differ diff --git a/External Source/QuincyKit/server/admin/blueprint/src/ie.css b/External Source/QuincyKit/server/admin/blueprint/src/ie.css new file mode 100755 index 000000000..214b87907 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/src/ie.css @@ -0,0 +1,76 @@ +/* -------------------------------------------------------------- + + ie.css + + Contains every hack for Internet Explorer, + so that our core files stay sweet and nimble. + +-------------------------------------------------------------- */ + +/* Make sure the layout is centered in IE5 */ +body { text-align: center; } +.container { text-align: left; } + +/* Fixes IE margin bugs */ +* html .column, * html div.span-1, * html div.span-2, +* html div.span-3, * html div.span-4, * html div.span-5, +* html div.span-6, * html div.span-7, * html div.span-8, +* html div.span-9, * html div.span-10, * html div.span-11, +* html div.span-12, * html div.span-13, * html div.span-14, +* html div.span-15, * html div.span-16, * html div.span-17, +* html div.span-18, * html div.span-19, * html div.span-20, +* html div.span-21, * html div.span-22, * html div.span-23, +* html div.span-24 { display:inline; overflow-x: hidden; } + + +/* Elements +-------------------------------------------------------------- */ + +/* Fixes incorrect styling of legend in IE6. */ +* html legend { margin:0px -8px 16px 0; padding:0; } + +/* Fixes wrong line-height on sup/sub in IE. */ +sup { vertical-align:text-top; } +sub { vertical-align:text-bottom; } + +/* Fixes IE7 missing wrapping of code elements. */ +html>body p code { *white-space: normal; } + +/* IE 6&7 has problems with setting proper
margins. */ +hr { margin:-8px auto 11px; } + +/* Explicitly set interpolation, allowing dynamically resized images to not look horrible */ +img { -ms-interpolation-mode:bicubic; } + +/* Clearing +-------------------------------------------------------------- */ + +/* Makes clearfix actually work in IE */ +.clearfix, .container { display:inline-block; } +* html .clearfix, +* html .container { height:1%; } + + +/* Forms +-------------------------------------------------------------- */ + +/* Fixes padding on fieldset */ +fieldset { padding-top:0; } + +/* Makes classic textareas in IE 6 resemble other browsers */ +textarea { overflow:auto; } + +/* Fixes rule that IE 6 ignores */ +input.text, input.title, textarea { background-color:#fff; border:1px solid #bbb; } +input.text:focus, input.title:focus { border-color:#666; } +input.text, input.title, textarea, select { margin:0.5em 0; } +input.checkbox, input.radio { position:relative; top:.25em; } + +/* Fixes alignment of inline form elements */ +form.inline div, form.inline p { vertical-align:middle; } +form.inline label { position:relative;top:-0.25em; } +form.inline input.checkbox, form.inline input.radio, +form.inline input.button, form.inline button { + margin:0.5em 0; +} +button, input.button { position:relative;top:0.25em; } \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/blueprint/src/print.css b/External Source/QuincyKit/server/admin/blueprint/src/print.css new file mode 100755 index 000000000..d30302944 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/src/print.css @@ -0,0 +1,85 @@ +/* -------------------------------------------------------------- + + print.css + * Gives you some sensible styles for printing pages. + * See Readme file in this directory for further instructions. + + Some additions you'll want to make, customized to your markup: + #header, #footer, #navigation { display:none; } + +-------------------------------------------------------------- */ + +body { + line-height: 1.5; + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + color:#000; + background: none; + font-size: 10pt; +} + + +/* Layout +-------------------------------------------------------------- */ + +.container { + background: none; +} + +hr { + background:#ccc; + color:#ccc; + width:100%; + height:2px; + margin:2em 0; + padding:0; + border:none; +} +hr.space { + background: #fff; + color: #fff; + visibility: hidden; +} + + +/* Text +-------------------------------------------------------------- */ + +h1,h2,h3,h4,h5,h6 { font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif; } +code { font:.9em "Courier New", Monaco, Courier, monospace; } + +a img { border:none; } +p img.top { margin-top: 0; } + +blockquote { + margin:1.5em; + padding:1em; + font-style:italic; + font-size:.9em; +} + +.small { font-size: .9em; } +.large { font-size: 1.1em; } +.quiet { color: #999; } +.hide { display:none; } + + +/* Links +-------------------------------------------------------------- */ + +a:link, a:visited { + background: transparent; + font-weight:700; + text-decoration: underline; +} + +a:link:after, a:visited:after { + content: " (" attr(href) ")"; + font-size: 90%; +} + +/* If you're having trouble printing relative links, uncomment and customize this: + (note: This is valid CSS3, but it still won't go through the W3C CSS Validator) */ + +/* a[href^="/"]:after { + content: " (http://www.yourdomain.com" attr(href) ") "; +} */ diff --git a/External Source/QuincyKit/server/admin/blueprint/src/reset.css b/External Source/QuincyKit/server/admin/blueprint/src/reset.css new file mode 100755 index 000000000..fc0788c8c --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/src/reset.css @@ -0,0 +1,38 @@ +/* -------------------------------------------------------------- + + reset.css + * Resets default browser CSS. + +-------------------------------------------------------------- */ + +html, body, div, span, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, code, +del, dfn, em, img, q, dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +body { + line-height: 1.5; +} + +/* Tables still need 'cellspacing="0"' in the markup. */ +table { border-collapse: separate; border-spacing: 0; } +caption, th, td { text-align: left; font-weight: normal; } +table, td, th { vertical-align: middle; } + +/* Remove possible quote marks (") from ,
. */ +blockquote:before, blockquote:after, q:before, q:after { content: ""; } +blockquote, q { quotes: "" ""; } + +/* Remove annoying border on linked images. */ +a img { border: none; } diff --git a/External Source/QuincyKit/server/admin/blueprint/src/typography.css b/External Source/QuincyKit/server/admin/blueprint/src/typography.css new file mode 100755 index 000000000..6cc099c67 --- /dev/null +++ b/External Source/QuincyKit/server/admin/blueprint/src/typography.css @@ -0,0 +1,106 @@ +/* -------------------------------------------------------------- + + typography.css + * Sets up some sensible default typography. + +-------------------------------------------------------------- */ + +/* Default font settings. + The font-size percentage is of 16px. (0.75 * 16px = 12px) */ +html { font-size:100.01%; } +body { + font-size: 75%; + color: #222; + background: #fff; + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; +} + + +/* Headings +-------------------------------------------------------------- */ + +h1,h2,h3,h4,h5,h6 { font-weight: normal; color: #111; } + +h1 { font-size: 3em; line-height: 1; margin-bottom: 0.5em; } +h2 { font-size: 2em; margin-bottom: 0.75em; } +h3 { font-size: 1.5em; line-height: 1; margin-bottom: 1em; } +h4 { font-size: 1.2em; line-height: 1.25; margin-bottom: 1.25em; } +h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.5em; } +h6 { font-size: 1em; font-weight: bold; } + +h1 img, h2 img, h3 img, +h4 img, h5 img, h6 img { + margin: 0; +} + + +/* Text elements +-------------------------------------------------------------- */ + +p { margin: 0 0 1.5em; } +p img.left { float: left; margin: 1.5em 1.5em 1.5em 0; padding: 0; } +p img.right { float: right; margin: 1.5em 0 1.5em 1.5em; } + +a:focus, +a:hover { color: #000; } +a { color: #009; text-decoration: underline; } + +blockquote { margin: 1.5em; color: #666; font-style: italic; } +strong { font-weight: bold; } +em,dfn { font-style: italic; } +dfn { font-weight: bold; } +sup, sub { line-height: 0; } + +abbr, +acronym { border-bottom: 1px dotted #666; } +address { margin: 0 0 1.5em; font-style: italic; } +del { color:#666; } + +pre { margin: 1.5em 0; white-space: pre; } +pre,code,tt { font: 1em 'andale mono', 'lucida console', monospace; line-height: 1.5; } + + +/* Lists +-------------------------------------------------------------- */ + +li ul, +li ol { margin: 0; } +ul, ol { margin: 0 1.5em 1.5em 0; padding-left: 3.333em; } + +ul { list-style-type: disc; } +ol { list-style-type: decimal; } + +dl { margin: 0 0 1.5em 0; } +dl dt { font-weight: bold; } +dd { margin-left: 1.5em;} + + +/* Tables +-------------------------------------------------------------- */ + +table { margin-bottom: 1.4em; width:100%; } +th { font-weight: bold; } +thead th { background: #c3d9ff; } +th,td,caption { padding: 4px 10px 4px 5px; } +tr.even td { background: #e5ecf9; } +tfoot { font-style: italic; } +caption { background: #eee; } + + +/* Misc classes +-------------------------------------------------------------- */ + +.small { font-size: .8em; margin-bottom: 1.875em; line-height: 1.875em; } +.large { font-size: 1.2em; line-height: 2.5em; margin-bottom: 1.25em; } +.hide { display: none; } + +.quiet { color: #666; } +.loud { color: #000; } +.highlight { background:#ff0; } +.added { background:#060; color: #fff; } +.removed { background:#900; color: #fff; } + +.first { margin-left:0; padding-left:0; } +.last { margin-right:0; padding-right:0; } +.top { margin-top:0; padding-top:0; } +.bottom { margin-bottom:0; padding-bottom:0; } diff --git a/External Source/QuincyKit/server/admin/common.inc b/External Source/QuincyKit/server/admin/common.inc new file mode 100644 index 000000000..51dde560d --- /dev/null +++ b/External Source/QuincyKit/server/admin/common.inc @@ -0,0 +1,266 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +// +// This part is responsible common used functions +// + +function show_header($title) +{ + global $admintitle; + + echo ''; + echo ''.$admintitle.' '.$title.''; + echo ''; + echo ''; + echo ''; + echo ""; + echo ""; + echo ""; + echo ""; +?> + + + + + + + + + + +
'; + echo '

'.$admintitle.'

'; +} + +function end_with_result($result) +{ + return ''.$result.''; +} + +function init_database() +{ + global $server, $loginsql, $passsql, $base; + + $GLOBALS['link'] = mysql_connect($server, $loginsql, $passsql) or die(end_with_result('No database connection')); + mysql_select_db($base) or die(end_with_result('No database connection')); +} + + +function parse_parameters($allowed_args) +{ + foreach(array_keys($_GET) as $k) { + $temp = ",$k,"; + if(strpos($allowed_args,$temp) !== false) { $GLOBALS[$k] = $_GET[$k]; } + } +} + +function parse_parameters_post($allowed_args) +{ + foreach(array_keys($_POST) as $k) { + $temp = ",$k,"; + if(strpos($allowed_args,$temp) !== false) { $GLOBALS[$k] = $_POST[$k]; } + } +} + + +function add_option($text, $value, $currentvalue) +{ + echo ''; +} + +function create_link($text, $link, $button, $variables) +{ + $result = ""; + $result .= ' 0) { + $result .= '&'; + } + $result .= $vars[$k].'='.$GLOBALS[$vars[$k]]; + } + } else { + if ($i > 0) { + $result .= '&'; + } + $result .= $vars[$k]; + } + $i++; + } + } + $result .= '"'; + + if ($button) + $result .= ' class="button"'; + $result .= '>'.$text.''; + + return $result; +} + +function show_search($text, $currenttype, $break = false, $style = "float: right;") +{ + global $bundleidentifier, $version; + + echo '
'; + echo ''; + if ($version != "") + echo ''; + echo ''; + if ($break) echo "
"; + echo '
'; + echo '
'; +} + +function currentPageURL() +{ + $pageURL = 'http'; + if (@$_SERVER["HTTPS"] == "on") {$pageURL .= "s";} + $pageURL .= "://"; + if ($_SERVER["SERVER_PORT"] != "80") { + $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; + } else { + $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]; + } + return $pageURL; +} + +function create_issue($bundleidentifier, $issuelink) +{ + global $dbapptable, $createIssueTitle; + + $query = "SELECT issuetrackerurl FROM ".$dbapptable." WHERE bundleidentifier = '".$bundleidentifier."'"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) + { + if ($row[0] != "") + { + $issuetrackerurl = $row[0]; + $issuetrackerurl = str_replace('%subject%', urlencode($createIssueTitle), $issuetrackerurl); + $issuetrackerurl = str_replace('%description%', urlencode('Crash Log: '.$issuelink), $issuetrackerurl); + return "New issue"; + } + } + } + + return ''; +} + + + +function stringEndsWith($haystack,$needle,$case=true) { + if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);} + return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0); +} + +function mapPlatform($device) +{ + $platform = $device; + + switch ($device) { + case "iPhone1,1": + $platform = "1G"; + break; + case "iPhone1,2": + $platform = "3G"; + break; + case "iPhone2,1": + $platform = "3GS"; + break; + case "iPhone3,1": + $platform = "4"; + break; + case "iPhone3,3": + $platform = "4 CDMA"; + break; + case "iPhone4,1": + $platform = "4S"; + break; + case "iPad1,1": + $platform = "iPad"; + break; + case "iPad2,1": + $platform = "iPad2 WiFi"; + break; + case "iPad2,2": + $platform = "iPad2 GSM"; + break; + case "iPad2,3": + $platform = "iPad2 CDMA"; + break; + case "iPod1,1": + $platform = "iPod1G"; + break; + case "iPod2,1": + $platform = "iPod2G"; + break; + case "iPod3,1": + $platform = "iPod3G"; + break; + case "iPod4,1": + $platform = "iPod4G"; + break; + case "AppleTV2,1": + $platform = "atv2G"; + break; + } + + if (stringEndsWith($platform, "86") || $platform == "x86_64") + $platform = "Simulator"; + + return $platform; +} + +?> diff --git a/External Source/QuincyKit/server/admin/crash_get.php b/External Source/QuincyKit/server/admin/crash_get.php new file mode 100755 index 000000000..4963ac6b0 --- /dev/null +++ b/External Source/QuincyKit/server/admin/crash_get.php @@ -0,0 +1,75 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde. + * 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. + */ + +// +// Download the crash log data in plain format +// +// This script is used by the remote symbolicate process to get the +// crash log data for a given crash id +// + +require_once('../config.php'); + +function end_with_result($result) +{ + return ''.$result.''; +} + +$allowed_args = ',id,'; + +$link = mysql_connect($server, $loginsql, $passsql) + or die(end_with_result('No database connection')); +mysql_select_db($base) or die(end_with_result('No database connection')); + +foreach(array_keys($_GET) as $k) { + $temp = ",$k,"; + if(strpos($allowed_args,$temp) !== false) { $$k = $_GET[$k]; } +} + +if (!isset($id)) $id = ""; + +if ($id == "") die(end_with_result('Wrong parameters')); + +$query = "SELECT log FROM ".$dbcrashtable." WHERE id = ".$id; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$dbversiontable)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + while ($row = mysql_fetch_row($result)) + { + echo $row[0]; + } + mysql_free_result($result); +} + +mysql_close($link); + + +?> \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/crash_update.php b/External Source/QuincyKit/server/admin/crash_update.php new file mode 100755 index 000000000..491209167 --- /dev/null +++ b/External Source/QuincyKit/server/admin/crash_update.php @@ -0,0 +1,81 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde. + * 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. + */ + +// +// Update crash log data for a crash +// +// This script is used by the remote symbolicate process to update +// the database with the symbolicated crash log data for a given +// crash id +// + +require_once('../config.php'); + + +$allowed_args = ',id,log,'; + +$link = mysql_connect($server, $loginsql, $passsql) + or die('error'); +mysql_select_db($base) or die('error'); + +foreach(array_keys($_POST) as $k) { + $temp = ",$k,"; + if(strpos($allowed_args,$temp) !== false) { $$k = $_POST[$k]; } +} + +if (!isset($id)) $id = ""; +if (!isset($log)) $log = ""; + +echo $id." ".$log."\n"; + +if ($id == "" || $log == "") { + mysql_close($link); + die('error'); +} + +$query = "UPDATE ".$dbcrashtable." SET log = '".mysql_real_escape_string($log)."' WHERE id = ".$id; +$result = mysql_query($query) or die('Error in SQL '.$dbcrashtable); + +if ($result) { + $query = "UPDATE ".$dbsymbolicatetable." SET done = 1 WHERE crashid = ".$id; + $result = mysql_query($query) or die('Error in SQL '.$dbsymbolicatetable); + + if ($result) + echo "success"; + else + echo "error"; +} else { + echo "error"; +} + +mysql_close($link); + + +?> \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/crashes.php b/External Source/QuincyKit/server/admin/crashes.php new file mode 100644 index 000000000..b0fade645 --- /dev/null +++ b/External Source/QuincyKit/server/admin/crashes.php @@ -0,0 +1,321 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +// +// Shows a list of crashes for a given crash group +// +// Shows all crashes for a given crash group. You can download each crash +// from this view, or see all the relevant information about this crash +// that is available +// + +require_once('../config.php'); +require_once('common.inc'); + +init_database(); +parse_parameters(',groupid,bundleidentifier,version,search,type,'); + +if (!isset($all)) $all = false; +if (!isset($groupid)) $groupid = ""; +if (!isset($bundleidentifier)) $bundleidentifier = ""; +if (!isset($version)) $version = ""; +if (!isset($search)) $search = ""; +if (!isset($type)) $type = ""; + +if ($bundleidentifier == "" && ($version == "" || $type = "")) die(end_with_result('Wrong parameters')); + +$whereclause = ""; +$pagelink = ""; + +if ($search != "" && $type != "") { + $pagelink = '?bundleidentifier='.$bundleidentifier.'&search='.$search.'&type='.$type; + $whereclause = " WHERE bundleidentifier = '".$bundleidentifier."'"; + if ($type == SEARCH_TYPE_ID) + $whereclause .= " AND id = '".$search."'"; + else if ($type == SEARCH_TYPE_DESCRIPTION) + $whereclause .= " AND description like '%".$search."%'"; + else if ($type == SEARCH_TYPE_CRASHLOG) + $whereclause .= " AND log like '%".$search."%'"; + else if ($type == SEARCH_TYPE_CONTACT) + $whereclause .= " AND contact like '%".$search."%'"; + if ($version != "") + $whereclause .= " AND version = '".$version."'"; +} else if ($groupid == "") { + $pagelink = '?bundleidentifier='.$bundleidentifier.'&version='.$version; + $whereclause = " WHERE bundleidentifier = '".$bundleidentifier."' AND version = '".$version."' AND groupid = 0"; +} else { + $pagelink = '?bundleidentifier='.$bundleidentifier.'&version='.$version.'&groupid='.$groupid; + $whereclause = " WHERE groupid = ".$groupid; +} + +show_header('- List'); + +$cols = ''; + +echo '

'; + +if (!$acceptallapps) + echo 'Apps - '; + +echo create_link($bundleidentifier, 'app_versions.php', false, 'bundleidentifier').' - '; + +if ($version != "") + echo create_link('Version '.$version, 'groups.php', false, 'bundleidentifier,version').' - '; + +if ($groupid != "") { + $query = "SELECT pattern FROM ".$dbgrouptable." WHERE id = ".$groupid; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + + $numrows = mysql_num_rows($result); + if ($numrows == 1) { + $row = mysql_fetch_row($result); + $title = $row[0]; + if (strlen($title) > 20) { + $title = substr($title,0,20)."..."; + } + echo create_link($title, 'crashes.php', false, $pagelink).'

'; + } else { + echo create_link('Crashes', 'crashes.php', false, $pagelink).''; + } + mysql_free_result($result); + +} else { + echo create_link('Crashes', 'crashes.php', false, $pagelink).''; +} + +if ($search != "" || $type != "") + show_search($search, $type); + +$osticks = ""; +$osvalues = ""; + +$crashestime = false; +$crashvaluesarray = array(); +$crashvalues = ""; + +if ($groupid !='') { + $cols2 = ''; + + $query = "SELECT fix, description FROM ".$dbgrouptable." WHERE id = '".$groupid."'"; + $result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + + $numrows = mysql_num_rows($result); + if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) { + $fix = $row[0]; + $description = $row[1]; + + $cols2 = ''; + echo ''.$cols2.''; + + echo ""; + echo ""; + echo "
Platform OverviewCrashes over timeSystem OS Overview
"; + + // get the amount of crashes per system version + $crashestime = true; + + $osticks = ""; + $osvalues = ""; + $query2 = "SELECT systemversion, COUNT(systemversion) FROM ".$dbcrashtable.$whereclause." group by systemversion order by systemversion desc"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) { + // get the status + while ($row2 = mysql_fetch_row($result2)) { + if ($osticks != "") $osticks = $osticks.", "; + $osticks .= "'".$row2[0]."'"; + if ($osvalues != "") $osvalues = $osvalues.", "; + $osvalues .= $row2[1]; + } + } + mysql_free_result($result2); + + // get the amount of crashes per system version + $crashestime = true; + + $platformticks = ""; + $platformvalues = ""; + $query2 = "SELECT platform, COUNT(platform) FROM ".$dbcrashtable.$whereclause." AND platform != \"\" group by platform order by platform desc"; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) { + // get the status + while ($row2 = mysql_fetch_row($result2)) { + if ($platformticks != "") $platformticks = $platformticks.", "; + $platformticks .= "'".mapPlatform($row2[0])."'"; + if ($platformvalues != "") $platformvalues = $platformvalues.", "; + $platformvalues .= $row2[1]; + } + } + mysql_free_result($result2); + + + + $cols2 = ''; + echo ''.$cols2.''; + echo ''; + + // get the amount of crashes + $amount = 0; + $query2 = "SELECT count(*) FROM ".$dbcrashtable.$whereclause; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); + $numrows2 = mysql_num_rows($result2); + if ($numrows2 == 1) { + $row2 = mysql_fetch_row($result2); + $amount = $row2[0]; + } + mysql_free_result($result2); + } + } + mysql_free_result($result); +} + +echo '
Group Details
'; + + echo '
'; + echo 'Description:'; + echo 'Assigned Fix Version:'; + echo "Update"; + echo create_issue($bundleidentifier, currentPageURL()); + echo '
'.$cols; +echo ""; +echo ''; + +// get all crashes +$query = "SELECT userid, contact, systemversion, timestamp, id, jailbreak, platform FROM ".$dbcrashtable.$whereclause." ORDER BY systemversion desc, timestamp desc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) { + $userid = $row[0]; + $contact = $row[1]; + $systemversion = $row[2]; + $timestamp = $row[3]; + $crashid = $row[4]; + $jailbreak = $row[5]; + $platform = $row[6]; + + $todo = 2; + $query2 = "SELECT done FROM ".$dbsymbolicatetable." WHERE crashid = ".$crashid; + $result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query)); + + $numrows2 = mysql_num_rows($result2); + if ($numrows2 > 0) + { + $row2 = mysql_fetch_row($result2); + $todo = $row2[0]; + } + mysql_free_result($result2); + + $now = time(); + + if ($timestamp != "" && ($timestampvalue = strtotime($timestamp)) !== false) + { + $timeindex = substr($timestamp, 0, 10); + + if ($now - $timestampvalue < 60*24*24) + $timestamp = "".$timestamp.""; + else if ($now - $timestampvalue < 60*24*24*2) + $timestamp = "".$timestamp.""; + else if ($now - $timestampvalue < 60*24*24*3) + $timestamp = "".$timestamp.""; + else + $timestamp = "".$timestamp.""; + + // add the value to the chart stuff + + if (!array_key_exists($timeindex, $crashvaluesarray)) { + $crashvaluesarray[$timeindex] = 0; + } + $crashvaluesarray[$timeindex]++; + } + + echo ""; + echo ""; + echo ""; + + echo ""; + } + + mysql_free_result($result); +} else { + echo ''; +} +echo '
SystemTimestampUser / ContactAction
".$systemversion; + if ($platform != "") echo "
".mapPlatform($platform); + if ($jailbreak == 1) echo "
Jailbroken"; + echo "
".$timestamp."".$userid."
".$contact."
"; + echo "View"; + + echo "Download "; + echo ""; + if ($todo == 0) + echo "Symbolicating..."; + else { + echo "Symbolicate"; + if ($todo != 2) + echo " again"; + echo ""; + } + + echo ""; + + echo " Delete
No data found
'; + +echo "".$cols; +echo ""; +echo "
DescriptionLog
"; + +mysql_close($link); + +?> + + + diff --git a/External Source/QuincyKit/server/admin/css/jquery.jqplot.css b/External Source/QuincyKit/server/admin/css/jquery.jqplot.css new file mode 100644 index 000000000..8c52270e8 --- /dev/null +++ b/External Source/QuincyKit/server/admin/css/jquery.jqplot.css @@ -0,0 +1,212 @@ +/*rules for the plot target div. These will be cascaded down to all plot elements according to css rules*/ +.jqplot-target { + position: relative; + color: #666666; + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 1em; +/* height: 300px; + width: 400px;*/ +} + +/*rules applied to all axes*/ +.jqplot-axis { + font-size: 0.75em; +} + +.jqplot-xaxis { + margin-top: 10px; +} + +.jqplot-x2axis { + margin-bottom: 10px; +} + +.jqplot-yaxis { + margin-right: 10px; +} + +.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis { + margin-left: 10px; + margin-right: 10px; +} + +/*rules applied to all axis tick divs*/ +.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { + position: absolute; +} + + +.jqplot-xaxis-tick { + top: 0px; + /* initial position untill tick is drawn in proper place */ + left: 15px; +/* padding-top: 10px;*/ + vertical-align: top; +} + +.jqplot-x2axis-tick { + bottom: 0px; + /* initial position untill tick is drawn in proper place */ + left: 15px; +/* padding-bottom: 10px;*/ + vertical-align: bottom; +} + +.jqplot-yaxis-tick { + right: 0px; + /* initial position untill tick is drawn in proper place */ + top: 15px; +/* padding-right: 10px;*/ + text-align: right; +} + +.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { + left: 0px; + /* initial position untill tick is drawn in proper place */ + top: 15px; +/* padding-left: 10px;*/ +/* padding-right: 15px;*/ + text-align: left; +} + +.jqplot-meterGauge-tick { + font-size: 0.75em; + color: #999999; +} + +.jqplot-meterGauge-label { + font-size: 1em; + color: #999999; +} +.jqplot-xaxis-label { + margin-top: 10px; + font-size: 11pt; + position: absolute; +} + +.jqplot-x2axis-label { + margin-bottom: 10px; + font-size: 11pt; + position: absolute; +} + +.jqplot-yaxis-label { + margin-right: 10px; +/* text-align: center;*/ + font-size: 11pt; + position: absolute; +} + +.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label { +/* text-align: center;*/ + font-size: 11pt; + position: absolute; +} + +table.jqplot-table-legend { + margin-top: 12px; + margin-bottom: 12px; + margin-left: 12px; + margin-right: 12px; +} + +table.jqplot-table-legend, table.jqplot-cursor-legend { + background-color: rgba(255,255,255,0.6); + border: 1px solid #cccccc; + position: absolute; + font-size: 0.75em; +} + +td.jqplot-table-legend { + vertical-align:middle; +} + +td.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active { + cursor: pointer; +} + +td.jqplot-table-legend > div { + border: 1px solid #cccccc; + padding:1px; +} + +div.jqplot-table-legend-swatch { + width:0px; + height:0px; + border-top-width: 5px; + border-bottom-width: 5px; + border-left-width: 6px; + border-right-width: 6px; + border-top-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-right-style: solid; +} + +.jqplot-title { + top: 0px; + left: 0px; + padding-bottom: 0.5em; + font-size: 1.2em; +} + +table.jqplot-cursor-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; +} + + +.jqplot-cursor-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208,208,208,0.5); + padding: 1px; +} + +.jqplot-highlighter-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208,208,208,0.5); + padding: 1px; +} + +.jqplot-point-label { + font-size: 0.75em; + z-index: 2; +} + +td.jqplot-cursor-legend-swatch { +vertical-align:middle; +text-align:center; +} + +div.jqplot-cursor-legend-swatch { +width:1.2em; +height:0.7em; +} + +.jqplot-error { +/* Styles added to the plot target container when there is an error go here.*/ + text-align: center; +} + +.jqplot-error-message { +/* Styling of the custom error message div goes here.*/ + position: relative; + top: 46%; + display: inline-block; +} + +div.jqplot-bubble-label { + font-size: 0.8em; +/* background: rgba(90%, 90%, 90%, 0.15);*/ + padding-left: 2px; + padding-right: 2px; + color: rgb(20%, 20%, 20%); +} + +div.jqplot-bubble-label.jqplot-bubble-label-highlight { + background: rgba(90%, 90%, 90%, 0.7); +} \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/css/layout.css b/External Source/QuincyKit/server/admin/css/layout.css new file mode 100644 index 000000000..3021f6537 --- /dev/null +++ b/External Source/QuincyKit/server/admin/css/layout.css @@ -0,0 +1,80 @@ +html, body { + font-family: 'helvetica neue', helvetica, arial, sans, sans-serif; +} + +a { + color: #ff4c7b; + text-decoration: none; +} + +a:hover { + color: #128ab2; + text-decoration: underline; +} + +td.message { + color: #990000; + text-decoration: none; + font-size:90%; +} + +td { + vertical-align: top; +} + +table, td, th { + border: 1px solid #ddd; +} + +table, td { + border-top: 0; +} + +table, form { + margin: 0; +} + +th { + background: #ddd; +} + +a.redButton:hover { + background-color: #ff0000!important; + color: white!important; +} + +a.redButton { + background-color: #cc0000!important; + color: white!important; +} + +textarea.description { + width:250px; + height:70px; + padding:5px; + font-size:90%; + color:#000; + background:#fff; + font-family:"Helvetica Neue", Arial, Helvetica, sans-serif; +} +div.short { + width:200px; + height:300px; + font-size:90%; + color:#000; + background:#fff; + font-family:"Helvetica Neue", Arial, Helvetica, sans-serif; + overflow: auto; + white-space:nowrap; +} +div.log { + width:710px; + height:300px; + font-size:90%; + color:#000; + border: 1px; + background:#fff; + font-family:"Courier New", Arial, Helvetica, sans-serif; + overflow: auto; + white-space:nowrap; +} diff --git a/External Source/QuincyKit/server/admin/css/style.css b/External Source/QuincyKit/server/admin/css/style.css new file mode 100644 index 000000000..ed028b5b8 --- /dev/null +++ b/External Source/QuincyKit/server/admin/css/style.css @@ -0,0 +1,42 @@ +@charset "UTF-8"; +/* CSS Document */ + +table { + border: solid 1px #D5D5D5; + border-collapse: collapse; + width:100%; +} + +table td { + border:1px solid #D5D5D5; + font-size:12px; + padding:7px 5px; +} + +table th { +/* background-color:#EEE; */ + border-right:1px solid #D5D5D5; + font-size:13.5px; + line-height:120%; + font-weight:bold; + padding:8px 5px; + text-align:left; +} +.ui-resizable { + position:relative; +} +.ui-resizable-handle { + display:block; + font-size:0.1px; + position:absolute; + z-index:99999; +} + +.ui-resizable-s { + background-color:#EEE; + border-top:1px solid #CCCCCC; + bottom:-5px; + cursor:s-resize; + height:14px; + left:0;width:100%; +} diff --git a/External Source/QuincyKit/server/admin/download.php b/External Source/QuincyKit/server/admin/download.php new file mode 100755 index 000000000..a0ba91e36 --- /dev/null +++ b/External Source/QuincyKit/server/admin/download.php @@ -0,0 +1,93 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +// +// Download a crash +// +// This script downloads a given crash to a local file +// + +require_once('../config.php'); + +function end_with_result($result) +{ + return ''.$result.''; +} + +$allowed_args = ',groupid,crashid,'; + +$link = mysql_connect($server, $loginsql, $passsql) + or die(end_with_result('No database connection')); +mysql_select_db($base) or die(end_with_result('No database connection')); + +foreach(array_keys($_GET) as $k) { + $temp = ",$k,"; + if(strpos($allowed_args,$temp) !== false) { $$k = $_GET[$k]; } +} + +if (!isset($groupid)) $groupid = ""; +if (!isset($crashid)) $crashid = ""; + +if ($groupid == "" && $crashid == "") die(end_with_result('Wrong parameters')); + +$query = ""; +if ($groupid != "") { + $query = "SELECT userid, contact, systemversion, description, log, timestamp FROM ".$dbcrashtable." WHERE groupid = '".$groupid."' ORDER BY systemversion desc, timestamp desc LIMIT 1"; +} else { + $query = "SELECT userid, contact, systemversion, description, log, timestamp FROM ".$dbcrashtable." WHERE id = '".$crashid."' ORDER BY systemversion desc, timestamp desc LIMIT 1"; +} +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + $row = mysql_fetch_row($result); + $userid = $row[0]; + $contact = $row[1]; + $systemversion = $row[2]; + $description = $row[3]; + $log = $row[4]; + $timestamp = $row[5]; + + // We'll be outputting a text file + header('Content-type: application/text'); + + // It will be called abc.txt + header('Content-Disposition: attachment; filename="'.$timestamp.'.crash"'); + echo $log; + + mysql_free_result($result); +} else { + echo 'Nothing found!'; +} + +mysql_close($link); + +?> diff --git a/External Source/QuincyKit/server/admin/groups.php b/External Source/QuincyKit/server/admin/groups.php new file mode 100755 index 000000000..111b8170f --- /dev/null +++ b/External Source/QuincyKit/server/admin/groups.php @@ -0,0 +1,253 @@ + + * + * Copyright (c) 2009-2011 Andreas Linde & Kent Sutherland. + * 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. + */ + +// +// This script shows all crash groups for a version +// +// This script shows a list of all crash groups of a version of an application, +// the amount of crash logs assigned to this group and the assigned bugfix version +// You can edit the bugfix version, if this version is not added yet, it will be added +// automatically to the version list. You can also assign a short description for +// this crash group or download the latest crash log data for this group directly. +// All crashes that weren't assigned to a group, will be shown in the list with in one +// combined entry too +// + +require_once('../config.php'); +require_once('common.inc'); + +init_database(); +parse_parameters(',bundleidentifier,version,'); + +if (!isset($bundleidentifier)) $bundleidentifier = ""; +if (!isset($version)) $version = ""; + +if ($bundleidentifier == "") die(end_with_result('Wrong parameters')); +if ($version == "") die(end_with_result('Wrong parameters')); + +show_header('- Crash Patterns'); + +echo '

'; +if (!$acceptallapps) + echo 'Apps - '; + +echo create_link($bundleidentifier, 'app_versions.php', false, 'bundleidentifier').' - '.create_link('Version '.$version, 'groups.php', false, 'bundleidentifier,version').'

'; + +$osticks = ""; +$osvalues = ""; + +$crashvaluesarray = array(); +$crashvalues = ""; + + +// get the amount of crashes over time + +$query = "SELECT timestamp FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' AND version = '".$version."' ORDER BY timestamp desc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + while ($row = mysql_fetch_row($result)) { + $timestamp = $row[0]; + + if ($timestamp != "" && ($timestampvalue = strtotime($timestamp)) !== false) + { + $timeindex = substr($timestamp, 0, 10); + + if (!array_key_exists($timeindex, $crashvaluesarray)) { + $crashvaluesarray[$timeindex] = 0; + } + $crashvaluesarray[$timeindex]++; + } + } +} +mysql_free_result($result); + + +$cols2 = ''; +echo ''.$cols2.''; + +echo ""; +echo ""; +echo ""; + +// get the amount of crashes per system version +$crashestime = true; + +$osticks = ""; +$osvalues = ""; +$whereclause = ""; + +$query2 = "SELECT systemversion, COUNT(systemversion) FROM ".$dbcrashtable.$whereclause." WHERE bundleidentifier = '".$bundleidentifier."' AND version = '".$version."' group by systemversion order by systemversion desc"; +$result2 = mysql_query($query2) or die(end_with_result('Error in SQL '.$query2)); +$numrows2 = mysql_num_rows($result2); +if ($numrows2 > 0) { + // get the status + while ($row2 = mysql_fetch_row($result2)) { + if ($osticks != "") $osticks = $osticks.", "; + $osticks .= "'".$row2[0]."'"; + if ($osvalues != "") $osvalues = $osvalues.", "; + $osvalues .= $row2[1]; + } +} +mysql_free_result($result2); + +// get the amount of crashes per system version +$crashestime = true; + +$platformticks = ""; +$platformvalues = ""; +$query = "SELECT platform, COUNT(platform) FROM ".$dbcrashtable." WHERE bundleidentifier = '".$bundleidentifier."' AND version = '".$version."' AND platform != \"\" group by platform order by platform desc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) { + if ($platformticks != "") $platformticks = $platformticks.", "; + $platformticks .= "'".mapPlatform($row[0])."'"; + if ($platformvalues != "") $platformvalues = $platformvalues.", "; + $platformvalues .= $row[1]; + } +} +mysql_free_result($result); +echo '
Platform OverviewCrashes over timeSystem OS Overview
'; + + +// START Group Deta +$cols2 = ''; +echo ''.$cols2.''; +echo '
Group Details
'; + +show_search("", -1, true, ""); + +echo " Delete All"; + +echo '
'; +// END Group Details + + +// START Group Listing +$cols = ''; + +echo ''.$cols; +echo ""; +echo '
PatternAmountLast UpdateAssigned Fix VersionDescriptionActions
'; + +echo '
'; + +// get all groups +$query = "SELECT fix, pattern, amount, id, description, latesttimestamp FROM ".$dbgrouptable." WHERE bundleidentifier = '".$bundleidentifier."' AND affected = '".$version."' ORDER BY fix desc, amount desc, pattern asc"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$query)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + // get the status + while ($row = mysql_fetch_row($result)) + { + $fix = $row[0]; + $pattern = $row[1]; + $amount = $row[2]; + $groupid = $row[3]; + $description = $row[4]; + $lastupdate = $row[5]; + + if ($notify_amount_group > 1 && $amount >= $notify_amount_group) + { + $amount = "".$amount.""; + } + + echo "
"; + echo ''.$cols; + $patterntitle = str_replace("%","\n",$pattern); + if (strlen($patterntitle) > 54) { + $patterntitle = substr($patterntitle,0,50)."..."; + } + + echo ""; + echo '
".$patterntitle."".$amount.""; + + if ($lastupdate != 0) { + $timestring = date("Y-m-d H:i:s", $lastupdate); + if (time() - $lastupdate < 60*24*24) + echo "".$timestring.""; + else if (time() - $lastupdate < 60*24*24*2) + echo "".$timestring.""; + else if (time() - $lastupdate < 60*24*24*3) + echo "".$timestring.""; + else + echo "".$timestring.""; + } else { + echo "-"; + } + + echo ''; + echo "Update "; + echo "Download "; + $issuelink = currentPageURL(); + $issuelink = substr($issuelink, 0, strrpos($issuelink, "/")+1); + echo create_issue($bundleidentifier, $issuelink.'crashes.php?groupid='.$groupid.'&bundleidentifier='.$bundleidentifier.'&version='.$version); + + echo " Delete
'; + echo '
'; + } + + mysql_free_result($result); +} + +// get all bugs not assigned to groups +$query = "SELECT count(*) FROM ".$dbcrashtable." WHERE groupid = 0 and bundleidentifier = '".$bundleidentifier."' AND version = '".$version."'"; +$result = mysql_query($query) or die(end_with_result('Error in SQL '.$dbcrashtable)); + +$numrows = mysql_num_rows($result); +if ($numrows > 0) { + $row = mysql_fetch_row($result); + $amount = $row[0]; + if ($amount > 0) + { + echo ''.$cols; + echo ''; + echo ''; + echo ""; + echo '
Ungrouped'.$amount.'Re-Group"; + echo "Delete
'; + } + mysql_free_result($result); +} + +mysql_close($link); + +?> +
+ + + \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/htaccess.txt b/External Source/QuincyKit/server/admin/htaccess.txt new file mode 100644 index 000000000..82cdb81d5 --- /dev/null +++ b/External Source/QuincyKit/server/admin/htaccess.txt @@ -0,0 +1,8 @@ +#Rename this file to .htaccess to password protect your admin forlder +#Create the .htpasswd using the htpasswd utility on your server + + +AuthUserFile /full/path/to/.htpasswd +AuthType Basic +AuthName "My Secret Folder" +Require valid-user diff --git a/External Source/QuincyKit/server/admin/index.html b/External Source/QuincyKit/server/admin/index.html new file mode 100644 index 000000000..46e6ab638 --- /dev/null +++ b/External Source/QuincyKit/server/admin/index.html @@ -0,0 +1,8 @@ + + + + + +Redirecting... + + \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/jqplot.php b/External Source/QuincyKit/server/admin/jqplot.php new file mode 100644 index 000000000..6fffeaeb1 --- /dev/null +++ b/External Source/QuincyKit/server/admin/jqplot.php @@ -0,0 +1,85 @@ + $.jqplot.config.enablePlugins = true; + + line1 = []; + plot1 = $.jqplot('platformdiv', [line1], { + seriesDefaults: { + renderer:$.jqplot.BarRenderer + }, + axesDefaults: { + tickRenderer: $.jqplot.CanvasAxisTickRenderer, + tickOptions: { fontSize: '9px'} + }, + axes:{ + xaxis:{ + renderer:$.jqplot.CategoryAxisRenderer, + ticks:[], + tickOptions: { angle: -30} + }, + yaxis:{ + min: 0, + tickOptions:{formatString:'%.0f'} + } + }, + highlighter: {show: false} + }); + 0) { + foreach ($crashvaluesarray as $key => $value) { + if ($crashvalues != "") $crashvalues = $crashvalues.", "; + $crashvalues .= "['".$key."', ".$value."]"; + } +?> + line1 = []; + plot1 = $.jqplot('crashdiv', [line1], { + seriesDefaults: {showMarker:false}, + series:[ + {pointLabels:{ + show: false + }}], + axes:{ + xaxis:{ + renderer:$.jqplot.DateAxisRenderer, + rendererOptions:{tickRenderer:$.jqplot.CanvasAxisTickRenderer}, + tickOptions:{formatString:'%m/%d',fontSize: '9px' } + }, + yaxis:{ + min: 0, + tickOptions:{formatString:'%.0f'} + } + }, + highlighter: {show: false} + }); + + line1 = []; + plot1 = $.jqplot('osdiv', [line1], { + seriesDefaults: { + renderer:$.jqplot.BarRenderer + }, + axesDefaults: { + tickRenderer: $.jqplot.CanvasAxisTickRenderer, + tickOptions: { fontSize: '9px'} + }, + axes:{ + xaxis:{ + renderer:$.jqplot.CategoryAxisRenderer, + ticks:[], + tickOptions: { angle: -30} + }, + yaxis:{ + min: 0, + tickOptions:{formatString:'%.0f'} + } + }, + highlighter: {show: false} + }); + \ No newline at end of file diff --git a/External Source/QuincyKit/server/admin/js/excanvas.min.js b/External Source/QuincyKit/server/admin/js/excanvas.min.js new file mode 100644 index 000000000..308b1be5a --- /dev/null +++ b/External Source/QuincyKit/server/admin/js/excanvas.min.js @@ -0,0 +1,35 @@ +document.createElement("canvas").getContext||function(){function Z(){return this.context_||(this.context_=new C(this))}function $(a,b){var c=P.call(arguments,2);return function(){return a.apply(b,c.concat(P.call(arguments)))}}function Q(a){return String(a).replace(/&/g,"&").replace(/"/g,""")}function R(a,b,c){a.namespaces[b]||a.namespaces.add(b,c,"#default#VML")}function S(a){R(a,"g_vml_","urn:schemas-microsoft-com:vml");R(a,"g_o_","urn:schemas-microsoft-com:office:office");if(!a.styleSheets.ex_canvas_){a= +a.createStyleSheet();a.owningElement.id="ex_canvas_";a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}function aa(a){var b=a.srcElement;switch(a.propertyName){case "width":b.getContext().clearRect();b.style.width=b.attributes.width.nodeValue+"px";b.firstChild.style.width=b.clientWidth+"px";break;case "height":b.getContext().clearRect();b.style.height=b.attributes.height.nodeValue+"px";b.firstChild.style.height=b.clientHeight+"px";break}}function ba(a){a= +a.srcElement;if(a.firstChild){a.firstChild.style.width=a.clientWidth+"px";a.firstChild.style.height=a.clientHeight+"px"}}function D(){return[[1,0,0],[0,1,0],[0,0,1]]}function u(a,b){for(var c=D(),d=0;d<3;d++)for(var e=0;e<3;e++){for(var f=0,h=0;h<3;h++)f+=a[d][h]*b[h][e];c[d][e]=f}return c}function T(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX; +b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.globalAlpha=a.globalAlpha;b.font=a.font;b.textAlign=a.textAlign;b.textBaseline=a.textBaseline;b.arcScaleX_=a.arcScaleX_;b.arcScaleY_=a.arcScaleY_;b.lineScale_=a.lineScale_}function U(a){var b=a.indexOf("(",3),c=a.indexOf(")",b+1);b=a.substring(b+1,c).split(",");if(b.length!=4||a.charAt(3)!="a")b[3]=1;return b}function E(a){return parseFloat(a)/100}function F(a,b,c){return Math.min(c,Math.max(b,a))}function ca(a){var b,c;c=parseFloat(a[0])/ +360%360;c<0&&c++;b=F(E(a[1]),0,1);a=F(E(a[2]),0,1);if(b==0)b=a=c=a;else{var d=a<0.5?a*(1+b):a+b-a*b,e=2*a-d;b=G(e,d,c+1/3);a=G(e,d,c);c=G(e,d,c-1/3)}return"#"+v[Math.floor(b*255)]+v[Math.floor(a*255)]+v[Math.floor(c*255)]}function G(a,b,c){c<0&&c++;c>1&&c--;return 6*c<1?a+(b-a)*6*c:2*c<1?b:3*c<2?a+(b-a)*(2/3-c)*6:a}function H(a){if(a in I)return I[a];var b,c=1;a=String(a);if(a.charAt(0)=="#")b=a;else if(/^rgb/.test(a)){c=U(a);b="#";for(var d,e=0;e<3;e++){d=c[e].indexOf("%")!=-1?Math.floor(E(c[e])* +255):+c[e];b+=v[F(d,0,255)]}c=+c[3]}else if(/^hsl/.test(a)){c=U(a);b=ca(c);c=c[3]}else b=da[a]||a;return I[a]={color:b,alpha:c}}function ea(a){if(J[a])return J[a];var b=document.createElement("div").style;try{b.font=a}catch(c){}return J[a]={style:b.fontStyle||w.style,variant:b.fontVariant||w.variant,weight:b.fontWeight||w.weight,size:b.fontSize||w.size,family:b.fontFamily||w.family}}function fa(a,b){var c={};for(var d in a)c[d]=a[d];b=parseFloat(b.currentStyle.fontSize);d=parseFloat(a.size);c.size= +typeof a.size=="number"?a.size:a.size.indexOf("px")!=-1?d:a.size.indexOf("em")!=-1?b*d:a.size.indexOf("%")!=-1?b/100*d:a.size.indexOf("pt")!=-1?d/0.75:b;c.size*=0.981;return c}function ga(a){return a.style+" "+a.variant+" "+a.weight+" "+a.size+"px "+a.family}function ha(a){return ia[a]||"square"}function C(a){this.m_=D();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=l*1;this.globalAlpha= +1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=a;var b="width:"+a.clientWidth+"px;height:"+a.clientHeight+"px;overflow:hidden;position:absolute",c=a.ownerDocument.createElement("div");c.style.cssText=b;a.appendChild(c);b=c.cloneNode(false);b.style.backgroundColor="red";b.style.filter="alpha(opacity=0)";a.appendChild(b);this.element_=c;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}function V(a,b,c,d){a.currentPath_.push({type:"bezierCurveTo",cp1x:b.x, +cp1y:b.y,cp2x:c.x,cp2y:c.y,x:d.x,y:d.y});a.currentX_=d.x;a.currentY_=d.y}function W(a,b){var c=H(a.strokeStyle),d=c.color;c=c.alpha*a.globalAlpha;var e=a.lineScale_*a.lineWidth;if(e<1)c*=e;b.push("')}function X(a,b,c,d){var e=a.fillStyle,f=a.arcScaleX_,h=a.arcScaleY_,j=d.x-c.x,m=d.y-c.y;if(e instanceof x){var k=0;d={x:0,y:0};var q=0, +o=1;if(e.type_=="gradient"){k=e.x1_/f;c=e.y1_/h;var n=p(a,e.x0_/f,e.y0_/h);k=p(a,k,c);k=Math.atan2(k.x-n.x,k.y-n.y)*180/Math.PI;if(k<0)k+=360;if(k<1.0E-6)k=0}else{n=p(a,e.x0_,e.y0_);d={x:(n.x-c.x)/j,y:(n.y-c.y)/m};j/=f*l;m/=h*l;o=r.max(j,m);q=2*e.r0_/o;o=2*e.r1_/o-q}f=e.colors_;f.sort(function(A,ja){return A.offset-ja.offset});h=f.length;n=f[0].color;c=f[h-1].color;j=f[0].alpha*a.globalAlpha;a=f[h-1].alpha*a.globalAlpha;m=[];for(var s=0;s')}else if(e instanceof K)j&&m&&b.push("');else{e=H(a.fillStyle);b.push('')}}function p(a,b,c){a=a.m_;return{x:l*(b*a[0][0]+c*a[1][0]+ +a[2][0])-t,y:l*(b*a[0][1]+c*a[1][1]+a[2][1])-t}}function ka(a){return isFinite(a[0][0])&&isFinite(a[0][1])&&isFinite(a[1][0])&&isFinite(a[1][1])&&isFinite(a[2][0])&&isFinite(a[2][1])}function z(a,b,c){if(ka(b)){a.m_=b;if(c)a.lineScale_=la(ma(b[0][0]*b[1][1]-b[0][1]*b[1][0]))}}function x(a){this.type_=a;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}function K(a,b){na(a);switch(b){case "repeat":case null:case "":this.repetition_="repeat";break;case "repeat-x":case "repeat-y":case "no-repeat":this.repetition_= +b;break;default:L("SYNTAX_ERR")}this.src_=a.src;this.width_=a.width;this.height_=a.height}function L(a){throw new M(a);}function na(a){if(!a||a.nodeType!=1||a.tagName!="IMG")L("TYPE_MISMATCH_ERR");a.readyState!="complete"&&L("INVALID_STATE_ERR")}function M(a){this.code=this[a];this.message=a+": DOM Exception "+this.code}var r=Math,i=r.round,N=r.sin,O=r.cos,ma=r.abs,la=r.sqrt,l=10,t=l/2;navigator.userAgent.match(/MSIE ([\d.]+)?/);var P=Array.prototype.slice;S(document);var Y={init:function(a){a=a|| +document;a.createElement("canvas");a.attachEvent("onreadystatechange",$(this.init_,this,a))},init_:function(a){a=a.getElementsByTagName("canvas");for(var b=0;b','","");this.element_.insertAdjacentHTML("BeforeEnd",n.join(""))};g.stroke=function(a){var b=[];b.push("d.x)d.x=f.x;if(c.y==null||f.yd.y)d.y=f.y}}b.push(' ">');a?X(this,b,c,d):W(this,b);b.push("");this.element_.insertAdjacentHTML("beforeEnd",b.join(""))};g.fill=function(){this.stroke(true)};g.closePath=function(){this.currentPath_.push({type:"close"})};g.save=function(){var a={};T(this,a);this.aStack_.push(a);this.mStack_.push(this.m_);this.m_=u(D(),this.m_)};g.restore=function(){if(this.aStack_.length){T(this.aStack_.pop(), +this);this.m_=this.mStack_.pop()}};g.translate=function(a,b){z(this,u([[1,0,0],[0,1,0],[a,b,1]],this.m_),false)};g.rotate=function(a){var b=O(a);a=N(a);z(this,u([[b,a,0],[-a,b,0],[0,0,1]],this.m_),false)};g.scale=function(a,b){this.arcScaleX_*=a;this.arcScaleY_*=b;z(this,u([[a,0,0],[0,b,0],[0,0,1]],this.m_),true)};g.transform=function(a,b,c,d,e,f){z(this,u([[a,b,0],[c,d,0],[e,f,1]],this.m_),true)};g.setTransform=function(a,b,c,d,e,f){z(this,[[a,b,0],[c,d,0],[e,f,1]],true)};g.drawText_=function(a, +b,c,d,e){var f=this.m_;d=0;var h=1E3,j={x:0,y:0},m=[],k=fa(ea(this.font),this.element_),q=ga(k),o=this.element_.currentStyle,n=this.textAlign.toLowerCase();switch(n){case "left":case "center":case "right":break;case "end":n=o.direction=="ltr"?"right":"left";break;case "start":n=o.direction=="rtl"?"right":"left";break;default:n="left"}switch(this.textBaseline){case "hanging":case "top":j.y=k.size/1.75;break;case "middle":break;default:case null:case "alphabetic":case "ideographic":case "bottom":j.y= +-k.size/2.25;break}switch(n){case "right":d=1E3;h=0.05;break;case "center":d=h=500;break}b=p(this,b+j.x,c+j.y);m.push('');e?W(this,m):X(this,m,{x:-d,y:0},{x:h,y:k.size});e=f[0][0].toFixed(3)+","+f[1][0].toFixed(3)+","+f[0][1].toFixed(3)+","+f[1][1].toFixed(3)+",0,0";b=i(b.x/l)+","+i(b.y/l);m.push('','','');this.element_.insertAdjacentHTML("beforeEnd",m.join(""))};g.fillText=function(a,b,c,d){this.drawText_(a,b,c,d,false)};g.strokeText=function(a,b,c,d){this.drawText_(a,b,c,d,true)};g.measureText=function(a){if(!this.textMeasureEl_){this.element_.insertAdjacentHTML("beforeEnd",''); +this.textMeasureEl_=this.element_.lastChild}var b=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(b.createTextNode(a));return{width:this.textMeasureEl_.offsetWidth}};g.clip=function(){};g.arcTo=function(){};g.createPattern=function(a,b){return new K(a,b)};x.prototype.addColorStop=function(a,b){b=H(b);this.colors_.push({offset:a,color:b.color,alpha:b.alpha})};g=M.prototype=new Error;g.INDEX_SIZE_ERR=1;g.DOMSTRING_SIZE_ERR= +2;g.HIERARCHY_REQUEST_ERR=3;g.WRONG_DOCUMENT_ERR=4;g.INVALID_CHARACTER_ERR=5;g.NO_DATA_ALLOWED_ERR=6;g.NO_MODIFICATION_ALLOWED_ERR=7;g.NOT_FOUND_ERR=8;g.NOT_SUPPORTED_ERR=9;g.INUSE_ATTRIBUTE_ERR=10;g.INVALID_STATE_ERR=11;g.SYNTAX_ERR=12;g.INVALID_MODIFICATION_ERR=13;g.NAMESPACE_ERR=14;g.INVALID_ACCESS_ERR=15;g.VALIDATION_ERR=16;g.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=Y;CanvasRenderingContext2D=C;CanvasGradient=x;CanvasPattern=K;DOMException=M}(); diff --git a/External Source/QuincyKit/server/admin/js/functions.js b/External Source/QuincyKit/server/admin/js/functions.js new file mode 100644 index 000000000..2e3f0d4f9 --- /dev/null +++ b/External Source/QuincyKit/server/admin/js/functions.js @@ -0,0 +1,99 @@ +function showCrashID (crashid) { + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: "action=getlogcrashid&id=" + crashid, + success: function(data) { + data = data.replace(/(\r\n|\n|\r)/gm, "
"); + $('#logarea').html("
" + data + "
"); + } + }); + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: "action=getdescriptioncrashid&id=" + crashid, + success: function(data) { + data = data.replace(/(\r\n|\n|\r)/gm, "
"); + $('#descriptionarea').html("
" + data + "
"); + } + }); +} + +function deleteCrashID (crashid, groupid) { + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: "action=deletecrashid&id=" + crashid + "&groupid=" + groupid, + success: function(data) { + if (data == "") { + $('#crashrow' + crashid).remove(); + } else { + alert('ERROR: ' + data); + } + } + }); +} + +function deleteGroupID (groupid) { + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: "action=deletegroupid&id=" + groupid, + success: function(data) { + if (data == "") { + $('#grouprow' + groupid).remove(); + } else { + alert('ERROR: ' + data); + } + } + }); +} + +function deleteGroups (bundleidentifier, version) { + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: "action=deletegroups&bundleidentifier=" + bundleidentifier + "&version=" + version, + success: function(data) { + if (data == "") { + $('#groups').remove(); + } else { + alert('ERROR: ' + data); + } + } + }); +} + +function symbolicateCrashID (crashid) { + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: "action=symbolicatecrashid&id=" + crashid, + success: function(data) { + if (data == "") { + $("#symbolicate" + crashid).html('Symbolicating...'); + } else { + alert('ERROR: ' + data); + } + } + }); +} + +function updateGroupMeta (groupid, bundleidentifier) { + $.ajax({ + type: "POST", + url: 'actionapi.php', + data: ({ + action: 'updategroupid', + id: groupid, + bundleidentifier: bundleidentifier, + fixversion: $("#fixversion" + groupid).val(), + description: $("#description" + groupid).val() + }), + success: function(data) { + if (data != "") { + alert('ERROR: ' + data); + } + } + }); +} diff --git a/External Source/QuincyKit/server/admin/js/jqplot.barRenderer.min.js b/External Source/QuincyKit/server/admin/js/jqplot.barRenderer.min.js new file mode 100644 index 000000000..54d4a0df8 --- /dev/null +++ b/External Source/QuincyKit/server/admin/js/jqplot.barRenderer.min.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2009 - 2010 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * jqPlot includes date instance methods and printf/sprintf functions by other authors: + * + * Date instance methods contained in jqplot.dateMethods.js: + * + * author Ken Snyder (ken d snyder at gmail dot com) + * date 2008-09-10 + * version 2.0.2 (http://kendsnyder.com/sandbox/date/) + * license Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) + * + * JavaScript printf/sprintf functions contained in jqplot.sprintf.js: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(d){d.jqplot.BarRenderer=function(){d.jqplot.LineRenderer.call(this)};d.jqplot.BarRenderer.prototype=new d.jqplot.LineRenderer();d.jqplot.BarRenderer.prototype.constructor=d.jqplot.BarRenderer;d.jqplot.BarRenderer.prototype.init=function(o,q){this.barPadding=8;this.barMargin=10;this.barDirection="vertical";this.barWidth=null;this.shadowOffset=2;this.shadowDepth=5;this.shadowAlpha=0.08;this.waterfall=false;this.groups=1;this.varyBarColor=false;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];if(o.highlightMouseDown&&o.highlightMouseOver==null){o.highlightMouseOver=false}d.extend(true,this,o);this.fill=true;if(this.waterfall){this.fillToZero=false;this.disableStack=true}if(this.barDirection=="vertical"){this._primaryAxis="_xaxis";this._stackAxis="y";this.fillAxis="y"}else{this._primaryAxis="_yaxis";this._stackAxis="x";this.fillAxis="x"}this._highlightedPoint=null;this._plotSeriesInfo=null;this._dataColors=[];this._barPoints=[];var p={lineJoin:"miter",lineCap:"round",fill:true,isarc:false,strokeStyle:this.color,fillStyle:this.color,closePath:this.fill};this.renderer.shapeRenderer.init(p);var n={lineJoin:"miter",lineCap:"round",fill:true,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,closePath:this.fill};this.renderer.shadowRenderer.init(n);q.postInitHooks.addOnce(h);q.postDrawHooks.addOnce(j);q.eventListenerHooks.addOnce("jqplotMouseMove",b);q.eventListenerHooks.addOnce("jqplotMouseDown",a);q.eventListenerHooks.addOnce("jqplotMouseUp",l);q.eventListenerHooks.addOnce("jqplotClick",e);q.eventListenerHooks.addOnce("jqplotRightClick",m)};function g(t,p,o,w){if(this.rendererOptions.barDirection=="horizontal"){this._stackAxis="x";this._primaryAxis="_yaxis"}if(this.rendererOptions.waterfall==true){this._data=d.extend(true,[],this.data);var s=0;var u=(!this.rendererOptions.barDirection||this.rendererOptions.barDirection=="vertical")?1:0;for(var q=0;q0){this.data[q][u]+=this.data[q-1][u]}}this.data[this.data.length]=(u==1)?[this.data.length+1,s]:[s,this.data.length+1];this._data[this._data.length]=(u==1)?[this._data.length+1,s]:[s,this._data.length+1]}if(this.rendererOptions.groups>1){this.breakOnNull=true;var n=this.data.length;var v=parseInt(n/this.rendererOptions.groups,10);var r=0;for(var q=v;q570)?n[p]*0.8:n[p]+0.3*(255-n[p]);n[p]=parseInt(n[p],10)}q.push("rgb("+n[0]+","+n[1]+","+n[2]+")")}return q}d.jqplot.BarRenderer.prototype.draw=function(E,J,q){var G;var A=(q!=undefined)?q:{};var v=(A.shadow!=undefined)?A.shadow:this.shadow;var M=(A.showLine!=undefined)?A.showLine:this.showLine;var F=(A.fill!=undefined)?A.fill:this.fill;var p=this.xaxis;var H=this.yaxis;var y=this._xaxis.series_u2p;var I=this._yaxis.series_u2p;var D,C,x,w,s;this._dataColors=[];this._barPoints=[];if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var L=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);x=L[0];w=L[1];s=L[2];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(w/2-0.5)+s)*(this.barWidth+this.barPadding)}if(M){var u=new d.jqplot.ColorGenerator(this.negativeSeriesColors);var B=new d.jqplot.ColorGenerator(this.seriesColors);var K=u.get(this.index);if(!this.useNegativeColors){K=A.fillStyle}var t=A.fillStyle;if(this.barDirection=="vertical"){for(var G=0;G0&&G0&&G-1){return n/this.pt2px}else{if(b.indexOf("pt")>-1){return n}else{if(b.indexOf("em")>-1){return n*12}else{if(b.indexOf("%")>-1){return n*12/100}else{return n/this.pt2px}}}}};a.jqplot.CanvasTextRenderer.prototype.fontWeight2Float=function(b){if(Number(b)){return b/400}else{switch(b){case"normal":return 1;break;case"bold":return 1.75;break;case"bolder":return 2.25;break;case"lighter":return 0.75;break;default:return 1;break}}};a.jqplot.CanvasTextRenderer.prototype.getText=function(){return this.text};a.jqplot.CanvasTextRenderer.prototype.setText=function(c,b){this.text=c;this.setWidth(b);return this};a.jqplot.CanvasTextRenderer.prototype.getWidth=function(b){return this.width};a.jqplot.CanvasTextRenderer.prototype.setWidth=function(c,b){if(!b){this.width=this.measure(c,this.text)}else{this.width=b}return this};a.jqplot.CanvasTextRenderer.prototype.getHeight=function(b){return this.height};a.jqplot.CanvasTextRenderer.prototype.setHeight=function(b){if(!b){this.height=this.normalizedFontSize*this.pt2px}else{this.height=b}return this};a.jqplot.CanvasTextRenderer.prototype.letter=function(b){return this.letters[b]};a.jqplot.CanvasTextRenderer.prototype.ascent=function(){return this.normalizedFontSize};a.jqplot.CanvasTextRenderer.prototype.descent=function(){return 7*this.normalizedFontSize/25};a.jqplot.CanvasTextRenderer.prototype.measure=function(d,f){var e=0;var b=f.length;for(i=0;i30)?2:2+(30-this.normalizedFontSize)/20;t.lineWidth=u*k*this.fontWeight2Float(this.fontWeight);for(var g=0;g":{width:24,points:[[4,18],[20,9],[4,0]]},"?":{width:18,points:[[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]]},"@":{width:27,points:[[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]]},A:{width:18,points:[[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]]},B:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]]},C:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]]},D:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]]},E:{width:19,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]]},F:{width:18,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]]},G:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]]},H:{width:22,points:[[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]]},I:{width:8,points:[[4,21],[4,0]]},J:{width:16,points:[[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]]},K:{width:21,points:[[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]]},L:{width:17,points:[[4,21],[4,0],[-1,-1],[4,0],[16,0]]},M:{width:24,points:[[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]]},N:{width:22,points:[[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]]},O:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]]},P:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]]},Q:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]]},R:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]]},S:{width:20,points:[[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},T:{width:16,points:[[8,21],[8,0],[-1,-1],[1,21],[15,21]]},U:{width:22,points:[[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]]},V:{width:18,points:[[1,21],[9,0],[-1,-1],[17,21],[9,0]]},W:{width:24,points:[[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]]},X:{width:20,points:[[3,21],[17,0],[-1,-1],[17,21],[3,0]]},Y:{width:18,points:[[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]]},Z:{width:20,points:[[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]]},"[":{width:14,points:[[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]]},"\\":{width:14,points:[[0,21],[14,-3]]},"]":{width:14,points:[[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]]},"^":{width:16,points:[[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]]},_:{width:16,points:[[0,-2],[16,-2]]},"`":{width:10,points:[[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]]},a:{width:19,points:[[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},b:{width:19,points:[[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},c:{width:18,points:[[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},d:{width:19,points:[[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},e:{width:18,points:[[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},f:{width:12,points:[[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]]},g:{width:19,points:[[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},h:{width:19,points:[[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},i:{width:8,points:[[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]]},j:{width:10,points:[[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]]},k:{width:17,points:[[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]]},l:{width:8,points:[[4,21],[4,0]]},m:{width:30,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]]},n:{width:19,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},o:{width:19,points:[[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]]},p:{width:19,points:[[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},q:{width:19,points:[[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},r:{width:13,points:[[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]]},s:{width:17,points:[[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]]},t:{width:12,points:[[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]]},u:{width:19,points:[[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]]},v:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0]]},w:{width:22,points:[[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]]},x:{width:17,points:[[3,14],[14,0],[-1,-1],[14,14],[3,0]]},y:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]]},z:{width:17,points:[[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]]},"{":{width:14,points:[[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]]},"|":{width:8,points:[[4,25],[4,-7]]},"}":{width:14,points:[[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]]},"~":{width:24,points:[[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]]}};a.jqplot.CanvasFontRenderer=function(b){b=b||{};if(!b.pt2px){b.pt2px=1.5}a.jqplot.CanvasTextRenderer.call(this,b)};a.jqplot.CanvasFontRenderer.prototype=new a.jqplot.CanvasTextRenderer({});a.jqplot.CanvasFontRenderer.prototype.constructor=a.jqplot.CanvasFontRenderer;a.jqplot.CanvasFontRenderer.prototype.measure=function(c,e){var d=this.fontSize+" "+this.fontFamily;c.save();c.font=d;var b=c.measureText(e).width;c.restore();return b};a.jqplot.CanvasFontRenderer.prototype.draw=function(e,g){var c=0;var h=this.height*0.72;e.save();var d,b;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){d=0;b=-Math.sin(this.angle)*this.width}else{if((0b.max||b.max==null){b.max=h[c][0]}}else{if(h[c][1]b.max||b.max==null){b.max=h[c][1]}}}}if(this.groupLabels.length){this.groups=this.groupLabels.length}};a.jqplot.CategoryAxisRenderer.prototype.createTicks=function(){var D=this._ticks;var z=this.ticks;var F=this.name;var C=this._dataBounds;var v,A;var q,w;var d,c;var b,x;if(z.length){if(this.groups>1&&!this._grouped){var r=z.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x1&&!this._grouped){var r=y.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x0&&o
');if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var g=this._label.draw(b);g.appendTo(this._elem)}var f=this._ticks;for(var e=0;e');g.html(this.groupLabels[e]);this._groupLabels.push(g);g.appendTo(this._elem)}}return this._elem};a.jqplot.CategoryAxisRenderer.prototype.set=function(){var e=0;var m;var k=0;var f=0;var d=(this._label==null)?false:this._label.show;if(this.show){var n=this._ticks;for(var c=0;ce){e=m}}}var j=0;for(var c=0;cj){j=m}}if(d){k=this._label._elem.outerWidth(true);f=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){e+=j+k;this._elem.css({width:e+"px",left:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}else{e+=j+k;this._elem.css({width:e+"px",right:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}}}}};a.jqplot.CategoryAxisRenderer.prototype.pack=function(e,c){var B=this._ticks;var v=this.max;var s=this.min;var n=c.max;var l=c.min;var q=(this._label==null)?false:this._label.show;for(var r in e){this._elem.css(r,e[r])}this._offsets=c;var g=n-l;var k=v-s;this.p2u=function(h){return(h-l)*k/g+s};this.u2p=function(h){return(h-s)*g/k+l};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(h-s)*g/k};this.series_p2u=function(h){return h*k/g+s}}else{this.series_u2p=function(h){return(h-v)*g/k};this.series_p2u=function(h){return h*k/g+v}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(i=0;i0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"middle":b=-o.getHeight()/2;break;default:b=-o.getHeight()/2;break}}else{b=-o.getHeight()/2}var C=this.u2p(o.value)+b+"px";o._elem.css("top",C);o.pack()}}var y=["left",0];if(q){var x=this._label._elem.outerHeight(true);this._label._elem.css("top",n-g/2-x/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px");y=["left",this._label._elem.outerWidth(true)]}else{this._label._elem.css("right","0px");y=["right",this._label._elem.outerWidth(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10);for(i=0;ic.max||c.max==null){c.max=l[e][0]}}else{l[e][1]=Date.create(l[e][1]).getTime();b[e][1]=Date.create(l[e][1]).getTime();k[e][1]=Date.create(l[e][1]).getTime();if(l[e][1]c.max||c.max==null){c.max=l[e][1]}}}}};a.jqplot.DateAxisRenderer.prototype.reset=function(){this.min=this._min;this.max=this._max;this.tickInterval=this._tickInterval;this.numberTicks=this._numberTicks;this.daTickInterval=this._daTickInterval};a.jqplot.DateAxisRenderer.prototype.createTicks=function(){var v=this._ticks;var r=this.ticks;var w=this.name;var u=this._dataBounds;var o,s;var m,p;var d,c;var b,q;if(r.length){for(q=0;q200){this.numberTicks=parseInt(3+(o-200)/100,10)}else{this.numberTicks=2}}}if(this.daTickInterval==null){this.daTickInterval=[j/(this.numberTicks-1)/1000,"seconds"]}for(var q=0;q