├── .gitignore ├── LICENSE ├── MacGap.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── MacGap.xccheckout │ └── xcuserdata │ │ ├── Alex.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── liamks.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ ├── Alex.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── MacGap.xcscheme │ │ └── xcschememanagement.plist │ └── liamks.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ ├── MacGap.xcscheme │ └── xcschememanagement.plist ├── MacGap ├── AppDelegate.h ├── AppDelegate.m ├── Classes │ ├── CallbackDelegate.h │ ├── CallbackDelegate.m │ ├── Commands │ │ ├── App.h │ │ ├── App.m │ │ ├── Command.h │ │ ├── Command.m │ │ ├── Dock.h │ │ ├── Dock.m │ │ ├── Growl.h │ │ ├── Growl.m │ │ ├── MenuItemProxy.h │ │ ├── MenuItemProxy.m │ │ ├── MenuProxy.h │ │ ├── MenuProxy.m │ │ ├── Notice.h │ │ ├── Notice.m │ │ ├── Path.h │ │ ├── Path.m │ │ ├── Sound.h │ │ ├── Sound.m │ │ ├── UserDefaults.h │ │ ├── UserDefaults.m │ │ ├── fonts.h │ │ └── fonts.m │ ├── Constants.h │ ├── ContentView.h │ ├── ContentView.m │ ├── JSEventHelper.h │ ├── JSEventHelper.m │ ├── Utils.h │ ├── Utils.m │ ├── WebViewDelegate.h │ ├── WebViewDelegate.m │ ├── Window.h │ └── Window.m ├── Clipboard.h ├── Clipboard.m ├── Growl.framework │ ├── Growl │ ├── Headers │ ├── Resources │ └── Versions │ │ ├── A │ │ ├── Growl │ │ ├── Headers │ │ │ ├── Growl.h │ │ │ ├── GrowlApplicationBridge.h │ │ │ └── GrowlDefines.h │ │ ├── Resources │ │ │ └── Info.plist │ │ └── _CodeSignature │ │ │ └── CodeResources │ │ └── Current ├── MacGap-Info.plist ├── MacGap-Prefix.pch ├── StatusBar.h ├── StatusBar.m ├── StatusMenu.xib ├── WindowController.h ├── WindowController.m ├── en.lproj │ ├── Credits.rtf │ ├── InfoPlist.strings │ ├── MainMenu.xib │ └── Window.xib └── main.m ├── README.md ├── application.icns └── public └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *xcuserdata* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MacGap was ported from phonegap-mac, and is under the same license (MIT) 2 | 3 | The MIT License 4 | ***************** 5 | 6 | Copyright (c) <2012> 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */ = {isa = PBXBuildFile; fileRef = 1495814E15C15CCC00E1CFE5 /* Notice.m */; }; 11 | 552AC06E1C9A62A4002C0C82 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAE451BE14BA79C600190544 /* Cocoa.framework */; }; 12 | 552AC0711C9A6326002C0C82 /* StatusBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 552AC0701C9A6326002C0C82 /* StatusBar.m */; }; 13 | 552AC0751C9A74FA002C0C82 /* StatusMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 552AC0741C9A74FA002C0C82 /* StatusMenu.xib */; }; 14 | 6F169DA718CC332E005EDDF3 /* Command.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA618CC332E005EDDF3 /* Command.m */; }; 15 | 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */; }; 16 | 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */; }; 17 | 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */; }; 18 | 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DB018CD906F005EDDF3 /* MenuProxy.m */; }; 19 | 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD672B518FE618E00C0DAAD /* UserDefaults.m */; }; 20 | 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */; }; 21 | 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 88746BED14CCA435001E160E /* JSEventHelper.m */; }; 22 | 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0645F14BDE10A00E4BCE2 /* Window.m */; }; 23 | 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88C0646414BDEC5800E4BCE2 /* Window.xib */; }; 24 | 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0646C14BDF6A600E4BCE2 /* WindowController.m */; }; 25 | F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = F2B80015179E0FC100B069A8 /* Clipboard.m */; }; 26 | FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA32509C14BA813600BF0781 /* WebKit.framework */; }; 27 | FA3250C314BA85E700BF0781 /* ContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BC14BA85E700BF0781 /* ContentView.m */; }; 28 | FA3250C514BA85E700BF0781 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BE14BA85E700BF0781 /* Utils.m */; }; 29 | FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C014BA85E700BF0781 /* WebViewDelegate.m */; }; 30 | FA3250D314BA860800BF0781 /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C914BA860800BF0781 /* App.m */; }; 31 | FA3250D514BA860800BF0781 /* Dock.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CB14BA860800BF0781 /* Dock.m */; }; 32 | FA3250D714BA860800BF0781 /* Growl.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CD14BA860800BF0781 /* Growl.m */; }; 33 | FA3250D914BA860800BF0781 /* Path.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CF14BA860800BF0781 /* Path.m */; }; 34 | FA3250DB14BA860800BF0781 /* Sound.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250D114BA860800BF0781 /* Sound.m */; }; 35 | FA3250DF14BA878D00BF0781 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = FA3250DE14BA878D00BF0781 /* Growl.framework */; }; 36 | FA3250E514BA883A00BF0781 /* public in Resources */ = {isa = PBXBuildFile; fileRef = FA3250E414BA883A00BF0781 /* public */; }; 37 | FA3250E714BA8BCE00BF0781 /* application.icns in Resources */ = {isa = PBXBuildFile; fileRef = FA3250E614BA8BCE00BF0781 /* application.icns */; }; 38 | FA3F7743168F70850027B324 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA32509E14BA816E00BF0781 /* Growl.framework */; }; 39 | FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAE451C714BA79C600190544 /* InfoPlist.strings */; }; 40 | FAE451CB14BA79C600190544 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451CA14BA79C600190544 /* main.m */; }; 41 | FAE451CF14BA79C600190544 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = FAE451CD14BA79C600190544 /* Credits.rtf */; }; 42 | FAE451D214BA79C600190544 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451D114BA79C600190544 /* AppDelegate.m */; }; 43 | FAE451D514BA79C600190544 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAE451D314BA79C600190544 /* MainMenu.xib */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXCopyFilesBuildPhase section */ 47 | FA3250DD14BA876F00BF0781 /* CopyFiles */ = { 48 | isa = PBXCopyFilesBuildPhase; 49 | buildActionMask = 2147483647; 50 | dstPath = ""; 51 | dstSubfolderSpec = 10; 52 | files = ( 53 | FA3250DF14BA878D00BF0781 /* Growl.framework in CopyFiles */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXCopyFilesBuildPhase section */ 58 | 59 | /* Begin PBXFileReference section */ 60 | 1495814D15C15CCC00E1CFE5 /* Notice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Notice.h; path = Classes/Commands/Notice.h; sourceTree = ""; }; 61 | 1495814E15C15CCC00E1CFE5 /* Notice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Notice.m; path = Classes/Commands/Notice.m; sourceTree = ""; }; 62 | 552AC06F1C9A6326002C0C82 /* StatusBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatusBar.h; sourceTree = ""; }; 63 | 552AC0701C9A6326002C0C82 /* StatusBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StatusBar.m; sourceTree = ""; }; 64 | 552AC0741C9A74FA002C0C82 /* StatusMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusMenu.xib; sourceTree = ""; }; 65 | 6F169DA518CC332E005EDDF3 /* Command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Command.h; path = Classes/Commands/Command.h; sourceTree = ""; }; 66 | 6F169DA618CC332E005EDDF3 /* Command.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Command.m; path = Classes/Commands/Command.m; sourceTree = ""; }; 67 | 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallbackDelegate.h; path = Classes/CallbackDelegate.h; sourceTree = ""; }; 68 | 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CallbackDelegate.m; path = Classes/CallbackDelegate.m; sourceTree = ""; }; 69 | 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 70 | 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuItemProxy.h; path = Classes/Commands/MenuItemProxy.h; sourceTree = ""; }; 71 | 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuItemProxy.m; path = Classes/Commands/MenuItemProxy.m; sourceTree = ""; }; 72 | 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuProxy.h; path = Classes/Commands/MenuProxy.h; sourceTree = ""; }; 73 | 6F169DB018CD906F005EDDF3 /* MenuProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuProxy.m; path = Classes/Commands/MenuProxy.m; sourceTree = ""; }; 74 | 6FD672B418FE618E00C0DAAD /* UserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserDefaults.h; path = Classes/Commands/UserDefaults.h; sourceTree = ""; }; 75 | 6FD672B518FE618E00C0DAAD /* UserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UserDefaults.m; path = Classes/Commands/UserDefaults.m; sourceTree = ""; }; 76 | 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fonts.h; path = Classes/Commands/fonts.h; sourceTree = ""; }; 77 | 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = fonts.m; path = Classes/Commands/fonts.m; sourceTree = ""; }; 78 | 88746BEC14CCA435001E160E /* JSEventHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSEventHelper.h; path = Classes/JSEventHelper.h; sourceTree = ""; }; 79 | 88746BED14CCA435001E160E /* JSEventHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSEventHelper.m; path = Classes/JSEventHelper.m; sourceTree = ""; }; 80 | 88C0645E14BDE10A00E4BCE2 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Window.h; path = Classes/Window.h; sourceTree = ""; }; 81 | 88C0645F14BDE10A00E4BCE2 /* Window.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Window.m; path = Classes/Window.m; sourceTree = ""; }; 82 | 88C0646514BDEC5800E4BCE2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Window.xib; sourceTree = ""; }; 83 | 88C0646B14BDF6A600E4BCE2 /* WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowController.h; sourceTree = ""; }; 84 | 88C0646C14BDF6A600E4BCE2 /* WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WindowController.m; sourceTree = ""; }; 85 | F2B80014179E0FC100B069A8 /* Clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clipboard.h; sourceTree = ""; }; 86 | F2B80015179E0FC100B069A8 /* Clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Clipboard.m; sourceTree = ""; }; 87 | FA32509C14BA813600BF0781 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 88 | FA32509E14BA816E00BF0781 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = MacGap/Growl.framework; sourceTree = ""; }; 89 | FA3250BA14BA85E700BF0781 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = Classes/Constants.h; sourceTree = ""; }; 90 | FA3250BB14BA85E700BF0781 /* ContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ContentView.h; path = Classes/ContentView.h; sourceTree = ""; }; 91 | FA3250BC14BA85E700BF0781 /* ContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ContentView.m; path = Classes/ContentView.m; sourceTree = ""; }; 92 | FA3250BD14BA85E700BF0781 /* Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = Classes/Utils.h; sourceTree = ""; }; 93 | FA3250BE14BA85E700BF0781 /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = Classes/Utils.m; sourceTree = ""; }; 94 | FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebViewDelegate.h; path = Classes/WebViewDelegate.h; sourceTree = ""; }; 95 | FA3250C014BA85E700BF0781 /* WebViewDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WebViewDelegate.m; path = Classes/WebViewDelegate.m; sourceTree = ""; }; 96 | FA3250C814BA860800BF0781 /* App.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = App.h; path = Classes/Commands/App.h; sourceTree = ""; }; 97 | FA3250C914BA860800BF0781 /* App.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = App.m; path = Classes/Commands/App.m; sourceTree = ""; }; 98 | FA3250CA14BA860800BF0781 /* Dock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dock.h; path = Classes/Commands/Dock.h; sourceTree = ""; }; 99 | FA3250CB14BA860800BF0781 /* Dock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Dock.m; path = Classes/Commands/Dock.m; sourceTree = ""; }; 100 | FA3250CC14BA860800BF0781 /* Growl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Growl.h; path = Classes/Commands/Growl.h; sourceTree = ""; }; 101 | FA3250CD14BA860800BF0781 /* Growl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Growl.m; path = Classes/Commands/Growl.m; sourceTree = ""; }; 102 | FA3250CE14BA860800BF0781 /* Path.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Path.h; path = Classes/Commands/Path.h; sourceTree = ""; }; 103 | FA3250CF14BA860800BF0781 /* Path.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Path.m; path = Classes/Commands/Path.m; sourceTree = ""; }; 104 | FA3250D014BA860800BF0781 /* Sound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Sound.h; path = Classes/Commands/Sound.h; sourceTree = ""; }; 105 | FA3250D114BA860800BF0781 /* Sound.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Sound.m; path = Classes/Commands/Sound.m; sourceTree = ""; }; 106 | FA3250DE14BA878D00BF0781 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = MacGap/Growl.framework; sourceTree = ""; }; 107 | FA3250E414BA883A00BF0781 /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; 108 | FA3250E614BA8BCE00BF0781 /* application.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = application.icns; sourceTree = SOURCE_ROOT; }; 109 | FAE451BA14BA79C600190544 /* MacGap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MacGap.app; sourceTree = BUILT_PRODUCTS_DIR; }; 110 | FAE451BE14BA79C600190544 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 111 | FAE451C114BA79C600190544 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 112 | FAE451C214BA79C600190544 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 113 | FAE451C314BA79C600190544 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 114 | FAE451C614BA79C600190544 /* MacGap-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MacGap-Info.plist"; sourceTree = ""; }; 115 | FAE451C814BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 116 | FAE451CA14BA79C600190544 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 117 | FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MacGap-Prefix.pch"; sourceTree = ""; }; 118 | FAE451CE14BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 119 | FAE451D014BA79C600190544 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 120 | FAE451D114BA79C600190544 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 121 | FAE451D414BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 122 | /* End PBXFileReference section */ 123 | 124 | /* Begin PBXFrameworksBuildPhase section */ 125 | FAE451B714BA79C600190544 /* Frameworks */ = { 126 | isa = PBXFrameworksBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | 552AC06E1C9A62A4002C0C82 /* Cocoa.framework in Frameworks */, 130 | 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */, 131 | FA3F7743168F70850027B324 /* Growl.framework in Frameworks */, 132 | FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */, 133 | ); 134 | runOnlyForDeploymentPostprocessing = 0; 135 | }; 136 | /* End PBXFrameworksBuildPhase section */ 137 | 138 | /* Begin PBXGroup section */ 139 | FA3250E014BA87B800BF0781 /* Classes */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | FA3250E114BA87DD00BF0781 /* Commands */, 143 | FA3250BA14BA85E700BF0781 /* Constants.h */, 144 | 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */, 145 | 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */, 146 | FA3250BB14BA85E700BF0781 /* ContentView.h */, 147 | FA3250BC14BA85E700BF0781 /* ContentView.m */, 148 | FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */, 149 | FA3250C014BA85E700BF0781 /* WebViewDelegate.m */, 150 | 88C0646B14BDF6A600E4BCE2 /* WindowController.h */, 151 | 88C0646C14BDF6A600E4BCE2 /* WindowController.m */, 152 | ); 153 | name = Classes; 154 | sourceTree = ""; 155 | }; 156 | FA3250E114BA87DD00BF0781 /* Commands */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 6F169DA518CC332E005EDDF3 /* Command.h */, 160 | 6F169DA618CC332E005EDDF3 /* Command.m */, 161 | 1495814D15C15CCC00E1CFE5 /* Notice.h */, 162 | 1495814E15C15CCC00E1CFE5 /* Notice.m */, 163 | FA3250CA14BA860800BF0781 /* Dock.h */, 164 | FA3250CB14BA860800BF0781 /* Dock.m */, 165 | 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */, 166 | 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */, 167 | FA3250BD14BA85E700BF0781 /* Utils.h */, 168 | FA3250BE14BA85E700BF0781 /* Utils.m */, 169 | 6FD672B418FE618E00C0DAAD /* UserDefaults.h */, 170 | 6FD672B518FE618E00C0DAAD /* UserDefaults.m */, 171 | FA3250CC14BA860800BF0781 /* Growl.h */, 172 | FA3250CD14BA860800BF0781 /* Growl.m */, 173 | FA3250CE14BA860800BF0781 /* Path.h */, 174 | FA3250CF14BA860800BF0781 /* Path.m */, 175 | FA3250D014BA860800BF0781 /* Sound.h */, 176 | FA3250D114BA860800BF0781 /* Sound.m */, 177 | FA3250C814BA860800BF0781 /* App.h */, 178 | FA3250C914BA860800BF0781 /* App.m */, 179 | 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */, 180 | 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */, 181 | 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */, 182 | 6F169DB018CD906F005EDDF3 /* MenuProxy.m */, 183 | 88C0645E14BDE10A00E4BCE2 /* Window.h */, 184 | 88C0645F14BDE10A00E4BCE2 /* Window.m */, 185 | 88746BEC14CCA435001E160E /* JSEventHelper.h */, 186 | 88746BED14CCA435001E160E /* JSEventHelper.m */, 187 | F2B80014179E0FC100B069A8 /* Clipboard.h */, 188 | F2B80015179E0FC100B069A8 /* Clipboard.m */, 189 | 552AC06F1C9A6326002C0C82 /* StatusBar.h */, 190 | 552AC0701C9A6326002C0C82 /* StatusBar.m */, 191 | ); 192 | name = Commands; 193 | sourceTree = ""; 194 | }; 195 | FAE451AF14BA79C600190544 = { 196 | isa = PBXGroup; 197 | children = ( 198 | FA3250E414BA883A00BF0781 /* public */, 199 | FAE451C414BA79C600190544 /* MacGap */, 200 | FAE451BD14BA79C600190544 /* Frameworks */, 201 | FAE451BB14BA79C600190544 /* Products */, 202 | ); 203 | sourceTree = ""; 204 | }; 205 | FAE451BB14BA79C600190544 /* Products */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | FAE451BA14BA79C600190544 /* MacGap.app */, 209 | ); 210 | name = Products; 211 | sourceTree = ""; 212 | }; 213 | FAE451BD14BA79C600190544 /* Frameworks */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */, 217 | FA3250DE14BA878D00BF0781 /* Growl.framework */, 218 | FA32509E14BA816E00BF0781 /* Growl.framework */, 219 | FA32509C14BA813600BF0781 /* WebKit.framework */, 220 | FAE451BE14BA79C600190544 /* Cocoa.framework */, 221 | FAE451C014BA79C600190544 /* Other Frameworks */, 222 | ); 223 | name = Frameworks; 224 | sourceTree = ""; 225 | }; 226 | FAE451C014BA79C600190544 /* Other Frameworks */ = { 227 | isa = PBXGroup; 228 | children = ( 229 | FAE451C114BA79C600190544 /* AppKit.framework */, 230 | FAE451C214BA79C600190544 /* CoreData.framework */, 231 | FAE451C314BA79C600190544 /* Foundation.framework */, 232 | ); 233 | name = "Other Frameworks"; 234 | sourceTree = ""; 235 | }; 236 | FAE451C414BA79C600190544 /* MacGap */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | FA3250E014BA87B800BF0781 /* Classes */, 240 | FAE451D014BA79C600190544 /* AppDelegate.h */, 241 | FAE451D114BA79C600190544 /* AppDelegate.m */, 242 | FAE451D314BA79C600190544 /* MainMenu.xib */, 243 | 552AC0741C9A74FA002C0C82 /* StatusMenu.xib */, 244 | 88C0646414BDEC5800E4BCE2 /* Window.xib */, 245 | FAE451C514BA79C600190544 /* Supporting Files */, 246 | ); 247 | path = MacGap; 248 | sourceTree = ""; 249 | }; 250 | FAE451C514BA79C600190544 /* Supporting Files */ = { 251 | isa = PBXGroup; 252 | children = ( 253 | FA3250E614BA8BCE00BF0781 /* application.icns */, 254 | FAE451C614BA79C600190544 /* MacGap-Info.plist */, 255 | FAE451C714BA79C600190544 /* InfoPlist.strings */, 256 | FAE451CA14BA79C600190544 /* main.m */, 257 | FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */, 258 | FAE451CD14BA79C600190544 /* Credits.rtf */, 259 | ); 260 | name = "Supporting Files"; 261 | sourceTree = ""; 262 | }; 263 | /* End PBXGroup section */ 264 | 265 | /* Begin PBXNativeTarget section */ 266 | FAE451B914BA79C600190544 /* MacGap */ = { 267 | isa = PBXNativeTarget; 268 | buildConfigurationList = FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */; 269 | buildPhases = ( 270 | FAE451B814BA79C600190544 /* Resources */, 271 | FAE451B614BA79C600190544 /* Sources */, 272 | FAE451B714BA79C600190544 /* Frameworks */, 273 | FA3250DD14BA876F00BF0781 /* CopyFiles */, 274 | ); 275 | buildRules = ( 276 | ); 277 | dependencies = ( 278 | ); 279 | name = MacGap; 280 | productName = MacGap; 281 | productReference = FAE451BA14BA79C600190544 /* MacGap.app */; 282 | productType = "com.apple.product-type.application"; 283 | }; 284 | /* End PBXNativeTarget section */ 285 | 286 | /* Begin PBXProject section */ 287 | FAE451B114BA79C600190544 /* Project object */ = { 288 | isa = PBXProject; 289 | attributes = { 290 | LastUpgradeCheck = 0450; 291 | ORGANIZATIONNAME = Twitter; 292 | }; 293 | buildConfigurationList = FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */; 294 | compatibilityVersion = "Xcode 3.2"; 295 | developmentRegion = English; 296 | hasScannedForEncodings = 0; 297 | knownRegions = ( 298 | en, 299 | ); 300 | mainGroup = FAE451AF14BA79C600190544; 301 | productRefGroup = FAE451BB14BA79C600190544 /* Products */; 302 | projectDirPath = ""; 303 | projectRoot = ""; 304 | targets = ( 305 | FAE451B914BA79C600190544 /* MacGap */, 306 | ); 307 | }; 308 | /* End PBXProject section */ 309 | 310 | /* Begin PBXResourcesBuildPhase section */ 311 | FAE451B814BA79C600190544 /* Resources */ = { 312 | isa = PBXResourcesBuildPhase; 313 | buildActionMask = 2147483647; 314 | files = ( 315 | FA3250E514BA883A00BF0781 /* public in Resources */, 316 | FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */, 317 | FAE451CF14BA79C600190544 /* Credits.rtf in Resources */, 318 | FAE451D514BA79C600190544 /* MainMenu.xib in Resources */, 319 | FA3250E714BA8BCE00BF0781 /* application.icns in Resources */, 320 | 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */, 321 | 552AC0751C9A74FA002C0C82 /* StatusMenu.xib in Resources */, 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | /* End PBXResourcesBuildPhase section */ 326 | 327 | /* Begin PBXSourcesBuildPhase section */ 328 | FAE451B614BA79C600190544 /* Sources */ = { 329 | isa = PBXSourcesBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */, 333 | FA3250D314BA860800BF0781 /* App.m in Sources */, 334 | FA3250D514BA860800BF0781 /* Dock.m in Sources */, 335 | 552AC0711C9A6326002C0C82 /* StatusBar.m in Sources */, 336 | FA3250D714BA860800BF0781 /* Growl.m in Sources */, 337 | FA3250D914BA860800BF0781 /* Path.m in Sources */, 338 | FA3250DB14BA860800BF0781 /* Sound.m in Sources */, 339 | FA3250C314BA85E700BF0781 /* ContentView.m in Sources */, 340 | FA3250C514BA85E700BF0781 /* Utils.m in Sources */, 341 | FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */, 342 | FAE451CB14BA79C600190544 /* main.m in Sources */, 343 | 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */, 344 | FAE451D214BA79C600190544 /* AppDelegate.m in Sources */, 345 | 6F169DA718CC332E005EDDF3 /* Command.m in Sources */, 346 | 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */, 347 | 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */, 348 | 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */, 349 | 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */, 350 | 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */, 351 | 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */, 352 | 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */, 353 | F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */, 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | /* End PBXSourcesBuildPhase section */ 358 | 359 | /* Begin PBXVariantGroup section */ 360 | 88C0646414BDEC5800E4BCE2 /* Window.xib */ = { 361 | isa = PBXVariantGroup; 362 | children = ( 363 | 88C0646514BDEC5800E4BCE2 /* en */, 364 | ); 365 | name = Window.xib; 366 | sourceTree = ""; 367 | }; 368 | FAE451C714BA79C600190544 /* InfoPlist.strings */ = { 369 | isa = PBXVariantGroup; 370 | children = ( 371 | FAE451C814BA79C600190544 /* en */, 372 | ); 373 | name = InfoPlist.strings; 374 | sourceTree = ""; 375 | }; 376 | FAE451CD14BA79C600190544 /* Credits.rtf */ = { 377 | isa = PBXVariantGroup; 378 | children = ( 379 | FAE451CE14BA79C600190544 /* en */, 380 | ); 381 | name = Credits.rtf; 382 | sourceTree = ""; 383 | }; 384 | FAE451D314BA79C600190544 /* MainMenu.xib */ = { 385 | isa = PBXVariantGroup; 386 | children = ( 387 | FAE451D414BA79C600190544 /* en */, 388 | ); 389 | name = MainMenu.xib; 390 | sourceTree = ""; 391 | }; 392 | /* End PBXVariantGroup section */ 393 | 394 | /* Begin XCBuildConfiguration section */ 395 | FAE451D614BA79C600190544 /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 400 | CLANG_ENABLE_OBJC_ARC = YES; 401 | COPY_PHASE_STRIP = NO; 402 | GCC_C_LANGUAGE_STANDARD = gnu99; 403 | GCC_DYNAMIC_NO_PIC = NO; 404 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 405 | GCC_OPTIMIZATION_LEVEL = 0; 406 | GCC_PREPROCESSOR_DEFINITIONS = ( 407 | "DEBUG=1", 408 | "$(inherited)", 409 | ); 410 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 411 | GCC_VERSION = ""; 412 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 413 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 414 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 415 | GCC_WARN_UNUSED_VARIABLE = YES; 416 | MACOSX_DEPLOYMENT_TARGET = 10.8; 417 | ONLY_ACTIVE_ARCH = YES; 418 | SDKROOT = ""; 419 | }; 420 | name = Debug; 421 | }; 422 | FAE451D714BA79C600190544 /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ALWAYS_SEARCH_USER_PATHS = NO; 426 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 427 | CLANG_ENABLE_OBJC_ARC = YES; 428 | COPY_PHASE_STRIP = YES; 429 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 430 | GCC_C_LANGUAGE_STANDARD = gnu99; 431 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 432 | GCC_VERSION = ""; 433 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 434 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 435 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 436 | GCC_WARN_UNUSED_VARIABLE = YES; 437 | MACOSX_DEPLOYMENT_TARGET = 10.8; 438 | SDKROOT = ""; 439 | }; 440 | name = Release; 441 | }; 442 | FAE451D914BA79C600190544 /* Debug */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; 446 | CLANG_CXX_LIBRARY = "compiler-default"; 447 | COMBINE_HIDPI_IMAGES = YES; 448 | FRAMEWORK_SEARCH_PATHS = ( 449 | "$(inherited)", 450 | "\"$(SRCROOT)/MacGap\"", 451 | ); 452 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 453 | GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch"; 454 | GCC_VERSION = ""; 455 | INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; 456 | MACOSX_DEPLOYMENT_TARGET = 10.8; 457 | PRODUCT_NAME = "$(TARGET_NAME)"; 458 | SDKROOT = macosx; 459 | WRAPPER_EXTENSION = app; 460 | }; 461 | name = Debug; 462 | }; 463 | FAE451DA14BA79C600190544 /* Release */ = { 464 | isa = XCBuildConfiguration; 465 | buildSettings = { 466 | CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; 467 | CLANG_CXX_LIBRARY = "compiler-default"; 468 | COMBINE_HIDPI_IMAGES = YES; 469 | FRAMEWORK_SEARCH_PATHS = ( 470 | "$(inherited)", 471 | "\"$(SRCROOT)/MacGap\"", 472 | ); 473 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 474 | GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch"; 475 | GCC_VERSION = ""; 476 | INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; 477 | MACOSX_DEPLOYMENT_TARGET = 10.8; 478 | PRODUCT_NAME = "$(TARGET_NAME)"; 479 | SDKROOT = macosx; 480 | WRAPPER_EXTENSION = app; 481 | }; 482 | name = Release; 483 | }; 484 | /* End XCBuildConfiguration section */ 485 | 486 | /* Begin XCConfigurationList section */ 487 | FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */ = { 488 | isa = XCConfigurationList; 489 | buildConfigurations = ( 490 | FAE451D614BA79C600190544 /* Debug */, 491 | FAE451D714BA79C600190544 /* Release */, 492 | ); 493 | defaultConfigurationIsVisible = 0; 494 | defaultConfigurationName = Release; 495 | }; 496 | FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */ = { 497 | isa = XCConfigurationList; 498 | buildConfigurations = ( 499 | FAE451D914BA79C600190544 /* Debug */, 500 | FAE451DA14BA79C600190544 /* Release */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | defaultConfigurationName = Release; 504 | }; 505 | /* End XCConfigurationList section */ 506 | }; 507 | rootObject = FAE451B114BA79C600190544 /* Project object */; 508 | } 509 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4D486E78-E297-4CC3-AAAE-1A58EDAC87E6 9 | IDESourceControlProjectName 10 | MacGap 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | E290DE2F-0285-42FA-BA1D-7AF656980698 14 | https://github.com/rawcreative/macgap.git 15 | 16 | IDESourceControlProjectPath 17 | MacGap.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | E290DE2F-0285-42FA-BA1D-7AF656980698 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/rawcreative/macgap.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | E290DE2F-0285-42FA-BA1D-7AF656980698 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | E290DE2F-0285-42FA-BA1D-7AF656980698 36 | IDESourceControlWCCName 37 | MGFork 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacGapProject/MacGap1/573047871833b50f1acf233ed5e47785b4736fd7/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacGapProject/MacGap1/573047871833b50f1acf233ed5e47785b4736fd7/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 19 | 20 | 33 | 34 | 47 | 48 | 61 | 62 | 75 | 76 | 89 | 90 | 103 | 104 | 116 | 117 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/MacGap.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MacGap.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FAE451B914BA79C600190544 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 19 | 20 | 33 | 34 | 47 | 48 | 61 | 62 | 75 | 76 | 89 | 90 | 103 | 104 | 117 | 118 | 131 | 132 | 145 | 146 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/MacGap.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MacGap.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FAE451B914BA79C600190544 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MacGap/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MacGap 4 | // 5 | // Created by Alex MacCaw on 08/01/2012. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Classes/ContentView.h" 11 | 12 | #import "WindowController.h" 13 | 14 | @interface AppDelegate : NSObject 15 | 16 | @property (retain, nonatomic) WindowController *windowController; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /MacGap/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MacGap 4 | // 5 | // Created by Alex MacCaw on 08/01/2012. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | @synthesize windowController; 14 | 15 | - (void) applicationWillFinishLaunching:(NSNotification *)aNotification 16 | { 17 | 18 | 19 | } 20 | 21 | -(BOOL)applicationShouldHandleReopen:(NSApplication*)application 22 | hasVisibleWindows:(BOOL)visibleWindows{ 23 | if(!visibleWindows){ 24 | [self.windowController.window makeKeyAndOrderFront: nil]; 25 | } 26 | return YES; 27 | } 28 | 29 | - (void) applicationDidFinishLaunching:(NSNotification *)aNotification { 30 | self.windowController = [[WindowController alloc] initWithURL: kStartPage]; 31 | [self.windowController showWindow: [NSApplication sharedApplication].delegate]; 32 | self.windowController.contentView.webView.alphaValue = 1.0; 33 | self.windowController.contentView.alphaValue = 1.0; 34 | [self.windowController showWindow:self]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /MacGap/Classes/CallbackDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // CallbackDelegate.h 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/10/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "Command.h" 10 | 11 | @interface CallbackDelegate : Command { 12 | } 13 | 14 | @property JSObjectRef callback; 15 | 16 | - (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback; 17 | - (id) call; 18 | - (id) callWithParams:(id)firstOrNil, ... NS_REQUIRES_NIL_TERMINATION; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MacGap/Classes/CallbackDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // CallbackDelegate.m 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/10/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "CallbackDelegate.h" 10 | #import 11 | 12 | @implementation CallbackDelegate 13 | 14 | @synthesize callback; 15 | 16 | - (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback 17 | { 18 | if (!aCallback) 19 | return nil; 20 | if ([aCallback isKindOfClass:[WebUndefined class]]) 21 | return nil; 22 | 23 | self = [super initWithContext:aContext]; 24 | if (!self) 25 | return nil; 26 | 27 | callback = [aCallback JSObject]; 28 | JSValueProtect(context, callback); 29 | return self; 30 | } 31 | 32 | - (void) dealloc 33 | { 34 | if (callback) 35 | { 36 | JSValueUnprotect(context, callback); 37 | callback = nil; 38 | } 39 | } 40 | 41 | - (id) objectFromValue:(JSValueRef)val 42 | { 43 | JSStringRef jstr; 44 | NSString *rets; 45 | 46 | switch(JSValueGetType(context, val)) 47 | { 48 | case kJSTypeUndefined: 49 | case kJSTypeNull: 50 | return nil; 51 | case kJSTypeBoolean: 52 | return [NSNumber numberWithBool:JSValueToBoolean(context, val)]; 53 | case kJSTypeNumber: 54 | return [NSNumber numberWithDouble:JSValueToNumber(context, val, NULL)]; 55 | case kJSTypeString: 56 | jstr = JSValueToStringCopy(context, val, NULL); 57 | size_t sz = JSStringGetMaximumUTF8CStringSize(jstr); 58 | char *buf = (char*)malloc(sz); 59 | JSStringGetUTF8CString(jstr, buf, sz); 60 | rets = [NSString stringWithUTF8String:buf]; 61 | free(buf); 62 | return rets; 63 | case kJSTypeObject: 64 | // TODO: dictionary or something 65 | return nil; 66 | default: 67 | NSAssert(false, @"Invalid JavaScript type"); 68 | return nil; 69 | } 70 | } 71 | 72 | - (JSValueRef) valueFromObject:(id)obj 73 | { 74 | JSValueRef val = nil; 75 | if (!obj) 76 | { 77 | val = JSValueMakeNull(context); 78 | } 79 | else if ([obj isKindOfClass:[NSString class]]) 80 | { 81 | JSStringRef jstr = JSStringCreateWithUTF8CString([obj UTF8String]); 82 | val = JSValueMakeString(context, jstr); 83 | JSStringRelease(jstr); 84 | } 85 | else if ([obj isKindOfClass:[NSNumber class]]) 86 | { 87 | val = JSValueMakeNumber(context, [obj doubleValue]); 88 | } 89 | else if ([obj isKindOfClass:[NSDictionary class]]) 90 | { 91 | JSObjectRef o = JSObjectMake(context, NULL, NULL); 92 | for (NSString *key in obj) 93 | { 94 | JSStringRef kstr = JSStringCreateWithUTF8CString([key UTF8String]); 95 | JSValueRef v = [self valueFromObject:[obj objectForKey:key]]; 96 | 97 | JSObjectSetProperty(context, o, kstr, v, kJSPropertyAttributeNone, NULL); 98 | JSStringRelease(kstr); 99 | } 100 | val = o; 101 | } 102 | else if ([obj isKindOfClass:[NSArray class]]) 103 | { 104 | NSUInteger pcount = [obj count]; 105 | JSValueRef jsArgs[pcount]; 106 | NSUInteger i=0; 107 | for (id v in obj) 108 | { 109 | jsArgs[i++] = [self valueFromObject:v]; 110 | } 111 | val = JSObjectMakeArray(context, pcount, jsArgs, NULL); 112 | } 113 | else if ([obj isKindOfClass:[NSDate class]]) 114 | { 115 | NSTimeInterval secs = [obj timeIntervalSince1970]; 116 | JSValueRef jsArgs[1]; 117 | // call the Date(milliseconds) constructor in JS 118 | jsArgs[0] = JSValueMakeNumber(context, secs * 1000.0); 119 | val = JSObjectMakeDate(context, 1, jsArgs, NULL); 120 | } 121 | else 122 | { 123 | NSLog(@"Warning: unknown object type for: %@", obj); 124 | val = JSValueMakeUndefined(context); 125 | } 126 | return val; 127 | } 128 | 129 | - (id) call 130 | { 131 | NSAssert(callback, @"Callback required"); 132 | if (!JSObjectIsFunction(context, callback)) 133 | return nil; 134 | 135 | JSValueRef jsArgs[0]; 136 | JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, 0, jsArgs, NULL); 137 | return [self objectFromValue:ret]; 138 | } 139 | 140 | - (id) callWithParams:(id)firstOrNil, ... 141 | { 142 | NSAssert(callback, @"Callback required"); 143 | if (!JSObjectIsFunction(context, callback)) 144 | return nil; 145 | NSUInteger pcount = 0; 146 | id p; 147 | va_list args; 148 | va_start(args, firstOrNil); 149 | for (p=firstOrNil; p; p=va_arg(args, id)) 150 | { 151 | pcount++; 152 | } 153 | va_end(args); 154 | 155 | JSValueRef jsArgs[pcount]; 156 | NSUInteger j = 0; 157 | va_start(args, firstOrNil); 158 | for (p=firstOrNil; p; p=va_arg(args, id)) 159 | { 160 | jsArgs[j++] = [self valueFromObject:p]; 161 | } 162 | va_end(args); 163 | 164 | JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, j, jsArgs, NULL); 165 | return [self objectFromValue:ret]; 166 | } 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/App.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "WindowController.h" 4 | 5 | @interface App : NSObject { 6 | 7 | } 8 | 9 | @property (nonatomic, retain) WebView *webView; 10 | 11 | - (id) initWithWebView:(WebView *)view; 12 | 13 | - (void) terminate; 14 | - (void) activate; 15 | - (void) hide; 16 | - (void) unhide; 17 | - (void) beep; 18 | - (void) bounce; 19 | - (void) setCustomUserAgent:(NSString *)userAgentString; 20 | - (NSNumber*) systemIdleTime; 21 | @end 22 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/App.m: -------------------------------------------------------------------------------- 1 | #import "App.h" 2 | 3 | #import "JSEventHelper.h" 4 | 5 | @implementation App 6 | 7 | @synthesize webView; 8 | 9 | - (id) initWithWebView:(WebView *) view{ 10 | self = [super init]; 11 | 12 | if (self) { 13 | self.webView = view; 14 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 15 | selector: @selector(receiveSleepNotification:) 16 | name: NSWorkspaceWillSleepNotification object: NULL]; 17 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 18 | selector: @selector(receiveWakeNotification:) 19 | name: NSWorkspaceDidWakeNotification object: NULL]; 20 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 21 | selector: @selector(receiveActivateNotification:) 22 | name: NSWorkspaceDidActivateApplicationNotification object: NULL]; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | - (void) terminate { 29 | [NSApp terminate:nil]; 30 | } 31 | 32 | - (void) activate { 33 | [NSApp activateIgnoringOtherApps:YES]; 34 | } 35 | 36 | - (void) hide { 37 | [NSApp hide:nil]; 38 | } 39 | 40 | - (void) unhide { 41 | [NSApp unhide:nil]; 42 | } 43 | 44 | - (void)beep { 45 | NSBeep(); 46 | } 47 | 48 | - (void) bounce { 49 | [NSApp requestUserAttention:NSInformationalRequest]; 50 | } 51 | 52 | - (void)setCustomUserAgent:(NSString *)userAgentString { 53 | [self.webView setCustomUserAgent: userAgentString]; 54 | } 55 | 56 | - (void) open:(NSString*)url { 57 | [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]]; 58 | } 59 | 60 | - (void) launch:(NSString *)name { 61 | [[NSWorkspace sharedWorkspace] launchApplication:name]; 62 | } 63 | 64 | - (void)receiveSleepNotification:(NSNotification*)note{ 65 | [JSEventHelper triggerEvent:@"sleep" forWebView:self.webView]; 66 | } 67 | 68 | - (void) receiveWakeNotification:(NSNotification*)note{ 69 | [JSEventHelper triggerEvent:@"wake" forWebView:self.webView]; 70 | } 71 | 72 | - (void) receiveActivateNotification:(NSNotification*)notification{ 73 | NSDictionary* userInfo = [notification userInfo]; 74 | NSRunningApplication* runningApplication = [userInfo objectForKey:NSWorkspaceApplicationKey]; 75 | if (runningApplication) { 76 | NSMutableDictionary* applicationDidGetFocusDict = [[NSMutableDictionary alloc] initWithCapacity:2]; 77 | [applicationDidGetFocusDict setObject:runningApplication.localizedName 78 | forKey:@"localizedName"]; 79 | [applicationDidGetFocusDict setObject:[runningApplication.bundleURL absoluteString] 80 | forKey:@"bundleURL"]; 81 | 82 | [JSEventHelper triggerEvent:@"appActivated" withArgs:applicationDidGetFocusDict forWebView:self.webView]; 83 | } 84 | } 85 | 86 | 87 | 88 | 89 | /* 90 | To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType. 91 | */ 92 | - (NSNumber*)systemIdleTime { 93 | CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType); 94 | 95 | return [NSNumber numberWithDouble:timeSinceLastEvent]; 96 | } 97 | 98 | 99 | 100 | 101 | + (NSString*) webScriptNameForSelector:(SEL)selector 102 | { 103 | id result = nil; 104 | 105 | if (selector == @selector(open:)) { 106 | result = @"open"; 107 | } else if (selector == @selector(launch:)) { 108 | result = @"launch"; 109 | } else if (selector == @selector(setCustomUserAgent:)) { 110 | result = @"setCustomUserAgent"; 111 | } else if (selector == @selector(systemIdleTime)) { 112 | result = @"systemIdleTime"; 113 | } 114 | 115 | return result; 116 | } 117 | 118 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 119 | { 120 | return NO; 121 | } 122 | 123 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 124 | { 125 | return YES; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Command.h: -------------------------------------------------------------------------------- 1 | // 2 | // Command.h 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/10/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface Command : NSObject { 13 | JSContextRef context; 14 | } 15 | 16 | - (id) initWithContext:(JSContextRef)aContext; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Command.m: -------------------------------------------------------------------------------- 1 | // 2 | // Command.m 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/10/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "Command.h" 10 | #import 11 | 12 | @implementation Command 13 | 14 | - (id) initWithContext:(JSContextRef)aContext { 15 | self = [super init]; 16 | if (!self) 17 | return nil; 18 | context = aContext; 19 | JSGlobalContextRetain((JSGlobalContextRef)context); 20 | return self; 21 | } 22 | 23 | - (void)dealloc 24 | { 25 | if (context) 26 | JSGlobalContextRelease((JSGlobalContextRef)context); 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Dock.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Dock : NSObject { 4 | 5 | } 6 | - (void) setBadge:(NSString*)value; 7 | - (NSString *) badge; 8 | 9 | @property (readwrite, copy) NSString *badge; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Dock.m: -------------------------------------------------------------------------------- 1 | #import "Dock.h" 2 | 3 | @implementation Dock 4 | 5 | @synthesize badge; 6 | 7 | - (void) setBadge:(NSString *)value 8 | { 9 | NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; 10 | [tile setBadgeLabel:value]; 11 | } 12 | 13 | - (NSString *) badge 14 | { 15 | NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; 16 | return [tile badgeLabel]; 17 | } 18 | 19 | #pragma mark WebScripting Protocol 20 | 21 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 22 | { 23 | return NO; 24 | } 25 | 26 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 27 | { 28 | return NO; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Growl.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #define APP_GROWL_NOTIFICATION @"Growl Notification" 5 | 6 | @interface Growl : NSObject { 7 | 8 | } 9 | 10 | - (void) notify:(NSDictionary*)message; 11 | - (NSString *)applicationNameForGrowl; 12 | - (NSImage *)applicationIconForGrowl; 13 | - (NSDictionary *)registrationDictionaryForGrowl; 14 | - (void) growlNotificationWasClicked:(id)clickContext; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Growl.m: -------------------------------------------------------------------------------- 1 | #import "Growl.h" 2 | 3 | @implementation Growl 4 | 5 | - (id) init { 6 | if (self = [super init]) { 7 | NSBundle *myBundle = [NSBundle bundleForClass:[self class]]; 8 | NSString *growlPath = [[myBundle privateFrameworksPath] 9 | stringByAppendingPathComponent:@"Growl.framework"]; 10 | NSBundle *growlBundle = [NSBundle bundleWithPath:growlPath]; 11 | if (growlBundle && [growlBundle load]) { 12 | // Register ourselves as a Growl delegate 13 | [GrowlApplicationBridge setGrowlDelegate:self]; 14 | } else { 15 | NSLog(@"Could not load Growl.framework"); 16 | } 17 | } 18 | 19 | return self; 20 | } 21 | 22 | - (void) notify:(NSDictionary *)message { 23 | [GrowlApplicationBridge notifyWithTitle:[message valueForKey:@"title"] 24 | description:[message valueForKey:@"content"] 25 | notificationName:APP_GROWL_NOTIFICATION 26 | iconData:nil 27 | priority:0 28 | isSticky:false 29 | clickContext:@""]; 30 | } 31 | 32 | - (NSString *)applicationNameForGrowl { 33 | return @"Callback"; 34 | } 35 | 36 | - (NSImage *)applicationIconForGrowl { 37 | return [NSImage imageNamed:@"NSApplicationIcon"]; 38 | } 39 | 40 | - (NSDictionary *)registrationDictionaryForGrowl { 41 | NSArray *allowedNotifications = [NSArray arrayWithObject:APP_GROWL_NOTIFICATION]; 42 | NSArray *defaultNotifications = [NSArray arrayWithObject:APP_GROWL_NOTIFICATION]; 43 | 44 | NSDictionary *ticket = [NSDictionary dictionaryWithObjectsAndKeys: 45 | allowedNotifications, GROWL_NOTIFICATIONS_ALL, 46 | defaultNotifications, GROWL_NOTIFICATIONS_DEFAULT, 47 | nil]; 48 | 49 | return ticket; 50 | } 51 | 52 | - (void) growlNotificationWasClicked:(id)clickContext { 53 | [NSApp activateIgnoringOtherApps:YES]; 54 | } 55 | 56 | 57 | #pragma mark WebScripting Protocol 58 | 59 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 60 | { 61 | if (selector == @selector(notify:)) 62 | return NO; 63 | 64 | return YES; 65 | } 66 | 67 | + (NSString*) webScriptNameForSelector:(SEL)selector 68 | { 69 | id result = nil; 70 | 71 | if (selector == @selector(notify:)) { 72 | result = @"notify"; 73 | } 74 | 75 | return result; 76 | } 77 | 78 | // right now exclude all properties (eg keys) 79 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 80 | { 81 | return YES; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/MenuItemProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // MenuItemProxy.h 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/15/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "Command.h" 10 | #import "CallbackDelegate.h" 11 | 12 | @class MenuProxy; 13 | 14 | @interface MenuItemProxy : Command { 15 | NSMenuItem *item; 16 | CallbackDelegate *callback; 17 | } 18 | 19 | + (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem; 20 | 21 | - (MenuProxy*)addSubmenu; 22 | 23 | - (void) remove; 24 | - (void) setCallback:(WebScriptObject*)aCallback; 25 | - (void) setKey:(NSString*)keyCommand; 26 | - (void) setTitle:(NSString*)title; 27 | - (void) enable; 28 | - (void) disable; 29 | - (MenuProxy*)submenu; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/MenuItemProxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // MenuItemProxy.m 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/15/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "MenuItemProxy.h" 10 | #import "MenuProxy.h" 11 | 12 | @implementation MenuItemProxy 13 | 14 | - (id) initWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem 15 | { 16 | NSAssert(anItem, @"anItem required"); 17 | self = [super initWithContext:aContext]; 18 | if (!self) 19 | return nil; 20 | item = anItem; 21 | item.representedObject = self; 22 | 23 | return self; 24 | } 25 | 26 | + (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem 27 | { 28 | MenuItemProxy *proxy = [anItem representedObject]; 29 | if (proxy) 30 | { 31 | NSLog(@"MIP Cache hit"); 32 | NSAssert([proxy class] == [MenuItemProxy class], @"Bad proxy"); 33 | return proxy; 34 | } 35 | return [[MenuItemProxy alloc] initWithContext:aContext andMenuItem:anItem]; 36 | } 37 | 38 | - (NSString*) description 39 | { 40 | return [item description]; 41 | } 42 | 43 | - (MenuProxy*)addSubmenu 44 | { 45 | NSMenu *s = [item submenu]; 46 | if (!s) 47 | { 48 | s = [[NSMenu alloc] initWithTitle:@"FFFFFFOOOOO"]; 49 | [item setSubmenu:s]; 50 | } 51 | return [MenuProxy proxyWithContext:context andMenu:s]; 52 | } 53 | 54 | - (void) remove 55 | { 56 | NSMenu *menu = [item menu]; 57 | [menu removeItem:item]; 58 | } 59 | 60 | - (void)callCallback:(id)sender 61 | { 62 | [callback callWithParams:[sender title], nil]; 63 | } 64 | 65 | - (void) setCallback:(WebScriptObject*)aCallback 66 | { 67 | NSAssert(item, @"item required"); 68 | callback = [[CallbackDelegate alloc] initWithContext:context forCallback:aCallback]; 69 | [item setAction:@selector(callCallback:)]; 70 | [item setTarget:self]; 71 | } 72 | 73 | - (void)setKey:(NSString*)keyCommand 74 | { 75 | NSString *aKey = [MenuProxy getKeyFromString:keyCommand]; 76 | [item setKeyEquivalent:aKey]; 77 | 78 | NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand]; 79 | [item setKeyEquivalentModifierMask:modifiers]; 80 | } 81 | 82 | - (void) setTitle:(NSString*)title 83 | { 84 | [item setTitle:title]; 85 | } 86 | 87 | - (MenuProxy*)submenu; 88 | { 89 | // TODO: make this work as a property 90 | NSMenu *s = [item submenu]; 91 | if (!s) 92 | return nil; 93 | return [MenuProxy proxyWithContext:context andMenu:s]; 94 | } 95 | 96 | - (void) enable 97 | { 98 | [item setEnabled:YES]; 99 | } 100 | 101 | - (void) disable 102 | { 103 | [item setEnabled:NO]; 104 | } 105 | 106 | #pragma mark WebScripting protocol 107 | 108 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 109 | { 110 | return [self webScriptNameForSelector:selector] == nil; 111 | } 112 | 113 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 114 | { 115 | return YES; 116 | } 117 | 118 | + (NSString*) webScriptNameForSelector:(SEL)selector 119 | { 120 | id result = nil; 121 | 122 | if (selector == @selector(addSubmenu)) { 123 | result = @"addSubmenu"; 124 | } 125 | else if (selector == @selector(remove)) { 126 | result = @"remove"; 127 | } 128 | else if (selector == @selector(setCallback:)) { 129 | result = @"setCallback"; 130 | } 131 | else if (selector == @selector(setKey:)) { 132 | result = @"setKey"; 133 | } 134 | else if (selector == @selector(setTitle:)) { 135 | result = @"setTitle"; 136 | } 137 | else if (selector == @selector(submenu)) { 138 | result = @"submenu"; 139 | } 140 | else if (selector == @selector(enable)) { 141 | result = @"enable"; 142 | } 143 | else if (selector == @selector(disable)) { 144 | result = @"disable"; 145 | } 146 | 147 | return result; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/MenuProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // MenuProxy.h 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/14/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "Command.h" 10 | 11 | @class MenuItemProxy; 12 | 13 | @interface MenuProxy : Command { 14 | NSMenu *menu; 15 | } 16 | 17 | + (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu; 18 | 19 | - (MenuItemProxy*)addItemWithTitle:(NSString*)title 20 | keyEquivalent:(NSString*)aKey 21 | callback:(WebScriptObject*)aCallback 22 | atIndex:(NSInteger)index; 23 | 24 | - (MenuItemProxy*)addSeparator; 25 | - (MenuItemProxy*)itemForKey:(id)key; 26 | - (MenuProxy*)removeItem:(id)key; 27 | 28 | + (NSString*)getKeyFromString:(NSString*)keyCommand; 29 | + (NSUInteger*)getModifiersFromString:(NSString*)keyCommand; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/MenuProxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // MenuProxy.m 3 | // MacGap 4 | // 5 | // Created by Joe Hildebrand on 1/14/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "MenuProxy.h" 13 | #import "MenuItemProxy.h" 14 | 15 | static char REPRESENTED_OBJECT; 16 | 17 | @interface NSMenu (represented) 18 | @property (strong) id representedObject; 19 | @end 20 | 21 | @implementation NSMenu (represented) 22 | 23 | - (id) representedObject 24 | { 25 | return objc_getAssociatedObject(self, &REPRESENTED_OBJECT); 26 | } 27 | 28 | - (void) setRepresentedObject:(id)representedObject 29 | { 30 | objc_setAssociatedObject(self, 31 | &REPRESENTED_OBJECT, 32 | representedObject, 33 | OBJC_ASSOCIATION_RETAIN); 34 | } 35 | 36 | @end 37 | 38 | @implementation MenuProxy 39 | 40 | - (id) initWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu 41 | { 42 | self = [super initWithContext:aContext]; 43 | if (!self) 44 | return nil; 45 | menu = aMenu; 46 | menu.representedObject = self; 47 | return self; 48 | } 49 | 50 | + (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu 51 | { 52 | // singleton-ish. 53 | MenuProxy *ret = [aMenu representedObject]; 54 | if (ret) 55 | { 56 | NSLog(@"MP cache hit"); 57 | return ret; 58 | } 59 | return [[MenuProxy alloc] initWithContext:aContext andMenu:aMenu]; 60 | } 61 | 62 | - (void) dealloc 63 | { 64 | menu.representedObject = nil; 65 | } 66 | 67 | - (NSString*) description 68 | { 69 | return [menu description]; 70 | } 71 | 72 | static BOOL isNullish(id o) 73 | { 74 | if (!o) 75 | return YES; 76 | if ([o isKindOfClass:[WebUndefined class]]) 77 | return YES; 78 | return NO; 79 | } 80 | 81 | - (MenuItemProxy*)addItemWithTitle:(NSString*)title 82 | keyEquivalent:(NSString*)keyCommand 83 | callback:(WebScriptObject*)aCallback 84 | atIndex:(NSInteger)index 85 | { 86 | if (isNullish(title)) 87 | title = @""; 88 | 89 | NSString *aKey = [MenuProxy getKeyFromString:keyCommand]; 90 | NSMenuItem *item = nil; 91 | 92 | if(index) { 93 | item = [menu insertItemWithTitle:title action:nil keyEquivalent:aKey atIndex:index ]; 94 | } else { 95 | item = [menu addItemWithTitle:title action:nil keyEquivalent:aKey ]; 96 | 97 | } 98 | 99 | // Set the modifiers. 100 | NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand]; 101 | [item setKeyEquivalentModifierMask:modifiers]; 102 | 103 | if(!menu.supermenu) { 104 | NSMenu *s = [[NSMenu alloc] initWithTitle:title]; 105 | [item setSubmenu:s]; 106 | } 107 | 108 | MenuItemProxy *mip = [MenuItemProxy proxyWithContext:context andMenuItem:item]; 109 | if (!isNullish(aCallback)) 110 | [mip setCallback:aCallback]; 111 | 112 | 113 | return mip; 114 | } 115 | 116 | + (NSString*)getKeyFromString:(NSString*)keyCommand { 117 | if (isNullish(keyCommand)) 118 | keyCommand = @""; 119 | 120 | // Obtain the key (if there are modifiers, it will be the last character). 121 | NSString *aKey = @""; 122 | if ([keyCommand length] > 0) { 123 | aKey = [keyCommand substringFromIndex:[keyCommand length] - 1]; 124 | } 125 | 126 | return aKey; 127 | } 128 | 129 | + (NSUInteger*)getModifiersFromString:(NSString*)keyCommand { 130 | // aKeys may optionally specify one or more modifiers. 131 | NSUInteger modifiers = 0; 132 | 133 | if ([keyCommand rangeOfString:@"caps"].location != NSNotFound) modifiers += NSAlphaShiftKeyMask; 134 | if ([keyCommand rangeOfString:@"shift"].location != NSNotFound) modifiers += NSShiftKeyMask; 135 | if ([keyCommand rangeOfString:@"cmd"].location != NSNotFound) modifiers += NSCommandKeyMask; 136 | if ([keyCommand rangeOfString:@"ctrl"].location != NSNotFound) modifiers += NSControlKeyMask; 137 | if ([keyCommand rangeOfString:@"opt"].location != NSNotFound) modifiers += NSAlternateKeyMask; 138 | if ([keyCommand rangeOfString:@"alt"].location != NSNotFound) modifiers += NSAlternateKeyMask; 139 | 140 | return modifiers; 141 | } 142 | 143 | - (MenuItemProxy*)addSeparator 144 | { 145 | NSMenuItem *sep = [NSMenuItem separatorItem]; 146 | [menu addItem:sep]; 147 | return [MenuItemProxy proxyWithContext:context andMenuItem:sep]; 148 | } 149 | 150 | - (MenuItemProxy*)itemForKey:(id)key 151 | { 152 | if (isNullish(key)) 153 | return nil; 154 | NSMenuItem *item = nil; 155 | if ([key isKindOfClass:[NSNumber class]]) 156 | { 157 | item = [menu itemAtIndex:[key intValue]]; 158 | } 159 | else if ([key isKindOfClass:[NSString class]]) 160 | { 161 | item = [menu itemWithTitle:key]; 162 | if (!item) 163 | { 164 | // Try again, with ... appended. e.g. "Save..." 165 | item = [menu itemWithTitle: 166 | [key stringByAppendingString:@"\u2026"]]; 167 | } 168 | } 169 | if (!item) 170 | return nil; 171 | 172 | return [MenuItemProxy proxyWithContext:context andMenuItem:item]; 173 | } 174 | 175 | - (MenuProxy*)removeItem:(id)key 176 | { 177 | if (isNullish(key)) 178 | return nil; 179 | 180 | NSMenuItem *item = nil; 181 | if ([key isKindOfClass:[NSNumber class]]) 182 | { 183 | item = [menu itemAtIndex:[key intValue]]; 184 | } 185 | else if ([key isKindOfClass:[NSString class]]) 186 | { 187 | item = [menu itemWithTitle:key]; 188 | if (!item) 189 | { 190 | // Try again, with ... appended. e.g. "Save..." 191 | item = [menu itemWithTitle: 192 | [key stringByAppendingString:@"\u2026"]]; 193 | } 194 | } 195 | if (!item) 196 | return nil; 197 | 198 | [menu removeItem:item]; 199 | return [MenuProxy proxyWithContext:context andMenu:menu]; 200 | } 201 | 202 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 203 | { 204 | return [self webScriptNameForSelector:selector] == nil; 205 | } 206 | 207 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 208 | { 209 | return YES; 210 | } 211 | 212 | + (NSString*) webScriptNameForSelector:(SEL)selector 213 | { 214 | id result = nil; 215 | 216 | if (selector == @selector(addItemWithTitle:keyEquivalent:callback:atIndex:)) { 217 | result = @"addItem"; 218 | } 219 | else if (selector == @selector(addSeparator)) { 220 | result = @"addSeparator"; 221 | } 222 | else if (selector == @selector(itemForKey:)) { 223 | result = @"getItem"; 224 | } 225 | else if (selector == @selector(removeItem:)) { 226 | result = @"removeMenu"; 227 | } 228 | 229 | return result; 230 | } 231 | 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Notice.h: -------------------------------------------------------------------------------- 1 | // 2 | // Notice.h 3 | // MacGap 4 | // 5 | // Created by Christian Sullivan on 7/26/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WindowController.h" 11 | 12 | #define APP_NOTICE_NOTIFICATION @"Notice" 13 | 14 | @interface Notice : NSObject { 15 | 16 | } 17 | 18 | @property (nonatomic, retain) WebView *webView; 19 | 20 | - (id) initWithWebView:(WebView *)view; 21 | - (void) notify:(NSDictionary*)message; 22 | - (void) close:(NSString*)notificationId; 23 | + (BOOL) available; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Notice.m: -------------------------------------------------------------------------------- 1 | // 2 | // Notice.m 3 | // MacGap 4 | // 5 | // Created by Christian Sullivan on 7/26/12. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "Notice.h" 10 | 11 | #import "JSEventHelper.h" 12 | 13 | @implementation Notice 14 | 15 | - (id) initWithWebView:(WebView*)view 16 | { 17 | if(self = [super init]) { 18 | self.webView = view; 19 | [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; 20 | } 21 | return self; 22 | } 23 | 24 | - (void) notify:(NSDictionary *)message { 25 | NSUserNotification *notification = [[NSUserNotification alloc] init]; 26 | [notification setTitle:[message valueForKey:@"title"]]; 27 | [notification setInformativeText:[message valueForKey:@"content"]]; 28 | [notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]]; 29 | BOOL playSound = true; // optional parameter, false only when {sound: false} 30 | @try { 31 | NSNumber *s = [message valueForKey:@"sound"]; 32 | if ([[s className] isEqual: @"__NSCFBoolean"]) { 33 | playSound = [s boolValue]; 34 | } 35 | } 36 | @catch (NSException *exception) { 37 | } 38 | if (playSound) { 39 | [notification setSoundName:NSUserNotificationDefaultSoundName]; 40 | } 41 | NSString *id = @""; // optional, needed for close 42 | @try { 43 | id = [message valueForKey:@"id"]; 44 | } 45 | @catch (NSException *exception) { 46 | } 47 | [notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:id, @"id", nil]]; 48 | NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; 49 | [center scheduleNotification:notification]; 50 | } 51 | 52 | // close all notifications with id == notificationId or close all notifications if notificationId == "*" 53 | - (void) close:(NSString*)notificationId { 54 | NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; 55 | for(NSUserNotification * deliveredNote in center.deliveredNotifications) { 56 | if ([notificationId isEqualToString:@"*"] || [deliveredNote.userInfo[@"id"] isEqualToString:notificationId]) { 57 | [center removeDeliveredNotification: deliveredNote]; 58 | } 59 | } 60 | } 61 | 62 | + (BOOL) available { 63 | if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)]) 64 | return YES; 65 | 66 | return NO; 67 | } 68 | 69 | - (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification 70 | { 71 | NSString *notificationId = [notification.userInfo valueForKey:@"id"]; 72 | [JSEventHelper triggerEvent:@"macgap.notify.activated" forDetail:notificationId forWebView:self.webView]; 73 | } 74 | 75 | #pragma mark WebScripting Protocol 76 | 77 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 78 | { 79 | BOOL result = YES; 80 | if (selector == @selector(notify:)) 81 | result = NO; 82 | if (selector == @selector(close:)) 83 | result = NO; 84 | 85 | return result; 86 | } 87 | 88 | + (NSString*) webScriptNameForSelector:(SEL)selector 89 | { 90 | id result = nil; 91 | 92 | if (selector == @selector(notify:)) { 93 | result = @"notify"; 94 | } 95 | if (selector == @selector(close:)) { 96 | result = @"close"; 97 | } 98 | 99 | return result; 100 | } 101 | 102 | // right now exclude all properties (eg keys) 103 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 104 | { 105 | return YES; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Path.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Path : NSObject { 4 | 5 | } 6 | 7 | - (NSString *) application; 8 | - (NSString *) resource; 9 | - (NSString *) documents; 10 | - (NSString *) library; 11 | - (NSString *) home; 12 | - (NSString *) temp; 13 | 14 | @property (readonly,copy) NSString* application; 15 | @property (readonly,copy) NSString* resource; 16 | @property (readonly,copy) NSString* documents; 17 | @property (readonly,copy) NSString* library; 18 | @property (readonly,copy) NSString* home; 19 | @property (readonly,copy) NSString* temp; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Path.m: -------------------------------------------------------------------------------- 1 | #import "Path.h" 2 | 3 | @implementation Path 4 | 5 | @synthesize application; 6 | @synthesize resource; 7 | @synthesize documents; 8 | @synthesize library; 9 | @synthesize home; 10 | @synthesize temp; 11 | 12 | - (NSString *)application { 13 | return [[NSBundle mainBundle] bundlePath]; 14 | } 15 | 16 | - (NSString *)resource { 17 | return [[NSBundle mainBundle] resourcePath]; 18 | } 19 | 20 | - (NSString *)documents { 21 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 22 | return [paths objectAtIndex:0]; 23 | } 24 | 25 | - (NSString *)library { 26 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); 27 | NSLog( @"%@", paths ); 28 | return [paths objectAtIndex:0]; 29 | } 30 | 31 | - (NSString *)home { 32 | return NSHomeDirectory(); 33 | } 34 | 35 | - (NSString *)temp { 36 | return NSTemporaryDirectory(); 37 | } 38 | 39 | #pragma mark WebScripting Protocol 40 | 41 | /* checks whether a selector is acceptable to be called from JavaScript */ 42 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 43 | { 44 | return NO; 45 | } 46 | 47 | // right now exclude all properties (eg keys) 48 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 49 | { 50 | return NO; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Sound.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "Command.h" 3 | #import "CallbackDelegate.h" 4 | 5 | 6 | @interface Sound : Command { 7 | 8 | } 9 | 10 | // pending callbacks for sounds being played, to keep 11 | // ARC from freeing them too early 12 | @property (nonatomic, strong) NSMutableSet *pending; 13 | 14 | - (void) play:(NSString*)file onComplete:(WebScriptObject*)callback; 15 | - (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/Sound.m: -------------------------------------------------------------------------------- 1 | #import "Sound.h" 2 | 3 | 4 | @interface PlayDelegate : CallbackDelegate { 5 | } 6 | 7 | @property (nonatomic, weak) Sound *sound; 8 | 9 | - (id) initWithContext:(JSContextRef)aContext 10 | forCallback:(WebScriptObject*)aCallback 11 | withSound:(Sound*)aSound; 12 | @end 13 | 14 | @implementation PlayDelegate 15 | 16 | @synthesize sound; 17 | 18 | - (id) initWithContext:(JSContextRef)aContext 19 | forCallback:(WebScriptObject*)aCallback 20 | withSound:(Sound*)aSound 21 | { 22 | self = [super initWithContext:aContext forCallback:aCallback]; 23 | if (!self) 24 | return nil; 25 | sound = aSound; 26 | return self; 27 | } 28 | 29 | - (void)sound:(NSSound *)aSound didFinishPlaying:(BOOL)finishedPlaying { 30 | [self callWithParams:[aSound name], nil]; 31 | [sound.pending removeObject:self]; 32 | } 33 | 34 | @end 35 | 36 | @implementation Sound 37 | 38 | @synthesize pending; 39 | 40 | - (id) initWithContext:(JSContextRef)aContext { 41 | self = [super initWithContext:aContext]; 42 | if (!self) { 43 | return nil; 44 | } 45 | 46 | pending = [NSMutableSet new]; 47 | return self; 48 | } 49 | 50 | - (void) playSound:(NSSound*)sound onComplete:(WebScriptObject*)callback { 51 | if (callback != (id)[WebUndefined undefined]) { 52 | PlayDelegate *d = [[PlayDelegate alloc] initWithContext:context 53 | forCallback:callback 54 | withSound:self]; 55 | [pending addObject:d]; 56 | [sound setDelegate:d]; 57 | } 58 | [sound play]; 59 | } 60 | 61 | - (void) play:(NSString*)file onComplete:(WebScriptObject*)callback { 62 | NSURL* fileUrl = [NSURL fileURLWithPath:[[Utils sharedInstance] pathForResource:file]]; 63 | DebugNSLog(@"Sound file:%@", [fileUrl description]); 64 | 65 | NSSound* sound = [[NSSound alloc] initWithContentsOfURL:fileUrl byReference:YES]; 66 | [self playSound:sound onComplete:callback]; 67 | } 68 | 69 | - (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback { 70 | NSSound *systemSound = [NSSound soundNamed:name]; 71 | [self playSound:systemSound onComplete:callback]; 72 | } 73 | 74 | #pragma mark WebScripting Protocol 75 | 76 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { 77 | return [self webScriptNameForSelector:selector] == nil; 78 | } 79 | 80 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name { 81 | return YES; 82 | } 83 | 84 | + (NSString*) webScriptNameForSelector:(SEL)selector { 85 | id result = nil; 86 | 87 | if (selector == @selector(play:onComplete:)) { 88 | result = @"play"; 89 | } 90 | else if (selector == @selector(playSystem:onComplete:)) { 91 | result = @"playSystem"; 92 | } 93 | 94 | return result; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/UserDefaults.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaults.h 3 | // MacGap 4 | // 5 | // Created by Jeff Hanbury on 16/04/2014. 6 | // Copyright (c) 2014 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "WindowController.h" 12 | 13 | @interface UserDefaults : NSObject 14 | 15 | @property (nonatomic, retain) WebView *webView; 16 | 17 | - (id) initWithWebView:(WebView *)view; 18 | - (NSString*) getMyDefaults; 19 | - (NSDictionary*) myDefaultsDictionary; 20 | - (void) removeObjectForKey:(NSString*)key; 21 | - (NSArray*) getUserDefaultsKeys; 22 | 23 | - (NSString*) addPrefix:(NSString*)key; 24 | 25 | - (void) setString:(NSString*)key withValue:(NSString*)value; 26 | - (NSString*) getString:(NSString*)key; 27 | 28 | - (void) setInteger:(NSString*)key withValue:(NSString*)value; 29 | - (NSNumber*) getInteger:(NSString*)key; 30 | 31 | - (void) setBool:(NSString*)key withValue:(NSString*)value; 32 | - (NSNumber*) getBool:(NSString*)key; 33 | 34 | - (void) setFloat:(NSString*)key withValue:(NSString*)value; 35 | - (NSNumber*) getFloat:(NSString*)key; 36 | 37 | // Could also be implemented: 38 | //– setObject:forKey: 39 | //– setDouble:forKey: 40 | //– setURL:forKey: 41 | 42 | @end 43 | 44 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/UserDefaults.m: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaults.m 3 | // MacGap 4 | // 5 | // Created by Jeff Hanbury on 16/04/2014. 6 | // Copyright (c) 2014 Twitter. All rights reserved. 7 | // 8 | 9 | #import "UserDefaults.h" 10 | #import "JSEventHelper.h" 11 | 12 | @interface UserDefaults() { 13 | 14 | } 15 | 16 | -(void) setupNotificationCenter; 17 | 18 | @end 19 | 20 | 21 | @implementation UserDefaults 22 | 23 | - (id) initWithWebView:(WebView *) view{ 24 | self = [super init]; 25 | 26 | if (self) { 27 | self.webView = view; 28 | [self setupNotificationCenter]; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | 35 | -(void) setupNotificationCenter{ 36 | [[NSNotificationCenter defaultCenter] addObserver:self 37 | selector:@selector(defaultsChanged:) 38 | name:NSUserDefaultsDidChangeNotification 39 | object:nil]; 40 | } 41 | 42 | - (void)defaultsChanged:(NSNotification *)notification { 43 | NSDictionary* returnDict = [self myDefaultsDictionary]; 44 | [JSEventHelper triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView]; 45 | } 46 | 47 | - (NSString*) getMyDefaults { 48 | NSDictionary* myDefaults = [self myDefaultsDictionary]; 49 | 50 | return [[Utils sharedInstance] convertDictionaryToJSON:myDefaults]; 51 | } 52 | 53 | - (NSDictionary*) myDefaultsDictionary { 54 | NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"]; 55 | NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init]; 56 | 57 | // Get the user defaults. 58 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 59 | 60 | // Build up a dictionary containing just the items beginning with our 61 | // prefix. 62 | for (NSString* key in [self getUserDefaultsKeys]) { 63 | if ([key hasPrefix:prefix]) { 64 | id val = [defaults valueForKey:key]; 65 | [returnDict setObject:val forKey:key]; 66 | } 67 | } 68 | 69 | return returnDict; 70 | } 71 | 72 | - (NSArray*) getUserDefaultsKeys { 73 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 74 | return [[prefs dictionaryRepresentation] allKeys]; 75 | } 76 | 77 | - (void) removeObjectForKey:(NSString*)key { 78 | NSString* prefixedKey; 79 | prefixedKey = [self addPrefix:key]; 80 | 81 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey]; 82 | [[NSUserDefaults standardUserDefaults] synchronize]; 83 | } 84 | 85 | // Check we have a standard prefix for JS-modified keys, for security purposes. 86 | // If not, add it. This stops JavaScript from ever being able to modify keys 87 | // it did not create. 88 | - (NSString*) addPrefix:(NSString*)key { 89 | NSString* prefix; 90 | prefix = [kWebScriptNamespace stringByAppendingString:@"_"]; 91 | 92 | if (![key hasPrefix:prefix]) { 93 | key = [prefix stringByAppendingString:key]; 94 | } 95 | return key; 96 | } 97 | 98 | // String 99 | 100 | - (void) setString:(NSString*)key withValue:(NSString*)value { 101 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 102 | NSString* prefixedKey; 103 | prefixedKey = [self addPrefix:key]; 104 | [prefs setObject:value forKey:prefixedKey]; 105 | } 106 | 107 | - (NSString*) getString:(NSString *)key { 108 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 109 | return [prefs stringForKey:key]; 110 | } 111 | 112 | // All the following must convert their type to NSNumber for JavaScript. 113 | 114 | // Integer 115 | 116 | - (void) setInteger:(NSString*)key withValue:(NSString*)value { 117 | NSString* prefixedKey; 118 | prefixedKey = [self addPrefix:key]; 119 | 120 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 121 | NSInteger myInt = [value intValue]; 122 | [prefs setInteger:myInt forKey:prefixedKey]; 123 | } 124 | 125 | - (NSNumber*) getInteger:(NSString *)key { 126 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 127 | return [NSNumber numberWithInteger:[prefs integerForKey:key]]; 128 | } 129 | 130 | // Boolean 131 | 132 | - (void) setBool:(NSString*)key withValue:(NSString*)value { 133 | NSString* prefixedKey; 134 | prefixedKey = [self addPrefix:key]; 135 | 136 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 137 | BOOL myBool = [value boolValue]; 138 | [prefs setBool:myBool forKey:prefixedKey]; 139 | } 140 | 141 | - (NSNumber*) getBool:(NSString *)key { 142 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 143 | return [NSNumber numberWithBool:[prefs boolForKey:key]]; 144 | } 145 | 146 | // Float 147 | 148 | - (void) setFloat:(NSString*)key withValue:(NSString*)value { 149 | NSString* prefixedKey; 150 | prefixedKey = [self addPrefix:key]; 151 | 152 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 153 | float myFloat = [value floatValue]; 154 | [prefs setFloat:myFloat forKey:prefixedKey]; 155 | } 156 | 157 | - (NSNumber*) getFloat:(NSString *)key { 158 | NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 159 | return [NSNumber numberWithFloat:[prefs floatForKey:key]]; 160 | } 161 | 162 | 163 | #pragma mark WebScripting Protocol 164 | 165 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { 166 | return NO; 167 | } 168 | 169 | + (NSString*) webScriptNameForSelector:(SEL)selector { 170 | id result = nil; 171 | 172 | if (selector == @selector(getMyDefaults)) { 173 | result = @"getMyDefaults"; 174 | } 175 | 176 | if (selector == @selector(removeObjectForKey:)) { 177 | result = @"removeObjectForKey"; 178 | } 179 | 180 | else if (selector == @selector(setString:withValue:)) { 181 | result = @"setString"; 182 | } else if (selector == @selector(getString:)) { 183 | result = @"getString"; 184 | } 185 | 186 | else if (selector == @selector(setInteger:withValue:)) { 187 | result = @"setInteger"; 188 | } else if (selector == @selector(getInteger:)) { 189 | result = @"getInteger"; 190 | } 191 | 192 | else if (selector == @selector(setBool:withValue:)) { 193 | result = @"setBool"; 194 | } else if (selector == @selector(getBool:)) { 195 | result = @"getBool"; 196 | } 197 | 198 | else if (selector == @selector(setFloat:withValue:)) { 199 | result = @"setFloat"; 200 | } else if (selector == @selector(getFloat:)) { 201 | result = @"getFloat"; 202 | } 203 | 204 | return result; 205 | } 206 | 207 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name { 208 | return NO; 209 | } 210 | 211 | @end 212 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/fonts.h: -------------------------------------------------------------------------------- 1 | @interface Fonts : NSObject { 2 | } 3 | 4 | - (NSArray*) availableFonts; 5 | - (NSArray*) availableFontFamilies; 6 | - (NSArray*) availableMembersOfFontFamily:(NSString*)fontFamily; 7 | - (CGFloat) defaultLineHeightForFont:(NSString *)theFontName ofSize:(CGFloat)theFontSize; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /MacGap/Classes/Commands/fonts.m: -------------------------------------------------------------------------------- 1 | #import "fonts.h" 2 | 3 | @implementation Fonts 4 | 5 | 6 | - (NSArray*) availableFonts { 7 | return [[NSFontManager sharedFontManager] availableFonts]; 8 | } 9 | 10 | - (NSArray*) availableFontFamilies { 11 | return [[NSFontManager sharedFontManager] availableFontFamilies]; 12 | } 13 | 14 | - (NSArray*) availableMembersOfFontFamily:(NSString *)fontFamily { 15 | return [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily]; 16 | } 17 | 18 | - (CGFloat) defaultLineHeightForFont:(NSString*)theFontName ofSize:(CGFloat)theFontSize { 19 | NSFont *theFont = [NSFont fontWithName:theFontName size:theFontSize]; 20 | NSLayoutManager *lm = [[NSLayoutManager alloc] init]; 21 | 22 | return [lm defaultLineHeightForFont:theFont]; 23 | } 24 | 25 | 26 | #pragma mark WebScripting Protocol 27 | 28 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { 29 | return NO; 30 | } 31 | 32 | + (NSString*) webScriptNameForSelector:(SEL)selector { 33 | id result = nil; 34 | 35 | if (selector == @selector(availableMembersOfFontFamily:)) { 36 | result = @"availableMembersOfFontFamily"; 37 | } else if (selector == @selector(defaultLineHeightForFont:ofSize:)) { 38 | result = @"defaultLineHeightForFont"; 39 | } 40 | 41 | return result; 42 | } 43 | 44 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name { 45 | return NO; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /MacGap/Classes/Constants.h: -------------------------------------------------------------------------------- 1 | // Application constants 2 | 3 | #define kStartPage @"public/index.html" 4 | 5 | #define kStartFolder @"." 6 | 7 | #define kWebScriptNamespace @"macgap" -------------------------------------------------------------------------------- /MacGap/Classes/ContentView.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @class WebViewDelegate; 5 | 6 | @interface ContentView : NSView { 7 | IBOutlet WebView* webView; 8 | WebViewDelegate* delegate; 9 | } 10 | 11 | @property (retain) WebView* webView; 12 | @property (retain) WebViewDelegate* delegate; 13 | @property (strong) IBOutlet NSMenu *mainMenu; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MacGap/Classes/ContentView.m: -------------------------------------------------------------------------------- 1 | #import "ContentView.h" 2 | #import "WebViewDelegate.h" 3 | #import "AppDelegate.h" 4 | #import "JSEventHelper.h" 5 | 6 | @interface WebPreferences (WebPreferencesPrivate) 7 | - (void)_setLocalStorageDatabasePath:(NSString *)path; 8 | - (void) setLocalStorageEnabled: (BOOL) localStorageEnabled; 9 | - (void) setDatabasesEnabled:(BOOL)databasesEnabled; 10 | - (void) setDeveloperExtrasEnabled:(BOOL)developerExtrasEnabled; 11 | - (void) setWebGLEnabled:(BOOL)webGLEnabled; 12 | - (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled; 13 | @end 14 | 15 | @implementation ContentView 16 | 17 | @synthesize webView, delegate, mainMenu; 18 | 19 | - (void) awakeFromNib 20 | { 21 | WebPreferences *webPrefs = [WebPreferences standardPreferences]; 22 | 23 | NSString *cappBundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; 24 | NSString *applicationSupportFile = [@"~/Library/Application Support/" stringByExpandingTildeInPath]; 25 | NSString *savePath = [NSString pathWithComponents:[NSArray arrayWithObjects:applicationSupportFile, cappBundleName, @"LocalStorage", nil]]; 26 | [webPrefs _setLocalStorageDatabasePath:savePath]; 27 | [webPrefs setLocalStorageEnabled:YES]; 28 | [webPrefs setDatabasesEnabled:YES]; 29 | [webPrefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]]; 30 | [webPrefs setOfflineWebApplicationCacheEnabled:YES]; 31 | [webPrefs setWebGLEnabled:YES]; 32 | 33 | [self.webView setPreferences:webPrefs]; 34 | 35 | NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage 36 | sharedHTTPCookieStorage]; 37 | [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; 38 | 39 | [self.webView setApplicationNameForUserAgent: @"MacGap"]; 40 | 41 | self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]]; 42 | [self.webView setFrameLoadDelegate:self.delegate]; 43 | [self.webView setUIDelegate:self.delegate]; 44 | [self.webView setResourceLoadDelegate:self.delegate]; 45 | [self.webView setDownloadDelegate:self.delegate]; 46 | [self.webView setPolicyDelegate:self.delegate]; 47 | [self.webView setDrawsBackground:NO]; 48 | [self.webView setShouldCloseWithWindow:NO]; 49 | 50 | [self.webView setGroupName:@"MacGap"]; 51 | 52 | } 53 | 54 | - (void) windowResized:(NSNotification*)notification; 55 | { 56 | NSWindow* window = (NSWindow*)notification.object; 57 | NSSize size = [window frame].size; 58 | 59 | DebugNSLog(@"window width = %f, window height = %f", size.width, size.height); 60 | 61 | bool isFullScreen = (window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask; 62 | int titleBarHeight = isFullScreen ? 0 : [[Utils sharedInstance] titleBarHeight:window]; 63 | 64 | [self.webView setFrame:NSMakeRect(0, 0, size.width, size.height - titleBarHeight)]; 65 | [JSEventHelper triggerEvent:@"orientationchange" forWebView:self.webView]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /MacGap/Classes/JSEventHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Helper.h 3 | // MacGap 4 | // 5 | // Created by Liam Kaufman Simpkins on 12-01-22. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WindowController.h" 11 | 12 | @interface JSEventHelper : NSObject 13 | 14 | + (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView; 15 | + (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView; 16 | + (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView; 17 | + (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView; 18 | + (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MacGap/Classes/JSEventHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // Helper.m 3 | // MacGap 4 | // 5 | // Created by Liam Kaufman Simpkins on 12-01-22. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import "JSEventHelper.h" 10 | 11 | @implementation JSEventHelper 12 | 13 | + (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView { 14 | [self triggerEvent:event withArgs:[NSMutableDictionary dictionary] forObject:@"document" forWebView:webView]; 15 | } 16 | 17 | + (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView { 18 | [self triggerEvent:event withArgs:args forObject:@"document" forWebView:webView]; 19 | } 20 | 21 | + (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView { 22 | 23 | // Convert args Dictionary to JSON. 24 | NSString* jsonString = [[Utils sharedInstance] convertDictionaryToJSON:args]; 25 | 26 | // Create the event JavaScript and run it. 27 | NSString * str = [NSString stringWithFormat:@"var e = document.createEvent('Events'); e.initEvent('%@', true, false); e.data=%@; %@.dispatchEvent(e); ", event, jsonString, objName]; 28 | [webView stringByEvaluatingJavaScriptFromString:str]; 29 | } 30 | 31 | + (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView { 32 | [self triggerEvent:event forDetail:detail forObject:@"document" forWebView:webView]; 33 | } 34 | 35 | + (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView { 36 | NSString *detailEscaped = [detail stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; 37 | NSString *str = [NSString stringWithFormat:@"var e = new CustomEvent('%@', { 'detail': decodeURIComponent(\"%@\") }); %@.dispatchEvent(e); ", event, detailEscaped, objName]; 38 | [webView stringByEvaluatingJavaScriptFromString:str]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /MacGap/Classes/Utils.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #define DEG_EPS 0.001 5 | #define fequal(a,b) (fabs((a) - (b)) < DEG_EPS) 6 | #define fequalzero(a) (fabs(a) < DEG_EPS) 7 | 8 | @class LoadingView; 9 | 10 | @interface Utils : NSObject { 11 | } 12 | 13 | - (float) titleBarHeight:(NSWindow*)aWindow; 14 | - (NSString*) pathForResource:(NSString*)resourcepath; 15 | - (NSString*) convertDictionaryToJSON:(NSDictionary*)dict; 16 | - (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray; 17 | 18 | + (Utils*) sharedInstance; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MacGap/Classes/Utils.m: -------------------------------------------------------------------------------- 1 | #import "Utils.h" 2 | #import 3 | 4 | static Utils* sharedInstance = nil; 5 | 6 | @implementation Utils 7 | 8 | - (float) titleBarHeight:(NSWindow*)aWindow 9 | { 10 | NSRect frame = [aWindow frame]; 11 | NSRect contentRect = [NSWindow contentRectForFrameRect: frame 12 | styleMask: NSTitledWindowMask]; 13 | 14 | return (frame.size.height - contentRect.size.height); 15 | } 16 | 17 | - (NSString*) pathForResource:(NSString*)resourcepath 18 | { 19 | NSBundle * mainBundle = [NSBundle mainBundle]; 20 | NSMutableArray *directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]]; 21 | NSString *filename = [directoryParts lastObject]; 22 | [directoryParts removeLastObject]; 23 | 24 | NSString *directoryStr = [NSString stringWithFormat:@"%@/%@", kStartFolder, [directoryParts componentsJoinedByString:@"/"]]; 25 | return [mainBundle pathForResource:filename 26 | ofType:@"" 27 | inDirectory:directoryStr]; 28 | } 29 | 30 | - (NSString*) convertDictionaryToJSON:(NSDictionary*)dict { 31 | // Convert defaults Dictionary to JSON. 32 | NSError *error; 33 | NSData *jsonData = [NSJSONSerialization 34 | dataWithJSONObject:dict 35 | options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string 36 | error:&error]; 37 | 38 | NSString *jsonString; 39 | if (! jsonData) { 40 | NSLog(@"Got an error converting to JSON: %@", error); 41 | } 42 | else { 43 | jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 44 | } 45 | 46 | return jsonString; 47 | } 48 | 49 | // Convert JavaScript array (arrives as a WebScriptObject) into an NSArray of strings. 50 | - (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray { 51 | NSInteger count = [[jsArray valueForKey:@"length"] integerValue]; 52 | 53 | NSMutableArray *args = [NSMutableArray array]; 54 | for (int i = 0; i < count; i++) { 55 | NSString *item = [jsArray webScriptValueAtIndex:i]; 56 | if ([item isKindOfClass:[NSString class]]) { 57 | [args addObject:item]; 58 | } 59 | } 60 | 61 | return args; 62 | } 63 | 64 | #pragma mark - 65 | #pragma mark Singleton methods 66 | 67 | + (Utils*) sharedInstance 68 | { 69 | @synchronized(self) 70 | { 71 | if (sharedInstance == nil){ 72 | sharedInstance = [[Utils alloc] init]; 73 | } 74 | } 75 | return sharedInstance; 76 | } 77 | 78 | + (id) allocWithZone:(NSZone *)zone { 79 | @synchronized(self) { 80 | if (sharedInstance == nil) { 81 | sharedInstance = [super allocWithZone:zone]; 82 | return sharedInstance; // assignment and return on first allocation 83 | } 84 | } 85 | return nil; // on subsequent allocation attempts return nil 86 | } 87 | 88 | - (id) copyWithZone:(NSZone *)zone 89 | { 90 | return self; 91 | } 92 | 93 | @end -------------------------------------------------------------------------------- /MacGap/Classes/WebViewDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @class Sound; 5 | @class Dock; 6 | @class Growl; 7 | @class Notice; 8 | @class Path; 9 | @class App; 10 | @class Window; 11 | @class Clipboard; 12 | @class Fonts; 13 | @class MenuProxy; 14 | @class UserDefaults; 15 | @class StatusBar; 16 | 17 | @class WindowController; 18 | 19 | @interface WebViewDelegate : NSObject { 20 | Sound* sound; 21 | Dock* dock; 22 | Growl* growl; 23 | Notice* notice; 24 | Path* path; 25 | App* app; 26 | Window* window; 27 | Clipboard* clipboard; 28 | Fonts* fonts; 29 | NSMenu *mainMenu; 30 | UserDefaults* userDefaults; 31 | StatusBar* statusBar; 32 | } 33 | 34 | 35 | 36 | @property (nonatomic, retain) Sound* sound; 37 | @property (nonatomic, retain) Dock* dock; 38 | @property (nonatomic, retain) Growl* growl; 39 | @property (nonatomic, retain) Notice* notice; 40 | @property (nonatomic, retain) Path* path; 41 | @property (nonatomic, retain) App* app; 42 | @property (nonatomic, retain) Window* window; 43 | @property (nonatomic, retain) Clipboard* clipboard; 44 | @property (nonatomic, retain) Fonts* fonts; 45 | @property (nonatomic, retain) MenuProxy* menu; 46 | @property (nonatomic, retain) UserDefaults* userDefaults; 47 | @property (nonatomic, retain) StatusBar* statusBar; 48 | 49 | @property (nonatomic, retain) WindowController *requestedWindow; 50 | 51 | - (id) initWithMenu:(NSMenu*)menu; 52 | @end 53 | -------------------------------------------------------------------------------- /MacGap/Classes/WebViewDelegate.m: -------------------------------------------------------------------------------- 1 | #import "WebViewDelegate.h" 2 | #import "Sound.h" 3 | #import "Dock.h" 4 | #import "Growl.h" 5 | #import "Notice.h" 6 | #import "Path.h" 7 | #import "App.h" 8 | #import "Window.h" 9 | #import "WindowController.h" 10 | #import "Clipboard.h" 11 | #import "Fonts.h" 12 | #import "MenuProxy.h" 13 | #import "UserDefaults.h" 14 | #import "StatusBar.h" 15 | 16 | @implementation WebViewDelegate 17 | 18 | @synthesize sound; 19 | @synthesize dock; 20 | @synthesize growl; 21 | @synthesize notice; 22 | @synthesize path; 23 | @synthesize app; 24 | @synthesize window; 25 | @synthesize requestedWindow; 26 | @synthesize clipboard; 27 | @synthesize fonts; 28 | @synthesize menu; 29 | @synthesize userDefaults; 30 | @synthesize statusBar; 31 | 32 | - (id) initWithMenu:(NSMenu*)aMenu 33 | { 34 | self = [super init]; 35 | if (!self) 36 | return nil; 37 | 38 | mainMenu = aMenu; 39 | return self; 40 | } 41 | 42 | - (void) webView:(WebView*)webView didClearWindowObject:(WebScriptObject*)windowScriptObject forFrame:(WebFrame *)frame 43 | { 44 | JSContextRef context = [frame globalContext]; 45 | if (self.sound == nil) { self.sound = [[Sound alloc] initWithContext:context]; } 46 | if (self.dock == nil) { self.dock = [Dock new]; } 47 | if (self.growl == nil) { self.growl = [Growl new]; } 48 | if (self.path == nil) { self.path = [Path new]; } 49 | if (self.clipboard == nil) { self.clipboard = [Clipboard new]; } 50 | if (self.fonts == nil) { self.fonts = [Fonts new]; } 51 | 52 | if (self.notice == nil && [Notice available] == YES) { 53 | self.notice = [[Notice alloc] initWithWebView:webView]; 54 | } 55 | 56 | if (self.app == nil) { 57 | self.app = [[App alloc] initWithWebView:webView]; 58 | } 59 | 60 | if (self.window == nil) { 61 | self.window = [[Window alloc] initWithWebView:webView]; 62 | } 63 | 64 | if (self.menu == nil) { 65 | self.menu = [MenuProxy proxyWithContext:context andMenu:mainMenu]; 66 | } 67 | 68 | if (self.userDefaults == nil) { 69 | self.userDefaults = [[UserDefaults alloc] initWithWebView:webView]; 70 | } 71 | 72 | if (self.statusBar == nil) { 73 | self.statusBar = [[StatusBar alloc] initWithContext:context]; 74 | } 75 | 76 | [windowScriptObject setValue:self forKey:kWebScriptNamespace]; 77 | } 78 | 79 | 80 | - (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles{ 81 | 82 | NSOpenPanel * openDlg = [NSOpenPanel openPanel]; 83 | 84 | [openDlg setCanChooseFiles:YES]; 85 | [openDlg setCanChooseDirectories:NO]; 86 | 87 | [openDlg beginWithCompletionHandler:^(NSInteger result){ 88 | if (result == NSFileHandlingPanelOKButton) { 89 | NSArray * files = [[openDlg URLs] valueForKey: @"relativePath"]; 90 | [resultListener chooseFilenames: files]; 91 | } else { 92 | [resultListener cancel]; 93 | } 94 | }]; 95 | } 96 | 97 | - (void) webView:(WebView*)webView addMessageToConsole:(NSDictionary*)message 98 | { 99 | if (![message isKindOfClass:[NSDictionary class]]) { 100 | return; 101 | } 102 | 103 | NSLog(@"JavaScript console: %@:%@: %@", 104 | [[message objectForKey:@"sourceURL"] lastPathComponent], // could be nil 105 | [message objectForKey:@"lineNumber"], 106 | [message objectForKey:@"message"]); 107 | } 108 | 109 | - (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame 110 | { 111 | NSAlert *alert = [[NSAlert alloc] init]; 112 | [alert addButtonWithTitle:@"OK"]; 113 | [alert setMessageText:message]; 114 | [alert setAlertStyle:NSWarningAlertStyle]; 115 | [alert runModal]; 116 | } 117 | 118 | - (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame 119 | { 120 | NSAlert *alert = [[NSAlert alloc] init]; 121 | [alert addButtonWithTitle:@"Yes"]; 122 | [alert addButtonWithTitle:@"No"]; 123 | [alert setMessageText:message]; 124 | [alert setAlertStyle:NSWarningAlertStyle]; 125 | 126 | if ([alert runModal] == NSAlertFirstButtonReturn) 127 | return YES; 128 | else 129 | return NO; 130 | } 131 | 132 | /* 133 | By default the size of a database is set to 0 [1]. When a database is being created 134 | it calls this delegate method to get an increase in quota size - or call an error. 135 | PS this method is defined in WebUIDelegatePrivate and may make it difficult, but 136 | not impossible [2], to get an app accepted into the mac app store. 137 | 138 | Further reading: 139 | [1] http://stackoverflow.com/questions/353808/implementing-a-webview-database-quota-delegate 140 | [2] http://stackoverflow.com/questions/4527905/how-do-i-enable-local-storage-in-my-webkit-based-application/4608549#4608549 141 | */ 142 | - (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier 143 | { 144 | static const unsigned long long defaultQuota = 5 * 1024 * 1024; 145 | if ([origin respondsToSelector: @selector(setQuota:)]) { 146 | [origin performSelector:@selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]]; 147 | } else { 148 | NSLog(@"could not increase quota for %lld", defaultQuota); 149 | } 150 | } 151 | 152 | - (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems 153 | { 154 | NSMutableArray *webViewMenuItems = [defaultMenuItems mutableCopy]; 155 | 156 | if (webViewMenuItems) 157 | { 158 | NSEnumerator *itemEnumerator = [defaultMenuItems objectEnumerator]; 159 | NSMenuItem *menuItem = nil; 160 | while ((menuItem = [itemEnumerator nextObject])) 161 | { 162 | NSInteger tag = [menuItem tag]; 163 | 164 | switch (tag) 165 | { 166 | case WebMenuItemTagOpenLinkInNewWindow: 167 | case WebMenuItemTagDownloadLinkToDisk: 168 | case WebMenuItemTagCopyLinkToClipboard: 169 | case WebMenuItemTagOpenImageInNewWindow: 170 | case WebMenuItemTagDownloadImageToDisk: 171 | case WebMenuItemTagCopyImageToClipboard: 172 | case WebMenuItemTagOpenFrameInNewWindow: 173 | case WebMenuItemTagGoBack: 174 | case WebMenuItemTagGoForward: 175 | case WebMenuItemTagStop: 176 | case WebMenuItemTagOpenWithDefaultApplication: 177 | case WebMenuItemTagReload: 178 | [webViewMenuItems removeObjectIdenticalTo: menuItem]; 179 | } 180 | } 181 | } 182 | 183 | return webViewMenuItems; 184 | } 185 | 186 | - (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request{ 187 | requestedWindow = [[WindowController alloc] initWithRequest:request]; 188 | return requestedWindow.contentView.webView; 189 | } 190 | 191 | - (void)webViewShow:(WebView *)sender{ 192 | [requestedWindow showWindow:sender]; 193 | } 194 | 195 | - (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener 196 | { 197 | [[NSWorkspace sharedWorkspace] openURL:[request URL]]; 198 | [listener ignore]; 199 | } 200 | 201 | #pragma mark WebScripting protocol 202 | 203 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 204 | { 205 | return YES; 206 | } 207 | 208 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 209 | { 210 | return NO; 211 | } 212 | 213 | 214 | @end 215 | -------------------------------------------------------------------------------- /MacGap/Classes/Window.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "WindowController.h" 4 | 5 | @interface Window : NSObject{ 6 | CGRect _oldRestoreFrame; 7 | } 8 | 9 | @property (retain, nonatomic) WindowController *windowController; 10 | @property (nonatomic, retain) WebView *webView; 11 | 12 | - (id) initWithWebView:(WebView *)view; 13 | - (void) open:(NSDictionary *)properties; 14 | - (void) move:(NSDictionary *)properties; 15 | - (void) resize:(NSDictionary *) properties; 16 | - (Boolean) isMaximized; 17 | - (CGFloat) getX; 18 | - (CGFloat) getY; 19 | - (void) maximize; 20 | - (void) restore; 21 | - (void) toggleFullscreen; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MacGap/Classes/Window.m: -------------------------------------------------------------------------------- 1 | #import "Window.h" 2 | 3 | @implementation Window 4 | 5 | @synthesize windowController, webView; 6 | 7 | - (id) initWithWebView:(WebView*)view 8 | { 9 | if(self = [super init]) { 10 | self.webView = view; 11 | } 12 | return self; 13 | } 14 | 15 | - (void) open:(NSDictionary *)properties 16 | { 17 | self.windowController = [[WindowController alloc] initWithURL:[properties valueForKey:@"url"]]; 18 | [self.windowController showWindow: [NSApplication sharedApplication].delegate]; 19 | [self.windowController.window makeKeyWindow]; 20 | } 21 | 22 | - (void) minimize { 23 | [[NSApp mainWindow] miniaturize:[NSApp mainWindow]]; 24 | } 25 | 26 | - (void) toggleFullscreen { 27 | [[NSApp mainWindow] toggleFullScreen:[NSApp mainWindow]]; 28 | } 29 | 30 | - (void) maximize { 31 | CGRect a = [NSApp mainWindow].frame; 32 | _oldRestoreFrame = CGRectMake(a.origin.x, a.origin.y, a.size.width, a.size.height); 33 | [[NSApp mainWindow] setFrame:[[NSScreen mainScreen] visibleFrame] display:YES]; 34 | } 35 | 36 | - (Boolean) isMaximized { 37 | NSRect a = [NSApp mainWindow].frame; 38 | NSRect b = [[NSScreen mainScreen] visibleFrame]; 39 | return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height; 40 | } 41 | 42 | - (CGFloat) getX { 43 | NSRect frame = [self.webView window].frame; 44 | return frame.origin.x; 45 | } 46 | 47 | - (CGFloat) getY { 48 | NSRect frame = [self.webView window].frame; 49 | return frame.origin.y; 50 | } 51 | 52 | - (void) move:(NSDictionary *)properties 53 | { 54 | NSRect frame = [self.webView window].frame; 55 | frame.origin.x = [[properties valueForKey:@"x"] doubleValue]; 56 | frame.origin.y = [[properties valueForKey:@"y"] doubleValue]; 57 | [[self.webView window] setFrame:frame display:YES]; 58 | 59 | } 60 | 61 | - (void) resize:(NSDictionary *) properties 62 | { 63 | NSRect frame = [self.webView window].frame; 64 | frame.size.width = [[properties valueForKey:@"width"] doubleValue]; 65 | frame.size.height = [[properties valueForKey:@"height"] doubleValue]; 66 | [[self.webView window] setFrame:frame display:YES]; 67 | } 68 | 69 | 70 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 71 | { 72 | return NO; 73 | } 74 | 75 | + (NSString*) webScriptNameForSelector:(SEL)selector{ 76 | id result = nil; 77 | 78 | if (selector == @selector(open:)) { 79 | result = @"open"; 80 | }else if (selector == @selector(move:)){ 81 | result = @"move"; 82 | }else if (selector == @selector(resize:)){ 83 | result = @"resize"; 84 | } 85 | 86 | return result; 87 | } 88 | 89 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 90 | { 91 | return YES; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /MacGap/Clipboard.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Clipboard : NSObject { 4 | 5 | } 6 | 7 | - (void) copy:(NSString*)text; 8 | - (NSString *) paste; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /MacGap/Clipboard.m: -------------------------------------------------------------------------------- 1 | // 2 | // clipboard.m 3 | // MacGap 4 | // 5 | // Created by David Zorychta on 2013-07-22. 6 | // Copyright (c) 2013 Twitter. All rights reserved. 7 | // 8 | 9 | #import "Clipboard.h" 10 | 11 | @implementation Clipboard 12 | 13 | - (void) copy:(NSString*)text { 14 | [[NSPasteboard generalPasteboard] clearContents]; 15 | [[NSPasteboard generalPasteboard] setString:text forType:NSStringPboardType]; 16 | } 17 | 18 | - (NSString *) paste { 19 | NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 20 | NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; 21 | NSDictionary *options = [NSDictionary dictionary]; 22 | BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; 23 | if (ok) { 24 | NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; 25 | return (NSString *) [objectsToPaste objectAtIndex:0]; 26 | } 27 | return @""; 28 | } 29 | 30 | + (NSString*) webScriptNameForSelector:(SEL)selector 31 | { 32 | id result = nil; 33 | 34 | if (selector == @selector(copy:)) { 35 | result = @"copy"; 36 | } 37 | 38 | return result; 39 | } 40 | 41 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 42 | { 43 | return NO; 44 | } 45 | 46 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 47 | { 48 | return YES; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /MacGap/Growl.framework/Growl: -------------------------------------------------------------------------------- 1 | Versions/Current/Growl -------------------------------------------------------------------------------- /MacGap/Growl.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /MacGap/Growl.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/A/Growl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacGapProject/MacGap1/573047871833b50f1acf233ed5e47785b4736fd7/MacGap/Growl.framework/Versions/A/Growl -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/A/Headers/Growl.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __OBJC__ 4 | # include 5 | #endif 6 | -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h: -------------------------------------------------------------------------------- 1 | // 2 | // GrowlApplicationBridge.h 3 | // Growl 4 | // 5 | // Created by Evan Schoenberg on Wed Jun 16 2004. 6 | // Copyright 2004-2006 The Growl Project. All rights reserved. 7 | // 8 | 9 | /*! 10 | * @header GrowlApplicationBridge.h 11 | * @abstract Defines the GrowlApplicationBridge class. 12 | * @discussion This header defines the GrowlApplicationBridge class as well as 13 | * the GROWL_PREFPANE_BUNDLE_IDENTIFIER constant. 14 | */ 15 | 16 | #ifndef __GrowlApplicationBridge_h__ 17 | #define __GrowlApplicationBridge_h__ 18 | 19 | #import 20 | #import 21 | #import 22 | 23 | //Forward declarations 24 | @protocol GrowlApplicationBridgeDelegate; 25 | 26 | //------------------------------------------------------------------------------ 27 | #pragma mark - 28 | 29 | /*! 30 | * @class GrowlApplicationBridge 31 | * @abstract A class used to interface with Growl. 32 | * @discussion This class provides a means to interface with Growl. 33 | * 34 | * Currently it provides a way to detect if Growl is installed and launch the 35 | * GrowlHelperApp if it's not already running. 36 | */ 37 | @interface GrowlApplicationBridge : NSObject { 38 | 39 | } 40 | 41 | /*! 42 | * @method isGrowlInstalled 43 | * @abstract Detects whether Growl is installed. 44 | * @discussion Determines if the Growl prefpane and its helper app are installed. 45 | * @result this method will forever return YES. 46 | */ 47 | + (BOOL) isGrowlInstalled __attribute__((deprecated)); 48 | 49 | /*! 50 | * @method isGrowlRunning 51 | * @abstract Detects whether GrowlHelperApp is currently running. 52 | * @discussion Cycles through the process list to find whether GrowlHelperApp is running and returns its findings. 53 | * @result Returns YES if GrowlHelperApp is running, NO otherwise. 54 | */ 55 | + (BOOL) isGrowlRunning; 56 | 57 | 58 | /*! 59 | * @method isMistEnabled 60 | * @abstract Gives the caller a fairly good indication of whether or not built-in notifications(Mist) will be used. 61 | * @discussion since this call makes use of isGrowlRunning it is entirely possible for this value to change between call and 62 | * executing a notification dispatch 63 | * @result Returns YES if Growl isn't reachable and the developer has not opted-out of 64 | * Mist and the user hasn't set the global mist enable key to false. 65 | */ 66 | + (BOOL)isMistEnabled; 67 | 68 | /*! 69 | * @method setShouldUseBuiltInNotifications 70 | * @abstract opt-out mechanism for the mist notification style in the event growl can't be reached. 71 | * @discussion if growl is unavailable due to not being installed or as a result of being turned off then 72 | * this option can enable/disable a built-in fire and forget display style 73 | * @param should Specifies whether or not the developer wants to opt-in (default) or opt out 74 | * of the built-in Mist style in the event Growl is unreachable. 75 | */ 76 | + (void)setShouldUseBuiltInNotifications:(BOOL)should; 77 | 78 | /*! 79 | * @method shouldUseBuiltInNotifications 80 | * @abstract returns the current opt-in state of the framework's use of the Mist display style. 81 | * @result Returns NO if the developer opt-ed out of Mist, the default value is YES. 82 | */ 83 | + (BOOL)shouldUseBuiltInNotifications; 84 | 85 | #pragma mark - 86 | 87 | /*! 88 | * @method setGrowlDelegate: 89 | * @abstract Set the object which will be responsible for providing and receiving Growl information. 90 | * @discussion This must be called before using GrowlApplicationBridge. 91 | * 92 | * The methods in the GrowlApplicationBridgeDelegate protocol are required 93 | * and return the basic information needed to register with Growl. 94 | * 95 | * The methods in the GrowlApplicationBridgeDelegate_InformalProtocol 96 | * informal protocol are individually optional. They provide a greater 97 | * degree of interaction between the application and growl such as informing 98 | * the application when one of its Growl notifications is clicked by the user. 99 | * 100 | * The methods in the GrowlApplicationBridgeDelegate_Installation_InformalProtocol 101 | * informal protocol are individually optional and are only applicable when 102 | * using the Growl-WithInstaller.framework which allows for automated Growl 103 | * installation. 104 | * 105 | * When this method is called, data will be collected from inDelegate, Growl 106 | * will be launched if it is not already running, and the application will be 107 | * registered with Growl. 108 | * 109 | * If using the Growl-WithInstaller framework, if Growl is already installed 110 | * but this copy of the framework has an updated version of Growl, the user 111 | * will be prompted to update automatically. 112 | * 113 | * @param inDelegate The delegate for the GrowlApplicationBridge. It must conform to the GrowlApplicationBridgeDelegate protocol. 114 | */ 115 | + (void) setGrowlDelegate:(NSObject *)inDelegate; 116 | 117 | /*! 118 | * @method growlDelegate 119 | * @abstract Return the object responsible for providing and receiving Growl information. 120 | * @discussion See setGrowlDelegate: for details. 121 | * @result The Growl delegate. 122 | */ 123 | + (NSObject *) growlDelegate; 124 | 125 | #pragma mark - 126 | 127 | /*! 128 | * @method notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext: 129 | * @abstract Send a Growl notification. 130 | * @discussion This is the preferred means for sending a Growl notification. 131 | * The notification name and at least one of the title and description are 132 | * required (all three are preferred). All other parameters may be 133 | * nil (or 0 or NO as appropriate) to accept default values. 134 | * 135 | * If using the Growl-WithInstaller framework, if Growl is not installed the 136 | * user will be prompted to install Growl. If the user cancels, this method 137 | * will have no effect until the next application session, at which time when 138 | * it is called the user will be prompted again. The user is also given the 139 | * option to not be prompted again. If the user does choose to install Growl, 140 | * the requested notification will be displayed once Growl is installed and 141 | * running. 142 | * 143 | * @param title The title of the notification displayed to the user. 144 | * @param description The full description of the notification displayed to the user. 145 | * @param notifName The internal name of the notification. Should be human-readable, as it will be displayed in the Growl preference pane. 146 | * @param iconData NSData object to show with the notification as its icon. If nil, the application's icon will be used instead. 147 | * @param priority The priority of the notification. The default value is 0; positive values are higher priority and negative values are lower priority. Not all Growl displays support priority. 148 | * @param isSticky If YES, the notification will remain on screen until clicked. Not all Growl displays support sticky notifications. 149 | * @param clickContext A context passed back to the Growl delegate if it implements -(void)growlNotificationWasClicked: and the notification is clicked. Not all display plugins support clicking. The clickContext must be plist-encodable (completely of NSString, NSArray, NSNumber, NSDictionary, and NSData types). 150 | */ 151 | + (void) notifyWithTitle:(NSString *)title 152 | description:(NSString *)description 153 | notificationName:(NSString *)notifName 154 | iconData:(NSData *)iconData 155 | priority:(signed int)priority 156 | isSticky:(BOOL)isSticky 157 | clickContext:(id)clickContext; 158 | 159 | /*! 160 | * @method notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:identifier: 161 | * @abstract Send a Growl notification. 162 | * @discussion This is the preferred means for sending a Growl notification. 163 | * The notification name and at least one of the title and description are 164 | * required (all three are preferred). All other parameters may be 165 | * nil (or 0 or NO as appropriate) to accept default values. 166 | * 167 | * If using the Growl-WithInstaller framework, if Growl is not installed the 168 | * user will be prompted to install Growl. If the user cancels, this method 169 | * will have no effect until the next application session, at which time when 170 | * it is called the user will be prompted again. The user is also given the 171 | * option to not be prompted again. If the user does choose to install Growl, 172 | * the requested notification will be displayed once Growl is installed and 173 | * running. 174 | * 175 | * @param title The title of the notification displayed to the user. 176 | * @param description The full description of the notification displayed to the user. 177 | * @param notifName The internal name of the notification. Should be human-readable, as it will be displayed in the Growl preference pane. 178 | * @param iconData NSData object to show with the notification as its icon. If nil, the application's icon will be used instead. 179 | * @param priority The priority of the notification. The default value is 0; positive values are higher priority and negative values are lower priority. Not all Growl displays support priority. 180 | * @param isSticky If YES, the notification will remain on screen until clicked. Not all Growl displays support sticky notifications. 181 | * @param clickContext A context passed back to the Growl delegate if it implements -(void)growlNotificationWasClicked: and the notification is clicked. Not all display plugins support clicking. The clickContext must be plist-encodable (completely of NSString, NSArray, NSNumber, NSDictionary, and NSData types). 182 | * @param identifier An identifier for this notification. Notifications with equal identifiers are coalesced. 183 | */ 184 | + (void) notifyWithTitle:(NSString *)title 185 | description:(NSString *)description 186 | notificationName:(NSString *)notifName 187 | iconData:(NSData *)iconData 188 | priority:(signed int)priority 189 | isSticky:(BOOL)isSticky 190 | clickContext:(id)clickContext 191 | identifier:(NSString *)identifier; 192 | 193 | /*! @method notifyWithDictionary: 194 | * @abstract Notifies using a userInfo dictionary suitable for passing to 195 | * NSDistributedNotificationCenter. 196 | * @param userInfo The dictionary to notify with. 197 | * @discussion Before Growl 0.6, your application would have posted 198 | * notifications using NSDistributedNotificationCenter by 199 | * creating a userInfo dictionary with the notification data. This had the 200 | * advantage of allowing you to add other data to the dictionary for programs 201 | * besides Growl that might be listening. 202 | * 203 | * This method allows you to use such dictionaries without being restricted 204 | * to using NSDistributedNotificationCenter. The keys for this dictionary 205 | * can be found in GrowlDefines.h. 206 | */ 207 | + (void) notifyWithDictionary:(NSDictionary *)userInfo; 208 | 209 | #pragma mark - 210 | 211 | /*! @method registerWithDictionary: 212 | * @abstract Register your application with Growl without setting a delegate. 213 | * @discussion When you call this method with a dictionary, 214 | * GrowlApplicationBridge registers your application using that dictionary. 215 | * If you pass nil, GrowlApplicationBridge will ask the delegate 216 | * (if there is one) for a dictionary, and if that doesn't work, it will look 217 | * in your application's bundle for an auto-discoverable plist. 218 | * (XXX refer to more information on that) 219 | * 220 | * If you pass a dictionary to this method, it must include the 221 | * GROWL_APP_NAME key, unless a delegate is set. 222 | * 223 | * This method is mainly an alternative to the delegate system introduced 224 | * with Growl 0.6. Without a delegate, you cannot receive callbacks such as 225 | * -growlIsReady (since they are sent to the delegate). You can, 226 | * however, set a delegate after registering without one. 227 | * 228 | * This method was introduced in Growl.framework 0.7. 229 | */ 230 | + (BOOL) registerWithDictionary:(NSDictionary *)regDict; 231 | 232 | /*! @method reregisterGrowlNotifications 233 | * @abstract Reregister the notifications for this application. 234 | * @discussion This method does not normally need to be called. If your 235 | * application changes what notifications it is registering with Growl, call 236 | * this method to have the Growl delegate's 237 | * -registrationDictionaryForGrowl method called again and the 238 | * Growl registration information updated. 239 | * 240 | * This method is now implemented using -registerWithDictionary:. 241 | */ 242 | + (void) reregisterGrowlNotifications; 243 | 244 | #pragma mark - 245 | 246 | /*! @method setWillRegisterWhenGrowlIsReady: 247 | * @abstract Tells GrowlApplicationBridge to register with Growl when Growl 248 | * launches (or not). 249 | * @discussion When Growl has started listening for notifications, it posts a 250 | * GROWL_IS_READY notification on the Distributed Notification 251 | * Center. GrowlApplicationBridge listens for this notification, using it to 252 | * perform various tasks (such as calling your delegate's 253 | * -growlIsReady method, if it has one). If this method is 254 | * called with YES, one of those tasks will be to reregister 255 | * with Growl (in the manner of -reregisterGrowlNotifications). 256 | * 257 | * This attribute is automatically set back to NO (the default) 258 | * after every GROWL_IS_READY notification. 259 | * @param flag YES if you want GrowlApplicationBridge to register with 260 | * Growl when next it is ready; NO if not. 261 | */ 262 | + (void) setWillRegisterWhenGrowlIsReady:(BOOL)flag; 263 | /*! @method willRegisterWhenGrowlIsReady 264 | * @abstract Reports whether GrowlApplicationBridge will register with Growl 265 | * when Growl next launches. 266 | * @result YES if GrowlApplicationBridge will register with Growl 267 | * when next it posts GROWL_IS_READY; NO if not. 268 | */ 269 | + (BOOL) willRegisterWhenGrowlIsReady; 270 | 271 | #pragma mark - 272 | 273 | /*! @method registrationDictionaryFromDelegate 274 | * @abstract Asks the delegate for a registration dictionary. 275 | * @discussion If no delegate is set, or if the delegate's 276 | * -registrationDictionaryForGrowl method returns 277 | * nil, this method returns nil. 278 | * 279 | * This method does not attempt to clean up the dictionary in any way - for 280 | * example, if it is missing the GROWL_APP_NAME key, the result 281 | * will be missing it too. Use +[GrowlApplicationBridge 282 | * registrationDictionaryByFillingInDictionary:] or 283 | * +[GrowlApplicationBridge 284 | * registrationDictionaryByFillingInDictionary:restrictToKeys:] to try 285 | * to fill in missing keys. 286 | * 287 | * This method was introduced in Growl.framework 0.7. 288 | * @result A registration dictionary. 289 | */ 290 | + (NSDictionary *) registrationDictionaryFromDelegate; 291 | 292 | /*! @method registrationDictionaryFromBundle: 293 | * @abstract Looks in a bundle for a registration dictionary. 294 | * @discussion This method looks in a bundle for an auto-discoverable 295 | * registration dictionary file using -[NSBundle 296 | * pathForResource:ofType:]. If it finds one, it loads the file using 297 | * +[NSDictionary dictionaryWithContentsOfFile:] and returns the 298 | * result. 299 | * 300 | * If you pass nil as the bundle, the main bundle is examined. 301 | * 302 | * This method does not attempt to clean up the dictionary in any way - for 303 | * example, if it is missing the GROWL_APP_NAME key, the result 304 | * will be missing it too. Use +[GrowlApplicationBridge 305 | * registrationDictionaryByFillingInDictionary:] or 306 | * +[GrowlApplicationBridge 307 | * registrationDictionaryByFillingInDictionary:restrictToKeys:] to try 308 | * to fill in missing keys. 309 | * 310 | * This method was introduced in Growl.framework 0.7. 311 | * @result A registration dictionary. 312 | */ 313 | + (NSDictionary *) registrationDictionaryFromBundle:(NSBundle *)bundle; 314 | 315 | /*! @method bestRegistrationDictionary 316 | * @abstract Obtains a registration dictionary, filled out to the best of 317 | * GrowlApplicationBridge's knowledge. 318 | * @discussion This method creates a registration dictionary as best 319 | * GrowlApplicationBridge knows how. 320 | * 321 | * First, GrowlApplicationBridge contacts the Growl delegate (if there is 322 | * one) and gets the registration dictionary from that. If no such dictionary 323 | * was obtained, GrowlApplicationBridge looks in your application's main 324 | * bundle for an auto-discoverable registration dictionary file. If that 325 | * doesn't exist either, this method returns nil. 326 | * 327 | * Second, GrowlApplicationBridge calls 328 | * +registrationDictionaryByFillingInDictionary: with whatever 329 | * dictionary was obtained. The result of that method is the result of this 330 | * method. 331 | * 332 | * GrowlApplicationBridge uses this method when you call 333 | * +setGrowlDelegate:, or when you call 334 | * +registerWithDictionary: with nil. 335 | * 336 | * This method was introduced in Growl.framework 0.7. 337 | * @result A registration dictionary. 338 | */ 339 | + (NSDictionary *) bestRegistrationDictionary; 340 | 341 | #pragma mark - 342 | 343 | /*! @method registrationDictionaryByFillingInDictionary: 344 | * @abstract Tries to fill in missing keys in a registration dictionary. 345 | * @discussion This method examines the passed-in dictionary for missing keys, 346 | * and tries to work out correct values for them. As of 0.7, it uses: 347 | * 348 | * Key Value 349 | * --- ----- 350 | * GROWL_APP_NAME CFBundleExecutableName 351 | * GROWL_APP_ICON_DATA The data of the icon of the application. 352 | * GROWL_APP_LOCATION The location of the application. 353 | * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL 354 | * 355 | * Keys are only filled in if missing; if a key is present in the dictionary, 356 | * its value will not be changed. 357 | * 358 | * This method was introduced in Growl.framework 0.7. 359 | * @param regDict The dictionary to fill in. 360 | * @result The dictionary with the keys filled in. This is an autoreleased 361 | * copy of regDict. 362 | */ 363 | + (NSDictionary *) registrationDictionaryByFillingInDictionary:(NSDictionary *)regDict; 364 | /*! @method registrationDictionaryByFillingInDictionary:restrictToKeys: 365 | * @abstract Tries to fill in missing keys in a registration dictionary. 366 | * @discussion This method examines the passed-in dictionary for missing keys, 367 | * and tries to work out correct values for them. As of 0.7, it uses: 368 | * 369 | * Key Value 370 | * --- ----- 371 | * GROWL_APP_NAME CFBundleExecutableName 372 | * GROWL_APP_ICON_DATA The data of the icon of the application. 373 | * GROWL_APP_LOCATION The location of the application. 374 | * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL 375 | * 376 | * Only those keys that are listed in keys will be filled in. 377 | * Other missing keys are ignored. Also, keys are only filled in if missing; 378 | * if a key is present in the dictionary, its value will not be changed. 379 | * 380 | * This method was introduced in Growl.framework 0.7. 381 | * @param regDict The dictionary to fill in. 382 | * @param keys The keys to fill in. If nil, any missing keys are filled in. 383 | * @result The dictionary with the keys filled in. This is an autoreleased 384 | * copy of regDict. 385 | */ 386 | + (NSDictionary *) registrationDictionaryByFillingInDictionary:(NSDictionary *)regDict restrictToKeys:(NSSet *)keys; 387 | 388 | /*! @brief Tries to fill in missing keys in a notification dictionary. 389 | * @param notifDict The dictionary to fill in. 390 | * @return The dictionary with the keys filled in. This will be a separate instance from \a notifDict. 391 | * @discussion This function examines the \a notifDict for missing keys, and 392 | * tries to get them from the last known registration dictionary. As of 1.1, 393 | * the keys that it will look for are: 394 | * 395 | * \li GROWL_APP_NAME 396 | * \li GROWL_APP_ICON_DATA 397 | * 398 | * @since Growl.framework 1.1 399 | */ 400 | + (NSDictionary *) notificationDictionaryByFillingInDictionary:(NSDictionary *)regDict; 401 | 402 | + (NSDictionary *) frameworkInfoDictionary; 403 | @end 404 | 405 | //------------------------------------------------------------------------------ 406 | #pragma mark - 407 | 408 | /*! 409 | * @protocol GrowlApplicationBridgeDelegate 410 | * @abstract Required protocol for the Growl delegate. 411 | * @discussion The methods in this protocol are required and are called 412 | * automatically as needed by GrowlApplicationBridge. See 413 | * +[GrowlApplicationBridge setGrowlDelegate:]. 414 | * See also GrowlApplicationBridgeDelegate_InformalProtocol. 415 | */ 416 | 417 | @protocol GrowlApplicationBridgeDelegate 418 | 419 | // -registrationDictionaryForGrowl has moved to the informal protocol as of 0.7. 420 | 421 | @end 422 | 423 | //------------------------------------------------------------------------------ 424 | #pragma mark - 425 | 426 | /*! 427 | * @category NSObject(GrowlApplicationBridgeDelegate_InformalProtocol) 428 | * @abstract Methods which may be optionally implemented by the GrowlDelegate. 429 | * @discussion The methods in this informal protocol will only be called if implemented by the delegate. 430 | */ 431 | @interface NSObject (GrowlApplicationBridgeDelegate_InformalProtocol) 432 | 433 | /*! 434 | * @method registrationDictionaryForGrowl 435 | * @abstract Return the dictionary used to register this application with Growl. 436 | * @discussion The returned dictionary gives Growl the complete list of 437 | * notifications this application will ever send, and it also specifies which 438 | * notifications should be enabled by default. Each is specified by an array 439 | * of NSString objects. 440 | * 441 | * For most applications, these two arrays can be the same (if all sent 442 | * notifications should be displayed by default). 443 | * 444 | * The NSString objects of these arrays will correspond to the 445 | * notificationName: parameter passed in 446 | * +[GrowlApplicationBridge 447 | * notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:] calls. 448 | * 449 | * The dictionary should have the required key object pairs: 450 | * key: GROWL_NOTIFICATIONS_ALL object: NSArray of NSString objects 451 | * key: GROWL_NOTIFICATIONS_DEFAULT object: NSArray of NSString objects 452 | * 453 | * The dictionary may have the following key object pairs: 454 | * key: GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES object: NSDictionary of key: notification name object: human-readable notification name 455 | * 456 | * You do not need to implement this method if you have an auto-discoverable 457 | * plist file in your app bundle. (XXX refer to more information on that) 458 | * 459 | * @result The NSDictionary to use for registration. 460 | */ 461 | - (NSDictionary *) registrationDictionaryForGrowl; 462 | 463 | /*! 464 | * @method applicationNameForGrowl 465 | * @abstract Return the name of this application which will be used for Growl bookkeeping. 466 | * @discussion This name is used both internally and in the Growl preferences. 467 | * 468 | * This should remain stable between different versions and incarnations of 469 | * your application. 470 | * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and 471 | * "SurfWriter Lite" are not. 472 | * 473 | * You do not need to implement this method if you are providing the 474 | * application name elsewhere, meaning in an auto-discoverable plist file in 475 | * your app bundle (XXX refer to more information on that) or in the result 476 | * of -registrationDictionaryForGrowl. 477 | * 478 | * @result The name of the application using Growl. 479 | */ 480 | - (NSString *) applicationNameForGrowl; 481 | 482 | /*! 483 | * @method applicationIconForGrowl 484 | * @abstract Return the NSImage to treat as the application icon. 485 | * @discussion The delegate may optionally return an NSImage 486 | * object to use as the application icon. If this method is not implemented, 487 | * {{{-applicationIconDataForGrowl}}} is tried. If that method is not 488 | * implemented, the application's own icon is used. Neither method is 489 | * generally needed. 490 | * @result The NSImage to treat as the application icon. 491 | */ 492 | - (NSImage *) applicationIconForGrowl; 493 | 494 | /*! 495 | * @method applicationIconDataForGrowl 496 | * @abstract Return the NSData to treat as the application icon. 497 | * @discussion The delegate may optionally return an NSData 498 | * object to use as the application icon; if this is not implemented, the 499 | * application's own icon is used. This is not generally needed. 500 | * @result The NSData to treat as the application icon. 501 | * @deprecated In version 1.1, in favor of {{{-applicationIconForGrowl}}}. 502 | */ 503 | - (NSData *) applicationIconDataForGrowl; 504 | 505 | /*! 506 | * @method growlIsReady 507 | * @abstract Informs the delegate that Growl has launched. 508 | * @discussion Informs the delegate that Growl (specifically, the 509 | * GrowlHelperApp) was launched successfully. The application can take actions 510 | * with the knowledge that Growl is installed and functional. 511 | */ 512 | - (void) growlIsReady; 513 | 514 | /*! 515 | * @method growlNotificationWasClicked: 516 | * @abstract Informs the delegate that a Growl notification was clicked. 517 | * @discussion Informs the delegate that a Growl notification was clicked. It 518 | * is only sent for notifications sent with a non-nil 519 | * clickContext, so if you want to receive a message when a notification is 520 | * clicked, clickContext must not be nil when calling 521 | * +[GrowlApplicationBridge notifyWithTitle: description:notificationName:iconData:priority:isSticky:clickContext:]. 522 | * @param clickContext The clickContext passed when displaying the notification originally via +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:]. 523 | */ 524 | - (void) growlNotificationWasClicked:(id)clickContext; 525 | 526 | /*! 527 | * @method growlNotificationTimedOut: 528 | * @abstract Informs the delegate that a Growl notification timed out. 529 | * @discussion Informs the delegate that a Growl notification timed out. It 530 | * is only sent for notifications sent with a non-nil 531 | * clickContext, so if you want to receive a message when a notification is 532 | * clicked, clickContext must not be nil when calling 533 | * +[GrowlApplicationBridge notifyWithTitle: description:notificationName:iconData:priority:isSticky:clickContext:]. 534 | * @param clickContext The clickContext passed when displaying the notification originally via +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:]. 535 | */ 536 | - (void) growlNotificationTimedOut:(id)clickContext; 537 | 538 | 539 | /*! 540 | * @method hasNetworkClientEntitlement 541 | * @abstract Used only in sandboxed situations since we don't know whether the app has com.apple.security.network.client entitlement 542 | * @discussion GrowlDelegate calls to find out if we have the com.apple.security.network.client entitlement, 543 | * since we can't find this out without hitting the sandbox. We only call it if we detect that the application is sandboxed. 544 | */ 545 | - (BOOL) hasNetworkClientEntitlement; 546 | 547 | @end 548 | 549 | #pragma mark - 550 | 551 | #endif /* __GrowlApplicationBridge_h__ */ 552 | -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/A/Headers/GrowlDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // GrowlDefines.h 3 | // 4 | 5 | #ifndef _GROWLDEFINES_H 6 | #define _GROWLDEFINES_H 7 | 8 | #ifdef __OBJC__ 9 | #define XSTR(x) (@x) 10 | #else 11 | #define XSTR CFSTR 12 | #endif 13 | 14 | /*! @header GrowlDefines.h 15 | * @abstract Defines all the notification keys. 16 | * @discussion Defines all the keys used for registration with Growl and for 17 | * Growl notifications. 18 | * 19 | * Most applications should use the functions or methods of Growl.framework 20 | * instead of posting notifications such as those described here. 21 | * @updated 2004-01-25 22 | */ 23 | 24 | // UserInfo Keys for Registration 25 | #pragma mark UserInfo Keys for Registration 26 | 27 | /*! @group Registration userInfo keys */ 28 | /* @abstract Keys for the userInfo dictionary of a GROWL_APP_REGISTRATION distributed notification. 29 | * @discussion The values of these keys describe the application and the 30 | * notifications it may post. 31 | * 32 | * Your application must register with Growl before it can post Growl 33 | * notifications (and have them not be ignored). However, as of Growl 0.6, 34 | * posting GROWL_APP_REGISTRATION notifications directly is no longer the 35 | * preferred way to register your application. Your application should instead 36 | * use Growl.framework's delegate system. 37 | * See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for 38 | * more information. 39 | */ 40 | 41 | /*! @defined GROWL_APP_NAME 42 | * @abstract The name of your application. 43 | * @discussion The name of your application. This should remain stable between 44 | * different versions and incarnations of your application. 45 | * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and 46 | * "SurfWriter Lite" are not. 47 | */ 48 | #define GROWL_APP_NAME XSTR("ApplicationName") 49 | /*! @defined GROWL_APP_ID 50 | * @abstract The bundle identifier of your application. 51 | * @discussion The bundle identifier of your application. This key should 52 | * be unique for your application while there may be several applications 53 | * with the same GROWL_APP_NAME. 54 | * This key is optional. 55 | */ 56 | #define GROWL_APP_ID XSTR("ApplicationId") 57 | /*! @defined GROWL_APP_ICON_DATA 58 | * @abstract The image data for your application's icon. 59 | * @discussion Image data representing your application's icon. This may be 60 | * superimposed on a notification icon as a badge, used as the notification 61 | * icon when a notification-specific icon is not supplied, or ignored 62 | * altogether, depending on the display. Must be in a format supported by 63 | * NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. 64 | * 65 | * Optional. Not supported by all display plugins. 66 | */ 67 | #define GROWL_APP_ICON_DATA XSTR("ApplicationIcon") 68 | /*! @defined GROWL_NOTIFICATIONS_DEFAULT 69 | * @abstract The array of notifications to turn on by default. 70 | * @discussion These are the names of the notifications that should be enabled 71 | * by default when your application registers for the first time. If your 72 | * application reregisters, Growl will look here for any new notification 73 | * names found in GROWL_NOTIFICATIONS_ALL, but ignore any others. 74 | */ 75 | #define GROWL_NOTIFICATIONS_DEFAULT XSTR("DefaultNotifications") 76 | /*! @defined GROWL_NOTIFICATIONS_ALL 77 | * @abstract The array of all notifications your application can send. 78 | * @discussion These are the names of all of the notifications that your 79 | * application may post. See GROWL_NOTIFICATION_NAME for a discussion of good 80 | * notification names. 81 | */ 82 | #define GROWL_NOTIFICATIONS_ALL XSTR("AllNotifications") 83 | /*! @defined GROWL_NOTIFICATIONS_HUMAN_READABLE_DESCRIPTIONS 84 | * @abstract A dictionary of human-readable names for your notifications. 85 | * @discussion By default, the Growl UI will display notifications by the names given in GROWL_NOTIFICATIONS_ALL 86 | * which correspond to the GROWL_NOTIFICATION_NAME. This dictionary specifies the human-readable name to display. 87 | * The keys of the dictionary are GROWL_NOTIFICATION_NAME strings; the objects are the human-readable versions. 88 | * For any GROWL_NOTIFICATION_NAME not specific in this dictionary, the GROWL_NOTIFICATION_NAME will be displayed. 89 | * 90 | * This key is optional. 91 | */ 92 | #define GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES XSTR("HumanReadableNames") 93 | /*! @defined GROWL_NOTIFICATIONS_DESCRIPTIONS 94 | * @abstract A dictionary of descriptions of _when_ each notification occurs 95 | * @discussion This is an NSDictionary whose keys are GROWL_NOTIFICATION_NAME strings and whose objects are 96 | * descriptions of _when_ each notification occurs, such as "You received a new mail message" or 97 | * "A file finished downloading". 98 | * 99 | * This key is optional. 100 | */ 101 | #define GROWL_NOTIFICATIONS_DESCRIPTIONS XSTR("NotificationDescriptions") 102 | 103 | /*! @defined GROWL_TICKET_VERSION 104 | * @abstract The version of your registration ticket. 105 | * @discussion Include this key in a ticket plist file that you put in your 106 | * application bundle for auto-discovery. The current ticket version is 1. 107 | */ 108 | #define GROWL_TICKET_VERSION XSTR("TicketVersion") 109 | // UserInfo Keys for Notifications 110 | #pragma mark UserInfo Keys for Notifications 111 | 112 | /*! @group Notification userInfo keys */ 113 | /* @abstract Keys for the userInfo dictionary of a GROWL_NOTIFICATION distributed notification. 114 | * @discussion The values of these keys describe the content of a Growl 115 | * notification. 116 | * 117 | * Not all of these keys are supported by all displays. Only the name, title, 118 | * and description of a notification are universal. Most of the built-in 119 | * displays do support all of these keys, and most other visual displays 120 | * probably will also. But, as of 0.6, the Log, MailMe, and Speech displays 121 | * support only textual data. 122 | */ 123 | 124 | /*! @defined GROWL_NOTIFICATION_NAME 125 | * @abstract The name of the notification. 126 | * @discussion The name of the notification. Note that if you do not define 127 | * GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES when registering your ticket originally this name 128 | * will the one displayed within the Growl preference pane and should be human-readable. 129 | */ 130 | #define GROWL_NOTIFICATION_NAME XSTR("NotificationName") 131 | /*! @defined GROWL_NOTIFICATION_TITLE 132 | * @abstract The title to display in the notification. 133 | * @discussion The title of the notification. Should be very brief. 134 | * The title usually says what happened, e.g. "Download complete". 135 | */ 136 | #define GROWL_NOTIFICATION_TITLE XSTR("NotificationTitle") 137 | /*! @defined GROWL_NOTIFICATION_DESCRIPTION 138 | * @abstract The description to display in the notification. 139 | * @discussion The description should be longer and more verbose than the title. 140 | * The description usually tells the subject of the action, 141 | * e.g. "Growl-0.6.dmg downloaded in 5.02 minutes". 142 | */ 143 | #define GROWL_NOTIFICATION_DESCRIPTION XSTR("NotificationDescription") 144 | /*! @defined GROWL_NOTIFICATION_ICON 145 | * @discussion Image data for the notification icon. Image data must be in a format 146 | * supported by NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. 147 | * 148 | * Optional. Not supported by all display plugins. 149 | */ 150 | #define GROWL_NOTIFICATION_ICON_DATA XSTR("NotificationIcon") 151 | /*! @defined GROWL_NOTIFICATION_APP_ICON 152 | * @discussion Image data for the application icon, in case GROWL_APP_ICON does 153 | * not apply for some reason. Image data be in a format supported by NSImage, such 154 | * as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. 155 | * 156 | * Optional. Not supported by all display plugins. 157 | */ 158 | #define GROWL_NOTIFICATION_APP_ICON_DATA XSTR("NotificationAppIcon") 159 | /*! @defined GROWL_NOTIFICATION_PRIORITY 160 | * @discussion The priority of the notification as an integer number from 161 | * -2 to +2 (+2 being highest). 162 | * 163 | * Optional. Not supported by all display plugins. 164 | */ 165 | #define GROWL_NOTIFICATION_PRIORITY XSTR("NotificationPriority") 166 | /*! @defined GROWL_NOTIFICATION_STICKY 167 | * @discussion A Boolean number controlling whether the notification is sticky. 168 | * 169 | * Optional. Not supported by all display plugins. 170 | */ 171 | #define GROWL_NOTIFICATION_STICKY XSTR("NotificationSticky") 172 | /*! @defined GROWL_NOTIFICATION_CLICK_CONTEXT 173 | * @abstract Identifies which notification was clicked. 174 | * @discussion An identifier for the notification for clicking purposes. 175 | * 176 | * This will be passed back to the application when the notification is 177 | * clicked. It must be plist-encodable (a data, dictionary, array, number, or 178 | * string object), and it should be unique for each notification you post. 179 | * A good click context would be a UUID string returned by NSProcessInfo or 180 | * CFUUID. 181 | * 182 | * Optional. Not supported by all display plugins. 183 | */ 184 | #define GROWL_NOTIFICATION_CLICK_CONTEXT XSTR("NotificationClickContext") 185 | 186 | /*! @defined GROWL_NOTIFICATION_IDENTIFIER 187 | * @abstract An identifier for the notification for coalescing purposes. 188 | * Notifications with the same identifier fall into the same class; only 189 | * the last notification of a class is displayed on the screen. If a 190 | * notification of the same class is currently being displayed, it is 191 | * replaced by this notification. 192 | * 193 | * Optional. Not supported by all display plugins. 194 | */ 195 | #define GROWL_NOTIFICATION_IDENTIFIER XSTR("GrowlNotificationIdentifier") 196 | 197 | /*! @defined GROWL_APP_PID 198 | * @abstract The process identifier of the process which sends this 199 | * notification. If this field is set, the application will only receive 200 | * clicked and timed out notifications which originate from this process. 201 | * 202 | * Optional. 203 | */ 204 | #define GROWL_APP_PID XSTR("ApplicationPID") 205 | 206 | /*! @defined GROWL_NOTIFICATION_PROGRESS 207 | * @abstract If this key is set, it should contain a double value wrapped 208 | * in a NSNumber which describes some sort of progress (from 0.0 to 100.0). 209 | * If this is key is not set, no progress bar is shown. 210 | * 211 | * Optional. Not supported by all display plugins. 212 | */ 213 | #define GROWL_NOTIFICATION_PROGRESS XSTR("NotificationProgress") 214 | 215 | // Notifications 216 | #pragma mark Notifications 217 | 218 | /*! @group Notification names */ 219 | /* @abstract Names of distributed notifications used by Growl. 220 | * @discussion These are notifications used by applications (directly or 221 | * indirectly) to interact with Growl, and by Growl for interaction between 222 | * its components. 223 | * 224 | * Most of these should no longer be used in Growl 0.6 and later, in favor of 225 | * Growl.framework's GrowlApplicationBridge APIs. 226 | */ 227 | 228 | /*! @defined GROWL_APP_REGISTRATION 229 | * @abstract The distributed notification for registering your application. 230 | * @discussion This is the name of the distributed notification that can be 231 | * used to register applications with Growl. 232 | * 233 | * The userInfo dictionary for this notification can contain these keys: 234 | *
    235 | *
  • GROWL_APP_NAME
  • 236 | *
  • GROWL_APP_ICON_DATA
  • 237 | *
  • GROWL_NOTIFICATIONS_ALL
  • 238 | *
  • GROWL_NOTIFICATIONS_DEFAULT
  • 239 | *
240 | * 241 | * No longer recommended as of Growl 0.6. An alternate method of registering 242 | * is to use Growl.framework's delegate system. 243 | * See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for 244 | * more information. 245 | */ 246 | #define GROWL_APP_REGISTRATION XSTR("GrowlApplicationRegistrationNotification") 247 | /*! @defined GROWL_APP_REGISTRATION_CONF 248 | * @abstract The distributed notification for confirming registration. 249 | * @discussion The name of the distributed notification sent to confirm the 250 | * registration. Used by the Growl preference pane. Your application probably 251 | * does not need to use this notification. 252 | */ 253 | #define GROWL_APP_REGISTRATION_CONF XSTR("GrowlApplicationRegistrationConfirmationNotification") 254 | /*! @defined GROWL_NOTIFICATION 255 | * @abstract The distributed notification for Growl notifications. 256 | * @discussion This is what it all comes down to. This is the name of the 257 | * distributed notification that your application posts to actually send a 258 | * Growl notification. 259 | * 260 | * The userInfo dictionary for this notification can contain these keys: 261 | *
    262 | *
  • GROWL_NOTIFICATION_NAME (required)
  • 263 | *
  • GROWL_NOTIFICATION_TITLE (required)
  • 264 | *
  • GROWL_NOTIFICATION_DESCRIPTION (required)
  • 265 | *
  • GROWL_NOTIFICATION_ICON
  • 266 | *
  • GROWL_NOTIFICATION_APP_ICON
  • 267 | *
  • GROWL_NOTIFICATION_PRIORITY
  • 268 | *
  • GROWL_NOTIFICATION_STICKY
  • 269 | *
  • GROWL_NOTIFICATION_CLICK_CONTEXT
  • 270 | *
  • GROWL_APP_NAME (required)
  • 271 | *
272 | * 273 | * No longer recommended as of Growl 0.6. Three alternate methods of posting 274 | * notifications are +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:], 275 | * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext, and 276 | * Growl_PostNotification. 277 | */ 278 | #define GROWL_NOTIFICATION XSTR("GrowlNotification") 279 | /*! @defined GROWL_PING 280 | * @abstract A distributed notification to check whether Growl is running. 281 | * @discussion This is used by the Growl preference pane. If it receives a 282 | * GROWL_PONG, the preference pane takes this to mean that Growl is running. 283 | */ 284 | #define GROWL_PING XSTR("Honey, Mind Taking Out The Trash") 285 | /*! @defined GROWL_PONG 286 | * @abstract The distributed notification sent in reply to GROWL_PING. 287 | * @discussion GrowlHelperApp posts this in reply to GROWL_PING. 288 | */ 289 | #define GROWL_PONG XSTR("What Do You Want From Me, Woman") 290 | /*! @defined GROWL_IS_READY 291 | * @abstract The distributed notification sent when Growl starts up. 292 | * @discussion GrowlHelperApp posts this when it has begin listening on all of 293 | * its sources for new notifications. GrowlApplicationBridge (in 294 | * Growl.framework), upon receiving this notification, reregisters using the 295 | * registration dictionary supplied by its delegate. 296 | */ 297 | #define GROWL_IS_READY XSTR("Lend Me Some Sugar; I Am Your Neighbor!") 298 | 299 | 300 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX 301 | * @abstract Part of the name of the distributed notification sent when a supported notification is clicked. 302 | * @discussion When a Growl notification with a click context is clicked on by 303 | * the user, Growl posts a distributed notification whose name is in the format: 304 | * [NSString stringWithFormat:@"%@-%d-%@", appName, pid, GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX] 305 | * The GrowlApplicationBridge responds to this notification by calling a callback in its delegate. 306 | */ 307 | #define GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX XSTR("GrowlClicked!") 308 | 309 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX 310 | * @abstract Part of the name of the distributed notification sent when a supported notification times out without being clicked. 311 | * @discussion When a Growl notification with a click context times out, Growl posts a distributed notification 312 | * whose name is in the format: 313 | * [NSString stringWithFormat:@"%@-%d-%@", appName, pid, GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX] 314 | * The GrowlApplicationBridge responds to this notification by calling a callback in its delegate. 315 | * NOTE: The user may have actually clicked the 'close' button; this triggers an *immediate* time-out of the notification. 316 | */ 317 | #define GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX XSTR("GrowlTimedOut!") 318 | 319 | /*! @group Other symbols */ 320 | /* Symbols which don't fit into any of the other categories. */ 321 | 322 | /*! @defined GROWL_KEY_CLICKED_CONTEXT 323 | * @abstract Used internally as the key for the clickedContext passed over DNC. 324 | * @discussion This key is used in GROWL_NOTIFICATION_CLICKED, and contains the 325 | * click context that was supplied in the original notification. 326 | */ 327 | #define GROWL_KEY_CLICKED_CONTEXT XSTR("ClickedContext") 328 | /*! @defined GROWL_REG_DICT_EXTENSION 329 | * @abstract The filename extension for registration dictionaries. 330 | * @discussion The GrowlApplicationBridge in Growl.framework registers with 331 | * Growl by creating a file with the extension of .(GROWL_REG_DICT_EXTENSION) 332 | * and opening it in the GrowlHelperApp. This happens whether or not Growl is 333 | * running; if it was stopped, it quits immediately without listening for 334 | * notifications. 335 | */ 336 | #define GROWL_REG_DICT_EXTENSION XSTR("growlRegDict") 337 | 338 | 339 | #define GROWL_POSITION_PREFERENCE_KEY @"GrowlSelectedPosition" 340 | 341 | #endif //ndef _GROWLDEFINES_H 342 | -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 11C74 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | Growl 11 | CFBundleIdentifier 12 | com.growl.growlframework 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.3.1 19 | CFBundleSignature 20 | GRRR 21 | CFBundleVersion 22 | 1.3.1 23 | DTCompiler 24 | com.apple.compilers.llvm.clang.1_0 25 | DTPlatformBuild 26 | 4D199 27 | DTPlatformVersion 28 | GM 29 | DTSDKBuild 30 | 11C63 31 | DTSDKName 32 | macosx10.7 33 | DTXcode 34 | 0420 35 | DTXcodeBuild 36 | 4D199 37 | NSPrincipalClass 38 | GrowlApplicationBridge 39 | 40 | 41 | -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/A/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Resources/Info.plist 8 | 9 | SwzGt9RQsuVafBBrfBalB75dCwU= 10 | 11 | 12 | rules 13 | 14 | ^Resources/ 15 | 16 | ^Resources/.*\.lproj/ 17 | 18 | optional 19 | 20 | weight 21 | 1000 22 | 23 | ^Resources/.*\.lproj/locversion.plist$ 24 | 25 | omit 26 | 27 | weight 28 | 1100 29 | 30 | ^version.plist$ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /MacGap/Growl.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /MacGap/MacGap-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | application.icns 11 | CFBundleIdentifier 12 | com.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /MacGap/MacGap-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'MacGap' target in the 'MacGap' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #ifdef _DEBUG 7 | #define DebugNSLog(format, ...) NSLog(format, ## __VA_ARGS__) 8 | #else 9 | #define DebugNSLog(format, ...) 10 | #endif 11 | 12 | #import 13 | #import "Constants.h" 14 | #import "Utils.h" 15 | #endif 16 | -------------------------------------------------------------------------------- /MacGap/StatusBar.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "WindowController.h" 3 | 4 | @class MenuProxy; 5 | 6 | @interface StatusBar : NSObject { 7 | MenuProxy *statusMenu; 8 | } 9 | 10 | @property (nonatomic, retain) IBOutlet NSMenu *menu; 11 | @property (nonatomic, retain) MenuProxy *statusMenu; 12 | @property (nonatomic, retain) NSString *imageName; 13 | @property (nonatomic, retain) NSString *title; 14 | 15 | - (id)initWithContext:(JSContextRef)aContext; 16 | - (void)show; 17 | - (void)showWithImageName:(NSString *)name; 18 | - (void)showWithTitle:(NSString *)title; 19 | - (void)hide; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MacGap/StatusBar.m: -------------------------------------------------------------------------------- 1 | #import "StatusBar.h" 2 | #import "MenuProxy.h" 3 | 4 | @interface StatusBar() 5 | @property (nonatomic, retain) NSStatusItem *statusItem; 6 | 7 | - (void)setupMenu; 8 | @end 9 | 10 | 11 | @implementation StatusBar 12 | 13 | @synthesize statusMenu; 14 | 15 | - (id) initWithContext:(JSContextRef)aContext 16 | { 17 | if(self = [super init]) { 18 | if ([[NSBundle mainBundle] loadNibNamed:@"StatusMenu" owner:self topLevelObjects:nil]) { 19 | self.statusMenu = [MenuProxy proxyWithContext:aContext andMenu:self.menu]; 20 | } 21 | } 22 | 23 | return self; 24 | } 25 | 26 | - (void)show { 27 | // Give the image priority in-case both imageName and title are set 28 | if (self.imageName != nil) { 29 | [self showWithImageName:self.imageName]; 30 | } 31 | else if (self.title != nil) { 32 | [self showWithTitle:self.title]; 33 | } 34 | } 35 | 36 | - (void)showWithImageName:(NSString *)name { 37 | self.imageName = name; 38 | self.title = nil; 39 | [self setupMenu]; 40 | } 41 | 42 | - (void)showWithTitle:(NSString *)title { 43 | self.imageName = nil; 44 | self.title = title; 45 | [self setupMenu]; 46 | } 47 | 48 | - (void)hide { 49 | [[NSStatusBar systemStatusBar] removeStatusItem:self.statusItem]; 50 | self.statusItem = nil; 51 | } 52 | 53 | - (NSStatusItem *)statusItem { 54 | if (!_statusItem) { 55 | _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 56 | 57 | _statusItem.button.title = self.title; 58 | _statusItem.button.image = [self image]; 59 | 60 | [_statusItem.image setTemplate:YES]; 61 | _statusItem.highlightMode = YES; 62 | } 63 | return _statusItem; 64 | } 65 | 66 | - (NSImage *)image { 67 | return [NSImage imageNamed:self.imageName]; 68 | } 69 | 70 | - (void)setupMenu { 71 | self.statusItem.menu = self.menu; 72 | } 73 | 74 | #pragma mark WebScripting Protocol 75 | 76 | + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector 77 | { 78 | BOOL result = YES; 79 | if (selector == @selector(showWithImageName:)) 80 | result = NO; 81 | if (selector == @selector(showWithTitle:)) 82 | result = NO; 83 | if (selector == @selector(show)) 84 | result = NO; 85 | if (selector == @selector(hide)) 86 | result = NO; 87 | if (selector == @selector(statusMenu)) 88 | result = NO; 89 | 90 | return result; 91 | } 92 | 93 | + (NSString*) webScriptNameForSelector:(SEL)selector 94 | { 95 | id result = nil; 96 | 97 | if (selector == @selector(showWithImageName:)) { 98 | result = @"showWithImageName"; 99 | } 100 | if (selector == @selector(showWithTitle:)) { 101 | result = @"showWithTitle"; 102 | } 103 | if (selector == @selector(show)) { 104 | result = @"show"; 105 | } 106 | if (selector == @selector(close)) { 107 | result = @"hide"; 108 | } 109 | if (selector == @selector(statusMenu)) { 110 | result = @"statusMenu"; 111 | } 112 | 113 | return result; 114 | } 115 | 116 | // right now exclude all properties (eg keys) 117 | + (BOOL) isKeyExcludedFromWebScript:(const char*)name 118 | { 119 | BOOL result = YES; 120 | 121 | if (strcmp(name, "statusMenu")) { 122 | result = NO; 123 | } 124 | else if (strcmp(name, "title")) { 125 | result = NO; 126 | } 127 | else if (strcmp(name, "imageName")) { 128 | result = NO; 129 | } 130 | 131 | return result; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /MacGap/StatusMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /MacGap/WindowController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "ContentView.h" 3 | 4 | @interface WindowController : NSWindowController { 5 | 6 | } 7 | 8 | - (id) initWithURL:(NSString *) url; 9 | - (id) initWithRequest: (NSURLRequest *)request; 10 | @property (retain) NSURL * url; 11 | @property (retain) IBOutlet ContentView *contentView; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MacGap/WindowController.m: -------------------------------------------------------------------------------- 1 | #import "WindowController.h" 2 | 3 | 4 | @interface WindowController() { 5 | 6 | } 7 | 8 | -(void) notificationCenter; 9 | 10 | @end 11 | 12 | @implementation WindowController 13 | 14 | @synthesize contentView, url; 15 | 16 | - (id) initWithURL:(NSString *) relativeURL{ 17 | self = [super initWithWindowNibName:@"Window"]; 18 | self.url = [NSURL URLWithString:relativeURL relativeToURL:[[NSBundle mainBundle] resourceURL]]; 19 | 20 | [self.window setFrameAutosaveName:@"MacGapWindow"]; 21 | [self notificationCenter]; 22 | 23 | return self; 24 | } 25 | 26 | -(id) initWithRequest: (NSURLRequest *)request{ 27 | self = [super initWithWindowNibName:@"Window"]; 28 | [self notificationCenter]; 29 | [[self.contentView.webView mainFrame] loadRequest:request]; 30 | 31 | return self; 32 | } 33 | 34 | -(void) notificationCenter{ 35 | [[NSNotificationCenter defaultCenter] addObserver:self.contentView 36 | selector:@selector(windowResized:) 37 | name:NSWindowDidResizeNotification 38 | object:[self window]]; 39 | } 40 | 41 | - (void)windowDidLoad 42 | { 43 | [super windowDidLoad]; 44 | 45 | if (self.url != nil) { 46 | [self.contentView.webView setMainFrameURL:[self.url absoluteString]]; 47 | } 48 | 49 | 50 | // Implement this method to handle any initialization after your 51 | // window controller's window has been loaded from its nib file. 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /MacGap/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /MacGap/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MacGap/en.lproj/Window.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1070 5 | 11C74 6 | 1938 7 | 1138.23 8 | 567.00 9 | 10 | YES 11 | 12 | YES 13 | com.apple.InterfaceBuilder.CocoaPlugin 14 | com.apple.WebKitIBPlugin 15 | 16 | 17 | YES 18 | 1938 19 | 822 20 | 21 | 22 | 23 | YES 24 | NSWindowTemplate 25 | NSView 26 | NSCustomObject 27 | WebView 28 | 29 | 30 | YES 31 | com.apple.InterfaceBuilder.CocoaPlugin 32 | com.apple.WebKitIBPlugin 33 | 34 | 35 | PluginDependencyRecalculationVersion 36 | 37 | 38 | 39 | YES 40 | 41 | WindowController 42 | 43 | 44 | FirstResponder 45 | 46 | 47 | NSApplication 48 | 49 | 50 | 15 51 | 2 52 | {{196, 240}, {758, 410}} 53 | 544735232 54 | Window 55 | NSWindow 56 | 57 | 58 | 59 | 60 | 256 61 | 62 | YES 63 | 64 | 65 | 274 66 | 67 | YES 68 | 69 | YES 70 | Apple HTML pasteboard type 71 | Apple PDF pasteboard type 72 | Apple PICT pasteboard type 73 | Apple URL pasteboard type 74 | Apple Web Archive pasteboard type 75 | NSColor pasteboard type 76 | NSFilenamesPboardType 77 | NSStringPboardType 78 | NeXT RTFD pasteboard type 79 | NeXT Rich Text Format v1.0 pasteboard type 80 | NeXT TIFF v4.0 pasteboard type 81 | WebURLsWithTitlesPboardType 82 | public.png 83 | public.url 84 | public.url-name 85 | 86 | 87 | {758, 410} 88 | 89 | 90 | 91 | 2 92 | _NS:51 93 | 94 | 95 | 96 | 97 | 98 | YES 99 | 100 | YES 101 | WebKitDefaultFixedFontSize 102 | WebKitDefaultFontSize 103 | WebKitMinimumFontSize 104 | 105 | 106 | YES 107 | 108 | 109 | 110 | 111 | 112 | 113 | YES 114 | YES 115 | 116 | 117 | {758, 410} 118 | 119 | 120 | 121 | 122 | {{0, 0}, {1920, 1178}} 123 | {10000000000000, 10000000000000} 124 | 128 125 | YES 126 | 127 | 128 | 129 | 130 | YES 131 | 132 | 133 | contentView 134 | 135 | 136 | 137 | 23 138 | 139 | 140 | 141 | window 142 | 143 | 144 | 145 | 25 146 | 147 | 148 | 149 | title: contentView.webView.mainFrameTitle 150 | 151 | 152 | 153 | 154 | 155 | title: contentView.webView.mainFrameTitle 156 | title 157 | contentView.webView.mainFrameTitle 158 | 2 159 | 160 | 161 | 31 162 | 163 | 164 | 165 | webView 166 | 167 | 168 | 169 | 19 170 | 171 | 172 | 173 | 174 | YES 175 | 176 | 0 177 | 178 | YES 179 | 180 | 181 | 182 | 183 | 184 | -2 185 | 186 | 187 | File's Owner 188 | 189 | 190 | -1 191 | 192 | 193 | First Responder 194 | 195 | 196 | -3 197 | 198 | 199 | Application 200 | 201 | 202 | 1 203 | 204 | 205 | YES 206 | 207 | 208 | 209 | 210 | 211 | 2 212 | 213 | 214 | YES 215 | 216 | 217 | 218 | 219 | 220 | 5 221 | 222 | 223 | 224 | 225 | 226 | 227 | YES 228 | 229 | YES 230 | -1.IBPluginDependency 231 | -2.IBPluginDependency 232 | -3.IBPluginDependency 233 | 1.IBPluginDependency 234 | 1.IBWindowTemplateEditedContentRect 235 | 1.NSWindowTemplate.visibleAtLaunch 236 | 2.CustomClassName 237 | 2.IBPluginDependency 238 | 5.IBPluginDependency 239 | 240 | 241 | YES 242 | com.apple.InterfaceBuilder.CocoaPlugin 243 | com.apple.InterfaceBuilder.CocoaPlugin 244 | com.apple.InterfaceBuilder.CocoaPlugin 245 | com.apple.InterfaceBuilder.CocoaPlugin 246 | {{357, 418}, {480, 270}} 247 | 248 | ContentView 249 | com.apple.InterfaceBuilder.CocoaPlugin 250 | com.apple.WebKitIBPlugin 251 | 252 | 253 | 254 | YES 255 | 256 | 257 | 258 | 259 | 260 | YES 261 | 262 | 263 | 264 | 265 | 31 266 | 267 | 268 | 269 | YES 270 | 271 | ContentView 272 | NSView 273 | 274 | webView 275 | WebView 276 | 277 | 278 | webView 279 | 280 | webView 281 | WebView 282 | 283 | 284 | 285 | IBProjectSource 286 | ./Classes/ContentView.h 287 | 288 | 289 | 290 | WebView 291 | 292 | reloadFromOrigin: 293 | id 294 | 295 | 296 | reloadFromOrigin: 297 | 298 | reloadFromOrigin: 299 | id 300 | 301 | 302 | 303 | IBProjectSource 304 | ./Classes/WebView.h 305 | 306 | 307 | 308 | WindowController 309 | NSWindowController 310 | 311 | contentView 312 | ContentView 313 | 314 | 315 | contentView 316 | 317 | contentView 318 | ContentView 319 | 320 | 321 | 322 | IBProjectSource 323 | ./Classes/WindowController.h 324 | 325 | 326 | 327 | 328 | 0 329 | IBCocoaFramework 330 | 331 | com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 332 | 333 | 334 | YES 335 | 3 336 | 337 | 338 | -------------------------------------------------------------------------------- /MacGap/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MacGap 4 | // 5 | // Created by Alex MacCaw on 08/01/2012. 6 | // Copyright (c) 2012 Twitter. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MacGap 2 | 3 | The MacGap project provides HTML/JS/CSS developers an Xcode project for developing Native OSX Apps that run in OSX's WebView and take advantage of WebKit technologies. 4 | 5 | The project exposes a JavaScript API for OS X integration, such as displaying native OS X 10.9 notifications. The MacGap project is extremely lightweight and nimble; a blank application is about 980KB. 6 | 7 | ### Features: 8 | * tiny compiled app sizes 9 | * Mac App Store compatible 10 | * access to many Mac OS X-specific features 11 | 12 | ## Pre-requisites 13 | 14 | MacGap works on OSX 10.6 and later. 15 | 16 | Generate apps with the [macgap generator](http://github.com/maccman/macgap-rb), no compile necessary. 17 | ```bash 18 | gem install macgap 19 | 20 | macgap new myapp 21 | macgap build myapp 22 | ``` 23 | 24 | ## API 25 | 26 | MacGap exposes an object called `macgap` inside JavaScript. You can use it to alter the Dock icon and display Growl notifications, amongst other things. The API is documented in the WIKI on GitHub: https://github.com/maccman/macgap/wiki 27 | 28 | 29 | ## Attributes 30 | 31 | MacGap was forked/ported from Phonegap-mac. It's under the same license (MIT). 32 | 33 | ## Custom Build 34 | 35 | To build, make sure you have installed the latest Mac OSX Core Library. Download at [http://developer.apple.com/](http://developer.apple.com/). 36 | 37 | Just clone the repository and build in Xcode. The file `public/index.html` is loaded on startup. 38 | -------------------------------------------------------------------------------- /application.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacGapProject/MacGap1/573047871833b50f1acf233ed5e47785b4736fd7/application.icns -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MacGap 5 | 23 | 24 | 25 | 26 | 27 | 40 | 41 |

MacGap

42 | 43 | --------------------------------------------------------------------------------