├── .gitignore ├── Demo ├── JNWAnimatableWindowDemo.xcodeproj │ └── project.pbxproj └── JNWAnimatableWindowDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ └── MainMenu.xib │ ├── JNWAnimatableWindowDemo-Info.plist │ ├── JNWAnimatableWindowDemo-Prefix.pch │ ├── en.lproj │ ├── Credits.rtf │ └── InfoPlist.strings │ └── main.m ├── JNWAnimatableWindow.podspec ├── LICENSE.md ├── Package.swift ├── README.md └── Sources └── JNWAnimatableWindow ├── JNWAnimatableWindow.m └── include └── JNWAnimatableWindow.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 84B3ED6A25E9094600F252CB /* JNWAnimatableWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B3ED6925E9094600F252CB /* JNWAnimatableWindow.m */; }; 11 | AB8C9E0C16B309E700CA98C3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C9E0B16B309E700CA98C3 /* Cocoa.framework */; }; 12 | AB8C9E1616B309E700CA98C3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB8C9E1416B309E700CA98C3 /* InfoPlist.strings */; }; 13 | AB8C9E1816B309E700CA98C3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AB8C9E1716B309E700CA98C3 /* main.m */; }; 14 | AB8C9E1C16B309E700CA98C3 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = AB8C9E1A16B309E700CA98C3 /* Credits.rtf */; }; 15 | AB8C9E1F16B309E700CA98C3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AB8C9E1E16B309E700CA98C3 /* AppDelegate.m */; }; 16 | AB8C9E2216B309E700CA98C3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB8C9E2016B309E700CA98C3 /* MainMenu.xib */; }; 17 | AB8C9E2C16B30A8A00CA98C3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C9E2B16B30A8A00CA98C3 /* QuartzCore.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 846F8D2325E9183800C8F9A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 22 | 84B3ED6925E9094600F252CB /* JNWAnimatableWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JNWAnimatableWindow.m; path = ../../Sources/JNWAnimatableWindow/JNWAnimatableWindow.m; sourceTree = ""; }; 23 | 84B3ED7D25E90DAD00F252CB /* JNWAnimatableWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JNWAnimatableWindow.h; path = ../../Sources/JNWAnimatableWindow/include/JNWAnimatableWindow.h; sourceTree = ""; }; 24 | AB8C9E0816B309E700CA98C3 /* JNWAnimatableWindowDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JNWAnimatableWindowDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | AB8C9E0B16B309E700CA98C3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 26 | AB8C9E0E16B309E700CA98C3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 27 | AB8C9E0F16B309E700CA98C3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 28 | AB8C9E1016B309E700CA98C3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | AB8C9E1316B309E700CA98C3 /* JNWAnimatableWindowDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "JNWAnimatableWindowDemo-Info.plist"; sourceTree = ""; }; 30 | AB8C9E1516B309E700CA98C3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 31 | AB8C9E1716B309E700CA98C3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | AB8C9E1916B309E700CA98C3 /* JNWAnimatableWindowDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JNWAnimatableWindowDemo-Prefix.pch"; sourceTree = ""; }; 33 | AB8C9E1B16B309E700CA98C3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 34 | AB8C9E1D16B309E700CA98C3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | AB8C9E1E16B309E700CA98C3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | AB8C9E2B16B30A8A00CA98C3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | AB8C9E0516B309E700CA98C3 /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | AB8C9E2C16B30A8A00CA98C3 /* QuartzCore.framework in Frameworks */, 45 | AB8C9E0C16B309E700CA98C3 /* Cocoa.framework in Frameworks */, 46 | ); 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | /* End PBXFrameworksBuildPhase section */ 50 | 51 | /* Begin PBXGroup section */ 52 | AB8C9DFF16B309E700CA98C3 = { 53 | isa = PBXGroup; 54 | children = ( 55 | AB8C9E1116B309E700CA98C3 /* JNWAnimatableWindowDemo */, 56 | AB8C9E0A16B309E700CA98C3 /* Frameworks */, 57 | AB8C9E0916B309E700CA98C3 /* Products */, 58 | ); 59 | sourceTree = ""; 60 | }; 61 | AB8C9E0916B309E700CA98C3 /* Products */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | AB8C9E0816B309E700CA98C3 /* JNWAnimatableWindowDemo.app */, 65 | ); 66 | name = Products; 67 | sourceTree = ""; 68 | }; 69 | AB8C9E0A16B309E700CA98C3 /* Frameworks */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | AB8C9E2B16B30A8A00CA98C3 /* QuartzCore.framework */, 73 | AB8C9E0B16B309E700CA98C3 /* Cocoa.framework */, 74 | AB8C9E0D16B309E700CA98C3 /* Other Frameworks */, 75 | ); 76 | name = Frameworks; 77 | sourceTree = ""; 78 | }; 79 | AB8C9E0D16B309E700CA98C3 /* Other Frameworks */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | AB8C9E0E16B309E700CA98C3 /* AppKit.framework */, 83 | AB8C9E0F16B309E700CA98C3 /* CoreData.framework */, 84 | AB8C9E1016B309E700CA98C3 /* Foundation.framework */, 85 | ); 86 | name = "Other Frameworks"; 87 | sourceTree = ""; 88 | }; 89 | AB8C9E1116B309E700CA98C3 /* JNWAnimatableWindowDemo */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 84B3ED7D25E90DAD00F252CB /* JNWAnimatableWindow.h */, 93 | 84B3ED6925E9094600F252CB /* JNWAnimatableWindow.m */, 94 | AB8C9E1D16B309E700CA98C3 /* AppDelegate.h */, 95 | AB8C9E1E16B309E700CA98C3 /* AppDelegate.m */, 96 | AB8C9E2016B309E700CA98C3 /* MainMenu.xib */, 97 | AB8C9E1216B309E700CA98C3 /* Supporting Files */, 98 | ); 99 | path = JNWAnimatableWindowDemo; 100 | sourceTree = ""; 101 | }; 102 | AB8C9E1216B309E700CA98C3 /* Supporting Files */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | AB8C9E1316B309E700CA98C3 /* JNWAnimatableWindowDemo-Info.plist */, 106 | AB8C9E1416B309E700CA98C3 /* InfoPlist.strings */, 107 | AB8C9E1716B309E700CA98C3 /* main.m */, 108 | AB8C9E1916B309E700CA98C3 /* JNWAnimatableWindowDemo-Prefix.pch */, 109 | AB8C9E1A16B309E700CA98C3 /* Credits.rtf */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | /* End PBXGroup section */ 115 | 116 | /* Begin PBXNativeTarget section */ 117 | AB8C9E0716B309E700CA98C3 /* JNWAnimatableWindowDemo */ = { 118 | isa = PBXNativeTarget; 119 | buildConfigurationList = AB8C9E2516B309E700CA98C3 /* Build configuration list for PBXNativeTarget "JNWAnimatableWindowDemo" */; 120 | buildPhases = ( 121 | AB8C9E0416B309E700CA98C3 /* Sources */, 122 | AB8C9E0516B309E700CA98C3 /* Frameworks */, 123 | AB8C9E0616B309E700CA98C3 /* Resources */, 124 | ); 125 | buildRules = ( 126 | ); 127 | dependencies = ( 128 | ); 129 | name = JNWAnimatableWindowDemo; 130 | productName = JNWAnimatableWindowDemo; 131 | productReference = AB8C9E0816B309E700CA98C3 /* JNWAnimatableWindowDemo.app */; 132 | productType = "com.apple.product-type.application"; 133 | }; 134 | /* End PBXNativeTarget section */ 135 | 136 | /* Begin PBXProject section */ 137 | AB8C9E0016B309E700CA98C3 /* Project object */ = { 138 | isa = PBXProject; 139 | attributes = { 140 | LastUpgradeCheck = 1240; 141 | ORGANIZATIONNAME = AppJon; 142 | }; 143 | buildConfigurationList = AB8C9E0316B309E700CA98C3 /* Build configuration list for PBXProject "JNWAnimatableWindowDemo" */; 144 | compatibilityVersion = "Xcode 3.2"; 145 | developmentRegion = en; 146 | hasScannedForEncodings = 0; 147 | knownRegions = ( 148 | en, 149 | Base, 150 | ); 151 | mainGroup = AB8C9DFF16B309E700CA98C3; 152 | productRefGroup = AB8C9E0916B309E700CA98C3 /* Products */; 153 | projectDirPath = ""; 154 | projectRoot = ""; 155 | targets = ( 156 | AB8C9E0716B309E700CA98C3 /* JNWAnimatableWindowDemo */, 157 | ); 158 | }; 159 | /* End PBXProject section */ 160 | 161 | /* Begin PBXResourcesBuildPhase section */ 162 | AB8C9E0616B309E700CA98C3 /* Resources */ = { 163 | isa = PBXResourcesBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | AB8C9E1616B309E700CA98C3 /* InfoPlist.strings in Resources */, 167 | AB8C9E1C16B309E700CA98C3 /* Credits.rtf in Resources */, 168 | AB8C9E2216B309E700CA98C3 /* MainMenu.xib in Resources */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXResourcesBuildPhase section */ 173 | 174 | /* Begin PBXSourcesBuildPhase section */ 175 | AB8C9E0416B309E700CA98C3 /* Sources */ = { 176 | isa = PBXSourcesBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | AB8C9E1816B309E700CA98C3 /* main.m in Sources */, 180 | 84B3ED6A25E9094600F252CB /* JNWAnimatableWindow.m in Sources */, 181 | AB8C9E1F16B309E700CA98C3 /* AppDelegate.m in Sources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXSourcesBuildPhase section */ 186 | 187 | /* Begin PBXVariantGroup section */ 188 | AB8C9E1416B309E700CA98C3 /* InfoPlist.strings */ = { 189 | isa = PBXVariantGroup; 190 | children = ( 191 | AB8C9E1516B309E700CA98C3 /* en */, 192 | ); 193 | name = InfoPlist.strings; 194 | sourceTree = ""; 195 | }; 196 | AB8C9E1A16B309E700CA98C3 /* Credits.rtf */ = { 197 | isa = PBXVariantGroup; 198 | children = ( 199 | AB8C9E1B16B309E700CA98C3 /* en */, 200 | ); 201 | name = Credits.rtf; 202 | sourceTree = ""; 203 | }; 204 | AB8C9E2016B309E700CA98C3 /* MainMenu.xib */ = { 205 | isa = PBXVariantGroup; 206 | children = ( 207 | 846F8D2325E9183800C8F9A3 /* Base */, 208 | ); 209 | name = MainMenu.xib; 210 | sourceTree = ""; 211 | }; 212 | /* End PBXVariantGroup section */ 213 | 214 | /* Begin XCBuildConfiguration section */ 215 | AB8C9E2316B309E700CA98C3 /* Debug */ = { 216 | isa = XCBuildConfiguration; 217 | buildSettings = { 218 | ALWAYS_SEARCH_USER_PATHS = NO; 219 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 220 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 221 | CLANG_CXX_LIBRARY = "libc++"; 222 | CLANG_ENABLE_MODULES = YES; 223 | CLANG_ENABLE_OBJC_ARC = YES; 224 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 225 | CLANG_WARN_BOOL_CONVERSION = YES; 226 | CLANG_WARN_COMMA = YES; 227 | CLANG_WARN_CONSTANT_CONVERSION = YES; 228 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 229 | CLANG_WARN_EMPTY_BODY = YES; 230 | CLANG_WARN_ENUM_CONVERSION = YES; 231 | CLANG_WARN_INFINITE_RECURSION = YES; 232 | CLANG_WARN_INT_CONVERSION = YES; 233 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 234 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 235 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 236 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 237 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 238 | CLANG_WARN_STRICT_PROTOTYPES = YES; 239 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 240 | CLANG_WARN_UNREACHABLE_CODE = YES; 241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 242 | COPY_PHASE_STRIP = NO; 243 | ENABLE_STRICT_OBJC_MSGSEND = YES; 244 | ENABLE_TESTABILITY = YES; 245 | GCC_C_LANGUAGE_STANDARD = gnu99; 246 | GCC_DYNAMIC_NO_PIC = NO; 247 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 248 | GCC_NO_COMMON_BLOCKS = YES; 249 | GCC_OPTIMIZATION_LEVEL = 0; 250 | GCC_PREPROCESSOR_DEFINITIONS = ( 251 | "DEBUG=1", 252 | "$(inherited)", 253 | ); 254 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 255 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 256 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 257 | GCC_WARN_UNDECLARED_SELECTOR = YES; 258 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 259 | GCC_WARN_UNUSED_FUNCTION = YES; 260 | GCC_WARN_UNUSED_VARIABLE = YES; 261 | MACOSX_DEPLOYMENT_TARGET = 10.9; 262 | ONLY_ACTIVE_ARCH = YES; 263 | SDKROOT = macosx; 264 | }; 265 | name = Debug; 266 | }; 267 | AB8C9E2416B309E700CA98C3 /* Release */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 277 | CLANG_WARN_BOOL_CONVERSION = YES; 278 | CLANG_WARN_COMMA = YES; 279 | CLANG_WARN_CONSTANT_CONVERSION = YES; 280 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 281 | CLANG_WARN_EMPTY_BODY = YES; 282 | CLANG_WARN_ENUM_CONVERSION = YES; 283 | CLANG_WARN_INFINITE_RECURSION = YES; 284 | CLANG_WARN_INT_CONVERSION = YES; 285 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 286 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 287 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 288 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 289 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 290 | CLANG_WARN_STRICT_PROTOTYPES = YES; 291 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 292 | CLANG_WARN_UNREACHABLE_CODE = YES; 293 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 294 | COPY_PHASE_STRIP = YES; 295 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 296 | ENABLE_STRICT_OBJC_MSGSEND = YES; 297 | GCC_C_LANGUAGE_STANDARD = gnu99; 298 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 299 | GCC_NO_COMMON_BLOCKS = YES; 300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 301 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 302 | GCC_WARN_UNDECLARED_SELECTOR = YES; 303 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 304 | GCC_WARN_UNUSED_FUNCTION = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | MACOSX_DEPLOYMENT_TARGET = 10.9; 307 | SDKROOT = macosx; 308 | }; 309 | name = Release; 310 | }; 311 | AB8C9E2616B309E700CA98C3 /* Debug */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | COMBINE_HIDPI_IMAGES = YES; 315 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 316 | GCC_PREFIX_HEADER = "JNWAnimatableWindowDemo/JNWAnimatableWindowDemo-Prefix.pch"; 317 | INFOPLIST_FILE = "JNWAnimatableWindowDemo/JNWAnimatableWindowDemo-Info.plist"; 318 | PRODUCT_BUNDLE_IDENTIFIER = "com.AppJon.${PRODUCT_NAME:rfc1034identifier}"; 319 | PRODUCT_NAME = "$(TARGET_NAME)"; 320 | WRAPPER_EXTENSION = app; 321 | }; 322 | name = Debug; 323 | }; 324 | AB8C9E2716B309E700CA98C3 /* Release */ = { 325 | isa = XCBuildConfiguration; 326 | buildSettings = { 327 | COMBINE_HIDPI_IMAGES = YES; 328 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 329 | GCC_PREFIX_HEADER = "JNWAnimatableWindowDemo/JNWAnimatableWindowDemo-Prefix.pch"; 330 | INFOPLIST_FILE = "JNWAnimatableWindowDemo/JNWAnimatableWindowDemo-Info.plist"; 331 | PRODUCT_BUNDLE_IDENTIFIER = "com.AppJon.${PRODUCT_NAME:rfc1034identifier}"; 332 | PRODUCT_NAME = "$(TARGET_NAME)"; 333 | WRAPPER_EXTENSION = app; 334 | }; 335 | name = Release; 336 | }; 337 | /* End XCBuildConfiguration section */ 338 | 339 | /* Begin XCConfigurationList section */ 340 | AB8C9E0316B309E700CA98C3 /* Build configuration list for PBXProject "JNWAnimatableWindowDemo" */ = { 341 | isa = XCConfigurationList; 342 | buildConfigurations = ( 343 | AB8C9E2316B309E700CA98C3 /* Debug */, 344 | AB8C9E2416B309E700CA98C3 /* Release */, 345 | ); 346 | defaultConfigurationIsVisible = 0; 347 | defaultConfigurationName = Release; 348 | }; 349 | AB8C9E2516B309E700CA98C3 /* Build configuration list for PBXNativeTarget "JNWAnimatableWindowDemo" */ = { 350 | isa = XCConfigurationList; 351 | buildConfigurations = ( 352 | AB8C9E2616B309E700CA98C3 /* Debug */, 353 | AB8C9E2716B309E700CA98C3 /* Release */, 354 | ); 355 | defaultConfigurationIsVisible = 0; 356 | defaultConfigurationName = Release; 357 | }; 358 | /* End XCConfigurationList section */ 359 | }; 360 | rootObject = AB8C9E0016B309E700CA98C3 /* Project object */; 361 | } 362 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JNWAnimatableWindowDemo 4 | // 5 | // Created by Jonathan Willing on 1/25/13. 6 | // Copyright (c) 2013 AppJon. All rights reserved. 7 | // 8 | 9 | @import Cocoa; 10 | @import QuartzCore; 11 | #import "JNWAnimatableWindow.h" 12 | 13 | @interface AppDelegate : NSObject 14 | 15 | @property (assign) IBOutlet JNWAnimatableWindow *window; 16 | 17 | - (IBAction)moveAround:(id)sender; 18 | - (IBAction)animateOut:(id)sender; 19 | - (IBAction)animateFrame:(id)sender; 20 | 21 | - (IBAction)animateOutExplicitly:(id)sender; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JNWAnimatableWindowDemo 4 | // 5 | // Created by Jonathan Willing on 1/25/13. 6 | // Copyright (c) 2013 AppJon. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | @import QuartzCore; 11 | 12 | @implementation AppDelegate 13 | 14 | #pragma mark Convenience Methods 15 | 16 | - (CFTimeInterval)animationDuration { 17 | // Return a slower time if the shift key is held down, for testing. 18 | return ((([NSApp currentEvent].modifierFlags & NSShiftKeyMask) == NSShiftKeyMask) ? 5.f : 0.7f); 19 | } 20 | 21 | - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag { 22 | // If we're already visible, no need to animate. 23 | if (self.window.isVisible) 24 | return NO; 25 | 26 | // If we are full screen, just order the window front instead of trying to animate. 27 | if ((self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask) { 28 | [self.window makeKeyAndOrderFront:nil]; 29 | return NO; 30 | } 31 | 32 | 33 | [self.window makeKeyAndOrderFrontWithDuration:self.animationDuration timing:nil setup:^(CALayer *layer) { 34 | // Anything done in this setup block is performed without any animation. 35 | // The layer will not be visible during this time so now is our chance to set initial 36 | // values for opacity, transform, etc. 37 | layer.transform = CATransform3DMakeTranslation(0.f, -50., 0.f); 38 | layer.opacity = 0.f; 39 | } animations:^(CALayer *layer) { 40 | 41 | // Now we're actually animating. In order to make the transition as seamless as possible, 42 | // we want to set the final values to their original states, so that when the fake window 43 | // is removed there will be no discernible jump to that state. 44 | // 45 | // To change the default timing and duration, just wrap the animations in an NSAnimationContext. 46 | layer.transform = CATransform3DIdentity; 47 | layer.opacity = 1.f; 48 | }]; 49 | 50 | return NO; 51 | } 52 | 53 | - (void)animateOut:(id)sender { 54 | [self.window orderOutWithDuration:self.animationDuration timing:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] animations:^(CALayer *layer) { 55 | // We can now basically whatever we want with this layer. Everything is already wrapped in a CATransaction so it is animated implicitly. 56 | // To change the duration and other properties, just modify the current context. It will apply to the animation. 57 | layer.transform = CATransform3DMakeTranslation(0.f, -50.f, 0.f); 58 | layer.opacity = 0.f; 59 | }]; 60 | } 61 | 62 | - (void)animateOutExplicitly:(id)sender { 63 | CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"]; 64 | opacity.toValue = @0; 65 | 66 | CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"]; 67 | translation.toValue = @(-50.f); 68 | 69 | CAAnimationGroup *group = [CAAnimationGroup animation]; 70 | group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 71 | group.animations = @[ opacity, translation ]; 72 | group.duration = self.animationDuration; 73 | 74 | [self.window orderOutWithAnimation:group]; 75 | } 76 | 77 | - (void)animateFrame:(id)sender { 78 | CGRect rect = CGRectInset(self.window.frame, -100, -50); 79 | [self.window setFrame:rect withDuration:self.animationDuration timing:nil]; 80 | } 81 | 82 | 83 | #pragma mark Manual Animations 84 | 85 | // Here is a somewhat more complex example of animating the window's layer property directly. 86 | // Since this isn't wrapped in one of the convenience methods, we are responsible 87 | // for getting rid of the window when we are done. 88 | - (void)moveAround:(id)sender { 89 | // Apply a perspective transform onto the layer. 90 | CATransform3D transform = CATransform3DIdentity; 91 | transform.m34 = -1.f / 700.f; 92 | self.window.layer.transform = transform; 93 | 94 | // Do a barrel roll. 95 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"]; 96 | animation.duration = 3.f; 97 | animation.toValue = @(2*M_PI); 98 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 99 | 100 | // Set the delegate on the animation so we know when to remove the fake window. 101 | animation.delegate = self; 102 | [self.window.layer addAnimation:animation forKey:nil]; 103 | } 104 | 105 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 106 | // Animation is done, so lets get back to our real window by destroying the fake one. 107 | // Note this only needs to happen if we initiate the creation of the layer ourselves by referencing it, 108 | // otherwise it is automatically destroyed for us, as mentioned above. 109 | [self.window destroyTransformingWindow]; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1080 5 | 12C3006 6 | 3084 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.CocoaPlugin 11 | 3084 12 | 13 | 14 | NSButton 15 | NSButtonCell 16 | NSCustomObject 17 | NSMenu 18 | NSMenuItem 19 | NSTextField 20 | NSTextFieldCell 21 | NSView 22 | NSWindowTemplate 23 | 24 | 25 | com.apple.InterfaceBuilder.CocoaPlugin 26 | 27 | 28 | PluginDependencyRecalculationVersion 29 | 30 | 31 | 32 | 33 | NSApplication 34 | 35 | 36 | FirstResponder 37 | 38 | 39 | NSApplication 40 | 41 | 42 | AMainMenu 43 | 44 | 45 | 46 | JNWAnimatableWindowDemo 47 | 48 | 1048576 49 | 2147483647 50 | 51 | NSImage 52 | NSMenuCheckmark 53 | 54 | 55 | NSImage 56 | NSMenuMixedState 57 | 58 | submenuAction: 59 | 60 | JNWAnimatableWindowDemo 61 | 62 | 63 | 64 | About JNWAnimatableWindowDemo 65 | 66 | 2147483647 67 | 68 | 69 | 70 | 71 | 72 | YES 73 | YES 74 | 75 | 76 | 1048576 77 | 2147483647 78 | 79 | 80 | 81 | 82 | 83 | Preferences… 84 | , 85 | 1048576 86 | 2147483647 87 | 88 | 89 | 90 | 91 | 92 | YES 93 | YES 94 | 95 | 96 | 1048576 97 | 2147483647 98 | 99 | 100 | 101 | 102 | 103 | Services 104 | 105 | 1048576 106 | 2147483647 107 | 108 | 109 | submenuAction: 110 | 111 | Services 112 | 113 | _NSServicesMenu 114 | 115 | 116 | 117 | 118 | YES 119 | YES 120 | 121 | 122 | 1048576 123 | 2147483647 124 | 125 | 126 | 127 | 128 | 129 | Hide JNWAnimatableWindowDemo 130 | h 131 | 1048576 132 | 2147483647 133 | 134 | 135 | 136 | 137 | 138 | Hide Others 139 | h 140 | 1572864 141 | 2147483647 142 | 143 | 144 | 145 | 146 | 147 | Show All 148 | 149 | 1048576 150 | 2147483647 151 | 152 | 153 | 154 | 155 | 156 | YES 157 | YES 158 | 159 | 160 | 1048576 161 | 2147483647 162 | 163 | 164 | 165 | 166 | 167 | Quit JNWAnimatableWindowDemo 168 | q 169 | 1048576 170 | 2147483647 171 | 172 | 173 | 174 | 175 | _NSAppleMenu 176 | 177 | 178 | 179 | 180 | File 181 | 182 | 1048576 183 | 2147483647 184 | 185 | 186 | submenuAction: 187 | 188 | File 189 | 190 | 191 | 192 | New 193 | n 194 | 1048576 195 | 2147483647 196 | 197 | 198 | 199 | 200 | 201 | Open… 202 | o 203 | 1048576 204 | 2147483647 205 | 206 | 207 | 208 | 209 | 210 | Open Recent 211 | 212 | 1048576 213 | 2147483647 214 | 215 | 216 | submenuAction: 217 | 218 | Open Recent 219 | 220 | 221 | 222 | Clear Menu 223 | 224 | 1048576 225 | 2147483647 226 | 227 | 228 | 229 | 230 | _NSRecentDocumentsMenu 231 | 232 | 233 | 234 | 235 | YES 236 | YES 237 | 238 | 239 | 1048576 240 | 2147483647 241 | 242 | 243 | 244 | 245 | 246 | Close 247 | w 248 | 1048576 249 | 2147483647 250 | 251 | 252 | 253 | 254 | 255 | Save… 256 | s 257 | 1048576 258 | 2147483647 259 | 260 | 261 | 262 | 263 | 264 | Revert to Saved 265 | 266 | 2147483647 267 | 268 | 269 | 270 | 271 | 272 | YES 273 | YES 274 | 275 | 276 | 1048576 277 | 2147483647 278 | 279 | 280 | 281 | 282 | 283 | Page Setup... 284 | P 285 | 1179648 286 | 2147483647 287 | 288 | 289 | 290 | 291 | 292 | 293 | Print… 294 | p 295 | 1048576 296 | 2147483647 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | Edit 306 | 307 | 1048576 308 | 2147483647 309 | 310 | 311 | submenuAction: 312 | 313 | Edit 314 | 315 | 316 | 317 | Undo 318 | z 319 | 1048576 320 | 2147483647 321 | 322 | 323 | 324 | 325 | 326 | Redo 327 | Z 328 | 1179648 329 | 2147483647 330 | 331 | 332 | 333 | 334 | 335 | YES 336 | YES 337 | 338 | 339 | 1048576 340 | 2147483647 341 | 342 | 343 | 344 | 345 | 346 | Cut 347 | x 348 | 1048576 349 | 2147483647 350 | 351 | 352 | 353 | 354 | 355 | Copy 356 | c 357 | 1048576 358 | 2147483647 359 | 360 | 361 | 362 | 363 | 364 | Paste 365 | v 366 | 1048576 367 | 2147483647 368 | 369 | 370 | 371 | 372 | 373 | Paste and Match Style 374 | V 375 | 1572864 376 | 2147483647 377 | 378 | 379 | 380 | 381 | 382 | Delete 383 | 384 | 1048576 385 | 2147483647 386 | 387 | 388 | 389 | 390 | 391 | Select All 392 | a 393 | 1048576 394 | 2147483647 395 | 396 | 397 | 398 | 399 | 400 | YES 401 | YES 402 | 403 | 404 | 1048576 405 | 2147483647 406 | 407 | 408 | 409 | 410 | 411 | Find 412 | 413 | 1048576 414 | 2147483647 415 | 416 | 417 | submenuAction: 418 | 419 | Find 420 | 421 | 422 | 423 | Find… 424 | f 425 | 1048576 426 | 2147483647 427 | 428 | 429 | 1 430 | 431 | 432 | 433 | Find and Replace… 434 | f 435 | 1572864 436 | 2147483647 437 | 438 | 439 | 12 440 | 441 | 442 | 443 | Find Next 444 | g 445 | 1048576 446 | 2147483647 447 | 448 | 449 | 2 450 | 451 | 452 | 453 | Find Previous 454 | G 455 | 1179648 456 | 2147483647 457 | 458 | 459 | 3 460 | 461 | 462 | 463 | Use Selection for Find 464 | e 465 | 1048576 466 | 2147483647 467 | 468 | 469 | 7 470 | 471 | 472 | 473 | Jump to Selection 474 | j 475 | 1048576 476 | 2147483647 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | Spelling and Grammar 486 | 487 | 1048576 488 | 2147483647 489 | 490 | 491 | submenuAction: 492 | 493 | Spelling and Grammar 494 | 495 | 496 | 497 | Show Spelling and Grammar 498 | : 499 | 1048576 500 | 2147483647 501 | 502 | 503 | 504 | 505 | 506 | Check Document Now 507 | ; 508 | 1048576 509 | 2147483647 510 | 511 | 512 | 513 | 514 | 515 | YES 516 | YES 517 | 518 | 519 | 2147483647 520 | 521 | 522 | 523 | 524 | 525 | Check Spelling While Typing 526 | 527 | 1048576 528 | 2147483647 529 | 530 | 531 | 532 | 533 | 534 | Check Grammar With Spelling 535 | 536 | 1048576 537 | 2147483647 538 | 539 | 540 | 541 | 542 | 543 | Correct Spelling Automatically 544 | 545 | 2147483647 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | Substitutions 555 | 556 | 1048576 557 | 2147483647 558 | 559 | 560 | submenuAction: 561 | 562 | Substitutions 563 | 564 | 565 | 566 | Show Substitutions 567 | 568 | 2147483647 569 | 570 | 571 | 572 | 573 | 574 | YES 575 | YES 576 | 577 | 578 | 2147483647 579 | 580 | 581 | 582 | 583 | 584 | Smart Copy/Paste 585 | f 586 | 1048576 587 | 2147483647 588 | 589 | 590 | 1 591 | 592 | 593 | 594 | Smart Quotes 595 | g 596 | 1048576 597 | 2147483647 598 | 599 | 600 | 2 601 | 602 | 603 | 604 | Smart Dashes 605 | 606 | 2147483647 607 | 608 | 609 | 610 | 611 | 612 | Smart Links 613 | G 614 | 1179648 615 | 2147483647 616 | 617 | 618 | 3 619 | 620 | 621 | 622 | Text Replacement 623 | 624 | 2147483647 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | Transformations 634 | 635 | 2147483647 636 | 637 | 638 | submenuAction: 639 | 640 | Transformations 641 | 642 | 643 | 644 | Make Upper Case 645 | 646 | 2147483647 647 | 648 | 649 | 650 | 651 | 652 | Make Lower Case 653 | 654 | 2147483647 655 | 656 | 657 | 658 | 659 | 660 | Capitalize 661 | 662 | 2147483647 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | Speech 672 | 673 | 1048576 674 | 2147483647 675 | 676 | 677 | submenuAction: 678 | 679 | Speech 680 | 681 | 682 | 683 | Start Speaking 684 | 685 | 1048576 686 | 2147483647 687 | 688 | 689 | 690 | 691 | 692 | Stop Speaking 693 | 694 | 1048576 695 | 2147483647 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | Format 708 | 709 | 2147483647 710 | 711 | 712 | submenuAction: 713 | 714 | Format 715 | 716 | 717 | 718 | Font 719 | 720 | 2147483647 721 | 722 | 723 | submenuAction: 724 | 725 | Font 726 | 727 | 728 | 729 | Show Fonts 730 | t 731 | 1048576 732 | 2147483647 733 | 734 | 735 | 736 | 737 | 738 | Bold 739 | b 740 | 1048576 741 | 2147483647 742 | 743 | 744 | 2 745 | 746 | 747 | 748 | Italic 749 | i 750 | 1048576 751 | 2147483647 752 | 753 | 754 | 1 755 | 756 | 757 | 758 | Underline 759 | u 760 | 1048576 761 | 2147483647 762 | 763 | 764 | 765 | 766 | 767 | YES 768 | YES 769 | 770 | 771 | 2147483647 772 | 773 | 774 | 775 | 776 | 777 | Bigger 778 | + 779 | 1048576 780 | 2147483647 781 | 782 | 783 | 3 784 | 785 | 786 | 787 | Smaller 788 | - 789 | 1048576 790 | 2147483647 791 | 792 | 793 | 4 794 | 795 | 796 | 797 | YES 798 | YES 799 | 800 | 801 | 2147483647 802 | 803 | 804 | 805 | 806 | 807 | Kern 808 | 809 | 2147483647 810 | 811 | 812 | submenuAction: 813 | 814 | Kern 815 | 816 | 817 | 818 | Use Default 819 | 820 | 2147483647 821 | 822 | 823 | 824 | 825 | 826 | Use None 827 | 828 | 2147483647 829 | 830 | 831 | 832 | 833 | 834 | Tighten 835 | 836 | 2147483647 837 | 838 | 839 | 840 | 841 | 842 | Loosen 843 | 844 | 2147483647 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | Ligatures 854 | 855 | 2147483647 856 | 857 | 858 | submenuAction: 859 | 860 | Ligatures 861 | 862 | 863 | 864 | Use Default 865 | 866 | 2147483647 867 | 868 | 869 | 870 | 871 | 872 | Use None 873 | 874 | 2147483647 875 | 876 | 877 | 878 | 879 | 880 | Use All 881 | 882 | 2147483647 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | Baseline 892 | 893 | 2147483647 894 | 895 | 896 | submenuAction: 897 | 898 | Baseline 899 | 900 | 901 | 902 | Use Default 903 | 904 | 2147483647 905 | 906 | 907 | 908 | 909 | 910 | Superscript 911 | 912 | 2147483647 913 | 914 | 915 | 916 | 917 | 918 | Subscript 919 | 920 | 2147483647 921 | 922 | 923 | 924 | 925 | 926 | Raise 927 | 928 | 2147483647 929 | 930 | 931 | 932 | 933 | 934 | Lower 935 | 936 | 2147483647 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | YES 946 | YES 947 | 948 | 949 | 2147483647 950 | 951 | 952 | 953 | 954 | 955 | Show Colors 956 | C 957 | 1048576 958 | 2147483647 959 | 960 | 961 | 962 | 963 | 964 | YES 965 | YES 966 | 967 | 968 | 2147483647 969 | 970 | 971 | 972 | 973 | 974 | Copy Style 975 | c 976 | 1572864 977 | 2147483647 978 | 979 | 980 | 981 | 982 | 983 | Paste Style 984 | v 985 | 1572864 986 | 2147483647 987 | 988 | 989 | 990 | 991 | _NSFontMenu 992 | 993 | 994 | 995 | 996 | Text 997 | 998 | 2147483647 999 | 1000 | 1001 | submenuAction: 1002 | 1003 | Text 1004 | 1005 | 1006 | 1007 | Align Left 1008 | { 1009 | 1048576 1010 | 2147483647 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | Center 1017 | | 1018 | 1048576 1019 | 2147483647 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | Justify 1026 | 1027 | 2147483647 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | Align Right 1034 | } 1035 | 1048576 1036 | 2147483647 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | YES 1043 | YES 1044 | 1045 | 1046 | 2147483647 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | Writing Direction 1053 | 1054 | 2147483647 1055 | 1056 | 1057 | submenuAction: 1058 | 1059 | Writing Direction 1060 | 1061 | 1062 | 1063 | YES 1064 | Paragraph 1065 | 1066 | 2147483647 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | CURlZmF1bHQ 1073 | 1074 | 2147483647 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | CUxlZnQgdG8gUmlnaHQ 1081 | 1082 | 2147483647 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | CVJpZ2h0IHRvIExlZnQ 1089 | 1090 | 2147483647 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | YES 1097 | YES 1098 | 1099 | 1100 | 2147483647 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | YES 1107 | Selection 1108 | 1109 | 2147483647 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | CURlZmF1bHQ 1116 | 1117 | 2147483647 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | CUxlZnQgdG8gUmlnaHQ 1124 | 1125 | 2147483647 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | CVJpZ2h0IHRvIExlZnQ 1132 | 1133 | 2147483647 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | YES 1143 | YES 1144 | 1145 | 1146 | 2147483647 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | Show Ruler 1153 | 1154 | 2147483647 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | Copy Ruler 1161 | c 1162 | 1310720 1163 | 2147483647 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | Paste Ruler 1170 | v 1171 | 1310720 1172 | 2147483647 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | View 1185 | 1186 | 1048576 1187 | 2147483647 1188 | 1189 | 1190 | submenuAction: 1191 | 1192 | View 1193 | 1194 | 1195 | 1196 | Show Toolbar 1197 | t 1198 | 1572864 1199 | 2147483647 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | Customize Toolbar… 1206 | 1207 | 1048576 1208 | 2147483647 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | Window 1218 | 1219 | 1048576 1220 | 2147483647 1221 | 1222 | 1223 | submenuAction: 1224 | 1225 | Window 1226 | 1227 | 1228 | 1229 | Minimize 1230 | m 1231 | 1048576 1232 | 2147483647 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | Zoom 1239 | 1240 | 1048576 1241 | 2147483647 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | YES 1248 | YES 1249 | 1250 | 1251 | 1048576 1252 | 2147483647 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | Bring All to Front 1259 | 1260 | 1048576 1261 | 2147483647 1262 | 1263 | 1264 | 1265 | 1266 | _NSWindowsMenu 1267 | 1268 | 1269 | 1270 | 1271 | Help 1272 | 1273 | 2147483647 1274 | 1275 | 1276 | submenuAction: 1277 | 1278 | Help 1279 | 1280 | 1281 | 1282 | JNWAnimatableWindowDemo Help 1283 | ? 1284 | 1048576 1285 | 2147483647 1286 | 1287 | 1288 | 1289 | 1290 | _NSHelpMenu 1291 | 1292 | 1293 | 1294 | _NSMainMenu 1295 | 1296 | 1297 | 15 1298 | 2 1299 | {{335, 390}, {480, 393}} 1300 | 1954021376 1301 | JNWAnimatableWindowDemo 1302 | JNWAnimatableWindow 1303 | 1304 | 1305 | 1306 | 1307 | 256 1308 | 1309 | 1310 | 1311 | 266 1312 | {{6, 325}, {457, 48}} 1313 | 1314 | 1315 | _NS:1535 1316 | YES 1317 | 1318 | 67108864 1319 | 138412032 1320 | I'm just a normal window with the class set to JNWAnimatableWindow. 1321 | 1322 | LucidaGrande-Bold 1323 | 17 1324 | 16 1325 | 1326 | _NS:1535 1327 | 1328 | 1329 | 6 1330 | System 1331 | controlColor 1332 | 1333 | 3 1334 | MC42NjY2NjY2NjY3AA 1335 | 1336 | 1337 | 1338 | 6 1339 | System 1340 | controlTextColor 1341 | 1342 | 3 1343 | MAA 1344 | 1345 | 1346 | 1347 | NO 1348 | 1349 | 1350 | 1351 | 292 1352 | {{26, 46}, {118, 32}} 1353 | 1354 | 1355 | _NS:9 1356 | YES 1357 | 1358 | 67108864 1359 | 134217728 1360 | Animate out 1361 | 1362 | LucidaGrande 1363 | 13 1364 | 1044 1365 | 1366 | _NS:9 1367 | 1368 | -2038284288 1369 | 129 1370 | 1371 | 1372 | 200 1373 | 25 1374 | 1375 | NO 1376 | 1377 | 1378 | 1379 | 289 1380 | {{331, 46}, {135, 32}} 1381 | 1382 | 1383 | _NS:9 1384 | YES 1385 | 1386 | 67108864 1387 | 134217728 1388 | Do a barrel roll 1389 | 1390 | _NS:9 1391 | 1392 | -2038284288 1393 | 129 1394 | 1395 | 1396 | 200 1397 | 25 1398 | 1399 | NO 1400 | 1401 | 1402 | 1403 | 266 1404 | {{6, 301}, {457, 16}} 1405 | 1406 | 1407 | _NS:1535 1408 | YES 1409 | 1410 | 67108864 1411 | 138412032 1412 | Once closed, just click the dock icon again to reopen. 1413 | 1414 | LucidaGrande 1415 | 12 1416 | 16 1417 | 1418 | _NS:1535 1419 | 1420 | 1421 | 1422 | 1423 | NO 1424 | 1425 | 1426 | 1427 | 289 1428 | {{330, 13}, {136, 32}} 1429 | 1430 | _NS:9 1431 | YES 1432 | 1433 | 67108864 1434 | 134217728 1435 | Animate Frame 1436 | 1437 | _NS:9 1438 | 1439 | -2038284288 1440 | 129 1441 | 1442 | 1443 | 200 1444 | 25 1445 | 1446 | NO 1447 | 1448 | 1449 | 1450 | 292 1451 | {{26, 13}, {187, 32}} 1452 | 1453 | 1454 | _NS:9 1455 | YES 1456 | 1457 | 67108864 1458 | 134217728 1459 | Animate out (explicitly) 1460 | 1461 | _NS:9 1462 | 1463 | -2038284288 1464 | 129 1465 | 1466 | 1467 | 200 1468 | 25 1469 | 1470 | NO 1471 | 1472 | 1473 | {480, 393} 1474 | 1475 | 1476 | 1477 | {{0, 0}, {1440, 878}} 1478 | {10000000000000, 10000000000000} 1479 | 128 1480 | YES 1481 | 1482 | 1483 | AppDelegate 1484 | 1485 | 1486 | NSFontManager 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | terminate: 1494 | 1495 | 1496 | 1497 | 449 1498 | 1499 | 1500 | 1501 | orderFrontStandardAboutPanel: 1502 | 1503 | 1504 | 1505 | 142 1506 | 1507 | 1508 | 1509 | delegate 1510 | 1511 | 1512 | 1513 | 495 1514 | 1515 | 1516 | 1517 | performMiniaturize: 1518 | 1519 | 1520 | 1521 | 37 1522 | 1523 | 1524 | 1525 | arrangeInFront: 1526 | 1527 | 1528 | 1529 | 39 1530 | 1531 | 1532 | 1533 | print: 1534 | 1535 | 1536 | 1537 | 86 1538 | 1539 | 1540 | 1541 | runPageLayout: 1542 | 1543 | 1544 | 1545 | 87 1546 | 1547 | 1548 | 1549 | clearRecentDocuments: 1550 | 1551 | 1552 | 1553 | 127 1554 | 1555 | 1556 | 1557 | performClose: 1558 | 1559 | 1560 | 1561 | 193 1562 | 1563 | 1564 | 1565 | toggleContinuousSpellChecking: 1566 | 1567 | 1568 | 1569 | 222 1570 | 1571 | 1572 | 1573 | undo: 1574 | 1575 | 1576 | 1577 | 223 1578 | 1579 | 1580 | 1581 | copy: 1582 | 1583 | 1584 | 1585 | 224 1586 | 1587 | 1588 | 1589 | checkSpelling: 1590 | 1591 | 1592 | 1593 | 225 1594 | 1595 | 1596 | 1597 | paste: 1598 | 1599 | 1600 | 1601 | 226 1602 | 1603 | 1604 | 1605 | stopSpeaking: 1606 | 1607 | 1608 | 1609 | 227 1610 | 1611 | 1612 | 1613 | cut: 1614 | 1615 | 1616 | 1617 | 228 1618 | 1619 | 1620 | 1621 | showGuessPanel: 1622 | 1623 | 1624 | 1625 | 230 1626 | 1627 | 1628 | 1629 | redo: 1630 | 1631 | 1632 | 1633 | 231 1634 | 1635 | 1636 | 1637 | selectAll: 1638 | 1639 | 1640 | 1641 | 232 1642 | 1643 | 1644 | 1645 | startSpeaking: 1646 | 1647 | 1648 | 1649 | 233 1650 | 1651 | 1652 | 1653 | delete: 1654 | 1655 | 1656 | 1657 | 235 1658 | 1659 | 1660 | 1661 | performZoom: 1662 | 1663 | 1664 | 1665 | 240 1666 | 1667 | 1668 | 1669 | performFindPanelAction: 1670 | 1671 | 1672 | 1673 | 241 1674 | 1675 | 1676 | 1677 | centerSelectionInVisibleArea: 1678 | 1679 | 1680 | 1681 | 245 1682 | 1683 | 1684 | 1685 | toggleGrammarChecking: 1686 | 1687 | 1688 | 1689 | 347 1690 | 1691 | 1692 | 1693 | toggleSmartInsertDelete: 1694 | 1695 | 1696 | 1697 | 355 1698 | 1699 | 1700 | 1701 | toggleAutomaticQuoteSubstitution: 1702 | 1703 | 1704 | 1705 | 356 1706 | 1707 | 1708 | 1709 | toggleAutomaticLinkDetection: 1710 | 1711 | 1712 | 1713 | 357 1714 | 1715 | 1716 | 1717 | saveDocument: 1718 | 1719 | 1720 | 1721 | 362 1722 | 1723 | 1724 | 1725 | revertDocumentToSaved: 1726 | 1727 | 1728 | 1729 | 364 1730 | 1731 | 1732 | 1733 | runToolbarCustomizationPalette: 1734 | 1735 | 1736 | 1737 | 365 1738 | 1739 | 1740 | 1741 | toggleToolbarShown: 1742 | 1743 | 1744 | 1745 | 366 1746 | 1747 | 1748 | 1749 | hide: 1750 | 1751 | 1752 | 1753 | 367 1754 | 1755 | 1756 | 1757 | hideOtherApplications: 1758 | 1759 | 1760 | 1761 | 368 1762 | 1763 | 1764 | 1765 | unhideAllApplications: 1766 | 1767 | 1768 | 1769 | 370 1770 | 1771 | 1772 | 1773 | newDocument: 1774 | 1775 | 1776 | 1777 | 373 1778 | 1779 | 1780 | 1781 | openDocument: 1782 | 1783 | 1784 | 1785 | 374 1786 | 1787 | 1788 | 1789 | raiseBaseline: 1790 | 1791 | 1792 | 1793 | 426 1794 | 1795 | 1796 | 1797 | lowerBaseline: 1798 | 1799 | 1800 | 1801 | 427 1802 | 1803 | 1804 | 1805 | copyFont: 1806 | 1807 | 1808 | 1809 | 428 1810 | 1811 | 1812 | 1813 | subscript: 1814 | 1815 | 1816 | 1817 | 429 1818 | 1819 | 1820 | 1821 | superscript: 1822 | 1823 | 1824 | 1825 | 430 1826 | 1827 | 1828 | 1829 | tightenKerning: 1830 | 1831 | 1832 | 1833 | 431 1834 | 1835 | 1836 | 1837 | underline: 1838 | 1839 | 1840 | 1841 | 432 1842 | 1843 | 1844 | 1845 | orderFrontColorPanel: 1846 | 1847 | 1848 | 1849 | 433 1850 | 1851 | 1852 | 1853 | useAllLigatures: 1854 | 1855 | 1856 | 1857 | 434 1858 | 1859 | 1860 | 1861 | loosenKerning: 1862 | 1863 | 1864 | 1865 | 435 1866 | 1867 | 1868 | 1869 | pasteFont: 1870 | 1871 | 1872 | 1873 | 436 1874 | 1875 | 1876 | 1877 | unscript: 1878 | 1879 | 1880 | 1881 | 437 1882 | 1883 | 1884 | 1885 | useStandardKerning: 1886 | 1887 | 1888 | 1889 | 438 1890 | 1891 | 1892 | 1893 | useStandardLigatures: 1894 | 1895 | 1896 | 1897 | 439 1898 | 1899 | 1900 | 1901 | turnOffLigatures: 1902 | 1903 | 1904 | 1905 | 440 1906 | 1907 | 1908 | 1909 | turnOffKerning: 1910 | 1911 | 1912 | 1913 | 441 1914 | 1915 | 1916 | 1917 | toggleAutomaticSpellingCorrection: 1918 | 1919 | 1920 | 1921 | 456 1922 | 1923 | 1924 | 1925 | orderFrontSubstitutionsPanel: 1926 | 1927 | 1928 | 1929 | 458 1930 | 1931 | 1932 | 1933 | toggleAutomaticDashSubstitution: 1934 | 1935 | 1936 | 1937 | 461 1938 | 1939 | 1940 | 1941 | toggleAutomaticTextReplacement: 1942 | 1943 | 1944 | 1945 | 463 1946 | 1947 | 1948 | 1949 | uppercaseWord: 1950 | 1951 | 1952 | 1953 | 464 1954 | 1955 | 1956 | 1957 | capitalizeWord: 1958 | 1959 | 1960 | 1961 | 467 1962 | 1963 | 1964 | 1965 | lowercaseWord: 1966 | 1967 | 1968 | 1969 | 468 1970 | 1971 | 1972 | 1973 | pasteAsPlainText: 1974 | 1975 | 1976 | 1977 | 486 1978 | 1979 | 1980 | 1981 | performFindPanelAction: 1982 | 1983 | 1984 | 1985 | 487 1986 | 1987 | 1988 | 1989 | performFindPanelAction: 1990 | 1991 | 1992 | 1993 | 488 1994 | 1995 | 1996 | 1997 | performFindPanelAction: 1998 | 1999 | 2000 | 2001 | 489 2002 | 2003 | 2004 | 2005 | showHelp: 2006 | 2007 | 2008 | 2009 | 493 2010 | 2011 | 2012 | 2013 | alignCenter: 2014 | 2015 | 2016 | 2017 | 518 2018 | 2019 | 2020 | 2021 | pasteRuler: 2022 | 2023 | 2024 | 2025 | 519 2026 | 2027 | 2028 | 2029 | toggleRuler: 2030 | 2031 | 2032 | 2033 | 520 2034 | 2035 | 2036 | 2037 | alignRight: 2038 | 2039 | 2040 | 2041 | 521 2042 | 2043 | 2044 | 2045 | copyRuler: 2046 | 2047 | 2048 | 2049 | 522 2050 | 2051 | 2052 | 2053 | alignJustified: 2054 | 2055 | 2056 | 2057 | 523 2058 | 2059 | 2060 | 2061 | alignLeft: 2062 | 2063 | 2064 | 2065 | 524 2066 | 2067 | 2068 | 2069 | makeBaseWritingDirectionNatural: 2070 | 2071 | 2072 | 2073 | 525 2074 | 2075 | 2076 | 2077 | makeBaseWritingDirectionLeftToRight: 2078 | 2079 | 2080 | 2081 | 526 2082 | 2083 | 2084 | 2085 | makeBaseWritingDirectionRightToLeft: 2086 | 2087 | 2088 | 2089 | 527 2090 | 2091 | 2092 | 2093 | makeTextWritingDirectionNatural: 2094 | 2095 | 2096 | 2097 | 528 2098 | 2099 | 2100 | 2101 | makeTextWritingDirectionLeftToRight: 2102 | 2103 | 2104 | 2105 | 529 2106 | 2107 | 2108 | 2109 | makeTextWritingDirectionRightToLeft: 2110 | 2111 | 2112 | 2113 | 530 2114 | 2115 | 2116 | 2117 | performFindPanelAction: 2118 | 2119 | 2120 | 2121 | 535 2122 | 2123 | 2124 | 2125 | addFontTrait: 2126 | 2127 | 2128 | 2129 | 421 2130 | 2131 | 2132 | 2133 | addFontTrait: 2134 | 2135 | 2136 | 2137 | 422 2138 | 2139 | 2140 | 2141 | modifyFont: 2142 | 2143 | 2144 | 2145 | 423 2146 | 2147 | 2148 | 2149 | orderFrontFontPanel: 2150 | 2151 | 2152 | 2153 | 424 2154 | 2155 | 2156 | 2157 | modifyFont: 2158 | 2159 | 2160 | 2161 | 425 2162 | 2163 | 2164 | 2165 | window 2166 | 2167 | 2168 | 2169 | 532 2170 | 2171 | 2172 | 2173 | animateOut: 2174 | 2175 | 2176 | 2177 | 552 2178 | 2179 | 2180 | 2181 | moveAround: 2182 | 2183 | 2184 | 2185 | 555 2186 | 2187 | 2188 | 2189 | animateFrame: 2190 | 2191 | 2192 | 2193 | 560 2194 | 2195 | 2196 | 2197 | animateOutExplicitly: 2198 | 2199 | 2200 | 2201 | 565 2202 | 2203 | 2204 | 2205 | 2206 | 2207 | 0 2208 | 2209 | 2210 | 2211 | 2212 | 2213 | -2 2214 | 2215 | 2216 | File's Owner 2217 | 2218 | 2219 | -1 2220 | 2221 | 2222 | First Responder 2223 | 2224 | 2225 | -3 2226 | 2227 | 2228 | Application 2229 | 2230 | 2231 | 29 2232 | 2233 | 2234 | 2235 | 2236 | 2237 | 2238 | 2239 | 2240 | 2241 | 2242 | 2243 | 2244 | 2245 | 19 2246 | 2247 | 2248 | 2249 | 2250 | 2251 | 2252 | 2253 | 56 2254 | 2255 | 2256 | 2257 | 2258 | 2259 | 2260 | 2261 | 217 2262 | 2263 | 2264 | 2265 | 2266 | 2267 | 2268 | 2269 | 83 2270 | 2271 | 2272 | 2273 | 2274 | 2275 | 2276 | 2277 | 81 2278 | 2279 | 2280 | 2281 | 2282 | 2283 | 2284 | 2285 | 2286 | 2287 | 2288 | 2289 | 2290 | 2291 | 2292 | 2293 | 2294 | 75 2295 | 2296 | 2297 | 2298 | 2299 | 78 2300 | 2301 | 2302 | 2303 | 2304 | 72 2305 | 2306 | 2307 | 2308 | 2309 | 82 2310 | 2311 | 2312 | 2313 | 2314 | 124 2315 | 2316 | 2317 | 2318 | 2319 | 2320 | 2321 | 2322 | 77 2323 | 2324 | 2325 | 2326 | 2327 | 73 2328 | 2329 | 2330 | 2331 | 2332 | 79 2333 | 2334 | 2335 | 2336 | 2337 | 112 2338 | 2339 | 2340 | 2341 | 2342 | 74 2343 | 2344 | 2345 | 2346 | 2347 | 125 2348 | 2349 | 2350 | 2351 | 2352 | 2353 | 2354 | 2355 | 126 2356 | 2357 | 2358 | 2359 | 2360 | 205 2361 | 2362 | 2363 | 2364 | 2365 | 2366 | 2367 | 2368 | 2369 | 2370 | 2371 | 2372 | 2373 | 2374 | 2375 | 2376 | 2377 | 2378 | 2379 | 2380 | 2381 | 2382 | 202 2383 | 2384 | 2385 | 2386 | 2387 | 198 2388 | 2389 | 2390 | 2391 | 2392 | 207 2393 | 2394 | 2395 | 2396 | 2397 | 214 2398 | 2399 | 2400 | 2401 | 2402 | 199 2403 | 2404 | 2405 | 2406 | 2407 | 203 2408 | 2409 | 2410 | 2411 | 2412 | 197 2413 | 2414 | 2415 | 2416 | 2417 | 206 2418 | 2419 | 2420 | 2421 | 2422 | 215 2423 | 2424 | 2425 | 2426 | 2427 | 218 2428 | 2429 | 2430 | 2431 | 2432 | 2433 | 2434 | 2435 | 216 2436 | 2437 | 2438 | 2439 | 2440 | 2441 | 2442 | 2443 | 200 2444 | 2445 | 2446 | 2447 | 2448 | 2449 | 2450 | 2451 | 2452 | 2453 | 2454 | 2455 | 2456 | 219 2457 | 2458 | 2459 | 2460 | 2461 | 201 2462 | 2463 | 2464 | 2465 | 2466 | 204 2467 | 2468 | 2469 | 2470 | 2471 | 220 2472 | 2473 | 2474 | 2475 | 2476 | 2477 | 2478 | 2479 | 2480 | 2481 | 2482 | 2483 | 2484 | 213 2485 | 2486 | 2487 | 2488 | 2489 | 210 2490 | 2491 | 2492 | 2493 | 2494 | 221 2495 | 2496 | 2497 | 2498 | 2499 | 208 2500 | 2501 | 2502 | 2503 | 2504 | 209 2505 | 2506 | 2507 | 2508 | 2509 | 57 2510 | 2511 | 2512 | 2513 | 2514 | 2515 | 2516 | 2517 | 2518 | 2519 | 2520 | 2521 | 2522 | 2523 | 2524 | 2525 | 2526 | 2527 | 58 2528 | 2529 | 2530 | 2531 | 2532 | 134 2533 | 2534 | 2535 | 2536 | 2537 | 150 2538 | 2539 | 2540 | 2541 | 2542 | 136 2543 | 2544 | 2545 | 2546 | 2547 | 144 2548 | 2549 | 2550 | 2551 | 2552 | 129 2553 | 2554 | 2555 | 2556 | 2557 | 143 2558 | 2559 | 2560 | 2561 | 2562 | 236 2563 | 2564 | 2565 | 2566 | 2567 | 131 2568 | 2569 | 2570 | 2571 | 2572 | 2573 | 2574 | 2575 | 149 2576 | 2577 | 2578 | 2579 | 2580 | 145 2581 | 2582 | 2583 | 2584 | 2585 | 130 2586 | 2587 | 2588 | 2589 | 2590 | 24 2591 | 2592 | 2593 | 2594 | 2595 | 2596 | 2597 | 2598 | 2599 | 2600 | 2601 | 92 2602 | 2603 | 2604 | 2605 | 2606 | 5 2607 | 2608 | 2609 | 2610 | 2611 | 239 2612 | 2613 | 2614 | 2615 | 2616 | 23 2617 | 2618 | 2619 | 2620 | 2621 | 295 2622 | 2623 | 2624 | 2625 | 2626 | 2627 | 2628 | 2629 | 296 2630 | 2631 | 2632 | 2633 | 2634 | 2635 | 2636 | 2637 | 2638 | 297 2639 | 2640 | 2641 | 2642 | 2643 | 298 2644 | 2645 | 2646 | 2647 | 2648 | 211 2649 | 2650 | 2651 | 2652 | 2653 | 2654 | 2655 | 2656 | 212 2657 | 2658 | 2659 | 2660 | 2661 | 2662 | 2663 | 2664 | 2665 | 195 2666 | 2667 | 2668 | 2669 | 2670 | 196 2671 | 2672 | 2673 | 2674 | 2675 | 346 2676 | 2677 | 2678 | 2679 | 2680 | 348 2681 | 2682 | 2683 | 2684 | 2685 | 2686 | 2687 | 2688 | 349 2689 | 2690 | 2691 | 2692 | 2693 | 2694 | 2695 | 2696 | 2697 | 2698 | 2699 | 2700 | 2701 | 2702 | 350 2703 | 2704 | 2705 | 2706 | 2707 | 351 2708 | 2709 | 2710 | 2711 | 2712 | 354 2713 | 2714 | 2715 | 2716 | 2717 | 371 2718 | 2719 | 2720 | 2721 | 2722 | 2723 | 2724 | 2725 | 372 2726 | 2727 | 2728 | 2729 | 2730 | 2731 | 2732 | 2733 | 2734 | 2735 | 2736 | 2737 | 2738 | 375 2739 | 2740 | 2741 | 2742 | 2743 | 2744 | 2745 | 2746 | 376 2747 | 2748 | 2749 | 2750 | 2751 | 2752 | 2753 | 2754 | 2755 | 377 2756 | 2757 | 2758 | 2759 | 2760 | 2761 | 2762 | 2763 | 388 2764 | 2765 | 2766 | 2767 | 2768 | 2769 | 2770 | 2771 | 2772 | 2773 | 2774 | 2775 | 2776 | 2777 | 2778 | 2779 | 2780 | 2781 | 2782 | 2783 | 2784 | 2785 | 2786 | 389 2787 | 2788 | 2789 | 2790 | 2791 | 390 2792 | 2793 | 2794 | 2795 | 2796 | 391 2797 | 2798 | 2799 | 2800 | 2801 | 392 2802 | 2803 | 2804 | 2805 | 2806 | 393 2807 | 2808 | 2809 | 2810 | 2811 | 394 2812 | 2813 | 2814 | 2815 | 2816 | 395 2817 | 2818 | 2819 | 2820 | 2821 | 396 2822 | 2823 | 2824 | 2825 | 2826 | 397 2827 | 2828 | 2829 | 2830 | 2831 | 2832 | 2833 | 2834 | 398 2835 | 2836 | 2837 | 2838 | 2839 | 2840 | 2841 | 2842 | 399 2843 | 2844 | 2845 | 2846 | 2847 | 2848 | 2849 | 2850 | 400 2851 | 2852 | 2853 | 2854 | 2855 | 401 2856 | 2857 | 2858 | 2859 | 2860 | 402 2861 | 2862 | 2863 | 2864 | 2865 | 403 2866 | 2867 | 2868 | 2869 | 2870 | 404 2871 | 2872 | 2873 | 2874 | 2875 | 405 2876 | 2877 | 2878 | 2879 | 2880 | 2881 | 2882 | 2883 | 2884 | 2885 | 2886 | 2887 | 406 2888 | 2889 | 2890 | 2891 | 2892 | 407 2893 | 2894 | 2895 | 2896 | 2897 | 408 2898 | 2899 | 2900 | 2901 | 2902 | 409 2903 | 2904 | 2905 | 2906 | 2907 | 410 2908 | 2909 | 2910 | 2911 | 2912 | 411 2913 | 2914 | 2915 | 2916 | 2917 | 2918 | 2919 | 2920 | 2921 | 2922 | 412 2923 | 2924 | 2925 | 2926 | 2927 | 413 2928 | 2929 | 2930 | 2931 | 2932 | 414 2933 | 2934 | 2935 | 2936 | 2937 | 415 2938 | 2939 | 2940 | 2941 | 2942 | 2943 | 2944 | 2945 | 2946 | 2947 | 2948 | 416 2949 | 2950 | 2951 | 2952 | 2953 | 417 2954 | 2955 | 2956 | 2957 | 2958 | 418 2959 | 2960 | 2961 | 2962 | 2963 | 419 2964 | 2965 | 2966 | 2967 | 2968 | 420 2969 | 2970 | 2971 | 2972 | 2973 | 450 2974 | 2975 | 2976 | 2977 | 2978 | 2979 | 2980 | 2981 | 451 2982 | 2983 | 2984 | 2985 | 2986 | 2987 | 2988 | 2989 | 2990 | 2991 | 452 2992 | 2993 | 2994 | 2995 | 2996 | 453 2997 | 2998 | 2999 | 3000 | 3001 | 454 3002 | 3003 | 3004 | 3005 | 3006 | 457 3007 | 3008 | 3009 | 3010 | 3011 | 459 3012 | 3013 | 3014 | 3015 | 3016 | 460 3017 | 3018 | 3019 | 3020 | 3021 | 462 3022 | 3023 | 3024 | 3025 | 3026 | 465 3027 | 3028 | 3029 | 3030 | 3031 | 466 3032 | 3033 | 3034 | 3035 | 3036 | 485 3037 | 3038 | 3039 | 3040 | 3041 | 490 3042 | 3043 | 3044 | 3045 | 3046 | 3047 | 3048 | 3049 | 491 3050 | 3051 | 3052 | 3053 | 3054 | 3055 | 3056 | 3057 | 492 3058 | 3059 | 3060 | 3061 | 3062 | 494 3063 | 3064 | 3065 | 3066 | 3067 | 496 3068 | 3069 | 3070 | 3071 | 3072 | 3073 | 3074 | 3075 | 497 3076 | 3077 | 3078 | 3079 | 3080 | 3081 | 3082 | 3083 | 3084 | 3085 | 3086 | 3087 | 3088 | 3089 | 3090 | 3091 | 3092 | 498 3093 | 3094 | 3095 | 3096 | 3097 | 499 3098 | 3099 | 3100 | 3101 | 3102 | 500 3103 | 3104 | 3105 | 3106 | 3107 | 501 3108 | 3109 | 3110 | 3111 | 3112 | 502 3113 | 3114 | 3115 | 3116 | 3117 | 503 3118 | 3119 | 3120 | 3121 | 3122 | 3123 | 3124 | 3125 | 504 3126 | 3127 | 3128 | 3129 | 3130 | 505 3131 | 3132 | 3133 | 3134 | 3135 | 506 3136 | 3137 | 3138 | 3139 | 3140 | 507 3141 | 3142 | 3143 | 3144 | 3145 | 508 3146 | 3147 | 3148 | 3149 | 3150 | 3151 | 3152 | 3153 | 3154 | 3155 | 3156 | 3157 | 3158 | 3159 | 3160 | 3161 | 509 3162 | 3163 | 3164 | 3165 | 3166 | 510 3167 | 3168 | 3169 | 3170 | 3171 | 511 3172 | 3173 | 3174 | 3175 | 3176 | 512 3177 | 3178 | 3179 | 3180 | 3181 | 513 3182 | 3183 | 3184 | 3185 | 3186 | 514 3187 | 3188 | 3189 | 3190 | 3191 | 515 3192 | 3193 | 3194 | 3195 | 3196 | 516 3197 | 3198 | 3199 | 3200 | 3201 | 517 3202 | 3203 | 3204 | 3205 | 3206 | 534 3207 | 3208 | 3209 | 3210 | 3211 | 536 3212 | 3213 | 3214 | 3215 | 3216 | 3217 | 3218 | 3219 | 537 3220 | 3221 | 3222 | 3223 | 3224 | 550 3225 | 3226 | 3227 | 3228 | 3229 | 3230 | 3231 | 3232 | 551 3233 | 3234 | 3235 | 3236 | 3237 | 553 3238 | 3239 | 3240 | 3241 | 3242 | 3243 | 3244 | 3245 | 554 3246 | 3247 | 3248 | 3249 | 3250 | 556 3251 | 3252 | 3253 | 3254 | 3255 | 3256 | 3257 | 3258 | 557 3259 | 3260 | 3261 | 3262 | 3263 | 558 3264 | 3265 | 3266 | 3267 | 3268 | 3269 | 3270 | 3271 | 559 3272 | 3273 | 3274 | 3275 | 3276 | 561 3277 | 3278 | 3279 | 3280 | 3281 | 3282 | 3283 | 3284 | 562 3285 | 3286 | 3287 | 3288 | 3289 | 3290 | 3291 | com.apple.InterfaceBuilder.CocoaPlugin 3292 | com.apple.InterfaceBuilder.CocoaPlugin 3293 | com.apple.InterfaceBuilder.CocoaPlugin 3294 | com.apple.InterfaceBuilder.CocoaPlugin 3295 | com.apple.InterfaceBuilder.CocoaPlugin 3296 | com.apple.InterfaceBuilder.CocoaPlugin 3297 | com.apple.InterfaceBuilder.CocoaPlugin 3298 | com.apple.InterfaceBuilder.CocoaPlugin 3299 | com.apple.InterfaceBuilder.CocoaPlugin 3300 | com.apple.InterfaceBuilder.CocoaPlugin 3301 | com.apple.InterfaceBuilder.CocoaPlugin 3302 | com.apple.InterfaceBuilder.CocoaPlugin 3303 | com.apple.InterfaceBuilder.CocoaPlugin 3304 | com.apple.InterfaceBuilder.CocoaPlugin 3305 | com.apple.InterfaceBuilder.CocoaPlugin 3306 | com.apple.InterfaceBuilder.CocoaPlugin 3307 | com.apple.InterfaceBuilder.CocoaPlugin 3308 | com.apple.InterfaceBuilder.CocoaPlugin 3309 | com.apple.InterfaceBuilder.CocoaPlugin 3310 | com.apple.InterfaceBuilder.CocoaPlugin 3311 | com.apple.InterfaceBuilder.CocoaPlugin 3312 | com.apple.InterfaceBuilder.CocoaPlugin 3313 | com.apple.InterfaceBuilder.CocoaPlugin 3314 | com.apple.InterfaceBuilder.CocoaPlugin 3315 | com.apple.InterfaceBuilder.CocoaPlugin 3316 | com.apple.InterfaceBuilder.CocoaPlugin 3317 | com.apple.InterfaceBuilder.CocoaPlugin 3318 | com.apple.InterfaceBuilder.CocoaPlugin 3319 | com.apple.InterfaceBuilder.CocoaPlugin 3320 | com.apple.InterfaceBuilder.CocoaPlugin 3321 | com.apple.InterfaceBuilder.CocoaPlugin 3322 | com.apple.InterfaceBuilder.CocoaPlugin 3323 | com.apple.InterfaceBuilder.CocoaPlugin 3324 | com.apple.InterfaceBuilder.CocoaPlugin 3325 | com.apple.InterfaceBuilder.CocoaPlugin 3326 | com.apple.InterfaceBuilder.CocoaPlugin 3327 | com.apple.InterfaceBuilder.CocoaPlugin 3328 | com.apple.InterfaceBuilder.CocoaPlugin 3329 | com.apple.InterfaceBuilder.CocoaPlugin 3330 | com.apple.InterfaceBuilder.CocoaPlugin 3331 | com.apple.InterfaceBuilder.CocoaPlugin 3332 | com.apple.InterfaceBuilder.CocoaPlugin 3333 | com.apple.InterfaceBuilder.CocoaPlugin 3334 | com.apple.InterfaceBuilder.CocoaPlugin 3335 | com.apple.InterfaceBuilder.CocoaPlugin 3336 | com.apple.InterfaceBuilder.CocoaPlugin 3337 | com.apple.InterfaceBuilder.CocoaPlugin 3338 | com.apple.InterfaceBuilder.CocoaPlugin 3339 | com.apple.InterfaceBuilder.CocoaPlugin 3340 | com.apple.InterfaceBuilder.CocoaPlugin 3341 | com.apple.InterfaceBuilder.CocoaPlugin 3342 | com.apple.InterfaceBuilder.CocoaPlugin 3343 | com.apple.InterfaceBuilder.CocoaPlugin 3344 | com.apple.InterfaceBuilder.CocoaPlugin 3345 | com.apple.InterfaceBuilder.CocoaPlugin 3346 | com.apple.InterfaceBuilder.CocoaPlugin 3347 | com.apple.InterfaceBuilder.CocoaPlugin 3348 | com.apple.InterfaceBuilder.CocoaPlugin 3349 | com.apple.InterfaceBuilder.CocoaPlugin 3350 | com.apple.InterfaceBuilder.CocoaPlugin 3351 | com.apple.InterfaceBuilder.CocoaPlugin 3352 | {{380, 496}, {480, 360}} 3353 | 3354 | com.apple.InterfaceBuilder.CocoaPlugin 3355 | com.apple.InterfaceBuilder.CocoaPlugin 3356 | com.apple.InterfaceBuilder.CocoaPlugin 3357 | com.apple.InterfaceBuilder.CocoaPlugin 3358 | com.apple.InterfaceBuilder.CocoaPlugin 3359 | com.apple.InterfaceBuilder.CocoaPlugin 3360 | com.apple.InterfaceBuilder.CocoaPlugin 3361 | com.apple.InterfaceBuilder.CocoaPlugin 3362 | com.apple.InterfaceBuilder.CocoaPlugin 3363 | com.apple.InterfaceBuilder.CocoaPlugin 3364 | com.apple.InterfaceBuilder.CocoaPlugin 3365 | com.apple.InterfaceBuilder.CocoaPlugin 3366 | com.apple.InterfaceBuilder.CocoaPlugin 3367 | com.apple.InterfaceBuilder.CocoaPlugin 3368 | com.apple.InterfaceBuilder.CocoaPlugin 3369 | com.apple.InterfaceBuilder.CocoaPlugin 3370 | com.apple.InterfaceBuilder.CocoaPlugin 3371 | com.apple.InterfaceBuilder.CocoaPlugin 3372 | com.apple.InterfaceBuilder.CocoaPlugin 3373 | com.apple.InterfaceBuilder.CocoaPlugin 3374 | com.apple.InterfaceBuilder.CocoaPlugin 3375 | com.apple.InterfaceBuilder.CocoaPlugin 3376 | com.apple.InterfaceBuilder.CocoaPlugin 3377 | com.apple.InterfaceBuilder.CocoaPlugin 3378 | com.apple.InterfaceBuilder.CocoaPlugin 3379 | com.apple.InterfaceBuilder.CocoaPlugin 3380 | com.apple.InterfaceBuilder.CocoaPlugin 3381 | com.apple.InterfaceBuilder.CocoaPlugin 3382 | com.apple.InterfaceBuilder.CocoaPlugin 3383 | com.apple.InterfaceBuilder.CocoaPlugin 3384 | com.apple.InterfaceBuilder.CocoaPlugin 3385 | com.apple.InterfaceBuilder.CocoaPlugin 3386 | com.apple.InterfaceBuilder.CocoaPlugin 3387 | com.apple.InterfaceBuilder.CocoaPlugin 3388 | com.apple.InterfaceBuilder.CocoaPlugin 3389 | com.apple.InterfaceBuilder.CocoaPlugin 3390 | com.apple.InterfaceBuilder.CocoaPlugin 3391 | com.apple.InterfaceBuilder.CocoaPlugin 3392 | com.apple.InterfaceBuilder.CocoaPlugin 3393 | com.apple.InterfaceBuilder.CocoaPlugin 3394 | com.apple.InterfaceBuilder.CocoaPlugin 3395 | com.apple.InterfaceBuilder.CocoaPlugin 3396 | com.apple.InterfaceBuilder.CocoaPlugin 3397 | com.apple.InterfaceBuilder.CocoaPlugin 3398 | com.apple.InterfaceBuilder.CocoaPlugin 3399 | com.apple.InterfaceBuilder.CocoaPlugin 3400 | com.apple.InterfaceBuilder.CocoaPlugin 3401 | com.apple.InterfaceBuilder.CocoaPlugin 3402 | com.apple.InterfaceBuilder.CocoaPlugin 3403 | com.apple.InterfaceBuilder.CocoaPlugin 3404 | com.apple.InterfaceBuilder.CocoaPlugin 3405 | com.apple.InterfaceBuilder.CocoaPlugin 3406 | com.apple.InterfaceBuilder.CocoaPlugin 3407 | com.apple.InterfaceBuilder.CocoaPlugin 3408 | com.apple.InterfaceBuilder.CocoaPlugin 3409 | com.apple.InterfaceBuilder.CocoaPlugin 3410 | com.apple.InterfaceBuilder.CocoaPlugin 3411 | com.apple.InterfaceBuilder.CocoaPlugin 3412 | com.apple.InterfaceBuilder.CocoaPlugin 3413 | com.apple.InterfaceBuilder.CocoaPlugin 3414 | com.apple.InterfaceBuilder.CocoaPlugin 3415 | com.apple.InterfaceBuilder.CocoaPlugin 3416 | com.apple.InterfaceBuilder.CocoaPlugin 3417 | com.apple.InterfaceBuilder.CocoaPlugin 3418 | com.apple.InterfaceBuilder.CocoaPlugin 3419 | com.apple.InterfaceBuilder.CocoaPlugin 3420 | com.apple.InterfaceBuilder.CocoaPlugin 3421 | com.apple.InterfaceBuilder.CocoaPlugin 3422 | com.apple.InterfaceBuilder.CocoaPlugin 3423 | com.apple.InterfaceBuilder.CocoaPlugin 3424 | com.apple.InterfaceBuilder.CocoaPlugin 3425 | com.apple.InterfaceBuilder.CocoaPlugin 3426 | com.apple.InterfaceBuilder.CocoaPlugin 3427 | com.apple.InterfaceBuilder.CocoaPlugin 3428 | com.apple.InterfaceBuilder.CocoaPlugin 3429 | com.apple.InterfaceBuilder.CocoaPlugin 3430 | com.apple.InterfaceBuilder.CocoaPlugin 3431 | com.apple.InterfaceBuilder.CocoaPlugin 3432 | com.apple.InterfaceBuilder.CocoaPlugin 3433 | com.apple.InterfaceBuilder.CocoaPlugin 3434 | com.apple.InterfaceBuilder.CocoaPlugin 3435 | com.apple.InterfaceBuilder.CocoaPlugin 3436 | com.apple.InterfaceBuilder.CocoaPlugin 3437 | com.apple.InterfaceBuilder.CocoaPlugin 3438 | com.apple.InterfaceBuilder.CocoaPlugin 3439 | com.apple.InterfaceBuilder.CocoaPlugin 3440 | com.apple.InterfaceBuilder.CocoaPlugin 3441 | com.apple.InterfaceBuilder.CocoaPlugin 3442 | com.apple.InterfaceBuilder.CocoaPlugin 3443 | com.apple.InterfaceBuilder.CocoaPlugin 3444 | com.apple.InterfaceBuilder.CocoaPlugin 3445 | com.apple.InterfaceBuilder.CocoaPlugin 3446 | com.apple.InterfaceBuilder.CocoaPlugin 3447 | com.apple.InterfaceBuilder.CocoaPlugin 3448 | com.apple.InterfaceBuilder.CocoaPlugin 3449 | com.apple.InterfaceBuilder.CocoaPlugin 3450 | com.apple.InterfaceBuilder.CocoaPlugin 3451 | com.apple.InterfaceBuilder.CocoaPlugin 3452 | com.apple.InterfaceBuilder.CocoaPlugin 3453 | com.apple.InterfaceBuilder.CocoaPlugin 3454 | com.apple.InterfaceBuilder.CocoaPlugin 3455 | com.apple.InterfaceBuilder.CocoaPlugin 3456 | com.apple.InterfaceBuilder.CocoaPlugin 3457 | 3458 | 3459 | 3460 | 3461 | 3462 | 565 3463 | 3464 | 3465 | 0 3466 | IBCocoaFramework 3467 | YES 3468 | 3 3469 | 3470 | {11, 11} 3471 | {10, 3} 3472 | 3473 | 3474 | 3475 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/JNWAnimatableWindowDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 AppJon. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/JNWAnimatableWindowDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'JNWAnimatableWindowDemo' target in the 'JNWAnimatableWindowDemo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Demo/JNWAnimatableWindowDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JNWAnimatableWindowDemo 4 | // 5 | // Created by Jonathan Willing on 1/25/13. 6 | // Copyright (c) 2013 AppJon. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /JNWAnimatableWindow.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "JNWAnimatableWindow" 3 | s.version = "0.9.0" 4 | s.summary = "Smooth animation of a NSWindow using a CALayer." 5 | s.homepage = "https://github.com/jwilling/JNWAnimatableWindow" 6 | s.license = 'MIT' 7 | s.author = { "Jonathan Willing" => "hi@jwilling.com" } 8 | s.source = { :git => "https://github.com/jwilling/JNWAnimatableWindow.git", :tag => s.version.to_s } 9 | s.platform = :osx, '10.7' 10 | s.source_files = 'Sources/JNWAnimatableWindow/JNWAnimatableWindow.m', 'Sources/JNWAnimatableWindow/include/JNWAnimatableWindow.h' 11 | 12 | s.framework = 'QuartzCore' 13 | s.requires_arc = true 14 | end 15 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Jonathan Willing 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "JNWAnimatableWindow", 8 | platforms: [.macOS("10.9")], 9 | products: [ 10 | // Products define the executables and libraries a package produces, and make them visible to other packages. 11 | .library( 12 | name: "JNWAnimatableWindow", 13 | targets: ["JNWAnimatableWindow"]), 14 | ], 15 | dependencies: [ 16 | // Dependencies declare other packages that this package depends on. 17 | // .package(url: /* package url */, from: "1.0.0"), 18 | ], 19 | targets: [ 20 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 21 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 22 | .target( 23 | name: "JNWAnimatableWindow", 24 | dependencies: []), 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## JNWAnimatableWindow ## 2 | `JNWAnimatableWindow` is a `NSWindow` subclass that adds a `layer` property onto the window, allowing you to animate it as you wish. 3 | 4 | ![](http://www.jwilling.com/serve/github/jnwanimatablewindow/preview.gif) 5 | 6 | ## Installation ## 7 | 8 | ### Swift Package Manager ### 9 | 10 | In Xcode 11 or later click `File` -> `Swift Packages` -> `Add Package Dependency...`. 11 | 12 | Enter the following URL: 13 | `https://github.com/jwilling/JNWAnimatableWindow.git` 14 | 15 | Then select the branch `master`. 16 | 17 | ### CocoaPods ### 18 | 19 | Add `pod 'JNWAnimatableWindow', '~> 0.9'` to your Podfile similar to the following: 20 | 21 | ``` 22 | target 'MyApp' do 23 | pod 'JNWAnimatableWindow', '~> 0.9' 24 | end 25 | ``` 26 | 27 | Then run a `pod install` inside your terminal, or from CocoaPods.app. 28 | 29 | 30 | ## Getting Started ## 31 | 32 | `JNWAnimatableWindow` has provides both a layer property and a set of order out & order front methods to simplify common animations. If you would like to animate the window manually and if the window is already visible, you can just manipulate the `layer` property on the window. 33 | 34 | The following methods exist to animate the window using implicit animations: 35 | 36 | ``` objc 37 | - (void)orderOutWithDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timingFunction animations:(void (^)(CALayer *windowLayer))animations; 38 | - (void)makeKeyAndOrderFrontWithDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timingFunction setup:(void (^)(CALayer *windowLayer))setup animations:(void (^)(CALayer *layer))animations; 39 | - (void)setFrame:(NSRect)frameRect withDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timing; 40 | ``` 41 | 42 | If you would like to animate the window explicitly, you can do so using the following methods: 43 | 44 | ``` objc 45 | - (void)orderOutWithAnimation:(CAAnimation *)animation; 46 | - (void)makeKeyAndOrderFrontWithAnimation:(CAAnimation *)animation; 47 | ``` 48 | 49 | **All of these methods are explained fully in the header's documentation.** 50 | 51 | 52 | ### Examples ### 53 | 54 | Closing: 55 | 56 | ``` objc 57 | [self.window orderOutWithDuration:0.7 timing:nil animations:^(CALayer *layer) { 58 | layer.opacity = 0.f; 59 | }]; 60 | ``` 61 | Opening: 62 | 63 | ``` objc 64 | [self.window makeKeyAndOrderFrontWithDuration:0.7 timing:nil setup:^(CALayer *layer) { 65 | // Setup is not animated 66 | layer.opacity = 0.f; 67 | } animations:^(CALayer *layer) { 68 | // This is animated 69 | layer.opacity = 1.f; 70 | }]; 71 | ``` 72 | Frame change: 73 | 74 | ``` objc 75 | [self.window setFrame:newFrame withDuration:0.7 timing:nil]; 76 | ``` 77 | 78 | Explicit animation: 79 | 80 | ``` objc 81 | CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"]; 82 | opacity.toValue = @0; 83 | [self.window orderOutWithAnimation:opacity]; 84 | ``` 85 | 86 | ### More Information ### 87 | 88 | In the convenience methods, everything is wrapped in an animated `CATransaction`, so you can modify any layer property you wish and it should be implicitly animated. Also note that passing in nil for the timing function will result in a default animation of ease-in-out. 89 | 90 | If you want to just make your windows fly around the screen like a boss on a whim, you can directly use the `layer` property on `JNWAnimatableWindow`. The first time this property is accessed, it will lazily create an image representation of the window and place that into a layer which is then animatable. When you are done with the layer, you are responsible for calling `-destroyTransformingWindow`, which will remove the extra window and release resources. This is not necessary if you use one of the convenience methods listed above. 91 | 92 | See the demo for more examples, and see the header files for more complete documentation. 93 | 94 | ## Limitations ## 95 | Due to the way `NSWindow` works, there are some large limitations with what this library can provide. It works by taking an image representation of the window, and placing it in a layer, which is in an additional non-opaque fullscreen window. As a result of this static representation, if the window updates its contents while the layer is shown, that change will not be reflected in the layer. So as a result, this class is more geared toward short animations that take place during a time where the content is most unlikely to change, such as when the window is opening or closing. 96 | 97 | 98 | ## License ## 99 | `JNWAnimatableWindow` is licensed under the [MIT](http://opensource.org/licenses/MIT) license. See [LICENSE.md](https://github.com/jwilling/JNWAnimatableWindow/blob/master/LICENSE.md). 100 | 101 | But really, all I care about is that you put this library to good use. I want to help make OS X development a friendlier place, and this is one of my attempts at doing so. If you use this, *please* make a note on the [**Wiki**](https://github.com/jwilling/JNWAnimatableWindow/wiki/JNWAnimatableWindow-in-use.), or get in touch with me and I'll do it for you. 102 | 103 | ## Get In Touch ## 104 | You can follow me on Twitter as [@willing](http://twitter.com/willing), email me at the email listed on my GitHub profile, or read my blog at [jwilling.com](http://www.jwilling.com). 105 | -------------------------------------------------------------------------------- /Sources/JNWAnimatableWindow/JNWAnimatableWindow.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013, Jonathan Willing. All rights reserved. 3 | Licensed under the MIT license 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 8 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 15 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 16 | IN THE SOFTWARE. 17 | */ 18 | 19 | 20 | #import "include/JNWAnimatableWindow.h" 21 | @import QuartzCore; 22 | 23 | // Since we're using completion blocks to determine when to kill the extra window, we need 24 | // a way to keep track of the outstanding number of transactions, so we keep increment and 25 | // decrement this to determine whether or not the completion block needs to be called. 26 | static NSUInteger JNWAnimatableWindowOpenTransactions = 0; 27 | 28 | // These are attempts at determining the default shadow settings on a normal window. These 29 | // aren't perfect, but since NSWindow actually uses CGS functions to set the window I am not 30 | // entirely sure there's a way to translate the actual shadow values to these values. 31 | static const CGFloat JNWAnimatableWindowShadowOpacity = 0.58f; 32 | static const CGSize JNWAnimatableWindowShadowOffset = (CGSize){ 0, -30.f }; 33 | static const CGFloat JNWAnimatableWindowShadowRadius = 19.f; 34 | static const CGFloat JNWAnimatableWindowShadowHorizontalOutset = 7.f; 35 | static const CGFloat JNWAnimatableWindowShadowTopOffset = 14.f; 36 | 37 | // Use an ease-in-out timing function if none are specified. 38 | #define JNWAnimatableWindowDefaultAnimationCurve kCAMediaTimingFunctionEaseInEaseOut 39 | 40 | @interface JNWAnimatableWindowContentView : NSView 41 | @end 42 | 43 | @interface JNWAnimatableWindow() { 44 | // When we want to move the window off-screen to take the screen shot, we want 45 | // to make sure we aren't being constrained. Although the documentation does not 46 | // state that it constrains windows when moved using -setFrame:display:, such is the case. 47 | BOOL _disableConstrainedWindow; 48 | } 49 | 50 | @property (nonatomic, strong) NSWindow *fullScreenWindow; 51 | @property (nonatomic, strong) CALayer *windowRepresentationLayer; 52 | @end 53 | 54 | @implementation JNWAnimatableWindow 55 | 56 | #pragma mark Initialization 57 | 58 | - (void)initializeWindowRepresentationLayer { 59 | self.windowRepresentationLayer = [CALayer layer]; 60 | self.windowRepresentationLayer.contentsScale = self.backingScaleFactor; 61 | 62 | CGColorRef shadowColor = CGColorCreateGenericRGB(0, 0, 0, JNWAnimatableWindowShadowOpacity); 63 | self.windowRepresentationLayer.shadowColor = shadowColor; 64 | self.windowRepresentationLayer.shadowOffset = JNWAnimatableWindowShadowOffset; 65 | self.windowRepresentationLayer.shadowRadius = JNWAnimatableWindowShadowRadius; 66 | self.windowRepresentationLayer.shadowOpacity = 1.f; 67 | CGColorRelease(shadowColor); 68 | 69 | CGPathRef shadowPath = CGPathCreateWithRect(self.shadowRect, NULL); 70 | self.windowRepresentationLayer.shadowPath = shadowPath; 71 | CGPathRelease(shadowPath); 72 | 73 | self.windowRepresentationLayer.contentsGravity = kCAGravityResize; 74 | self.windowRepresentationLayer.opaque = YES; 75 | } 76 | 77 | - (void)initializeFullScreenWindow { 78 | self.fullScreenWindow = [[NSWindow alloc] initWithContentRect:(CGRect){ .size = self.screen.frame.size } 79 | styleMask:NSBorderlessWindowMask 80 | backing:NSBackingStoreBuffered 81 | defer:NO 82 | screen:self.screen]; 83 | 84 | self.fullScreenWindow.animationBehavior = NSWindowAnimationBehaviorNone; 85 | self.fullScreenWindow.backgroundColor = NSColor.clearColor; 86 | self.fullScreenWindow.movableByWindowBackground = NO; 87 | self.fullScreenWindow.ignoresMouseEvents = YES; 88 | self.fullScreenWindow.level = self.level; 89 | self.fullScreenWindow.hasShadow = NO; 90 | self.fullScreenWindow.opaque = NO; 91 | self.fullScreenWindow.contentView = [[JNWAnimatableWindowContentView alloc] initWithFrame:CGRectZero]; 92 | } 93 | 94 | - (CALayer *)layer { 95 | // If the layer does not exist at this point, we create it and set it up. 96 | [self setupIfNeeded]; 97 | 98 | return self.windowRepresentationLayer; 99 | } 100 | 101 | - (CGRect)shadowRect { 102 | CGRect windowBounds = (CGRect){ .size = self.frame.size }; 103 | CGRect rect = CGRectInset(windowBounds, -JNWAnimatableWindowShadowHorizontalOutset, 0); 104 | rect.size.height += JNWAnimatableWindowShadowTopOffset; 105 | 106 | return rect; 107 | } 108 | 109 | #pragma mark Setup and Drawing 110 | 111 | - (void)setupIfNeeded { 112 | [self setupIfNeededWithSetupBlock:nil]; 113 | } 114 | 115 | - (void)setupIfNeededWithSetupBlock:(void(^)(CALayer *))setupBlock { 116 | if (self.windowRepresentationLayer != nil) { 117 | return; 118 | } 119 | 120 | [self initializeFullScreenWindow]; 121 | [self initializeWindowRepresentationLayer]; 122 | 123 | self.windowRepresentationLayer.frame = [self convertWindowFrameToScreenFrame:self.frame]; 124 | 125 | [[self.fullScreenWindow.contentView layer] addSublayer:self.windowRepresentationLayer]; 126 | 127 | NSImage *image = [self imageRepresentationOffscreen:NO]; 128 | 129 | // Begin a non-animated transaction to ensure that the layer's contents are set before we get rid of the real window. 130 | [CATransaction begin]; 131 | [CATransaction setDisableActions:YES]; 132 | 133 | self.windowRepresentationLayer.contents = image; 134 | 135 | // The setup block is called when we are ordering in. We want this non-animated and done before the the fake window 136 | // is shown, so we do in in the same transaction. 137 | if (setupBlock != nil) { 138 | setupBlock(self.windowRepresentationLayer); 139 | } 140 | 141 | [CATransaction commit]; 142 | 143 | [self.fullScreenWindow makeKeyAndOrderFront:nil]; 144 | 145 | // Effectively hide the original window. If we are ordering in, the window will become visible again once 146 | // the fake window is destroyed. 147 | self.alphaValue = 0.f; 148 | } 149 | 150 | - (NSImage *)imageRepresentationOffscreen:(BOOL)forceOffscreen { 151 | CGRect originalWindowFrame = self.frame; 152 | BOOL onScreen = self.isVisible; 153 | //CGFloat alpha = self.alphaValue; 154 | 155 | if (!onScreen || forceOffscreen) { 156 | // So the window is closed, and we need to get a screenshot of it without flashing. 157 | // First, we find the frame that covers all the connected screens. 158 | CGRect allWindowsFrame = CGRectZero; 159 | 160 | for(NSScreen *screen in [NSScreen screens]) { 161 | allWindowsFrame = NSUnionRect(allWindowsFrame, screen.frame); 162 | } 163 | 164 | // Position our window to the very right-most corner out of visible range, plus padding for the shadow. 165 | CGRect frame = (CGRect){ 166 | .origin = CGPointMake(CGRectGetWidth(allWindowsFrame) + 2*JNWAnimatableWindowShadowRadius, 0), 167 | .size = originalWindowFrame.size 168 | }; 169 | 170 | // This is where things get nasty. Against what the documentation states, windows seem to be constrained 171 | // to the screen, so we override `constrainFrameRect:toScreen:` to return the original frame, which allows 172 | // us to put the window off-screen. 173 | _disableConstrainedWindow = YES; 174 | 175 | self.alphaValue = 0.f; 176 | if (!onScreen) 177 | [super makeKeyAndOrderFront:nil]; 178 | 179 | [self setFrame:frame display:NO]; 180 | 181 | _disableConstrainedWindow = NO; 182 | } 183 | 184 | // If we are ordering ourself in, we will be off-screen and will not be visible. 185 | self.alphaValue = 1.f; 186 | 187 | // Grab the image representation of the window, without the shadows. 188 | CGImageRef windowImageRef = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, (CGWindowID)self.windowNumber, kCGWindowImageBoundsIgnoreFraming); 189 | 190 | // So there's a problem. As it turns out, CGWindowListCreateImage() returns a CGImageRef 191 | // that apparently is backed by pixels that don't actually exist until they are queried. 192 | // 193 | // This is a significant problem, because what we actually want to do is to grab the image 194 | // from the window, then set its alpha to 0. But if the actual pixels haven't been grabbed 195 | // yet, then by the time we actually use them sometime later in the run loop the alpha of 196 | // the window will have already gone flying off into the distance and we're left with a 197 | // completely transparent image. That's no good. 198 | // 199 | // So here's a workaround. What we're doing is actually forcing the real pixels 200 | // to get copied over from the WindowServer by actually drawing them into another context 201 | // that has settings optimized for use with Core Animation. This isn't too wasteful, and it's 202 | // far better than actually copying over all of the real pixel data. 203 | CGColorSpaceRef colorSpace = CGImageGetColorSpace(windowImageRef); 204 | CGSize imageSize = CGSizeMake(CGImageGetWidth(windowImageRef), CGImageGetHeight(windowImageRef)); 205 | CGContextRef ctx = JNWCreateGraphicsContext(imageSize, colorSpace); 206 | 207 | // Draw the window image into the newly-created context. 208 | CGContextDrawImage(ctx, (CGRect){ .size = imageSize }, windowImageRef); 209 | 210 | CGImageRef copiedWindowImageRef = CGBitmapContextCreateImage(ctx); 211 | NSImage *image = [[NSImage alloc] initWithCGImage:copiedWindowImageRef size:imageSize]; 212 | 213 | CGContextRelease(ctx); 214 | CGImageRelease(windowImageRef); 215 | CGImageRelease(copiedWindowImageRef); 216 | 217 | // If we weren't originally on the screen, there's a good chance we shouldn't be visible yet. 218 | if (!onScreen || forceOffscreen) { 219 | self.alphaValue = 0.f; 220 | } 221 | 222 | // If we moved the window offscreen to get the screenshot, we want to move back to the original frame. 223 | if (!CGRectEqualToRect(originalWindowFrame, self.frame)) { 224 | [self setFrame:originalWindowFrame display:NO]; 225 | } 226 | 227 | return image; 228 | } 229 | 230 | - (CGRect)convertWindowFrameToScreenFrame:(CGRect)windowFrame { 231 | return (CGRect) { 232 | .size = windowFrame.size, 233 | .origin.x = windowFrame.origin.x - self.screen.frame.origin.x, 234 | .origin.y = windowFrame.origin.y - self.screen.frame.origin.y 235 | }; 236 | } 237 | 238 | #pragma mark Graphics context creation 239 | 240 | CGContextRef JNWCreateGraphicsContext(CGSize size, CGColorSpaceRef colorSpace) { 241 | size_t width = size.width; 242 | size_t height = size.height; 243 | size_t bitsPerComponent = 8; 244 | size_t bytesPerRow = 4 * width; 245 | CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst; 246 | CGContextRef ctx = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); 247 | return ctx; 248 | } 249 | 250 | #pragma mark Window Overrides 251 | 252 | - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { 253 | return (_disableConstrainedWindow ? frameRect : [super constrainFrameRect:frameRect toScreen:screen]); 254 | } 255 | 256 | #pragma mark Convenince Window Methods 257 | 258 | - (void)orderOutWithDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timing animations:(void (^)(CALayer *))animations { 259 | [self setupIfNeeded]; 260 | 261 | // The fake window is in the exact same position as the real one, so we can safely order ourself out. 262 | [super orderOut:nil]; 263 | [self performAnimations:animations withDuration:duration timing:timing]; 264 | } 265 | 266 | - (void)orderOutWithAnimation:(CAAnimation *)animation { 267 | [self setupIfNeeded]; 268 | 269 | [super orderOut:nil]; 270 | [self performAnimation:animation forKey:@"JNWOrderOut"]; 271 | } 272 | 273 | - (void)makeKeyAndOrderFrontWithDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timing 274 | setup:(void (^)(CALayer *))setup animations:(void (^)(CALayer *))animations { 275 | [self setupIfNeededWithSetupBlock:setup]; 276 | 277 | // Avoid unnecessary layout passes if we're already visible when this method is called. This could take place if the window 278 | // is still being animated out, but the user suddenly changes their mind and the window needs to come back on screen again. 279 | if (!self.isVisible) 280 | [super makeKeyAndOrderFront:nil]; 281 | 282 | [self performAnimations:animations withDuration:duration timing:timing]; 283 | } 284 | 285 | - (void)makeKeyAndOrderFrontWithAnimation:(CAAnimation *)animation initialOpacity:(CGFloat)opacity { 286 | [self setupIfNeededWithSetupBlock:^(CALayer *layer) { 287 | layer.opacity = opacity; 288 | }]; 289 | 290 | if (!self.isVisible) 291 | [super makeKeyAndOrderFront:nil]; 292 | 293 | [self performAnimation:animation forKey:@"JNWMakeKeyAndOrderFront"]; 294 | } 295 | 296 | - (void)setFrame:(NSRect)frameRect withDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timing { 297 | [self setupIfNeeded]; 298 | 299 | [super setFrame:frameRect display:YES animate:NO]; 300 | 301 | // We need to explicitly animate the shadow path to reflect the new size. 302 | CGPathRef shadowPath = CGPathCreateWithRect(self.shadowRect, NULL); 303 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"shadowPath"]; 304 | animation.fromValue = (id)self.windowRepresentationLayer.shadowPath; 305 | animation.toValue = (__bridge id)(shadowPath); 306 | animation.duration = duration; 307 | animation.timingFunction = timing?:[CAMediaTimingFunction functionWithName:JNWAnimatableWindowDefaultAnimationCurve]; 308 | [self.windowRepresentationLayer addAnimation:animation forKey:@"shadowPath"]; 309 | self.windowRepresentationLayer.shadowPath = shadowPath; 310 | CGPathRelease(shadowPath); 311 | 312 | NSImage *finalState = [self imageRepresentationOffscreen:YES]; 313 | [self performAnimations:^(CALayer *layer) { 314 | self.windowRepresentationLayer.frame = [self convertWindowFrameToScreenFrame:frameRect]; 315 | self.windowRepresentationLayer.contents = finalState; 316 | } withDuration:duration timing:timing]; 317 | } 318 | 319 | - (void)performAnimations:(void (^)(CALayer *layer))animations withDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timing { 320 | [NSAnimationContext beginGrouping]; 321 | 322 | [CATransaction begin]; 323 | [CATransaction setAnimationDuration:duration]; 324 | [CATransaction setAnimationTimingFunction:timing?:[CAMediaTimingFunction functionWithName:JNWAnimatableWindowDefaultAnimationCurve]]; 325 | [CATransaction setCompletionBlock:^{ 326 | [self destroyTransformingWindowIfNeeded]; 327 | }]; 328 | 329 | animations(self.windowRepresentationLayer); 330 | JNWAnimatableWindowOpenTransactions++; 331 | 332 | [CATransaction commit]; 333 | [NSAnimationContext endGrouping]; 334 | } 335 | 336 | - (void)performAnimation:(CAAnimation *)animation forKey:(NSString *)key { 337 | animation.delegate = self; 338 | animation.removedOnCompletion = NO; 339 | [self.windowRepresentationLayer addAnimation:animation forKey:key]; 340 | JNWAnimatableWindowOpenTransactions++; 341 | } 342 | 343 | // Called when the window is animated using CAAnimations. 344 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 345 | [self destroyTransformingWindowIfNeeded]; 346 | } 347 | 348 | #pragma mark Lifecycle 349 | 350 | // Calls `-destroyTransformingWindow` only when the running animation count is zero. 351 | - (void)destroyTransformingWindowIfNeeded { 352 | JNWAnimatableWindowOpenTransactions--; 353 | 354 | // If there are zero pending operations remaining, we can safely assume that it is time for the window to be destroyed. 355 | if (JNWAnimatableWindowOpenTransactions == 0) { 356 | [self destroyTransformingWindow]; 357 | } 358 | } 359 | 360 | // Called when the ordering methods are complete. If the layer is used 361 | // manually, this should be called when animations are complete. 362 | - (void)destroyTransformingWindow { 363 | self.alphaValue = 1.f; 364 | 365 | [self.windowRepresentationLayer removeFromSuperlayer]; 366 | self.windowRepresentationLayer.contents = nil; 367 | self.windowRepresentationLayer = nil; 368 | 369 | [self.fullScreenWindow orderOut:nil]; 370 | self.fullScreenWindow = nil; 371 | } 372 | 373 | @end 374 | 375 | @implementation JNWAnimatableWindowContentView 376 | 377 | - (id)initWithFrame:(NSRect)frameRect { 378 | self = [super initWithFrame:frameRect]; 379 | if (self == nil) return nil; 380 | 381 | // Make the content view a layer-hosting view, so we can safely add sublayers instead of subviews. 382 | self.layer = [CALayer layer]; 383 | self.wantsLayer = YES; 384 | self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawNever; 385 | 386 | return self; 387 | } 388 | 389 | @end 390 | -------------------------------------------------------------------------------- /Sources/JNWAnimatableWindow/include/JNWAnimatableWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013, Jonathan Willing. All rights reserved. 3 | Licensed under the MIT license 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 8 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 15 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 16 | IN THE SOFTWARE. 17 | */ 18 | 19 | 20 | @import Cocoa; 21 | @import QuartzCore; 22 | 23 | /// Allows for an extremely flexible manipulation of a static representation of the window. 24 | /// 25 | /// Since it uses a visual representation of the window, the window cannot be interacted with 26 | /// while a transform is applied, nor is it automatically updated to reflect the window's state. 27 | @interface JNWAnimatableWindow : NSWindow 28 | 29 | /// This layer can be transformed as much as desired. As soon as the property is first used an image 30 | /// representation of the current window's state will be grabbed and used for the layer's contents. 31 | /// 32 | /// Because it is a static image, it will not reflect the state of the window if it changes. 33 | /// If the window needs to change content while still having a transformed state, 34 | /// call `-updateImageRepresentation` to update the backing image. 35 | /// 36 | /// Important note: This layer is optimized with a shadow path. If you need to change the bounds 37 | /// or the size of the layer, you will need to update the shadow path yourself to reflect this change. 38 | @property (nonatomic, assign, readonly) CALayer *layer; 39 | 40 | /// Destroys the layer and fake window. Only necessary for use if the layer is animated manually. 41 | /// If the convenience methods are used below, calling this is not necessary as it is done automatically. 42 | - (void)destroyTransformingWindow; 43 | 44 | /// Order a window out with an animation. The `animations` block is wrapped in a `CATransaction`, so implicit 45 | /// animations will be enabled. Pass in nil for the timing function to default to ease-in-out. 46 | /// 47 | /// The layer and the extra window will be destroyed automatically after the animation completes. 48 | - (void)orderOutWithDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timingFunction 49 | animations:(void (^)(CALayer *windowLayer))animations; 50 | 51 | /// Order a window out with an animation, automatically cleaning up after completion. 52 | /// 53 | /// The delegate of the animation will be changed. 54 | - (void)orderOutWithAnimation:(CAAnimation *)animation; 55 | 56 | /// Make a window key and visible with an animation. The setup block will be performed with implicit animations 57 | /// disabled, so it is an ideal time to set the initial state for your animation. The `animations` block is wrapped 58 | /// in a `CATransaction`, so implicit animations will be enabled. Pass in nil for the timing function to default to ease-in-out. 59 | /// 60 | /// The layer and the extra window will be destroyed automatically after the animation completes. 61 | - (void)makeKeyAndOrderFrontWithDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timingFunction 62 | setup:(void (^)(CALayer *windowLayer))setup animations:(void (^)(CALayer *layer))animations; 63 | 64 | /// Make a window key and visible with an animation, automatically cleaning up after completion. 65 | /// 66 | /// The delegate of the animation will be changed. 67 | /// 68 | /// The opacity of the layer will be set to the passed in opacity before it is shown. 69 | - (void)makeKeyAndOrderFrontWithAnimation:(CAAnimation *)animation initialOpacity:(CGFloat)opacity; 70 | 71 | /// Sets the window to the frame specified using a layer The animation behavior is the same as 72 | /// NSWindow's full-screen animation, which cross-fades between the initial and final state images. 73 | /// 74 | /// The layer and the extra window will be destroyed automatically after the animation completes. 75 | - (void)setFrame:(NSRect)frameRect withDuration:(CFTimeInterval)duration timing:(CAMediaTimingFunction *)timing; 76 | 77 | @end 78 | --------------------------------------------------------------------------------