diff --git a/source/Icons.xcodeproj/project.pbxproj b/source/Icons.xcodeproj/project.pbxproj new file mode 100644 index 0000000..df8a546 --- /dev/null +++ b/source/Icons.xcodeproj/project.pbxproj @@ -0,0 +1,333 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + ADFBC31F1D15E1E400A5011F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ADFBC31E1D15E1E400A5011F /* AppDelegate.m */; }; + ADFBC3221D15E1E400A5011F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ADFBC3211D15E1E400A5011F /* main.m */; }; + ADFBC3241D15E1E400A5011F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ADFBC3231D15E1E400A5011F /* Assets.xcassets */; }; + ADFBC3271D15E1E400A5011F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = ADFBC3251D15E1E400A5011F /* MainMenu.xib */; }; + ADFBC3301D15E75000A5011F /* MTDragDropView.m in Sources */ = {isa = PBXBuildFile; fileRef = ADFBC32F1D15E75000A5011F /* MTDragDropView.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + AD2A39E31E5F2BA500A68CA5 /* Icons.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Icons.entitlements; sourceTree = ""; }; + ADFBC31A1D15E1E400A5011F /* Icons.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Icons.app; sourceTree = BUILT_PRODUCTS_DIR; }; + ADFBC31D1D15E1E400A5011F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + ADFBC31E1D15E1E400A5011F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + ADFBC3211D15E1E400A5011F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + ADFBC3231D15E1E400A5011F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + ADFBC3261D15E1E400A5011F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + ADFBC3281D15E1E400A5011F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + ADFBC32E1D15E75000A5011F /* MTDragDropView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTDragDropView.h; sourceTree = ""; }; + ADFBC32F1D15E75000A5011F /* MTDragDropView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTDragDropView.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + ADFBC3171D15E1E400A5011F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + ADFBC3111D15E1E400A5011F = { + isa = PBXGroup; + children = ( + ADFBC31C1D15E1E400A5011F /* Icons */, + ADFBC31B1D15E1E400A5011F /* Products */, + ); + sourceTree = ""; + }; + ADFBC31B1D15E1E400A5011F /* Products */ = { + isa = PBXGroup; + children = ( + ADFBC31A1D15E1E400A5011F /* Icons.app */, + ); + name = Products; + sourceTree = ""; + }; + ADFBC31C1D15E1E400A5011F /* Icons */ = { + isa = PBXGroup; + children = ( + AD2A39E31E5F2BA500A68CA5 /* Icons.entitlements */, + ADFBC31D1D15E1E400A5011F /* AppDelegate.h */, + ADFBC31E1D15E1E400A5011F /* AppDelegate.m */, + ADFBC3231D15E1E400A5011F /* Assets.xcassets */, + ADFBC3251D15E1E400A5011F /* MainMenu.xib */, + ADFBC32E1D15E75000A5011F /* MTDragDropView.h */, + ADFBC32F1D15E75000A5011F /* MTDragDropView.m */, + ADFBC3281D15E1E400A5011F /* Info.plist */, + ADFBC3201D15E1E400A5011F /* Supporting Files */, + ); + path = Icons; + sourceTree = ""; + }; + ADFBC3201D15E1E400A5011F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ADFBC3211D15E1E400A5011F /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + ADFBC3191D15E1E400A5011F /* Icons */ = { + isa = PBXNativeTarget; + buildConfigurationList = ADFBC32B1D15E1E400A5011F /* Build configuration list for PBXNativeTarget "Icons" */; + buildPhases = ( + ADFBC3161D15E1E400A5011F /* Sources */, + ADFBC3171D15E1E400A5011F /* Frameworks */, + ADFBC3181D15E1E400A5011F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Icons; + productName = "Casper Icon Creator"; + productReference = ADFBC31A1D15E1E400A5011F /* Icons.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + ADFBC3121D15E1E400A5011F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0900; + ORGANIZATIONNAME = "SAP SE"; + TargetAttributes = { + ADFBC3191D15E1E400A5011F = { + CreatedOnToolsVersion = 7.3.1; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + }; + }; + buildConfigurationList = ADFBC3151D15E1E400A5011F /* Build configuration list for PBXProject "Icons" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = ADFBC3111D15E1E400A5011F; + productRefGroup = ADFBC31B1D15E1E400A5011F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + ADFBC3191D15E1E400A5011F /* Icons */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + ADFBC3181D15E1E400A5011F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ADFBC3241D15E1E400A5011F /* Assets.xcassets in Resources */, + ADFBC3271D15E1E400A5011F /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + ADFBC3161D15E1E400A5011F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ADFBC3221D15E1E400A5011F /* main.m in Sources */, + ADFBC31F1D15E1E400A5011F /* AppDelegate.m in Sources */, + ADFBC3301D15E75000A5011F /* MTDragDropView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + ADFBC3251D15E1E400A5011F /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + ADFBC3261D15E1E400A5011F /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + ADFBC3291D15E1E400A5011F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + ADFBC32A1D15E1E400A5011F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + ADFBC32C1D15E1E400A5011F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Icons/Icons.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Icons/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = corp.sap.Icons; + PRODUCT_NAME = Icons; + PROVISIONING_PROFILE_SPECIFIER = ""; + }; + name = Debug; + }; + ADFBC32D1D15E1E400A5011F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Icons/Icons.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Icons/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = corp.sap.Icons; + PRODUCT_NAME = Icons; + PROVISIONING_PROFILE_SPECIFIER = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + ADFBC3151D15E1E400A5011F /* Build configuration list for PBXProject "Icons" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ADFBC3291D15E1E400A5011F /* Debug */, + ADFBC32A1D15E1E400A5011F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + ADFBC32B1D15E1E400A5011F /* Build configuration list for PBXNativeTarget "Icons" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ADFBC32C1D15E1E400A5011F /* Debug */, + ADFBC32D1D15E1E400A5011F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = ADFBC3121D15E1E400A5011F /* Project object */; +} diff --git a/source/Icons.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/source/Icons.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..8acb41b --- /dev/null +++ b/source/Icons.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/source/Icons.xcodeproj/project.xcworkspace/xcuserdata/d065182.xcuserdatad/UserInterfaceState.xcuserstate b/source/Icons.xcodeproj/project.xcworkspace/xcuserdata/d065182.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..7890a74 Binary files /dev/null and b/source/Icons.xcodeproj/project.xcworkspace/xcuserdata/d065182.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcschemes/Icons.xcscheme b/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcschemes/Icons.xcscheme new file mode 100644 index 0000000..c586d37 --- /dev/null +++ b/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcschemes/Icons.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcschemes/xcschememanagement.plist b/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c185ce3 --- /dev/null +++ b/source/Icons.xcodeproj/xcuserdata/d065182.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + Icons.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + ADFBC3191D15E1E400A5011F + + primary + + + + + diff --git a/source/Icons/AppDelegate.h b/source/Icons/AppDelegate.h new file mode 100644 index 0000000..f15778a --- /dev/null +++ b/source/Icons/AppDelegate.h @@ -0,0 +1,24 @@ +/* + AppDelegate.h + Copyright 2016-2017 SAP SE + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import +#import + +@interface AppDelegate : NSObject + +@end + diff --git a/source/Icons/AppDelegate.m b/source/Icons/AppDelegate.m new file mode 100644 index 0000000..b4f3edf --- /dev/null +++ b/source/Icons/AppDelegate.m @@ -0,0 +1,336 @@ +/* + AppDelegate.m + Copyright 2016-2017 SAP SE + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "AppDelegate.h" +#import "MTDragDropView.h" + +@interface AppDelegate () +@property (weak) IBOutlet NSWindow *window; +@property (weak) IBOutlet MTDragDropView *dragDropView; +@property (weak) IBOutlet NSImageView *processedImageView; +@property (weak) IBOutlet NSPopUpButton *imageSizesMenu; + +@property (nonatomic, strong, readwrite) NSArray *imageSizes; +@property (nonatomic, assign) NSInteger imageOutputSize; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + // fill the popup menu + self.imageSizes = [[NSArray alloc] initWithObjects: + [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:64], @"value", @"64 x 64 pixels", @"name", nil], + [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:128], @"value", @"128 x 128 pixels", @"name", nil], + [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:256], @"value", @"256 x 256 pixels", @"name", nil], + [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:512], @"value", @"512 x 512 pixels", @"name", nil], + nil]; + + // define the standard output size + _imageOutputSize = 128; + + // get the currently selected size or set the standard size + if ([[NSUserDefaults standardUserDefaults] objectForKey:@"imageSize"]) { + _imageOutputSize = [[[NSUserDefaults standardUserDefaults] objectForKey:@"imageSize"] integerValue]; + } else { + [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInteger:_imageOutputSize] forKey:@"imageSize"]; + } + + // select the correct value in the popup menu + NSUInteger sizeIndex = [self.imageSizes indexOfObjectPassingTest:^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop) + { + return [[dict objectForKey:@"value"] isEqual:[NSNumber numberWithInteger:_imageOutputSize]]; + }]; + if (sizeIndex != NSNotFound) { [_imageSizesMenu selectItemAtIndex:sizeIndex]; } + + // restore the window position + NSString *windowPosition = [[NSUserDefaults standardUserDefaults] objectForKey:@"WindowPosition"]; + + if (windowPosition) { + [_window setFrameFromString:windowPosition]; + } else { + [_window center]; + } + + // show up the main window + [_window makeKeyAndOrderFront:self]; + + // add an observer to the main window to save position and size changes to the prefs + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateUserDefaults:) name:NSWindowDidResizeNotification object:_window]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateUserDefaults:) name:NSWindowDidMoveNotification object:_window]; + + // observe our drop view for image changes + [_dragDropView addObserver:self forKeyPath:@"image" options:0 context:nil]; +} + +- (void) observeValueForKeyPath:(NSString *)path ofObject:(id) object change:(NSDictionary *) change context:(void *)context +{ + if (object == _dragDropView && [path isEqualToString:@"image"]) { + + // create the uninstall image + NSImage *originalImage = [[_dragDropView image] copy]; + NSSize imageSize = [originalImage size]; + + float boxDiameter = imageSize.height * .23; + NSImage *removeOverlay = [self getCloseBoxWithDiameter:boxDiameter]; + + // we scale the new image a bit down to make sure our close box is a bit outside the icon + NSImage *sizedImage = [[NSImage alloc] initWithSize:imageSize]; + [sizedImage lockFocus]; + [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; + [originalImage drawInRect:NSMakeRect(imageSize.width * .04, 0, imageSize.width * .96, imageSize.height * .96) + fromRect:NSMakeRect(0, 0, originalImage.size.width, originalImage.size.height) + operation:NSCompositeCopy + fraction:1.0]; + + [removeOverlay drawAtPoint:NSMakePoint(0, imageSize.height - boxDiameter) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + [sizedImage unlockFocus]; + [_processedImageView setImage:sizedImage]; + + // let the icon shake once + [_processedImageView setWantsLayer:YES]; + [[_processedImageView layer] addAnimation:[self shakeIcon] forKey:@"transform.rotation.z"]; + } +} + +- (IBAction)popupButtonPressed:(id)sender +{ + // update the preference file for the selected timeout + NSInteger selectedIndex = [sender indexOfSelectedItem]; + NSDictionary *sizeDict = [self.imageSizes objectAtIndex:selectedIndex]; + NSInteger imageSize = [[sizeDict valueForKey:@"value"] integerValue]; + + if (imageSize > 0) { + [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInteger:imageSize] forKey:@"imageSize"]; + _imageOutputSize = imageSize; + } +} + +- (NSImage*)getCloseBoxWithDiameter:(float)diameter +{ + NSImage *newImage = [[NSImage alloc] initWithSize:NSMakeSize(diameter, diameter)]; + [newImage lockFocus]; + [NSGraphicsContext saveGraphicsState]; + + // define the shadow + float shadowSize = diameter * .03; + float shadowBlurRadius = shadowSize; + NSShadow *theShadow = [[NSShadow alloc] init]; + [theShadow setShadowOffset:NSMakeSize(shadowSize, -shadowSize)]; + [theShadow setShadowBlurRadius:shadowBlurRadius]; + [theShadow setShadowColor:[[NSColor blackColor] colorWithAlphaComponent:0.3]]; + [theShadow set]; + + // draw the outer white circle + NSBezierPath *circlePath = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(0, shadowSize, diameter - shadowSize - shadowBlurRadius, diameter - shadowSize - shadowBlurRadius)]; + [[NSColor whiteColor] setFill]; + [circlePath fill]; + + [NSGraphicsContext restoreGraphicsState]; + + // draw the inner black circle + float lineWith = diameter * .17; + NSRect innerCircleRect = NSMakeRect(lineWith/2, lineWith/2 + shadowSize, diameter - lineWith - shadowSize - shadowBlurRadius, diameter - lineWith - shadowSize - shadowBlurRadius); + circlePath = [NSBezierPath bezierPathWithOvalInRect:innerCircleRect]; + [[NSColor blackColor] setFill]; + [circlePath fill]; + + // draw the crossing lines + NSBezierPath *linePath = [NSBezierPath bezierPath]; + [linePath setLineWidth:lineWith/2]; + lineWith = lineWith * 1.3; + [[NSColor whiteColor] setStroke]; + [linePath moveToPoint:NSMakePoint(innerCircleRect.origin.x + lineWith, innerCircleRect.origin.y + lineWith)]; + [linePath lineToPoint:NSMakePoint(innerCircleRect.origin.x + innerCircleRect.size.width - lineWith, innerCircleRect.origin.y + innerCircleRect.size.height - lineWith)]; + [linePath stroke]; + + [linePath moveToPoint:NSMakePoint(innerCircleRect.origin.x + lineWith, innerCircleRect.origin.y + innerCircleRect.size.height - lineWith)]; + [linePath lineToPoint:NSMakePoint(innerCircleRect.origin.x + innerCircleRect.size.width - lineWith, innerCircleRect.origin.y + lineWith)]; + [linePath stroke]; + + [newImage unlockFocus]; + + return newImage; +} + +- (CAKeyframeAnimation*)shakeIcon +{ + // animate the icon as the user knows it from Apple's launchpad + CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; + [animation setDuration:.2]; + [animation setRepeatCount:1]; + [animation setDelegate:self]; + + // define the rotation + NSArray *values = [NSArray arrayWithObjects: + [NSNumber numberWithFloat:(-2.0 / 180.0) * M_PI], + [NSNumber numberWithFloat:(2.0 / 180.0) * M_PI], + [NSNumber numberWithFloat:(-2.0 / 180.0) * M_PI], + nil]; + [animation setValues:values]; + + return animation; +} + +- (NSImage*)rotateImage:(NSImage*)sourceImage byDegrees:(CGFloat)degrees +{ + NSSize imageSize = [sourceImage size]; + NSImage *rotatedImage = [[NSImage alloc] initWithSize:imageSize]; + + [rotatedImage lockFocus]; + [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; + NSAffineTransform *rotateTF = [NSAffineTransform transform]; + + // rotate from center + NSPoint centerPoint = NSMakePoint(imageSize.width/2, imageSize.height/2); + [rotateTF translateXBy:centerPoint.x yBy:centerPoint.y]; + [rotateTF rotateByDegrees:degrees]; + [rotateTF translateXBy:-centerPoint.x yBy:-centerPoint.y]; + [rotateTF concat]; + + [sourceImage drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, imageSize.width, imageSize.height) operation:NSCompositeSourceOver + fraction:1.0]; + [rotatedImage unlockFocus]; + + return rotatedImage; +} + +- (NSImage*)scaleImage:(NSImage*)sourceImage to:(NSSize)newSize +{ + NSImage *sizedImage = [[NSImage alloc] initWithSize:newSize]; + [sizedImage lockFocus]; + [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; + [sourceImage drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height) + fromRect:NSMakeRect(0, 0, sourceImage.size.width, sourceImage.size.height) + operation:NSCompositeCopy + fraction:1.0]; + [sizedImage unlockFocus]; + + return sizedImage; +} + +- (IBAction)saveFiles:(id)sender +{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setCanChooseFiles:NO]; + [panel setCanChooseDirectories:YES]; + [panel setAllowsMultipleSelection:NO]; + [panel setCanCreateDirectories:YES]; + [panel setPrompt:@"Choose"]; + [panel beginSheetModalForWindow:_window completionHandler:^(NSInteger result) { + + if (result == NSFileHandlingPanelOKButton) { + + // create a date string for the folder + NSDateFormatter *dateformate = [[NSDateFormatter alloc] init]; + [dateformate setDateFormat:@"yyyy-MM-dd HH-mm-ss"]; + NSString *dateString = [dateformate stringFromDate:[NSDate date]]; + + NSString *folderParentPath = [[[panel URLs] firstObject] path]; + NSString *folderPath = [folderParentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"icons_%@", dateString]]; + + // create a new subfolder + BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:folderPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + if (success) { + + // scale and save the install image + NSImage *installImage = [_dragDropView image]; + installImage = [self scaleImage:installImage to:NSMakeSize(_imageOutputSize, _imageOutputSize)]; + NSData *imageData = [installImage TIFFRepresentation]; + NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData]; + NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:NSImageInterlaced]; + imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps]; + [imageData writeToFile:[folderPath stringByAppendingPathComponent:@"install.png"] atomically:YES]; + + // scale and save the uninstall image + NSImage *uninstallImage = [_processedImageView image]; + uninstallImage = [self scaleImage:uninstallImage to:NSMakeSize(_imageOutputSize, _imageOutputSize)]; + imageData = [uninstallImage TIFFRepresentation]; + imageRep = [NSBitmapImageRep imageRepWithData:imageData]; + imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps]; + [imageData writeToFile:[folderPath stringByAppendingPathComponent:@"uninstall.png"] atomically:YES]; + + // create and save the animated uninstall image + + // define an infinite loop + NSDictionary *fileProperties = [NSDictionary dictionaryWithObject: + [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:0], (__bridge id)kCGImagePropertyAPNGLoopCount, + nil] forKey:(__bridge id)kCGImagePropertyPNGDictionary]; + + // define the delay between the frames + NSDictionary *frameProperties = [NSDictionary dictionaryWithObject: + [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithFloat:.03], (__bridge id)kCGImagePropertyAPNGDelayTime, + nil] forKey:(__bridge id)kCGImagePropertyPNGDictionary]; + + NSURL *fileURL = [[NSURL fileURLWithPath:folderPath] URLByAppendingPathComponent:@"uninstall_animated.png"]; + + // define the actual animation + NSArray *rotationPath = [NSArray arrayWithObjects: + [NSNumber numberWithInt:0], + [NSNumber numberWithInt:-1], + [NSNumber numberWithInt:-2], + [NSNumber numberWithInt:-1], + [NSNumber numberWithInt:0], + [NSNumber numberWithInt:1], + [NSNumber numberWithInt:2], + [NSNumber numberWithInt:1], nil]; + + CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypePNG, [rotationPath count], (__bridge CFDictionaryRef)fileProperties); + CGImageDestinationSetProperties(imageDestination, NULL); + + for (NSNumber *degrees in rotationPath) { + NSImage *rotatedImage = [self rotateImage:uninstallImage byDegrees:[degrees intValue]]; + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)[rotatedImage TIFFRepresentation], NULL); + CGImageDestinationAddImage(imageDestination, CGImageSourceCreateImageAtIndex(imageSource, 0, NULL), (__bridge CFDictionaryRef)frameProperties); + } + + if (!CGImageDestinationFinalize(imageDestination)) { NSLog(@"Failed to write image"); } + CFRelease(imageDestination); + + } + } + + }]; + +} + +- (void)updateUserDefaults:(NSNotification*)aNotification +{ + // update user prefs + if ([[aNotification object] isKindOfClass:[NSWindow class]]) { + [[NSUserDefaults standardUserDefaults] setValue:[_window stringWithSavedFrame] forKey:@"WindowPosition"]; + } +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + + // remove our observers + [_dragDropView removeObserver:self forKeyPath:@"image"]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender +{ + return YES; +} + +@end diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/Contents.json b/source/Icons/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..3b21538 --- /dev/null +++ b/source/Icons/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icons-16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icons-32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icons-32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icons-64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icons-128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icons-256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icons-256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icons-512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icons-512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icons-1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-1024.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-1024.png new file mode 100644 index 0000000..e615281 Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-1024.png differ diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-128.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-128.png new file mode 100644 index 0000000..3a1a215 Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-128.png differ diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-16.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-16.png new file mode 100644 index 0000000..bde2474 Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-16.png differ diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-256.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-256.png new file mode 100644 index 0000000..0f0f4ee Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-256.png differ diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-32.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-32.png new file mode 100644 index 0000000..a88fbaa Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-32.png differ diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-512.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-512.png new file mode 100644 index 0000000..4601d90 Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-512.png differ diff --git a/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-64.png b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-64.png new file mode 100644 index 0000000..730f718 Binary files /dev/null and b/source/Icons/Assets.xcassets/AppIcon.appiconset/icons-64.png differ diff --git a/source/Icons/Base.lproj/MainMenu.xib b/source/Icons/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..1c5fc23 --- /dev/null +++ b/source/Icons/Base.lproj/MainMenu.xib @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIsNotNil + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/Icons/Icons.entitlements b/source/Icons/Icons.entitlements new file mode 100644 index 0000000..19afff1 --- /dev/null +++ b/source/Icons/Icons.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-write + + + diff --git a/source/Icons/Info.plist b/source/Icons/Info.plist new file mode 100644 index 0000000..f0f53cc --- /dev/null +++ b/source/Icons/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.1 + CFBundleSignature + ???? + CFBundleVersion + 45 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016-2017 SAP SE. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/source/Icons/MTDragDropView.h b/source/Icons/MTDragDropView.h new file mode 100644 index 0000000..938e39f --- /dev/null +++ b/source/Icons/MTDragDropView.h @@ -0,0 +1,24 @@ +/* + MTDragDropView.h + Copyright 2016-2017 SAP SE + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import + +@interface MTDragDropView : NSImageView + +- (id)initWithCoder:(NSCoder *)coder; + +@end diff --git a/source/Icons/MTDragDropView.m b/source/Icons/MTDragDropView.m new file mode 100644 index 0000000..07d1463 --- /dev/null +++ b/source/Icons/MTDragDropView.m @@ -0,0 +1,103 @@ +/* + MTDragDropView.m + Copyright 2016-2017 SAP SE + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import "MTDragDropView.h" + +@interface MTDragDropView () +@property (nonatomic, assign) BOOL highlight; +@end + +@implementation MTDragDropView + +- (id)initWithCoder:(NSCoder*)coder +{ + self = [super initWithCoder:coder]; + + if (self) { + [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; + } + + return self; +} + +- (NSDragOperation)draggingEntered:(id )sender +{ + _highlight = YES; + [self setNeedsDisplay: YES]; + return NSDragOperationCopy; +} + +- (void)draggingExited:(id )sender +{ + _highlight = NO; + [self setNeedsDisplay: YES]; +} + +- (BOOL)prepareForDragOperation:(id )sender +{ + _highlight = NO; + [self setNeedsDisplay: YES]; + return YES; +} + +- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender +{ + NSArray *draggedFilenames = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType]; + NSString *pathExtension = [[draggedFilenames objectAtIndex:0] pathExtension]; + + if ([pathExtension isEqual:@"app"] || [pathExtension isEqual:@"png"] || [pathExtension isEqual:@"jpg"] || [pathExtension isEqual:@"jpeg"]) { + return YES; + } else { + return NO; + } +} + +- (void)concludeDragOperation:(id )sender +{ + NSArray *draggedFilenames = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType]; + NSString *itemPath = [draggedFilenames firstObject]; + + if ([[itemPath pathExtension] isEqualToString:@"app"]) { + NSBundle *appBundle = [NSBundle bundleWithPath:itemPath]; + NSString *iconName = [appBundle objectForInfoDictionaryKey:@"CFBundleIconFile"]; + iconName = [[iconName componentsSeparatedByString:@"."] firstObject]; + + if (iconName) { itemPath = [appBundle pathForResource:iconName ofType:@"icns"]; } + } + + if (itemPath) { + + NSImage *currentImage = [[NSImage alloc] initWithContentsOfFile:itemPath]; + if (currentImage) { [self setImage:currentImage]; } + } +} + +- (void)drawRect:(NSRect)rect +{ + [super drawRect:rect]; + + if (_highlight) { + + NSRect roundedRect = NSMakeRect(rect.origin.x + 3, rect.origin.y + 3, rect.size.width - 6, rect.size.height - 6); + [[[NSColor blackColor] colorWithAlphaComponent:0.3] set]; + [NSBezierPath setDefaultLineWidth:5]; + NSBezierPath *roundedPath = [NSBezierPath bezierPathWithRoundedRect:roundedRect xRadius:5 yRadius:5]; + [roundedPath fill]; + } +} + +@end diff --git a/source/Icons/main.m b/source/Icons/main.m new file mode 100644 index 0000000..bd01cab --- /dev/null +++ b/source/Icons/main.m @@ -0,0 +1,22 @@ +/* + main.m + Copyright 2016-2017 SAP SE + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +}