├── .github └── workflows │ └── swift.yml ├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Art └── art.sketch ├── Demos ├── DSFDockTile Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── swiftpm │ │ └── Package.resolved ├── DSFDockTile Demo │ ├── AnimatedViewController.swift │ ├── AnimatedViewController.xib │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── AppIcon-macOS128.png │ │ │ ├── AppIcon-macOS128@2x.png │ │ │ ├── AppIcon-macOS16.png │ │ │ ├── AppIcon-macOS16@2x.png │ │ │ ├── AppIcon-macOS256.png │ │ │ ├── AppIcon-macOS256@2x.png │ │ │ ├── AppIcon-macOS32.png │ │ │ ├── AppIcon-macOS32@2x.png │ │ │ ├── AppIcon-macOS512.png │ │ │ ├── AppIcon-macOS512@2x.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── animate-charizard.dataset │ │ │ ├── Contents.json │ │ │ └── iu.gif │ │ ├── animate-shark.dataset │ │ │ ├── Contents.json │ │ │ └── shark.gif │ │ ├── baby-shark.imageset │ │ │ ├── Contents.json │ │ │ └── Image.png │ │ ├── demo-image.imageset │ │ │ ├── Contents.json │ │ │ └── demo_image.png │ │ └── marble.dataset │ │ │ ├── Contents.json │ │ │ └── marble.gif │ ├── AttentionViewController.swift │ ├── AttentionViewController.xib │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── DSFDockTile Demo.entitlements │ ├── DockViewController.swift │ ├── DockViewController.xib │ ├── ImageViewController.swift │ ├── ImageViewController.xib │ ├── Info.plist │ ├── NSInfoViewController.swift │ ├── NSInfoViewController.xib │ ├── XIBViewController.swift │ ├── XIBViewController.xib │ └── window-based │ │ ├── DockTile+SecondaryWindow.swift │ │ ├── WindowedDockTileViewController.swift │ │ └── WindowedDockTileViewController.xib ├── DSFDockTile Plugin Demo │ ├── DSFDockTile Plugin Demo.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── swiftpm │ │ │ └── Package.resolved │ ├── DSFDockTile Plugin Demo │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── dark.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── dark.png │ │ │ │ └── dark@2x.png │ │ │ └── light.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── light.png │ │ │ │ └── light@2x.png │ │ ├── ContentView.swift │ │ ├── DSFDockTile_Plugin_DemoApp.swift │ │ ├── LightDarkImage.swift │ │ └── Preview Content │ │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── DSFDockTile Plugin │ │ ├── DockTilePlugin.swift │ │ └── resources │ │ │ ├── dark.png │ │ │ └── light.png │ ├── DSFDockTile-Plugin-Demo-Info.plist │ └── DSFDockTilePlugin-Info.plist └── SwiftUI docktile demo │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── apple-icon.imageset │ │ ├── Contents.json │ │ └── iu.png │ └── marble.dataset │ │ ├── Contents.json │ │ └── marble.gif │ ├── ContentView.swift │ ├── DockTileContentView.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── SwiftUI_docktile_demo.entitlements │ └── SwiftUI_docktile_demoApp.swift ├── LICENSE ├── Package.resolved ├── Package.swift ├── README.md ├── Sources └── DSFDockTile │ ├── DSFDockTile+Animation.swift │ ├── DSFDockTile+Attention.swift │ ├── DSFDockTile+ConstantImage.swift │ ├── DSFDockTile+Core.swift │ ├── DSFDockTile+Image.swift │ ├── DSFDockTile+SwiftUI.swift │ ├── DSFDockTile+ViewController.swift │ ├── DSFDockTile.swift │ └── PrivacyInfo.xcprivacy └── Tests └── DSFDockTileTests └── DSFDockTileTests.swift /.github/workflows/swift.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Swift project 2 | 3 | name: Swift 4 | 5 | on: 6 | push: 7 | branches: [ "main" ] 8 | pull_request: 9 | branches: [ "main" ] 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: macos-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Build 19 | run: swift build -v -c release 20 | - name: Run tests 21 | run: swift test -v -c release 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | IDEWorkspaceChecks.plist 9 | .swiftpm/ 10 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Art/art.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Art/art.sketch -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2321A55126A13BF5003C94F8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2321A55026A13BF5003C94F8 /* AppDelegate.swift */; }; 11 | 2321A55326A13BF6003C94F8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2321A55226A13BF6003C94F8 /* Assets.xcassets */; }; 12 | 2321A55626A13BF6003C94F8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2321A55426A13BF6003C94F8 /* MainMenu.xib */; }; 13 | 2321A55E26A13E07003C94F8 /* ImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2321A55C26A13E07003C94F8 /* ImageViewController.swift */; }; 14 | 2321A55F26A13E07003C94F8 /* ImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2321A55D26A13E07003C94F8 /* ImageViewController.xib */; }; 15 | 2321A56226A13E15003C94F8 /* AnimatedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2321A56026A13E15003C94F8 /* AnimatedViewController.swift */; }; 16 | 2321A56326A13E15003C94F8 /* AnimatedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2321A56126A13E15003C94F8 /* AnimatedViewController.xib */; }; 17 | 2321A56626A13E26003C94F8 /* XIBViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2321A56426A13E26003C94F8 /* XIBViewController.swift */; }; 18 | 2321A56726A13E26003C94F8 /* XIBViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2321A56526A13E26003C94F8 /* XIBViewController.xib */; }; 19 | 2321A56F26A15194003C94F8 /* NSInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2321A56D26A15194003C94F8 /* NSInfoViewController.swift */; }; 20 | 2321A57026A15194003C94F8 /* NSInfoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2321A56E26A15194003C94F8 /* NSInfoViewController.xib */; }; 21 | 2321A57326A15299003C94F8 /* DockViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2321A57126A15299003C94F8 /* DockViewController.xib */; }; 22 | 2321A57426A15299003C94F8 /* DockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2321A57226A15299003C94F8 /* DockViewController.swift */; }; 23 | 2321A57B26A16928003C94F8 /* DSFDockTile in Frameworks */ = {isa = PBXBuildFile; productRef = 2321A57A26A16928003C94F8 /* DSFDockTile */; }; 24 | 232B361A27E94C6E001679EB /* SwiftUI_docktile_demoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232B361927E94C6E001679EB /* SwiftUI_docktile_demoApp.swift */; }; 25 | 232B361C27E94C6E001679EB /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232B361B27E94C6E001679EB /* ContentView.swift */; }; 26 | 232B361E27E94C6F001679EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 232B361D27E94C6F001679EB /* Assets.xcassets */; }; 27 | 232B362127E94C6F001679EB /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 232B362027E94C6F001679EB /* Preview Assets.xcassets */; }; 28 | 232B362727E94D33001679EB /* DockTileContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232B362627E94D33001679EB /* DockTileContentView.swift */; }; 29 | 232B362927E94E92001679EB /* DSFDockTile in Frameworks */ = {isa = PBXBuildFile; productRef = 232B362827E94E92001679EB /* DSFDockTile */; }; 30 | 235933D626A28D58002258AB /* AttentionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235933D426A28D58002258AB /* AttentionViewController.swift */; }; 31 | 235933D726A28D58002258AB /* AttentionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 235933D526A28D58002258AB /* AttentionViewController.xib */; }; 32 | 235933DD26A2AEF9002258AB /* DockTile+SecondaryWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235933DC26A2AEF9002258AB /* DockTile+SecondaryWindow.swift */; }; 33 | 235933E026A2B092002258AB /* WindowedDockTileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235933DE26A2B092002258AB /* WindowedDockTileViewController.swift */; }; 34 | 235933E126A2B092002258AB /* WindowedDockTileViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 235933DF26A2B092002258AB /* WindowedDockTileViewController.xib */; }; 35 | /* End PBXBuildFile section */ 36 | 37 | /* Begin PBXCopyFilesBuildPhase section */ 38 | 2356DB9926A4FA8700A39A25 /* Embed PlugIns */ = { 39 | isa = PBXCopyFilesBuildPhase; 40 | buildActionMask = 2147483647; 41 | dstPath = ""; 42 | dstSubfolderSpec = 13; 43 | files = ( 44 | ); 45 | name = "Embed PlugIns"; 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXCopyFilesBuildPhase section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | 2321A54D26A13BF5003C94F8 /* DSFDockTile Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DSFDockTile Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 2321A55026A13BF5003C94F8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 53 | 2321A55226A13BF6003C94F8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 2321A55526A13BF6003C94F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 55 | 2321A55C26A13E07003C94F8 /* ImageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewController.swift; sourceTree = ""; }; 56 | 2321A55D26A13E07003C94F8 /* ImageViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImageViewController.xib; sourceTree = ""; }; 57 | 2321A56026A13E15003C94F8 /* AnimatedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedViewController.swift; sourceTree = ""; }; 58 | 2321A56126A13E15003C94F8 /* AnimatedViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AnimatedViewController.xib; sourceTree = ""; }; 59 | 2321A56426A13E26003C94F8 /* XIBViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XIBViewController.swift; sourceTree = ""; }; 60 | 2321A56526A13E26003C94F8 /* XIBViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = XIBViewController.xib; sourceTree = ""; }; 61 | 2321A56D26A15194003C94F8 /* NSInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSInfoViewController.swift; sourceTree = ""; }; 62 | 2321A56E26A15194003C94F8 /* NSInfoViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NSInfoViewController.xib; sourceTree = ""; }; 63 | 2321A57126A15299003C94F8 /* DockViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DockViewController.xib; sourceTree = ""; }; 64 | 2321A57226A15299003C94F8 /* DockViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DockViewController.swift; sourceTree = ""; }; 65 | 2321A57826A1691C003C94F8 /* DSFDockTile */ = {isa = PBXFileReference; lastKnownFileType = folder; name = DSFDockTile; path = ..; sourceTree = ""; }; 66 | 232B361727E94C6E001679EB /* SwiftUI docktile demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SwiftUI docktile demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 67 | 232B361927E94C6E001679EB /* SwiftUI_docktile_demoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUI_docktile_demoApp.swift; sourceTree = ""; }; 68 | 232B361B27E94C6E001679EB /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 69 | 232B361D27E94C6F001679EB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 70 | 232B362027E94C6F001679EB /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 71 | 232B362227E94C6F001679EB /* SwiftUI_docktile_demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SwiftUI_docktile_demo.entitlements; sourceTree = ""; }; 72 | 232B362627E94D33001679EB /* DockTileContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DockTileContentView.swift; sourceTree = ""; }; 73 | 235933D426A28D58002258AB /* AttentionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttentionViewController.swift; sourceTree = ""; }; 74 | 235933D526A28D58002258AB /* AttentionViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AttentionViewController.xib; sourceTree = ""; }; 75 | 235933D826A29757002258AB /* DSFDockTile Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "DSFDockTile Demo.entitlements"; sourceTree = ""; }; 76 | 235933DC26A2AEF9002258AB /* DockTile+SecondaryWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DockTile+SecondaryWindow.swift"; sourceTree = ""; }; 77 | 235933DE26A2B092002258AB /* WindowedDockTileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowedDockTileViewController.swift; sourceTree = ""; }; 78 | 235933DF26A2B092002258AB /* WindowedDockTileViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WindowedDockTileViewController.xib; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 2321A54A26A13BF5003C94F8 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | 2321A57B26A16928003C94F8 /* DSFDockTile in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | 232B361427E94C6E001679EB /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | 232B362927E94E92001679EB /* DSFDockTile in Frameworks */, 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | /* End PBXFrameworksBuildPhase section */ 99 | 100 | /* Begin PBXGroup section */ 101 | 2321A54426A13BF5003C94F8 = { 102 | isa = PBXGroup; 103 | children = ( 104 | 2321A57826A1691C003C94F8 /* DSFDockTile */, 105 | 2321A54F26A13BF5003C94F8 /* DSFDockTile Demo */, 106 | 232B361827E94C6E001679EB /* SwiftUI docktile demo */, 107 | 2321A54E26A13BF5003C94F8 /* Products */, 108 | 2321A57926A16928003C94F8 /* Frameworks */, 109 | ); 110 | sourceTree = ""; 111 | }; 112 | 2321A54E26A13BF5003C94F8 /* Products */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 2321A54D26A13BF5003C94F8 /* DSFDockTile Demo.app */, 116 | 232B361727E94C6E001679EB /* SwiftUI docktile demo.app */, 117 | ); 118 | name = Products; 119 | sourceTree = ""; 120 | }; 121 | 2321A54F26A13BF5003C94F8 /* DSFDockTile Demo */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 235933D926A2AE68002258AB /* window-based */, 125 | 235933D826A29757002258AB /* DSFDockTile Demo.entitlements */, 126 | 2321A55026A13BF5003C94F8 /* AppDelegate.swift */, 127 | 2321A55226A13BF6003C94F8 /* Assets.xcassets */, 128 | 2321A55426A13BF6003C94F8 /* MainMenu.xib */, 129 | 2321A55C26A13E07003C94F8 /* ImageViewController.swift */, 130 | 2321A55D26A13E07003C94F8 /* ImageViewController.xib */, 131 | 2321A56026A13E15003C94F8 /* AnimatedViewController.swift */, 132 | 2321A56126A13E15003C94F8 /* AnimatedViewController.xib */, 133 | 2321A56426A13E26003C94F8 /* XIBViewController.swift */, 134 | 2321A56526A13E26003C94F8 /* XIBViewController.xib */, 135 | 2321A57226A15299003C94F8 /* DockViewController.swift */, 136 | 2321A57126A15299003C94F8 /* DockViewController.xib */, 137 | 2321A56D26A15194003C94F8 /* NSInfoViewController.swift */, 138 | 2321A56E26A15194003C94F8 /* NSInfoViewController.xib */, 139 | 235933D426A28D58002258AB /* AttentionViewController.swift */, 140 | 235933D526A28D58002258AB /* AttentionViewController.xib */, 141 | ); 142 | path = "DSFDockTile Demo"; 143 | sourceTree = ""; 144 | }; 145 | 2321A57926A16928003C94F8 /* Frameworks */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | ); 149 | name = Frameworks; 150 | sourceTree = ""; 151 | }; 152 | 232B361827E94C6E001679EB /* SwiftUI docktile demo */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 232B361927E94C6E001679EB /* SwiftUI_docktile_demoApp.swift */, 156 | 232B361B27E94C6E001679EB /* ContentView.swift */, 157 | 232B362627E94D33001679EB /* DockTileContentView.swift */, 158 | 232B361D27E94C6F001679EB /* Assets.xcassets */, 159 | 232B362227E94C6F001679EB /* SwiftUI_docktile_demo.entitlements */, 160 | 232B361F27E94C6F001679EB /* Preview Content */, 161 | ); 162 | path = "SwiftUI docktile demo"; 163 | sourceTree = ""; 164 | }; 165 | 232B361F27E94C6F001679EB /* Preview Content */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 232B362027E94C6F001679EB /* Preview Assets.xcassets */, 169 | ); 170 | path = "Preview Content"; 171 | sourceTree = ""; 172 | }; 173 | 235933D926A2AE68002258AB /* window-based */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 235933DC26A2AEF9002258AB /* DockTile+SecondaryWindow.swift */, 177 | 235933DE26A2B092002258AB /* WindowedDockTileViewController.swift */, 178 | 235933DF26A2B092002258AB /* WindowedDockTileViewController.xib */, 179 | ); 180 | path = "window-based"; 181 | sourceTree = ""; 182 | }; 183 | /* End PBXGroup section */ 184 | 185 | /* Begin PBXNativeTarget section */ 186 | 2321A54C26A13BF5003C94F8 /* DSFDockTile Demo */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = 2321A55926A13BF6003C94F8 /* Build configuration list for PBXNativeTarget "DSFDockTile Demo" */; 189 | buildPhases = ( 190 | 2321A54926A13BF5003C94F8 /* Sources */, 191 | 2321A54A26A13BF5003C94F8 /* Frameworks */, 192 | 2321A54B26A13BF5003C94F8 /* Resources */, 193 | 2356DB9926A4FA8700A39A25 /* Embed PlugIns */, 194 | ); 195 | buildRules = ( 196 | ); 197 | dependencies = ( 198 | ); 199 | name = "DSFDockTile Demo"; 200 | packageProductDependencies = ( 201 | 2321A57A26A16928003C94F8 /* DSFDockTile */, 202 | ); 203 | productName = "DSFDockTile Demo"; 204 | productReference = 2321A54D26A13BF5003C94F8 /* DSFDockTile Demo.app */; 205 | productType = "com.apple.product-type.application"; 206 | }; 207 | 232B361627E94C6E001679EB /* SwiftUI docktile demo */ = { 208 | isa = PBXNativeTarget; 209 | buildConfigurationList = 232B362527E94C6F001679EB /* Build configuration list for PBXNativeTarget "SwiftUI docktile demo" */; 210 | buildPhases = ( 211 | 232B361327E94C6E001679EB /* Sources */, 212 | 232B361427E94C6E001679EB /* Frameworks */, 213 | 232B361527E94C6E001679EB /* Resources */, 214 | ); 215 | buildRules = ( 216 | ); 217 | dependencies = ( 218 | ); 219 | name = "SwiftUI docktile demo"; 220 | packageProductDependencies = ( 221 | 232B362827E94E92001679EB /* DSFDockTile */, 222 | ); 223 | productName = "SwiftUI docktile demo"; 224 | productReference = 232B361727E94C6E001679EB /* SwiftUI docktile demo.app */; 225 | productType = "com.apple.product-type.application"; 226 | }; 227 | /* End PBXNativeTarget section */ 228 | 229 | /* Begin PBXProject section */ 230 | 2321A54526A13BF5003C94F8 /* Project object */ = { 231 | isa = PBXProject; 232 | attributes = { 233 | BuildIndependentTargetsInParallel = 1; 234 | LastSwiftUpdateCheck = 1330; 235 | LastUpgradeCheck = 1300; 236 | TargetAttributes = { 237 | 2321A54C26A13BF5003C94F8 = { 238 | CreatedOnToolsVersion = 13.0; 239 | }; 240 | 232B361627E94C6E001679EB = { 241 | CreatedOnToolsVersion = 13.3; 242 | }; 243 | }; 244 | }; 245 | buildConfigurationList = 2321A54826A13BF5003C94F8 /* Build configuration list for PBXProject "DSFDockTile Demo" */; 246 | compatibilityVersion = "Xcode 12.0"; 247 | developmentRegion = en; 248 | hasScannedForEncodings = 0; 249 | knownRegions = ( 250 | en, 251 | Base, 252 | ); 253 | mainGroup = 2321A54426A13BF5003C94F8; 254 | packageReferences = ( 255 | ); 256 | productRefGroup = 2321A54E26A13BF5003C94F8 /* Products */; 257 | projectDirPath = ""; 258 | projectRoot = ""; 259 | targets = ( 260 | 2321A54C26A13BF5003C94F8 /* DSFDockTile Demo */, 261 | 232B361627E94C6E001679EB /* SwiftUI docktile demo */, 262 | ); 263 | }; 264 | /* End PBXProject section */ 265 | 266 | /* Begin PBXResourcesBuildPhase section */ 267 | 2321A54B26A13BF5003C94F8 /* Resources */ = { 268 | isa = PBXResourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | 2321A56726A13E26003C94F8 /* XIBViewController.xib in Resources */, 272 | 235933D726A28D58002258AB /* AttentionViewController.xib in Resources */, 273 | 2321A57026A15194003C94F8 /* NSInfoViewController.xib in Resources */, 274 | 2321A57326A15299003C94F8 /* DockViewController.xib in Resources */, 275 | 2321A55326A13BF6003C94F8 /* Assets.xcassets in Resources */, 276 | 235933E126A2B092002258AB /* WindowedDockTileViewController.xib in Resources */, 277 | 2321A56326A13E15003C94F8 /* AnimatedViewController.xib in Resources */, 278 | 2321A55F26A13E07003C94F8 /* ImageViewController.xib in Resources */, 279 | 2321A55626A13BF6003C94F8 /* MainMenu.xib in Resources */, 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | }; 283 | 232B361527E94C6E001679EB /* Resources */ = { 284 | isa = PBXResourcesBuildPhase; 285 | buildActionMask = 2147483647; 286 | files = ( 287 | 232B362127E94C6F001679EB /* Preview Assets.xcassets in Resources */, 288 | 232B361E27E94C6F001679EB /* Assets.xcassets in Resources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | /* End PBXResourcesBuildPhase section */ 293 | 294 | /* Begin PBXSourcesBuildPhase section */ 295 | 2321A54926A13BF5003C94F8 /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | 2321A56626A13E26003C94F8 /* XIBViewController.swift in Sources */, 300 | 2321A56F26A15194003C94F8 /* NSInfoViewController.swift in Sources */, 301 | 2321A55E26A13E07003C94F8 /* ImageViewController.swift in Sources */, 302 | 235933E026A2B092002258AB /* WindowedDockTileViewController.swift in Sources */, 303 | 235933DD26A2AEF9002258AB /* DockTile+SecondaryWindow.swift in Sources */, 304 | 2321A55126A13BF5003C94F8 /* AppDelegate.swift in Sources */, 305 | 235933D626A28D58002258AB /* AttentionViewController.swift in Sources */, 306 | 2321A57426A15299003C94F8 /* DockViewController.swift in Sources */, 307 | 2321A56226A13E15003C94F8 /* AnimatedViewController.swift in Sources */, 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | }; 311 | 232B361327E94C6E001679EB /* Sources */ = { 312 | isa = PBXSourcesBuildPhase; 313 | buildActionMask = 2147483647; 314 | files = ( 315 | 232B362727E94D33001679EB /* DockTileContentView.swift in Sources */, 316 | 232B361C27E94C6E001679EB /* ContentView.swift in Sources */, 317 | 232B361A27E94C6E001679EB /* SwiftUI_docktile_demoApp.swift in Sources */, 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | /* End PBXSourcesBuildPhase section */ 322 | 323 | /* Begin PBXVariantGroup section */ 324 | 2321A55426A13BF6003C94F8 /* MainMenu.xib */ = { 325 | isa = PBXVariantGroup; 326 | children = ( 327 | 2321A55526A13BF6003C94F8 /* Base */, 328 | ); 329 | name = MainMenu.xib; 330 | sourceTree = ""; 331 | }; 332 | /* End PBXVariantGroup section */ 333 | 334 | /* Begin XCBuildConfiguration section */ 335 | 2321A55726A13BF6003C94F8 /* Debug */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | CLANG_ANALYZER_NONNULL = YES; 340 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 341 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 342 | CLANG_CXX_LIBRARY = "libc++"; 343 | CLANG_ENABLE_MODULES = YES; 344 | CLANG_ENABLE_OBJC_ARC = YES; 345 | CLANG_ENABLE_OBJC_WEAK = YES; 346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 347 | CLANG_WARN_BOOL_CONVERSION = YES; 348 | CLANG_WARN_COMMA = YES; 349 | CLANG_WARN_CONSTANT_CONVERSION = YES; 350 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 352 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 353 | CLANG_WARN_EMPTY_BODY = YES; 354 | CLANG_WARN_ENUM_CONVERSION = YES; 355 | CLANG_WARN_INFINITE_RECURSION = YES; 356 | CLANG_WARN_INT_CONVERSION = YES; 357 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 358 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 359 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 360 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 361 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 362 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 363 | CLANG_WARN_STRICT_PROTOTYPES = YES; 364 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 365 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | COPY_PHASE_STRIP = NO; 369 | DEBUG_INFORMATION_FORMAT = dwarf; 370 | ENABLE_STRICT_OBJC_MSGSEND = YES; 371 | ENABLE_TESTABILITY = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu11; 373 | GCC_DYNAMIC_NO_PIC = NO; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | MACOSX_DEPLOYMENT_TARGET = 10.14; 387 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 388 | MTL_FAST_MATH = YES; 389 | ONLY_ACTIVE_ARCH = YES; 390 | SDKROOT = macosx; 391 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 392 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 393 | }; 394 | name = Debug; 395 | }; 396 | 2321A55826A13BF6003C94F8 /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_SEARCH_USER_PATHS = NO; 400 | CLANG_ANALYZER_NONNULL = YES; 401 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 402 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 403 | CLANG_CXX_LIBRARY = "libc++"; 404 | CLANG_ENABLE_MODULES = YES; 405 | CLANG_ENABLE_OBJC_ARC = YES; 406 | CLANG_ENABLE_OBJC_WEAK = YES; 407 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 408 | CLANG_WARN_BOOL_CONVERSION = YES; 409 | CLANG_WARN_COMMA = YES; 410 | CLANG_WARN_CONSTANT_CONVERSION = YES; 411 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INFINITE_RECURSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 420 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 422 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 423 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 424 | CLANG_WARN_STRICT_PROTOTYPES = YES; 425 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 426 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 427 | CLANG_WARN_UNREACHABLE_CODE = YES; 428 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 429 | COPY_PHASE_STRIP = NO; 430 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 431 | ENABLE_NS_ASSERTIONS = NO; 432 | ENABLE_STRICT_OBJC_MSGSEND = YES; 433 | GCC_C_LANGUAGE_STANDARD = gnu11; 434 | GCC_NO_COMMON_BLOCKS = YES; 435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 437 | GCC_WARN_UNDECLARED_SELECTOR = YES; 438 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 439 | GCC_WARN_UNUSED_FUNCTION = YES; 440 | GCC_WARN_UNUSED_VARIABLE = YES; 441 | MACOSX_DEPLOYMENT_TARGET = 10.14; 442 | MTL_ENABLE_DEBUG_INFO = NO; 443 | MTL_FAST_MATH = YES; 444 | SDKROOT = macosx; 445 | SWIFT_COMPILATION_MODE = wholemodule; 446 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 447 | }; 448 | name = Release; 449 | }; 450 | 2321A55A26A13BF6003C94F8 /* Debug */ = { 451 | isa = XCBuildConfiguration; 452 | buildSettings = { 453 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 454 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 455 | CODE_SIGN_ENTITLEMENTS = "DSFDockTile Demo/DSFDockTile Demo.entitlements"; 456 | CODE_SIGN_STYLE = Automatic; 457 | COMBINE_HIDPI_IMAGES = YES; 458 | CURRENT_PROJECT_VERSION = 1; 459 | DEVELOPMENT_TEAM = 3L6RK3LGGW; 460 | ENABLE_APP_SANDBOX = YES; 461 | ENABLE_HARDENED_RUNTIME = NO; 462 | ENABLE_USER_SELECTED_FILES = readonly; 463 | GENERATE_INFOPLIST_FILE = YES; 464 | INFOPLIST_FILE = "DSFDockTile Demo/Info.plist"; 465 | INFOPLIST_KEY_CFBundleExecutable = "DSFDockTile Demo"; 466 | INFOPLIST_KEY_CFBundleName = "DSFDockTile Demo"; 467 | INFOPLIST_KEY_CFBundleVersion = 1; 468 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 469 | INFOPLIST_KEY_NSMainNibFile = MainMenu; 470 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 471 | LD_RUNPATH_SEARCH_PATHS = ( 472 | "$(inherited)", 473 | "@executable_path/../Frameworks", 474 | ); 475 | MARKETING_VERSION = 1.0; 476 | PRODUCT_BUNDLE_IDENTIFIER = com.dagronf.dsfdocktile.demo; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | SWIFT_EMIT_LOC_STRINGS = YES; 479 | SWIFT_VERSION = 5.0; 480 | }; 481 | name = Debug; 482 | }; 483 | 2321A55B26A13BF6003C94F8 /* Release */ = { 484 | isa = XCBuildConfiguration; 485 | buildSettings = { 486 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 487 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 488 | CODE_SIGN_ENTITLEMENTS = "DSFDockTile Demo/DSFDockTile Demo.entitlements"; 489 | CODE_SIGN_STYLE = Automatic; 490 | COMBINE_HIDPI_IMAGES = YES; 491 | CURRENT_PROJECT_VERSION = 1; 492 | DEVELOPMENT_TEAM = 3L6RK3LGGW; 493 | ENABLE_APP_SANDBOX = YES; 494 | ENABLE_HARDENED_RUNTIME = NO; 495 | ENABLE_USER_SELECTED_FILES = readonly; 496 | GENERATE_INFOPLIST_FILE = YES; 497 | INFOPLIST_FILE = "DSFDockTile Demo/Info.plist"; 498 | INFOPLIST_KEY_CFBundleExecutable = "DSFDockTile Demo"; 499 | INFOPLIST_KEY_CFBundleName = "DSFDockTile Demo"; 500 | INFOPLIST_KEY_CFBundleVersion = 1; 501 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 502 | INFOPLIST_KEY_NSMainNibFile = MainMenu; 503 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 504 | LD_RUNPATH_SEARCH_PATHS = ( 505 | "$(inherited)", 506 | "@executable_path/../Frameworks", 507 | ); 508 | MARKETING_VERSION = 1.0; 509 | PRODUCT_BUNDLE_IDENTIFIER = com.dagronf.dsfdocktile.demo; 510 | PRODUCT_NAME = "$(TARGET_NAME)"; 511 | SWIFT_EMIT_LOC_STRINGS = YES; 512 | SWIFT_VERSION = 5.0; 513 | }; 514 | name = Release; 515 | }; 516 | 232B362327E94C6F001679EB /* Debug */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 520 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 521 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 522 | CODE_SIGN_ENTITLEMENTS = "SwiftUI docktile demo/SwiftUI_docktile_demo.entitlements"; 523 | CODE_SIGN_STYLE = Automatic; 524 | COMBINE_HIDPI_IMAGES = YES; 525 | CURRENT_PROJECT_VERSION = 1; 526 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUI docktile demo/Preview Content\""; 527 | DEVELOPMENT_TEAM = 3L6RK3LGGW; 528 | ENABLE_HARDENED_RUNTIME = YES; 529 | ENABLE_PREVIEWS = YES; 530 | GENERATE_INFOPLIST_FILE = YES; 531 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 532 | LD_RUNPATH_SEARCH_PATHS = ( 533 | "$(inherited)", 534 | "@executable_path/../Frameworks", 535 | ); 536 | MACOSX_DEPLOYMENT_TARGET = 12.3; 537 | MARKETING_VERSION = 1.0; 538 | PRODUCT_BUNDLE_IDENTIFIER = "com.dagronf.valuebinderdemos.pagedview.SwiftUI-docktile-demo"; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | SWIFT_EMIT_LOC_STRINGS = YES; 541 | SWIFT_VERSION = 5.0; 542 | }; 543 | name = Debug; 544 | }; 545 | 232B362427E94C6F001679EB /* Release */ = { 546 | isa = XCBuildConfiguration; 547 | buildSettings = { 548 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 549 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 550 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 551 | CODE_SIGN_ENTITLEMENTS = "SwiftUI docktile demo/SwiftUI_docktile_demo.entitlements"; 552 | CODE_SIGN_STYLE = Automatic; 553 | COMBINE_HIDPI_IMAGES = YES; 554 | CURRENT_PROJECT_VERSION = 1; 555 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUI docktile demo/Preview Content\""; 556 | DEVELOPMENT_TEAM = 3L6RK3LGGW; 557 | ENABLE_HARDENED_RUNTIME = YES; 558 | ENABLE_PREVIEWS = YES; 559 | GENERATE_INFOPLIST_FILE = YES; 560 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 561 | LD_RUNPATH_SEARCH_PATHS = ( 562 | "$(inherited)", 563 | "@executable_path/../Frameworks", 564 | ); 565 | MACOSX_DEPLOYMENT_TARGET = 12.3; 566 | MARKETING_VERSION = 1.0; 567 | PRODUCT_BUNDLE_IDENTIFIER = "com.dagronf.valuebinderdemos.pagedview.SwiftUI-docktile-demo"; 568 | PRODUCT_NAME = "$(TARGET_NAME)"; 569 | SWIFT_EMIT_LOC_STRINGS = YES; 570 | SWIFT_VERSION = 5.0; 571 | }; 572 | name = Release; 573 | }; 574 | /* End XCBuildConfiguration section */ 575 | 576 | /* Begin XCConfigurationList section */ 577 | 2321A54826A13BF5003C94F8 /* Build configuration list for PBXProject "DSFDockTile Demo" */ = { 578 | isa = XCConfigurationList; 579 | buildConfigurations = ( 580 | 2321A55726A13BF6003C94F8 /* Debug */, 581 | 2321A55826A13BF6003C94F8 /* Release */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | defaultConfigurationName = Release; 585 | }; 586 | 2321A55926A13BF6003C94F8 /* Build configuration list for PBXNativeTarget "DSFDockTile Demo" */ = { 587 | isa = XCConfigurationList; 588 | buildConfigurations = ( 589 | 2321A55A26A13BF6003C94F8 /* Debug */, 590 | 2321A55B26A13BF6003C94F8 /* Release */, 591 | ); 592 | defaultConfigurationIsVisible = 0; 593 | defaultConfigurationName = Release; 594 | }; 595 | 232B362527E94C6F001679EB /* Build configuration list for PBXNativeTarget "SwiftUI docktile demo" */ = { 596 | isa = XCConfigurationList; 597 | buildConfigurations = ( 598 | 232B362327E94C6F001679EB /* Debug */, 599 | 232B362427E94C6F001679EB /* Release */, 600 | ); 601 | defaultConfigurationIsVisible = 0; 602 | defaultConfigurationName = Release; 603 | }; 604 | /* End XCConfigurationList section */ 605 | 606 | /* Begin XCSwiftPackageProductDependency section */ 607 | 2321A57A26A16928003C94F8 /* DSFDockTile */ = { 608 | isa = XCSwiftPackageProductDependency; 609 | productName = DSFDockTile; 610 | }; 611 | 232B362827E94E92001679EB /* DSFDockTile */ = { 612 | isa = XCSwiftPackageProductDependency; 613 | productName = DSFDockTile; 614 | }; 615 | /* End XCSwiftPackageProductDependency section */ 616 | }; 617 | rootObject = 2321A54526A13BF5003C94F8 /* Project object */; 618 | } 619 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "DSFImageFlipbook", 6 | "repositoryURL": "https://github.com/dagronf/DSFImageFlipbook", 7 | "state": { 8 | "branch": null, 9 | "revision": "8b6e1e7f862c1d39ce34c59705f9fa731d9fd539", 10 | "version": "1.0.1" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/AnimatedViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedViewController.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 16/7/21. 6 | // 7 | 8 | import AppKit 9 | 10 | import DSFDockTile 11 | import DSFImageFlipbook 12 | 13 | class AnimatedViewController: NSViewController { 14 | override var nibName: NSNib.Name? { 15 | return NSNib.Name("AnimatedViewController") 16 | } 17 | 18 | @objc dynamic var speed: Double = 1.0 19 | 20 | let dockTile: DSFDockTile.Animated = { 21 | let fb = DSFImageFlipbook() 22 | let da = NSDataAsset(name: NSDataAsset.Name("animate-shark"))! 23 | _ = fb.loadFrames(from: da.data) 24 | return DSFDockTile.Animated(fb) 25 | }() 26 | 27 | let charizard: DSFDockTile.Animated = { 28 | let fb = DSFImageFlipbook() 29 | let da = NSDataAsset(name: NSDataAsset.Name("animate-charizard"))! 30 | _ = fb.loadFrames(from: da.data) 31 | return DSFDockTile.Animated(fb) 32 | }() 33 | 34 | lazy var selectedDockImage: DSFDockTile.Animated = { 35 | dockTile 36 | }() 37 | 38 | override func viewDidLoad() { 39 | super.viewDidLoad() 40 | // Do view setup here. 41 | } 42 | 43 | @objc dynamic var isAnimating: Bool = false 44 | 45 | @IBAction func startAnimating(_ sender: Any) { 46 | selectedDockImage.startAnimating(speed: self.speed) 47 | isAnimating = true 48 | } 49 | 50 | @IBAction func stopAnimating(_ sender: Any) { 51 | selectedDockImage.stopAnimating() 52 | isAnimating = false 53 | } 54 | 55 | @IBAction func stopAnimatingAtEndOfLoop(_ sender: Any) { 56 | selectedDockImage.flipbook.animationDidComplete = { [unowned self] _ in 57 | isAnimating = false 58 | } 59 | selectedDockImage.stopAnimating(stopAtEndOfCurrentLoop: true) 60 | } 61 | 62 | override func viewWillAppear() { 63 | selectedDockImage.display() 64 | self.stopAnimating(self) 65 | } 66 | 67 | override func viewWillDisappear() { 68 | self.stopAnimating(self) 69 | } 70 | 71 | @IBAction func imageChanged(_ sender: NSSegmentedControl) { 72 | switch sender.selectedSegment { 73 | case 0: 74 | selectedDockImage = dockTile 75 | case 1: 76 | selectedDockImage = charizard 77 | default: 78 | fatalError() 79 | } 80 | selectedDockImage.display() 81 | } 82 | 83 | @IBAction func speedDidChange(_ sender: NSSlider) { 84 | switch Int(sender.doubleValue) { 85 | case 0: self.speed = 0.125 86 | case 1: self.speed = 0.25 87 | case 2: self.speed = 0.5 88 | case 3: self.speed = 1 89 | case 4: self.speed = 2 90 | case 5: self.speed = 3 91 | case 6: self.speed = 4 92 | default: fatalError() 93 | } 94 | } 95 | } 96 | 97 | extension AnimatedViewController { 98 | @IBAction func selectNewGIF(_ sender: Any) { 99 | let myOpen = NSOpenPanel() 100 | myOpen.allowedFileTypes = ["com.compuserve.gif"] 101 | myOpen.canChooseFiles = true 102 | myOpen.allowsMultipleSelection = false 103 | myOpen.beginSheetModal(for: self.view.window!) { [weak self] response in 104 | if response == .OK { 105 | DispatchQueue.main.async { [weak self] in 106 | self?.imageChanged(from: myOpen.url!) 107 | } 108 | } 109 | } 110 | } 111 | 112 | func imageChanged(from url: URL) { 113 | guard let image = NSImage(contentsOf: url) else { return } 114 | let fb = DSFImageFlipbook() 115 | _ = fb.loadFrames(from: image) 116 | if fb.frameCount > 0 { 117 | selectedDockImage = DSFDockTile.Animated(fb) 118 | selectedDockImage.display() 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/AnimatedViewController.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 | The docktile is being generated as an animation using the DSFImageFlipbook package, loading the frames directly from a GIF file. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | NSNegateBoolean 49 | 50 | 51 | 52 | 53 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | NSNegateBoolean 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 16/7/21. 6 | // 7 | 8 | import Cocoa 9 | import DSFDockTile 10 | 11 | @main 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | @IBOutlet var window: NSWindow! 15 | 16 | @objc dynamic var badgeLabel: String? { 17 | didSet { 18 | DSFDockTile.badgeLabel = self.badgeLabel 19 | } 20 | } 21 | 22 | @IBOutlet weak var tabView: NSTabView! 23 | 24 | let infoVC = NSInfoViewController() 25 | lazy var infoTC: NSTabViewItem = { NSTabViewItem(viewController: infoVC) }() 26 | let imageVC = ImageViewController() 27 | lazy var imageTC: NSTabViewItem = { NSTabViewItem(viewController: imageVC) }() 28 | let animatedVC = AnimatedViewController() 29 | lazy var animatedTC: NSTabViewItem = { NSTabViewItem(viewController: animatedVC) }() 30 | let xibVC = XIBViewController() 31 | lazy var xibTC: NSTabViewItem = { NSTabViewItem(viewController: xibVC) }() 32 | let attentionVC = AttentionViewController() 33 | lazy var attentionTC: NSTabViewItem = { NSTabViewItem(viewController: attentionVC) }() 34 | 35 | func applicationDidFinishLaunching(_ aNotification: Notification) { 36 | 37 | tabView.addTabViewItem(infoTC) 38 | tabView.addTabViewItem(imageTC) 39 | tabView.addTabViewItem(animatedTC) 40 | tabView.addTabViewItem(xibTC) 41 | tabView.addTabViewItem(attentionTC) 42 | 43 | self.window.toolbar?.selectedItemIdentifier = NSToolbarItem.Identifier("Toolbar-Info") 44 | 45 | tabView.selectTabViewItem(infoTC) 46 | 47 | self.window.makeKeyAndOrderFront(self) 48 | 49 | } 50 | 51 | func applicationWillTerminate(_ aNotification: Notification) { 52 | // Insert code here to tear down your application 53 | } 54 | 55 | func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 56 | return true 57 | } 58 | 59 | @IBAction func tabChanged(_ sender: NSToolbarItem) { 60 | switch sender.tag { 61 | case -1: tabView.selectTabViewItem(infoTC) 62 | case 0: tabView.selectTabViewItem(imageTC) 63 | case 1: tabView.selectTabViewItem(animatedTC) 64 | case 2: tabView.selectTabViewItem(xibTC) 65 | case 3: tabView.selectTabViewItem(attentionTC) 66 | default: fatalError() 67 | } 68 | } 69 | 70 | } 71 | 72 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS128.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS128@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS16.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS16@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS256.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS256@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS32.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS32@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS512.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-macOS512@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "AppIcon-macOS16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "AppIcon-macOS16@2x.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "AppIcon-macOS32.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "AppIcon-macOS32@2x.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "AppIcon-macOS128.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "AppIcon-macOS128@2x.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "AppIcon-macOS256.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "AppIcon-macOS256@2x.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "AppIcon-macOS512.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "AppIcon-macOS512@2x.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/animate-charizard.dataset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "data" : [ 3 | { 4 | "filename" : "iu.gif", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/animate-charizard.dataset/iu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/animate-charizard.dataset/iu.gif -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/animate-shark.dataset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "data" : [ 3 | { 4 | "filename" : "shark.gif", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/animate-shark.dataset/shark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/animate-shark.dataset/shark.gif -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/baby-shark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Image.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/baby-shark.imageset/Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/baby-shark.imageset/Image.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/demo-image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "demo_image.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/demo-image.imageset/demo_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/demo-image.imageset/demo_image.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/marble.dataset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "data" : [ 3 | { 4 | "filename" : "marble.gif", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Assets.xcassets/marble.dataset/marble.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Demo/Assets.xcassets/marble.dataset/marble.gif -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/AttentionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AttentionViewController.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 17/7/21. 6 | // 7 | 8 | import Cocoa 9 | import DSFDockTile 10 | 11 | class AttentionViewController: NSViewController { 12 | override var nibName: NSNib.Name? { 13 | return NSNib.Name("AttentionViewController") 14 | } 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | // Do view setup here. 19 | } 20 | 21 | @IBAction func informationalRequest(_ sender: Any) { 22 | self.activateOtherApplicationToLoseFocus() 23 | 24 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 25 | DSFDockTile.requestInformationalAttention() 26 | } 27 | } 28 | 29 | @IBAction func criticalRequest(_ sender: Any) { 30 | self.activateOtherApplicationToLoseFocus() 31 | 32 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 33 | DSFDockTile.requestCriticalAttention() 34 | } 35 | } 36 | 37 | 38 | func activateOtherApplicationToLoseFocus() { 39 | let prefsURL = URL(string: "x-apple.systempreferences:com.apple.preference")! 40 | NSWorkspace.shared.open(prefsURL) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/AttentionViewController.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 | You can 'bounce' an application icon in the dock. The 'bounce' only occurs IF the application is not the frontmost application on the system. 28 | 29 | To demonstrate this, clicking either of the two buttons below will open the 'System Preferences' application in order to de-focus this demo application. 30 | 31 | Informational: The dock icon will bounce for one second. 32 | Critical: The dock icon will bounce until either the app becomes active or the request is canceled. 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 54 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/DSFDockTile Demo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/DockViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DockViewController.swift 3 | // DockTile Stuff 4 | // 5 | // Created by Darren Ford on 16/7/21. 6 | // 7 | 8 | import Cocoa 9 | 10 | class DockViewController: NSViewController { 11 | 12 | override var nibName: NSNib.Name? { 13 | return NSNib.Name("DockViewController") 14 | } 15 | 16 | @IBOutlet weak var gradientArcView: GradientArcView! 17 | 18 | @objc dynamic var value: Double = 0 { 19 | didSet { 20 | gradientArcView.endAngle = CGFloat(360 * value) 21 | } 22 | } 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | // Do view setup here. 27 | } 28 | 29 | } 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | @IBDesignable 39 | class GradientArcView: NSView { 40 | 41 | /// Width of the stroke. 42 | 43 | @IBInspectable var lineWidth: CGFloat = 3 { didSet { setNeedsDisplay(bounds) } } 44 | 45 | /// Color of the stroke (at full alpha, at the end). 46 | 47 | @IBInspectable var strokeColor: NSColor = .blue { didSet { setNeedsDisplay(bounds) } } 48 | 49 | /// Where the arc should end, measured in degrees, where 0 = "3 o'clock". 50 | 51 | @IBInspectable var endAngle: CGFloat = 0 { didSet { setNeedsDisplay(bounds) } } 52 | 53 | /// What is the full angle of the arc, measured in degrees, e.g. 180 = half way around, 360 = all the way around, etc. 54 | 55 | @IBInspectable var maxAngle: CGFloat = 360 { didSet { setNeedsDisplay(bounds) } } 56 | 57 | /// What is the shape at the end of the arc. 58 | 59 | var lineCapStyle: NSBezierPath.LineCapStyle = .square { didSet { setNeedsDisplay(bounds) } } 60 | 61 | override func draw(_ dirtyRect: NSRect) { 62 | super.draw(dirtyRect) 63 | 64 | let gradations = 255 65 | 66 | let startAngle = -endAngle + maxAngle 67 | let center = NSPoint(x: bounds.midX, y: bounds.midY) 68 | let radius = (min(bounds.width, bounds.height) - lineWidth) / 2 69 | var angle = startAngle 70 | 71 | for i in 1 ... gradations { 72 | let percent = CGFloat(i) / CGFloat(gradations) 73 | let endAngle = startAngle - percent * maxAngle 74 | let path = NSBezierPath() 75 | path.lineWidth = lineWidth 76 | path.lineCapStyle = lineCapStyle 77 | path.appendArc(withCenter: center, radius: radius, startAngle: angle, endAngle: endAngle, clockwise: true) 78 | strokeColor.withAlphaComponent(percent).setStroke() 79 | path.stroke() 80 | angle = endAngle 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/DockViewController.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 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/ImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 16/7/21. 6 | // 7 | 8 | import Cocoa 9 | import DSFDockTile 10 | 11 | class ImageViewController: NSViewController { 12 | override var nibName: NSNib.Name? { 13 | return NSNib.Name("ImageViewController") 14 | } 15 | 16 | let dockImage = DSFDockTile.Image() 17 | 18 | static let DefaultImage = NSImage(named: NSImage.Name("baby-shark"))! 19 | @objc dynamic var image: NSImage = ImageViewController.DefaultImage { 20 | didSet { 21 | dockImage.display(image) 22 | } 23 | } 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | // Do view setup here. 28 | } 29 | 30 | override func viewDidAppear() { 31 | self.dockImage.display(self.image) 32 | } 33 | 34 | override func viewWillDisappear() {} 35 | } 36 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/ImageViewController.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 | The docktile is being generated from the content in DockViewController.

Drag the slider and change the color to see the DockTile dynamically update as the value changes

Drag an image file onto the image on the right to update the dock image
 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSMainNibFile 26 | MainMenu 27 | NSPrincipalClass 28 | NSApplication 29 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/NSInfoViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSInfoViewController.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 16/7/21. 6 | // 7 | 8 | import AppKit 9 | 10 | import DSFDockTile 11 | 12 | class NSInfoViewController: NSViewController { 13 | override var nibName: NSNib.Name? { 14 | return NSNib.Name("NSInfoViewController") 15 | } 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | // Do view setup here. 19 | } 20 | 21 | override func viewWillAppear() { 22 | super.viewWillAppear() 23 | 24 | DSFDockTile.AppIcon.display() 25 | } 26 | 27 | @IBAction func showSecondaryWindow(_ sender: Any) { 28 | OpenNewSubWindow() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/NSInfoViewController.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 | This app demonstrates the different applications for DSFDockTile 28 | 29 | Info: This text (which displays the Application Icon in the docktile) 30 | Image: Set the docktile to a simple image 31 | Animated: Uses DSFImageFlipbook to generate an animated docktile 32 | View: Using an NSViewController to control the content of the docktile 33 | Attention: Draw attention to your application by bouncing the docktile 34 | 35 | You can also attach any window's docktile to DSFDocktile (by default, the DSFDockTile will attach itself to the Application docktile). Click 'Open secondary window…' to present a window that demonstrates this. 36 | 37 | 38 | 39 | 40 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/XIBViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XIBViewController.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 16/7/21. 6 | // 7 | 8 | import AppKit 9 | 10 | import DSFDockTile 11 | 12 | class XIBViewController: NSViewController { 13 | override var nibName: NSNib.Name? { 14 | return NSNib.Name("XIBViewController") 15 | } 16 | 17 | /// The view controller to display on the docktile 18 | let dockViewController = DockViewController() 19 | 20 | /// The docktile instance handling the docktile 21 | lazy var updateDockTile: DSFDockTile.View = { 22 | dockViewController.loadView() 23 | return DSFDockTile.View(dockViewController) 24 | }() 25 | 26 | @IBOutlet var slider: NSSlider! 27 | 28 | override func viewDidLoad() { 29 | super.viewDidLoad() 30 | // Do view setup here. 31 | } 32 | 33 | override func viewWillAppear() { 34 | self.updateDockTile.display() 35 | } 36 | 37 | @IBAction func sliderDidUpdate(_ sender: NSSlider) { 38 | let value = sender.doubleValue 39 | 40 | // Change the value being displayed on the docktile 41 | self.dockViewController.value = value 42 | 43 | // NSDockTile does not update automatically so need to tell it when changes are made 44 | self.updateDockTile.display() 45 | } 46 | 47 | @IBAction func colorDidUpdate(_ sender: NSColorWell) { 48 | // Change the color of the gradient arc 49 | self.dockViewController.gradientArcView.strokeColor = sender.color 50 | 51 | // NSDockTile does not update automatically so need to tell it when changes are made 52 | self.updateDockTile.display() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/XIBViewController.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 | The docktile is being generated from the content in DockViewController.

Drag the slider and change the color to see the DockTile dynamically update as the value changes
 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/window-based/DockTile+SecondaryWindow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DockTile+SecondaryWindow.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 17/7/21. 6 | // 7 | 8 | import AppKit 9 | 10 | var windowedDockTile: NSWindow? 11 | var windowedDockTileViewController: WindowedDockTileViewController? 12 | 13 | func OpenNewSubWindow() { 14 | 15 | windowedDockTile?.close() 16 | 17 | windowedDockTileViewController = WindowedDockTileViewController() 18 | 19 | let w = NSWindow(contentViewController: windowedDockTileViewController!) 20 | w.title = "Secondary Window DockTile Demo" 21 | w.makeKeyAndOrderFront(nil) 22 | 23 | windowedDockTile = w 24 | } 25 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/window-based/WindowedDockTileViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WindowedDockTileViewController.swift 3 | // DSFDockTile Demo 4 | // 5 | // Created by Darren Ford on 17/7/21. 6 | // 7 | 8 | import Cocoa 9 | import DSFDockTile 10 | import DSFImageFlipbook 11 | 12 | class WindowedDockTileViewController: NSViewController { 13 | 14 | override var nibName: NSNib.Name? { 15 | return NSNib.Name("WindowedDockTileViewController") 16 | } 17 | 18 | lazy var animatedDockTile: DSFDockTile.Animated = { 19 | let fb = DSFImageFlipbook() 20 | let da = NSDataAsset(name: NSDataAsset.Name("marble"))! 21 | _ = fb.loadFrames(from: da.data) 22 | 23 | /// Attach to the window's docktile 24 | return DSFDockTile.Animated(fb, dockTile: self.view.window!.dockTile) 25 | }() 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | // Do view setup here. 30 | } 31 | 32 | @objc dynamic var isAnimating: Bool = false 33 | 34 | @IBAction func startAnimating(_ sender: Any) { 35 | guard isAnimating == false else { return } 36 | isAnimating = true 37 | self.view.window?.miniaturize(self) 38 | self.animatedDockTile.startAnimating() 39 | } 40 | 41 | @IBAction func stopAnimating(_ sender: Any) { 42 | isAnimating = false 43 | self.animatedDockTile.stopAnimating() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Demo/window-based/WindowedDockTileViewController.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 | This window demonstrates how to set the dock image for a minimised window. 27 | 28 | By clicking 'Start Animating' the window will automatically minimise and toggle between the 'standard' window docktile image and a custom image 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 55 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 23447D3926A52BDB0074ABF2 /* LightDarkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23447D3826A52BDB0074ABF2 /* LightDarkImage.swift */; }; 11 | 2356DBCA26A50AB100A39A25 /* DSFDockTile_Plugin_DemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2356DBC926A50AB100A39A25 /* DSFDockTile_Plugin_DemoApp.swift */; }; 12 | 2356DBCC26A50AB100A39A25 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2356DBCB26A50AB100A39A25 /* ContentView.swift */; }; 13 | 2356DBCE26A50AB200A39A25 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2356DBCD26A50AB200A39A25 /* Assets.xcassets */; }; 14 | 2356DBD126A50AB200A39A25 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2356DBD026A50AB200A39A25 /* Preview Assets.xcassets */; }; 15 | 2356DBE126A50B5D00A39A25 /* DSFDockTilePlugin.plugin in Embed PlugIns */ = {isa = PBXBuildFile; fileRef = 2356DBDB26A50B0100A39A25 /* DSFDockTilePlugin.plugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 2356DBF126A50C1300A39A25 /* DSFDockTile in Frameworks */ = {isa = PBXBuildFile; productRef = 2356DBF026A50C1300A39A25 /* DSFDockTile */; }; 17 | 2356DBF426A50D3800A39A25 /* DockTilePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2356DBE626A50BB100A39A25 /* DockTilePlugin.swift */; }; 18 | 2356DC0726A51DAC00A39A25 /* dark.png in Resources */ = {isa = PBXBuildFile; fileRef = 2356DC0626A51DAC00A39A25 /* dark.png */; }; 19 | 2356DC0926A51EB400A39A25 /* light.png in Resources */ = {isa = PBXBuildFile; fileRef = 2356DC0826A51EB400A39A25 /* light.png */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 2356DBE226A50B5D00A39A25 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 2356DBBE26A50AB100A39A25 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 2356DBDA26A50B0100A39A25; 28 | remoteInfo = DSFDockTilePlugin; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXCopyFilesBuildPhase section */ 33 | 2356DBE426A50B5D00A39A25 /* Embed PlugIns */ = { 34 | isa = PBXCopyFilesBuildPhase; 35 | buildActionMask = 2147483647; 36 | dstPath = ""; 37 | dstSubfolderSpec = 13; 38 | files = ( 39 | 2356DBE126A50B5D00A39A25 /* DSFDockTilePlugin.plugin in Embed PlugIns */, 40 | ); 41 | name = "Embed PlugIns"; 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXCopyFilesBuildPhase section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 23447D3826A52BDB0074ABF2 /* LightDarkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightDarkImage.swift; sourceTree = ""; }; 48 | 2356DBC626A50AB100A39A25 /* DSFDockTile Plugin Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DSFDockTile Plugin Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 2356DBC926A50AB100A39A25 /* DSFDockTile_Plugin_DemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSFDockTile_Plugin_DemoApp.swift; sourceTree = ""; }; 50 | 2356DBCB26A50AB100A39A25 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 51 | 2356DBCD26A50AB200A39A25 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52 | 2356DBD026A50AB200A39A25 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 53 | 2356DBDB26A50B0100A39A25 /* DSFDockTilePlugin.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DSFDockTilePlugin.plugin; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 2356DBE526A50B6800A39A25 /* DSFDockTile-Plugin-Demo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DSFDockTile-Plugin-Demo-Info.plist"; sourceTree = SOURCE_ROOT; }; 55 | 2356DBE626A50BB100A39A25 /* DockTilePlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DockTilePlugin.swift; sourceTree = ""; }; 56 | 2356DBFD26A5144C00A39A25 /* DSFDockTilePlugin-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DSFDockTilePlugin-Info.plist"; sourceTree = ""; }; 57 | 2356DC0626A51DAC00A39A25 /* dark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dark.png; sourceTree = ""; }; 58 | 2356DC0826A51EB400A39A25 /* light.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = light.png; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 2356DBC326A50AB100A39A25 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | 2356DBD826A50B0100A39A25 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | 2356DBF126A50C1300A39A25 /* DSFDockTile in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXFrameworksBuildPhase section */ 78 | 79 | /* Begin PBXGroup section */ 80 | 2356DBBD26A50AB100A39A25 = { 81 | isa = PBXGroup; 82 | children = ( 83 | 2356DBFD26A5144C00A39A25 /* DSFDockTilePlugin-Info.plist */, 84 | 2356DBC826A50AB100A39A25 /* DSFDockTile Plugin Demo */, 85 | 2356DBDF26A50B2B00A39A25 /* DSFDockTile Plugin */, 86 | 2356DBC726A50AB100A39A25 /* Products */, 87 | 2356DBE026A50B5D00A39A25 /* Frameworks */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 2356DBC726A50AB100A39A25 /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 2356DBC626A50AB100A39A25 /* DSFDockTile Plugin Demo.app */, 95 | 2356DBDB26A50B0100A39A25 /* DSFDockTilePlugin.plugin */, 96 | ); 97 | name = Products; 98 | sourceTree = ""; 99 | }; 100 | 2356DBC826A50AB100A39A25 /* DSFDockTile Plugin Demo */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 2356DBE526A50B6800A39A25 /* DSFDockTile-Plugin-Demo-Info.plist */, 104 | 2356DBC926A50AB100A39A25 /* DSFDockTile_Plugin_DemoApp.swift */, 105 | 2356DBCB26A50AB100A39A25 /* ContentView.swift */, 106 | 23447D3826A52BDB0074ABF2 /* LightDarkImage.swift */, 107 | 2356DBCD26A50AB200A39A25 /* Assets.xcassets */, 108 | 2356DBCF26A50AB200A39A25 /* Preview Content */, 109 | ); 110 | path = "DSFDockTile Plugin Demo"; 111 | sourceTree = ""; 112 | }; 113 | 2356DBCF26A50AB200A39A25 /* Preview Content */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 2356DBD026A50AB200A39A25 /* Preview Assets.xcassets */, 117 | ); 118 | path = "Preview Content"; 119 | sourceTree = ""; 120 | }; 121 | 2356DBDF26A50B2B00A39A25 /* DSFDockTile Plugin */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 2356DC0326A51D5100A39A25 /* resources */, 125 | 2356DBE626A50BB100A39A25 /* DockTilePlugin.swift */, 126 | ); 127 | path = "DSFDockTile Plugin"; 128 | sourceTree = ""; 129 | }; 130 | 2356DBE026A50B5D00A39A25 /* Frameworks */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | ); 134 | name = Frameworks; 135 | sourceTree = ""; 136 | }; 137 | 2356DC0326A51D5100A39A25 /* resources */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 2356DC0826A51EB400A39A25 /* light.png */, 141 | 2356DC0626A51DAC00A39A25 /* dark.png */, 142 | ); 143 | path = resources; 144 | sourceTree = ""; 145 | }; 146 | /* End PBXGroup section */ 147 | 148 | /* Begin PBXNativeTarget section */ 149 | 2356DBC526A50AB100A39A25 /* DSFDockTile Plugin Demo */ = { 150 | isa = PBXNativeTarget; 151 | buildConfigurationList = 2356DBD426A50AB200A39A25 /* Build configuration list for PBXNativeTarget "DSFDockTile Plugin Demo" */; 152 | buildPhases = ( 153 | 2356DBC226A50AB100A39A25 /* Sources */, 154 | 2356DBC326A50AB100A39A25 /* Frameworks */, 155 | 2356DBC426A50AB100A39A25 /* Resources */, 156 | 2356DBE426A50B5D00A39A25 /* Embed PlugIns */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | 2356DBE326A50B5D00A39A25 /* PBXTargetDependency */, 162 | ); 163 | name = "DSFDockTile Plugin Demo"; 164 | packageProductDependencies = ( 165 | ); 166 | productName = "DSFDockTile Plugin Demo"; 167 | productReference = 2356DBC626A50AB100A39A25 /* DSFDockTile Plugin Demo.app */; 168 | productType = "com.apple.product-type.application"; 169 | }; 170 | 2356DBDA26A50B0100A39A25 /* DSFDockTilePlugin */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = 2356DBDC26A50B0100A39A25 /* Build configuration list for PBXNativeTarget "DSFDockTilePlugin" */; 173 | buildPhases = ( 174 | 2356DBD726A50B0100A39A25 /* Sources */, 175 | 2356DBD826A50B0100A39A25 /* Frameworks */, 176 | 2356DBD926A50B0100A39A25 /* Resources */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | ); 182 | name = DSFDockTilePlugin; 183 | packageProductDependencies = ( 184 | 2356DBF026A50C1300A39A25 /* DSFDockTile */, 185 | ); 186 | productName = DSFDockTilePlugin; 187 | productReference = 2356DBDB26A50B0100A39A25 /* DSFDockTilePlugin.plugin */; 188 | productType = "com.apple.product-type.bundle"; 189 | }; 190 | /* End PBXNativeTarget section */ 191 | 192 | /* Begin PBXProject section */ 193 | 2356DBBE26A50AB100A39A25 /* Project object */ = { 194 | isa = PBXProject; 195 | attributes = { 196 | BuildIndependentTargetsInParallel = 1; 197 | LastSwiftUpdateCheck = 1300; 198 | LastUpgradeCheck = 1300; 199 | TargetAttributes = { 200 | 2356DBC526A50AB100A39A25 = { 201 | CreatedOnToolsVersion = 13.0; 202 | }; 203 | 2356DBDA26A50B0100A39A25 = { 204 | CreatedOnToolsVersion = 13.0; 205 | }; 206 | }; 207 | }; 208 | buildConfigurationList = 2356DBC126A50AB100A39A25 /* Build configuration list for PBXProject "DSFDockTile Plugin Demo" */; 209 | compatibilityVersion = "Xcode 13.0"; 210 | developmentRegion = en; 211 | hasScannedForEncodings = 0; 212 | knownRegions = ( 213 | en, 214 | Base, 215 | ); 216 | mainGroup = 2356DBBD26A50AB100A39A25; 217 | packageReferences = ( 218 | 2356DBEF26A50C1300A39A25 /* XCRemoteSwiftPackageReference "DSFDockTile" */, 219 | ); 220 | productRefGroup = 2356DBC726A50AB100A39A25 /* Products */; 221 | projectDirPath = ""; 222 | projectRoot = ""; 223 | targets = ( 224 | 2356DBC526A50AB100A39A25 /* DSFDockTile Plugin Demo */, 225 | 2356DBDA26A50B0100A39A25 /* DSFDockTilePlugin */, 226 | ); 227 | }; 228 | /* End PBXProject section */ 229 | 230 | /* Begin PBXResourcesBuildPhase section */ 231 | 2356DBC426A50AB100A39A25 /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 2356DBD126A50AB200A39A25 /* Preview Assets.xcassets in Resources */, 236 | 2356DBCE26A50AB200A39A25 /* Assets.xcassets in Resources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | 2356DBD926A50B0100A39A25 /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 2356DC0926A51EB400A39A25 /* light.png in Resources */, 245 | 2356DC0726A51DAC00A39A25 /* dark.png in Resources */, 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | }; 249 | /* End PBXResourcesBuildPhase section */ 250 | 251 | /* Begin PBXSourcesBuildPhase section */ 252 | 2356DBC226A50AB100A39A25 /* Sources */ = { 253 | isa = PBXSourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | 2356DBCC26A50AB100A39A25 /* ContentView.swift in Sources */, 257 | 23447D3926A52BDB0074ABF2 /* LightDarkImage.swift in Sources */, 258 | 2356DBCA26A50AB100A39A25 /* DSFDockTile_Plugin_DemoApp.swift in Sources */, 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | }; 262 | 2356DBD726A50B0100A39A25 /* Sources */ = { 263 | isa = PBXSourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | 2356DBF426A50D3800A39A25 /* DockTilePlugin.swift in Sources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | /* End PBXSourcesBuildPhase section */ 271 | 272 | /* Begin PBXTargetDependency section */ 273 | 2356DBE326A50B5D00A39A25 /* PBXTargetDependency */ = { 274 | isa = PBXTargetDependency; 275 | target = 2356DBDA26A50B0100A39A25 /* DSFDockTilePlugin */; 276 | targetProxy = 2356DBE226A50B5D00A39A25 /* PBXContainerItemProxy */; 277 | }; 278 | /* End PBXTargetDependency section */ 279 | 280 | /* Begin XCBuildConfiguration section */ 281 | 2356DBD226A50AB200A39A25 /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ALWAYS_SEARCH_USER_PATHS = NO; 285 | CLANG_ANALYZER_NONNULL = YES; 286 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 287 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 288 | CLANG_CXX_LIBRARY = "libc++"; 289 | CLANG_ENABLE_MODULES = YES; 290 | CLANG_ENABLE_OBJC_ARC = YES; 291 | CLANG_ENABLE_OBJC_WEAK = YES; 292 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 293 | CLANG_WARN_BOOL_CONVERSION = YES; 294 | CLANG_WARN_COMMA = YES; 295 | CLANG_WARN_CONSTANT_CONVERSION = YES; 296 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 297 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 298 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 299 | CLANG_WARN_EMPTY_BODY = YES; 300 | CLANG_WARN_ENUM_CONVERSION = YES; 301 | CLANG_WARN_INFINITE_RECURSION = YES; 302 | CLANG_WARN_INT_CONVERSION = YES; 303 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 304 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 305 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 307 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 308 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 309 | CLANG_WARN_STRICT_PROTOTYPES = YES; 310 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 311 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 312 | CLANG_WARN_UNREACHABLE_CODE = YES; 313 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 314 | COPY_PHASE_STRIP = NO; 315 | DEBUG_INFORMATION_FORMAT = dwarf; 316 | ENABLE_STRICT_OBJC_MSGSEND = YES; 317 | ENABLE_TESTABILITY = YES; 318 | GCC_C_LANGUAGE_STANDARD = gnu11; 319 | GCC_DYNAMIC_NO_PIC = NO; 320 | GCC_NO_COMMON_BLOCKS = YES; 321 | GCC_OPTIMIZATION_LEVEL = 0; 322 | GCC_PREPROCESSOR_DEFINITIONS = ( 323 | "DEBUG=1", 324 | "$(inherited)", 325 | ); 326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | GCC_WARN_UNUSED_VARIABLE = YES; 332 | MACOSX_DEPLOYMENT_TARGET = 11.4; 333 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 334 | MTL_FAST_MATH = YES; 335 | ONLY_ACTIVE_ARCH = YES; 336 | SDKROOT = macosx; 337 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 338 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 339 | }; 340 | name = Debug; 341 | }; 342 | 2356DBD326A50AB200A39A25 /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ALWAYS_SEARCH_USER_PATHS = NO; 346 | CLANG_ANALYZER_NONNULL = YES; 347 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 348 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 349 | CLANG_CXX_LIBRARY = "libc++"; 350 | CLANG_ENABLE_MODULES = YES; 351 | CLANG_ENABLE_OBJC_ARC = YES; 352 | CLANG_ENABLE_OBJC_WEAK = YES; 353 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 354 | CLANG_WARN_BOOL_CONVERSION = YES; 355 | CLANG_WARN_COMMA = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 358 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 359 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 360 | CLANG_WARN_EMPTY_BODY = YES; 361 | CLANG_WARN_ENUM_CONVERSION = YES; 362 | CLANG_WARN_INFINITE_RECURSION = YES; 363 | CLANG_WARN_INT_CONVERSION = YES; 364 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 365 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 366 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 367 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 368 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 369 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 370 | CLANG_WARN_STRICT_PROTOTYPES = YES; 371 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 372 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 373 | CLANG_WARN_UNREACHABLE_CODE = YES; 374 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 375 | COPY_PHASE_STRIP = NO; 376 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 377 | ENABLE_NS_ASSERTIONS = NO; 378 | ENABLE_STRICT_OBJC_MSGSEND = YES; 379 | GCC_C_LANGUAGE_STANDARD = gnu11; 380 | GCC_NO_COMMON_BLOCKS = YES; 381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 383 | GCC_WARN_UNDECLARED_SELECTOR = YES; 384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 385 | GCC_WARN_UNUSED_FUNCTION = YES; 386 | GCC_WARN_UNUSED_VARIABLE = YES; 387 | MACOSX_DEPLOYMENT_TARGET = 11.4; 388 | MTL_ENABLE_DEBUG_INFO = NO; 389 | MTL_FAST_MATH = YES; 390 | SDKROOT = macosx; 391 | SWIFT_COMPILATION_MODE = wholemodule; 392 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 393 | }; 394 | name = Release; 395 | }; 396 | 2356DBD526A50AB200A39A25 /* Debug */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 400 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 401 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 402 | CODE_SIGN_STYLE = Automatic; 403 | COMBINE_HIDPI_IMAGES = YES; 404 | CURRENT_PROJECT_VERSION = 1; 405 | DEVELOPMENT_ASSET_PATHS = "\"DSFDockTile Plugin Demo/Preview Content\""; 406 | ENABLE_APP_SANDBOX = YES; 407 | ENABLE_PREVIEWS = YES; 408 | ENABLE_USER_SELECTED_FILES = readonly; 409 | GENERATE_INFOPLIST_FILE = YES; 410 | INFOPLIST_FILE = "DSFDockTile-Plugin-Demo-Info.plist"; 411 | INFOPLIST_KEY_CFBundleExecutable = "DSFDockTile Plugin Demo"; 412 | INFOPLIST_KEY_CFBundleName = "DSFDockTile Plugin Demo"; 413 | INFOPLIST_KEY_CFBundleVersion = 1; 414 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 415 | LD_RUNPATH_SEARCH_PATHS = ( 416 | "$(inherited)", 417 | "@executable_path/../Frameworks", 418 | ); 419 | MACOSX_DEPLOYMENT_TARGET = 11.0; 420 | MARKETING_VERSION = 1.0; 421 | PRODUCT_BUNDLE_IDENTIFIER = "com.dagronf.dsfdocktile.plugin-demo.app"; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | SWIFT_EMIT_LOC_STRINGS = YES; 424 | SWIFT_VERSION = 5.0; 425 | }; 426 | name = Debug; 427 | }; 428 | 2356DBD626A50AB200A39A25 /* Release */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 433 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 434 | CODE_SIGN_STYLE = Automatic; 435 | COMBINE_HIDPI_IMAGES = YES; 436 | CURRENT_PROJECT_VERSION = 1; 437 | DEVELOPMENT_ASSET_PATHS = "\"DSFDockTile Plugin Demo/Preview Content\""; 438 | ENABLE_APP_SANDBOX = YES; 439 | ENABLE_PREVIEWS = YES; 440 | ENABLE_USER_SELECTED_FILES = readonly; 441 | GENERATE_INFOPLIST_FILE = YES; 442 | INFOPLIST_FILE = "DSFDockTile-Plugin-Demo-Info.plist"; 443 | INFOPLIST_KEY_CFBundleExecutable = "DSFDockTile Plugin Demo"; 444 | INFOPLIST_KEY_CFBundleName = "DSFDockTile Plugin Demo"; 445 | INFOPLIST_KEY_CFBundleVersion = 1; 446 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 447 | LD_RUNPATH_SEARCH_PATHS = ( 448 | "$(inherited)", 449 | "@executable_path/../Frameworks", 450 | ); 451 | MACOSX_DEPLOYMENT_TARGET = 11.0; 452 | MARKETING_VERSION = 1.0; 453 | PRODUCT_BUNDLE_IDENTIFIER = "com.dagronf.dsfdocktile.plugin-demo.app"; 454 | PRODUCT_NAME = "$(TARGET_NAME)"; 455 | SWIFT_EMIT_LOC_STRINGS = YES; 456 | SWIFT_VERSION = 5.0; 457 | }; 458 | name = Release; 459 | }; 460 | 2356DBDD26A50B0100A39A25 /* Debug */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | CODE_SIGN_STYLE = Automatic; 464 | COMBINE_HIDPI_IMAGES = YES; 465 | CURRENT_PROJECT_VERSION = 1; 466 | EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = NO; 467 | GENERATE_INFOPLIST_FILE = YES; 468 | INFOPLIST_FILE = "DSFDockTilePlugin-Info.plist"; 469 | INFOPLIST_KEY_CFBundleExecutable = DSFDockTilePlugin; 470 | INFOPLIST_KEY_CFBundleName = DSFDockTilePlugin; 471 | INFOPLIST_KEY_CFBundleVersion = 1; 472 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 473 | INFOPLIST_KEY_NSPrincipalClass = ""; 474 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 475 | MACOSX_DEPLOYMENT_TARGET = 11.0; 476 | MARKETING_VERSION = 1.0; 477 | PRODUCT_BUNDLE_IDENTIFIER = "com.dagronf.dsfdocktile.plugin-demo.plugin.DSFDockTilePlugin"; 478 | PRODUCT_NAME = "$(TARGET_NAME)"; 479 | SKIP_INSTALL = YES; 480 | SWIFT_EMIT_LOC_STRINGS = YES; 481 | SWIFT_VERSION = 5.0; 482 | WRAPPER_EXTENSION = plugin; 483 | }; 484 | name = Debug; 485 | }; 486 | 2356DBDE26A50B0100A39A25 /* Release */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | CODE_SIGN_STYLE = Automatic; 490 | COMBINE_HIDPI_IMAGES = YES; 491 | CURRENT_PROJECT_VERSION = 1; 492 | EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = NO; 493 | GENERATE_INFOPLIST_FILE = YES; 494 | INFOPLIST_FILE = "DSFDockTilePlugin-Info.plist"; 495 | INFOPLIST_KEY_CFBundleExecutable = DSFDockTilePlugin; 496 | INFOPLIST_KEY_CFBundleName = DSFDockTilePlugin; 497 | INFOPLIST_KEY_CFBundleVersion = 1; 498 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 499 | INFOPLIST_KEY_NSPrincipalClass = ""; 500 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 501 | MACOSX_DEPLOYMENT_TARGET = 11.0; 502 | MARKETING_VERSION = 1.0; 503 | PRODUCT_BUNDLE_IDENTIFIER = "com.dagronf.dsfdocktile.plugin-demo.plugin.DSFDockTilePlugin"; 504 | PRODUCT_NAME = "$(TARGET_NAME)"; 505 | SKIP_INSTALL = YES; 506 | SWIFT_EMIT_LOC_STRINGS = YES; 507 | SWIFT_VERSION = 5.0; 508 | WRAPPER_EXTENSION = plugin; 509 | }; 510 | name = Release; 511 | }; 512 | /* End XCBuildConfiguration section */ 513 | 514 | /* Begin XCConfigurationList section */ 515 | 2356DBC126A50AB100A39A25 /* Build configuration list for PBXProject "DSFDockTile Plugin Demo" */ = { 516 | isa = XCConfigurationList; 517 | buildConfigurations = ( 518 | 2356DBD226A50AB200A39A25 /* Debug */, 519 | 2356DBD326A50AB200A39A25 /* Release */, 520 | ); 521 | defaultConfigurationIsVisible = 0; 522 | defaultConfigurationName = Release; 523 | }; 524 | 2356DBD426A50AB200A39A25 /* Build configuration list for PBXNativeTarget "DSFDockTile Plugin Demo" */ = { 525 | isa = XCConfigurationList; 526 | buildConfigurations = ( 527 | 2356DBD526A50AB200A39A25 /* Debug */, 528 | 2356DBD626A50AB200A39A25 /* Release */, 529 | ); 530 | defaultConfigurationIsVisible = 0; 531 | defaultConfigurationName = Release; 532 | }; 533 | 2356DBDC26A50B0100A39A25 /* Build configuration list for PBXNativeTarget "DSFDockTilePlugin" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | 2356DBDD26A50B0100A39A25 /* Debug */, 537 | 2356DBDE26A50B0100A39A25 /* Release */, 538 | ); 539 | defaultConfigurationIsVisible = 0; 540 | defaultConfigurationName = Release; 541 | }; 542 | /* End XCConfigurationList section */ 543 | 544 | /* Begin XCRemoteSwiftPackageReference section */ 545 | 2356DBEF26A50C1300A39A25 /* XCRemoteSwiftPackageReference "DSFDockTile" */ = { 546 | isa = XCRemoteSwiftPackageReference; 547 | repositoryURL = "https://github.com/dagronf/DSFDockTile"; 548 | requirement = { 549 | kind = upToNextMajorVersion; 550 | minimumVersion = 0.5.2; 551 | }; 552 | }; 553 | /* End XCRemoteSwiftPackageReference section */ 554 | 555 | /* Begin XCSwiftPackageProductDependency section */ 556 | 2356DBF026A50C1300A39A25 /* DSFDockTile */ = { 557 | isa = XCSwiftPackageProductDependency; 558 | package = 2356DBEF26A50C1300A39A25 /* XCRemoteSwiftPackageReference "DSFDockTile" */; 559 | productName = DSFDockTile; 560 | }; 561 | /* End XCSwiftPackageProductDependency section */ 562 | }; 563 | rootObject = 2356DBBE26A50AB100A39A25 /* Project object */; 564 | } 565 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "DSFDockTile", 6 | "repositoryURL": "https://github.com/dagronf/DSFDockTile", 7 | "state": { 8 | "branch": null, 9 | "revision": "bb18b82cd3d64206eb322bd297f794b0a36dbf4d", 10 | "version": "0.5.2" 11 | } 12 | }, 13 | { 14 | "package": "DSFImageFlipbook", 15 | "repositoryURL": "https://github.com/dagronf/DSFImageFlipbook", 16 | "state": { 17 | "branch": null, 18 | "revision": "8b6e1e7f862c1d39ce34c59705f9fa731d9fd539", 19 | "version": "1.0.1" 20 | } 21 | } 22 | ] 23 | }, 24 | "version": 1 25 | } 26 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/dark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "dark.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "dark@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/dark.imageset/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/dark.imageset/dark.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/dark.imageset/dark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/dark.imageset/dark@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/light.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "light.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "light@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/light.imageset/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/light.imageset/light.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/light.imageset/light@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Assets.xcassets/light.imageset/light@2x.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // DSFDockTile Plugin Demo 4 | // 5 | // Created by Darren Ford on 19/7/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | @Environment(\.colorScheme) var scheme 13 | 14 | var body: some View { 15 | VStack(spacing: 16) { 16 | LightDarkImage() 17 | .frame(width: 196, height: 196) 18 | 19 | Text("NSDockTile Plugin Demo").font(.title) 20 | .frame(alignment: .center) 21 | 22 | VStack(alignment: .leading) { 23 | Text("This demo uses a NSDockTile plugin to display its dock content") 24 | Text("Change the appearance to/from dark mode to see the dock icon change") 25 | Text("Note this change occurs even if the app isn't running (but it has been added to the dock)") 26 | } 27 | } 28 | .padding() 29 | .frame(maxWidth: .infinity, maxHeight: .infinity) 30 | } 31 | } 32 | 33 | struct ContentView_Previews: PreviewProvider { 34 | static var previews: some View { 35 | ContentView() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/DSFDockTile_Plugin_DemoApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile_Plugin_DemoApp.swift 3 | // DSFDockTile Plugin Demo 4 | // 5 | // Created by Darren Ford on 19/7/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct DSFDockTile_Plugin_DemoApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | .onReceive(NotificationCenter.default.publisher(for: NSApplication.willUpdateNotification), perform: { _ in 16 | hideZoomButton() 17 | }) 18 | .navigationTitle("NSDockTilePlugin Demo") 19 | } 20 | } 21 | 22 | 23 | func hideZoomButton() { 24 | if let window = NSApplication.shared.windows.filter({ $0.title == "NSDockTilePlugin Demo" }).first { 25 | window.standardWindowButton(NSWindow.ButtonType.zoomButton)!.isHidden = true 26 | window.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)!.isHidden = true 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/LightDarkImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LightDarkImage.swift 3 | // DSFDockTile Plugin Demo 4 | // 5 | // Created by Darren Ford on 19/7/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LightDarkImage: View { 11 | @Environment(\.colorScheme) var scheme 12 | var body: some View { 13 | Group { 14 | if scheme == .light { 15 | Image("light").resizable() 16 | } 17 | else { 18 | Image("dark").resizable() 19 | } 20 | } 21 | .padding(0) 22 | } 23 | } 24 | 25 | struct LightDarkImage_Previews: PreviewProvider { 26 | static var previews: some View { 27 | HStack { 28 | LightDarkImage()//.previewLayout(.fixed(width: 196, height: 196)) 29 | .environment(\.colorScheme, .light) 30 | LightDarkImage()//.previewLayout(.fixed(width: 196, height: 196)) 31 | .environment(\.colorScheme, .dark) 32 | } 33 | .frame(width: 196 * 2, height: 196) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin Demo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin/DockTilePlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DockTilePlugin.swift 3 | // DockTilePluginTest 4 | // 5 | // Created by Darren Ford on 25/3/21. 6 | // 7 | 8 | import AppKit 9 | import Combine 10 | import os 11 | 12 | import DSFDockTile 13 | 14 | class DockTilePlugin: NSObject, NSDockTilePlugIn { 15 | 16 | // MARK: - Bundle loading 17 | 18 | private static func LoadImage(named name: String) -> NSImage { 19 | let bundle = Bundle(for: DockTilePlugin.self) 20 | let path = bundle.path(forResource: name, ofType: "png")! 21 | return NSImage(byReferencingFile: path)! 22 | } 23 | 24 | // MARK: - Images 25 | 26 | private lazy var lightImage: NSImage = { 27 | return Self.LoadImage(named: "light") 28 | }() 29 | 30 | private lazy var darkImage: NSImage = { 31 | return Self.LoadImage(named: "dark") 32 | }() 33 | 34 | // MARK: - Dock icon 35 | private var appIcon: DSFDockTile.Image? = nil 36 | 37 | weak var dockTile: NSDockTile? = nil { 38 | didSet { 39 | if let d = self.dockTile { 40 | appIcon = DSFDockTile.Image(dockTile: d) 41 | } 42 | else { 43 | appIcon = nil 44 | } 45 | } 46 | } 47 | 48 | // MARK: - Combine 49 | 50 | // publisher cancellable for theme changes 51 | private var cancellable: AnyCancellable? = nil 52 | 53 | // MARK: - Plugin callbacks 54 | 55 | /// Invoked when the plug-in is first loaded and when the application is removed from the Dock. 56 | func setDockTile(_ dockTile: NSDockTile?) { 57 | guard let dockTile = dockTile else { return } 58 | self.dockTile = dockTile 59 | 60 | self.updateDockTile() 61 | 62 | self.cancellable = NSApp.publisher(for: \.effectiveAppearance) 63 | .removeDuplicates() 64 | .sink { [weak self] appearance in 65 | self?.updateDockTile(appearance: appearance) 66 | } 67 | } 68 | } 69 | 70 | extension DockTilePlugin { 71 | private func updateDockTile(appearance: NSAppearance = NSApp.effectiveAppearance) { 72 | let isLight = appearance.bestMatch(from: [.aqua, .darkAqua]) == .aqua 73 | if isLight { 74 | appIcon?.display(self.lightImage) 75 | } 76 | else { 77 | appIcon?.display(self.darkImage) 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin/resources/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin/resources/dark.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin/resources/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/DSFDockTile Plugin Demo/DSFDockTile Plugin/resources/light.png -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTile-Plugin-Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleInfoDictionaryVersion 6 | 6.0 7 | NSDockTilePlugIn 8 | DSFDockTilePlugin.plugin 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demos/DSFDockTile Plugin Demo/DSFDockTilePlugin-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleInfoDictionaryVersion 6 | 6.0 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/apple-icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "iu.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/apple-icon.imageset/iu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/SwiftUI docktile demo/Assets.xcassets/apple-icon.imageset/iu.png -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/marble.dataset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "data" : [ 3 | { 4 | "filename" : "marble.gif", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Assets.xcassets/marble.dataset/marble.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagronf/DSFDockTile/74fe5412bf42d9bfd461598178fe2902b32edf99/Demos/SwiftUI docktile demo/Assets.xcassets/marble.dataset/marble.gif -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUI docktile demo 4 | // 5 | // Created by Darren Ford on 22/3/2022. 6 | // 7 | 8 | import SwiftUI 9 | import Combine 10 | import DSFDockTile 11 | 12 | 13 | struct ContentView: View { 14 | 15 | @Binding var isAnimating: Bool 16 | 17 | var body: some View { 18 | VStack(alignment: .leading, spacing: 8) { 19 | Text("Example SwiftUI DockTile View demo.").font(.title) 20 | Text("Try minimising this window to see a window docktile updating.") 21 | Toggle("Animate window dock tile", isOn: $isAnimating) 22 | } 23 | .padding() 24 | } 25 | } 26 | 27 | struct ContentView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | ContentView(isAnimating: .constant(false)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/DockTileContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DockTileContentView.swift 3 | // SwiftUI docktile demo 4 | // 5 | // Created by Darren Ford on 22/3/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | // The content to display in the dock tile 11 | struct DockTileContentView: View { 12 | let percent: Int 13 | var body: some View { 14 | ZStack { 15 | Image("apple-icon") 16 | .resizable() 17 | .scaledToFit() 18 | VStack { 19 | Spacer() 20 | Text("\(percent)%") 21 | .foregroundColor(.white).bold() 22 | .font(Font.system(size: 30)) 23 | .shadow(color: .black, radius: 1, x: 1, y: -2) 24 | .frame(maxWidth: .infinity) 25 | .background { 26 | RoundedRectangle(cornerRadius: 16) 27 | .fill(Color.blue.opacity(0.6)) 28 | } 29 | .padding(4) 30 | } 31 | } 32 | } 33 | } 34 | 35 | struct DockTileContentView_Previews: PreviewProvider { 36 | static var previews: some View { 37 | DockTileContentView(percent: 12) 38 | .frame(width: 128, height: 128) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/SwiftUI_docktile_demo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demos/SwiftUI docktile demo/SwiftUI_docktile_demoApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUI_docktile_demoApp.swift 3 | // SwiftUI docktile demo 4 | // 5 | // Created by Darren Ford on 22/3/2022. 6 | // 7 | 8 | import DSFDockTile 9 | import SwiftUI 10 | 11 | let animatedDockTile: DSFDockTile.Animated = { 12 | let da = NSDataAsset(name: NSDataAsset.Name("marble"))!.data 13 | return DSFDockTile.Animated(animatedImageData: da)! 14 | }() 15 | 16 | @main 17 | struct SwiftUI_docktile_demoApp: App { 18 | let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() 19 | @State var count = 0 20 | 21 | @State var animating: Bool = false 22 | 23 | var body: some Scene { 24 | WindowGroup { 25 | VStack { 26 | ContentView(isAnimating: $animating) 27 | .onReceive(timer) { input in 28 | count += 1 29 | } 30 | // The docktile for the application 31 | DockTile( 32 | label: "\(count)", 33 | content: DockTileContentView(percent: count % 100) 34 | ) 35 | 36 | // The docktile for the _window_ containing this view 37 | DockTile( 38 | .window, 39 | animation: animatedDockTile, 40 | isAnimating: animating) 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Darren Ford 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "DSFImageFlipbook", 6 | "repositoryURL": "https://github.com/dagronf/DSFImageFlipbook", 7 | "state": { 8 | "branch": null, 9 | "revision": "8b6e1e7f862c1d39ce34c59705f9fa731d9fd539", 10 | "version": "1.0.1" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.4 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "DSFDockTile", 7 | platforms: [ 8 | .macOS(.v10_13), 9 | ], 10 | products: [ 11 | .library( 12 | name: "DSFDockTile", 13 | targets: ["DSFDockTile"]), 14 | ], 15 | dependencies: [ 16 | .package(name: "DSFImageFlipbook", url: "https://github.com/dagronf/DSFImageFlipbook", from: Version(1, 0, 0)) 17 | ], 18 | targets: [ 19 | .target( 20 | name: "DSFDockTile", 21 | dependencies: ["DSFImageFlipbook"], 22 | resources: [ 23 | .copy("PrivacyInfo.xcprivacy"), 24 | ] 25 | ), 26 | .testTarget( 27 | name: "DSFDockTileTests", 28 | dependencies: ["DSFDockTile"]), 29 | ] 30 | ) 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DSFDockTile 2 | 3 | Easily display images, animations, badges and alerts to your macOS application's dock icon. 4 | 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | Swift Package Manager 13 |

14 | 15 | ![](https://github.com/dagronf/dagronf.github.io/blob/master/art/projects/DSFDockTile/stitch.gif?raw=true) 16 | 17 | ## Why? 18 | 19 | I was inspired by [Neil Sardesai](https://twitter.com/neilsardesai) after he posted [this on Twitter](https://twitter.com/neilsardesai/status/1362179114204073984?s=20). And this marvellous follow-up tweet by [Norbert M. Doerner](https://twitter.com/cdfinder/status/1365201157854015488?s=20). 20 | 21 | While the NSDockTile API isn't overly complex, I wanted something that made it easy to change the dock image, and even add basic animations from GIF images etc. 22 | 23 | ## Features 24 | 25 | * Set the badge label 26 | * Display an image 27 | * Display an animated image 28 | * Display the content of an NSView 29 | * Bounce the docktile 30 | 31 | By default a `DSFDockTile` instance operates on the Application's docktile. You can provide your own `NSDockTile` for any window (by calling `window.dockTile`) via the `init` functions on the badge generators. 32 | 33 | ## DockTile plugins 34 | 35 | Did you know that your application can show a custom DockTile image even when it's not running? Apple provides an `NSDockTilePlugin` prodocol that allows you to do exactly that. Want to provide different application icons for dark and light modes? `NSDockTilePlugin` allows you to! Want to tweak the dock icon when your application isn't running, but needs attention? `NSDockTilePlugin`! 36 | 37 | There is a demo application in the `Demos` folder called **'DSFDockTile Plugin Demo'** (macOS 11+) that demonstrates using `NSDockTilePlugin` and `DSFDockIcon` in SwiftUI. 38 | 39 | ## Integration 40 | 41 | ### Swift package manager 42 | 43 | Add `https://github.com/dagronf/DSFDockTile` to your project. 44 | 45 | If you don't want to include the `DSFImageFlipbook` package, copy all the files in the `Sources/` folder **EXCEPT** for `DSFDockTile+Animation.swift`. 46 | 47 | ### Demo 48 | 49 | There is a demo macOS application available in the `Demos` subfolder. 50 | 51 | ## Badge Label 52 | 53 | It's very easy to add a badge label to a docktile. 54 | 55 | ```swift 56 | // Set the label on the docktile to 1234 57 | DSFDockTile.badgeLabel = "1234" 58 | 59 | // Remove the badge label from the docktile 60 | DSFDockTile.badgeLabel = nil 61 | ``` 62 | 63 | ## DockTile Generators 64 | 65 | ### AppIcon 66 | 67 | Set the docktile to the application's icon. 68 | 69 | ```swift 70 | // Set the dock icon to the application icon 71 | DSFDockTile.AppIcon.display() 72 | ``` 73 | 74 | ### Constant Image 75 | 76 | This is a `DSFDockTile` object that displays a single image. Useful for if you have a set of images to display in the docktile that do not change and you want to the constantness. 77 | 78 | ```swift 79 | static let LockedImage = NSImage(named: NSImage.Name("padlock-locked"))! 80 | static let UnlockedImage = NSImage(named: NSImage.Name("padlock-unlocked"))! 81 | 82 | let LockedDockTileImage = DSFDockTile.ConstantImage(LockedImage) 83 | let UnlockedDockTileImage = DSFDockTile.ConstantImage(UnlockedImage) 84 | ... 85 | 86 | if application.isEditable { 87 | UnlockedDockTileImage.display() 88 | } 89 | else { 90 | LockedDockTileImage.display() 91 | } 92 | ``` 93 | 94 | ### Image 95 | 96 | This is a `DSFDockTile` object that can display images. 97 | 98 | ```swift 99 | static let LockedImage = NSImage(named: NSImage.Name("padlock-locked"))! 100 | static let UnlockedImage = NSImage(named: NSImage.Name("padlock-unlocked"))! 101 | 102 | let stateDockTile = DSFDockTile.Image() 103 | 104 | ... 105 | 106 | func viewDidLoad() { 107 | let image = application.isEditable ? UnlockedImage : LockedImage 108 | stateDockTile.display(image) 109 | } 110 | ``` 111 | 112 | ### View 113 | 114 | This is a `DSFDockTile` object that can display the content of a view managed by a view controller 115 | 116 | Due to NSDockTile restrictions, the view is not drawn live into the dock as the view is updated. You must call `display()` to update the dock tile with the view's current content whenever a change occurs in the view. 117 | 118 | ```swift 119 | /// The view controller to display on the docktile 120 | let dockViewController = DockViewController() 121 | 122 | /// The docktile instance handling the docktile 123 | lazy var updateDockTile: DSFDockTile.View = { 124 | dockViewController.loadView() 125 | return DSFDockTile.View(dockViewController) 126 | }() 127 | ... 128 | func doUpdate() { 129 | // Change the color of the item in the 130 | self.dockViewController.foregroundColor = .systemYellow 131 | 132 | // NSDockTile does not update automatically so need to tell it when changes are made 133 | self.updateDockTile.display() 134 | } 135 | ``` 136 | 137 | ### Animation 138 | 139 | This is a docktile that can display an animation. It uses `DSFImageFlipbook` under the seams to handle the animation itself. 140 | 141 | ```swift 142 | let animatedDockTile: DSFDockTile.Animated = { 143 | let fb = DSFImageFlipbook() 144 | let da = NSDataAsset(name: NSDataAsset.Name("animated-gif"))! 145 | _ = fb.loadFrames(from: da.data) 146 | return DSFDockTile.Animated(fb) 147 | }() 148 | 149 | ... 150 | 151 | @IBAction func startAnimating(_ sender: Any) { 152 | animatedDockTile.startAnimating() 153 | } 154 | 155 | @IBAction func stopAnimating(_ sender: Any) { 156 | animatedDockTile.stopAnimating() 157 | } 158 | ``` 159 | 160 | ## SwiftUI 161 | 162 | The `DockTile` view is used to manipulate the docktile for 163 | 164 | * The application (`.application`) 165 | * The window containing the `DockTile` View (`.window`) 166 | 167 | You can set which docktile you want to update in the initializer of the `DockTile` View 168 | 169 | ### Updating the badge 170 | 171 | To set a badge using SwiftUI, use the `DockTile` view and provide a label for the badge 172 | 173 | ```swift 174 | @State var badgeLabel: String = "" 175 | var body: some Scene { 176 | WindowGroup { 177 | ZStack { 178 | ContentView() 179 | DockTile(label: badgeLabel) 180 | } 181 | } 182 | } 183 | ``` 184 | 185 | ### Updating the content 186 | 187 | To set the content of a dock tile, provide a view to the initializer. Set to `nil` to return the docktile to its default. 188 | 189 | ```swift 190 | @State var dockText: String = "" 191 | var body: some Scene { 192 | WindowGroup { 193 | ZStack { 194 | ContentView() 195 | DockTile( 196 | .window, 197 | label: "3", 198 | content: ZStack { 199 | Color.white 200 | Text(dockText) 201 | } 202 | ) 203 | } 204 | } 205 | } 206 | ``` 207 | 208 | Remember that the DockTile API does not provide live docktile updating, and will require you to update the view for each 209 | visual change you want to make 210 | 211 | ## Attention Concepts 212 | 213 | You can request user information via the DockTile of an application if your application is not the front-most application. 214 | 215 | See [Apple's Documentation](https://developer.apple.com/documentation/appkit/nsapplication/1428358-requestuserattention) for more details. 216 | 217 | ### requestInformationalAttention() 218 | 219 | Request that the docktile 'bounce' to inform the user of something informational. The function returns an object which you can use to cancel the attention request. 220 | 221 | ```swift 222 | let cancellable = DSFDockTile.requestInformationalAttention() 223 | ``` 224 | 225 | The `cancellable` can be used to cancel the information request. 226 | 227 | See [Apple's Documentation](https://developer.apple.com/documentation/appkit/nsapplication/requestuserattentiontype/criticalrequest) 228 | 229 | ### requestCriticalAttention() 230 | 231 | Request that the docktile 'bounce' to inform the user of something informational. The function returns an object which you can use to cancel the attention request. 232 | 233 | ```swift 234 | let cancellable = DSFDockTile.requestCriticalAttention() 235 | ``` 236 | 237 | The `cancellable` can be used to cancel the critical request. 238 | 239 | See [Apple's Documentation](https://developer.apple.com/documentation/appkit/nsapplication/requestuserattentiontype/informationalrequest) 240 | 241 | ### Cancellation protocol (DSFDockTileUserAttentionCancellation) 242 | 243 | The user attention methods return an object that conforms to `DSFDockTileUserAttentionCancellation` that can be used to cancel an attention request. 244 | 245 | See [Apple's Documentation](https://developer.apple.com/documentation/appkit/nsapplication/1428683-canceluserattentionrequest) 246 | 247 | ## Thanks 248 | 249 | * [Neil Sardesai](https://twitter.com/neilsardesai) 250 | * [Norbert M. Doerner](https://twitter.com/cdfinder) 251 | * The images (light/dark) in the demo application are thanks to [brgfx on freepix](https://www.freepik.com/free-vector/opposite-adjectives-light-dark_1172843.htm) 252 | * Attribution - Background vector created by brgfx - www.freepik.com 253 | 254 | * Here is the project I used to understand how to use `NSDockTilePlugin` for my own project. [https://github.com/rrroyal/AutomaticDockTile](https://github.com/rrroyal/AutomaticDockTile) 255 | 256 | ## License 257 | 258 | MIT. Use it and abuse it for anything you want, just attribute my work. Let me know if you do use it somewhere, I'd love to hear about it! 259 | 260 | ``` 261 | MIT License 262 | 263 | Copyright (c) 2022 Darren Ford 264 | 265 | Permission is hereby granted, free of charge, to any person obtaining a copy 266 | of this software and associated documentation files (the "Software"), to deal 267 | in the Software without restriction, including without limitation the rights 268 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 269 | copies of the Software, and to permit persons to whom the Software is 270 | furnished to do so, subject to the following conditions: 271 | 272 | The above copyright notice and this permission notice shall be included in all 273 | copies or substantial portions of the Software. 274 | 275 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 276 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 277 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 278 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 279 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 280 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 281 | SOFTWARE. 282 | ``` 283 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+Animation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile+Animation.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | import DSFImageFlipbook 30 | 31 | extension DSFDockTile { 32 | 33 | /// A docktile object that handles an animation 34 | public class Animated: Image { 35 | 36 | /// The flipbook used to handle the animation 37 | public let flipbook: DSFImageFlipbook 38 | 39 | // Flipbook animation settings 40 | fileprivate var stopAtEndOfCurrentLoop: Bool = false 41 | 42 | /// Is the animation currently playing? 43 | @inlinable public var isAnimating: Bool { 44 | return flipbook.isAnimating() 45 | } 46 | 47 | /// Create a DockTile object presenting an animation 48 | /// - Parameters: 49 | /// - flipbook: The flipbook containing the image to present 50 | /// - dockTile: The docktile to update 51 | public init(_ flipbook: DSFImageFlipbook, 52 | dockTile: NSDockTile? = NSApp?.dockTile) { 53 | self.flipbook = flipbook 54 | super.init(dockTile: dockTile) 55 | } 56 | 57 | /// Create a DockTile object presenting an animation from the raw data 58 | /// - Parameters: 59 | /// - flipbook: The image data for the animation (eg. a gif file) 60 | /// - dockTile: The docktile to update 61 | public init?( 62 | animatedImageData: Data, 63 | dockTile: NSDockTile? = NSApp?.dockTile) 64 | { 65 | let fb = DSFImageFlipbook() 66 | _ = fb.loadFrames(from: animatedImageData) 67 | guard fb.frameCount > 0 else { 68 | return nil 69 | } 70 | self.flipbook = fb 71 | super.init(dockTile: dockTile) 72 | } 73 | 74 | /// Display the first frame of the animation 75 | public override func display() { 76 | if let image = flipbook.frame(at: 0)?.image { 77 | self.display(image) 78 | } 79 | } 80 | 81 | /// Start the flipbook animation on the docktile 82 | /// - Parameter frame: The frame in the flipbook to start animating at 83 | /// - Parameter speed: The speed to animate the dock tile 84 | public func startAnimating(atFrame frame: Int = 0, speed: Double = 1) { 85 | self.stopAtEndOfCurrentLoop = false 86 | flipbook.start( 87 | startAtFrame: frame, 88 | speed: speed) { [weak self] frame, currentFrame, count, stop in 89 | 90 | guard let `self` = self else { return } 91 | 92 | self.display(frame.image) 93 | 94 | if self.stopAtEndOfCurrentLoop, currentFrame == (count - 1) { 95 | stop = true 96 | } 97 | } 98 | } 99 | 100 | /// Stop the current docktile animation 101 | /// - Parameter stopAtEndOfCurrentLoop: If true, stops the animation at the end of the current animation loop 102 | public func stopAnimating(stopAtEndOfCurrentLoop: Bool = false) { 103 | if flipbook.isAnimating() == false || 104 | self.stopAtEndOfCurrentLoop 105 | { 106 | return 107 | } 108 | 109 | self.stopAtEndOfCurrentLoop = stopAtEndOfCurrentLoop 110 | 111 | if stopAtEndOfCurrentLoop == false { 112 | flipbook.stop(reason: .userStopped) 113 | } 114 | } 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+Attention.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile+Attention.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | 30 | /// Protocol for cancelling a user attention request 31 | public protocol DSFDockTileUserAttentionCancellation { 32 | /// Cancels a previous user attention request. 33 | func cancel() 34 | } 35 | 36 | public extension DSFDockTile { 37 | /// User attention cancellation object 38 | struct UserAttention: DSFDockTileUserAttentionCancellation { 39 | public let identifier: Int 40 | @inlinable internal init(_ identifier: Int) { 41 | self.identifier = identifier 42 | } 43 | 44 | /// Cancels a previous user attention request. 45 | @inlinable public func cancel() { 46 | NSApp.cancelUserAttentionRequest(self.identifier) 47 | } 48 | } 49 | 50 | /// Starts a critical attention request 51 | /// - Returns: A cancel object 52 | /// 53 | /// A request is canceled automatically by user activation of the app. 54 | /// 55 | /// See:- [https://developer.apple.com/documentation/appkit/nsapplication/requestuserattentiontype/criticalrequest](https://developer.apple.com/documentation/appkit/nsapplication/requestuserattentiontype/criticalrequest) 56 | @discardableResult 57 | @inlinable static func requestCriticalAttention() -> DSFDockTileUserAttentionCancellation { 58 | return UserAttention(NSApp.requestUserAttention(.criticalRequest)) 59 | } 60 | 61 | /// Starts an informational attention request 62 | /// - Returns: A cancel object 63 | /// 64 | /// See:- [https://developer.apple.com/documentation/appkit/nsapplication/requestuserattentiontype/informationalrequest](https://developer.apple.com/documentation/appkit/nsapplication/requestuserattentiontype/informationalrequest) 65 | @discardableResult 66 | @inlinable static func requestInformationalAttention() -> DSFDockTileUserAttentionCancellation { 67 | return UserAttention(NSApp.requestUserAttention(.informationalRequest)) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+ConstantImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile+ConstantImage.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | 30 | extension DSFDockTile { 31 | 32 | /// A docktile object which displays a constant image 33 | public class ConstantImage: Core { 34 | 35 | // Image settings 36 | private let image: NSImage 37 | 38 | // A lazy imageview to use when displaying images 39 | private let _imageDisplayView: NSImageView = { 40 | let v = NSImageView() 41 | v.wantsLayer = true 42 | v.imageScaling = .scaleProportionallyUpOrDown 43 | return v 44 | }() 45 | 46 | /// Create an instance which displays an image as a docktile 47 | /// - Parameters: 48 | /// - image: The image to initially display when creating this instance 49 | /// - dockTile: The docktile to update. By default, updates the application docktile. 50 | public init(_ image: NSImage, dockTile: NSDockTile = NSApp.dockTile) { 51 | self.image = image 52 | super.init(dockTile: dockTile) 53 | 54 | // Set the image 55 | self._imageDisplayView.image = image 56 | } 57 | 58 | // Present the stored image 59 | public func display() { 60 | precondition(Thread.isMainThread) 61 | 62 | guard let tile = self.dockTile else { 63 | return 64 | } 65 | 66 | let imageView = self._imageDisplayView 67 | 68 | // If we aren't already being displayed, then make sure to update the content view 69 | if tile.contentView !== imageView { 70 | tile.contentView = imageView 71 | } 72 | 73 | // And update the docktile display 74 | tile.display() 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+Core.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile+Core.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | 30 | extension DSFDockTile { 31 | 32 | /// Base type for a docktile. Can only be inherited from 33 | public class Core { 34 | // The docktile to update. By default, this is the App Icon 35 | public weak var dockTile: NSDockTile? 36 | 37 | /// Set the docktile badge label 38 | public var badgeLabel: String? { 39 | didSet { 40 | self.dockTile?.badgeLabel = self.badgeLabel 41 | } 42 | } 43 | 44 | internal init(dockTile: NSDockTile? = NSApp?.dockTile) { 45 | self.dockTile = dockTile 46 | } 47 | } 48 | } 49 | 50 | extension DSFDockTile { 51 | /// A docktile object that displays the default docktile content. 52 | public class AppIconType: Core { 53 | 54 | public override init(dockTile: NSDockTile? = NSApp?.dockTile) { 55 | super.init(dockTile: dockTile) 56 | } 57 | 58 | public func display() { 59 | if let tile = self.dockTile { 60 | tile.contentView = nil 61 | tile.display() 62 | } 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+Image.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile+Image.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | 30 | extension DSFDockTile { 31 | 32 | /// A docktile with an updatable image 33 | public class Image: Core { 34 | 35 | var image: NSImage? 36 | 37 | // A lazy imageview to use when displaying images 38 | private let _imageDisplayView: NSImageView = { 39 | let v = NSImageView() 40 | v.wantsLayer = true 41 | v.imageScaling = .scaleProportionallyUpOrDown 42 | return v 43 | }() 44 | 45 | /// Create an instance which displays an updatable image as a docktile 46 | /// - Parameters: 47 | /// - image: (optional) The image to initially display when creating this instance 48 | /// - dockTile: The docktile to update. By default, updates the application docktile. 49 | public init(_ image: NSImage? = nil, dockTile: NSDockTile? = NSApp?.dockTile) { 50 | self.image = image 51 | super.init(dockTile: dockTile) 52 | if let image = image { 53 | self.display(image) 54 | } 55 | } 56 | 57 | /// Set image as docktile 58 | /// - Parameter cgImage: The image to display in the docktile 59 | public func display(_ cgImage: CGImage) { 60 | let i = NSImage(cgImage: cgImage, size: .zero) 61 | self.image = i 62 | self.display(i) 63 | } 64 | 65 | public func display() { 66 | if let i = self.image { 67 | self.display(i) 68 | } 69 | } 70 | 71 | /// Set image as docktile 72 | /// - Parameter nsImage: The image to display in the docktile 73 | public func display(_ nsImage: NSImage) { 74 | self.image = nsImage 75 | precondition(Thread.isMainThread) 76 | 77 | guard let tile = self.dockTile else { 78 | return 79 | } 80 | 81 | let imageView = self._imageDisplayView 82 | 83 | // Update the image view with the new image 84 | imageView.image = nsImage 85 | 86 | // If we aren't already being displayed, then make sure to update the content view 87 | if tile.contentView !== imageView { 88 | tile.contentView = imageView 89 | } 90 | 91 | // And update the docktile display 92 | tile.display() 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+SwiftUI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIView.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 22/3/2022. 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | #if canImport(SwiftUI) 29 | 30 | import SwiftUI 31 | 32 | /// The doctile to modify 33 | public enum DockTileLocation { 34 | /// The application's docktile 35 | case application 36 | /// The docktile for the window containing the `DockTile` view 37 | case window 38 | } 39 | 40 | /// A SwiftUI view for setting the content of a dock tile. 41 | /// 42 | /// To set the content of the dock tile, use the `DockView` view and provide the view content/label to the initializer. 43 | /// You can set the docktile content from anywhere in your code, but it would be prudent to centralise access to a single location. 44 | /// 45 | /// ```swift 46 | /// @State var dockText: String = "" 47 | /// var body: some Scene { 48 | /// WindowGroup { 49 | /// ZStack { 50 | /// ContentView() 51 | /// DockTile( 52 | /// .window, 53 | /// label: "3", 54 | /// content: ZStack { 55 | /// Color.white 56 | /// Text(dockText) 57 | /// } 58 | /// ) 59 | /// } 60 | /// } 61 | /// } 62 | /// ``` 63 | @available(macOS 10.15, *) 64 | public struct DockTile: NSViewRepresentable { 65 | private let location: DockTileLocation 66 | private let label: String 67 | private let content: AnyView? 68 | private let animation: DSFDockTile.Animated? 69 | private let isAnimating: Bool 70 | 71 | /// Create a docktile container 72 | /// - Parameters: 73 | /// - location: Which docktile to update (.application for the application docktile, .window for the docktile for the window containing the View) 74 | /// - label: The label to apply to the docktile 75 | public init(_ location: DockTileLocation = .application, label: String) { 76 | self.content = nil 77 | self.location = location 78 | self.label = label 79 | self.animation = nil 80 | self.isAnimating = false 81 | } 82 | 83 | /// Create a docktile container 84 | /// - Parameters: 85 | /// - location: Which docktile to update (.application for the application docktile, .window for the docktile for the window containing the View) 86 | /// - label: The label to apply to the docktile 87 | /// - content: The content View to display in the docktile, or nil to restore the default doctile view 88 | public init(_ which: DockTileLocation = .application, label: String = "", content: ViewContentType?) { 89 | self.content = AnyView(content) 90 | self.location = which 91 | self.label = label 92 | self.animation = nil 93 | self.isAnimating = false 94 | } 95 | 96 | public func makeNSView(context: Context) -> NSView { 97 | let c = NSView() 98 | c.translatesAutoresizingMaskIntoConstraints = false 99 | c.widthAnchor.constraint(equalToConstant: 0).isActive = true 100 | c.heightAnchor.constraint(equalToConstant: 0).isActive = true 101 | return c 102 | } 103 | 104 | public func updateNSView(_ nsView: NSView, context: Context) { 105 | let which = (location == .window) ? nsView.window?.dockTile : NSApp?.dockTile 106 | 107 | if let which = which { 108 | if let animation = animation { 109 | animation.dockTile = which 110 | if self.isAnimating { 111 | if animation.isAnimating == false { 112 | animation.startAnimating() 113 | } 114 | } 115 | else { 116 | animation.stopAnimating(stopAtEndOfCurrentLoop: true) 117 | } 118 | } 119 | else if let content = content { 120 | let dockViewController = NSHostingController(rootView: content) 121 | let dt = DSFDockTile.View(dockViewController, dockTile: which) 122 | dt.display() 123 | } 124 | else { 125 | which.contentView = nil 126 | } 127 | } 128 | 129 | which?.badgeLabel = self.label 130 | } 131 | 132 | public typealias NSViewType = NSView 133 | } 134 | 135 | // MARK: - Animation handling 136 | 137 | @available(macOS 10.15, *) 138 | extension DockTile { 139 | public init( 140 | _ location: DockTileLocation = .application, 141 | label: String = "", 142 | animation: DSFDockTile.Animated, 143 | isAnimating: Bool 144 | ) { 145 | self.animation = animation 146 | self.label = label 147 | self.content = nil 148 | self.location = location 149 | self.isAnimating = isAnimating 150 | } 151 | } 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile+ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile+ViewController.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | 30 | extension DSFDockTile { 31 | 32 | /// Display the content of a view as a dock tile 33 | public class View: Core { 34 | 35 | /// The view controller 36 | internal weak var viewController: NSViewController? 37 | 38 | /// Create an instance which uses a view as the content of a docktile 39 | /// - Parameters: 40 | /// - viewController: The viewController handling the view being displayed in the dock tile. This parameter is weakly held by this object, so it's important to make sure you hold onto this view controller outside the instance 41 | /// - dockTile: The docktile to update. By default, updates the application docktile. 42 | public init(_ viewController: NSViewController, dockTile: NSDockTile = NSApp.dockTile) { 43 | self.viewController = viewController 44 | super.init(dockTile: dockTile) 45 | } 46 | 47 | // Set view as docktile 48 | public func display() { 49 | precondition(Thread.isMainThread) 50 | 51 | guard let tile = self.dockTile, 52 | let vc = self.viewController else { 53 | return 54 | } 55 | 56 | // Make sure the docktile is showing our view 57 | if tile.contentView !== vc.view { 58 | tile.contentView = vc.view 59 | } 60 | 61 | // And update the docktile display 62 | tile.display() 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/DSFDockTile.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSFDockTile.swift 3 | // DSFDockTile 4 | // 5 | // Created by Darren Ford on 17/7/21 6 | // 7 | // MIT License 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | 28 | import AppKit 29 | 30 | public class DSFDockTile { 31 | /// A docktile that represents the current application's icon 32 | public static let AppIcon = DSFDockTile.AppIconType() 33 | 34 | /// Set the badge label to be displayed on the application's docktile 35 | public static var badgeLabel: String? { 36 | get { 37 | NSApp.dockTile.badgeLabel 38 | } 39 | set { 40 | NSApp.dockTile.badgeLabel = newValue 41 | } 42 | } 43 | 44 | /// Set the badge label to be displayed on a provided docktile 45 | @inlinable public static func setBadgeLabel(_ label: String?, dockTile: NSDockTile? = NSApp.dockTile) { 46 | dockTile?.badgeLabel = label 47 | } 48 | 49 | func reset() { 50 | NSApp.dockTile.contentView = nil 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/DSFDockTile/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | NSPrivacyCollectedDataTypes 8 | 9 | NSPrivacyTracking 10 | 11 | NSPrivacyTrackingDomains 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Tests/DSFDockTileTests/DSFDockTileTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import DSFDockTile 3 | 4 | final class DSFDockTileTests: XCTestCase { 5 | // func testExample() throws { 6 | // // This is an example of a functional test case. 7 | // // Use XCTAssert and related functions to verify your tests produce the correct 8 | // // results. 9 | // XCTAssertEqual(DSFDockTile().text, "Hello, World!") 10 | // } 11 | } 12 | --------------------------------------------------------------------------------