From da455533cb9eb077ddab073103e9702dff4943ae Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Fri, 20 Mar 2015 22:25:56 +0200 Subject: [PATCH 01/11] Changes screenshots loading approach. (loads images only in visible cells) --- Alcatraz.xcodeproj/project.pbxproj | 6 ++ .../Controllers/ATZPackageTableViewDelegate.h | 3 + .../Controllers/ATZPackageTableViewDelegate.m | 69 +++++++------------ .../Controllers/ATZPluginWindowController.m | 42 ++++++++--- Alcatraz/Helpers/ATZScreenshotsStorage.h | 21 ++++++ Alcatraz/Helpers/ATZScreenshotsStorage.m | 53 ++++++++++++++ Alcatraz/Views/ATZPackageListTableCellView.h | 2 + 7 files changed, 139 insertions(+), 57 deletions(-) create mode 100644 Alcatraz/Helpers/ATZScreenshotsStorage.h create mode 100644 Alcatraz/Helpers/ATZScreenshotsStorage.m diff --git a/Alcatraz.xcodeproj/project.pbxproj b/Alcatraz.xcodeproj/project.pbxproj index f45dda2..237849c 100644 --- a/Alcatraz.xcodeproj/project.pbxproj +++ b/Alcatraz.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 0C7AF650186B4E890064EE7B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C7AF64F186B4E890064EE7B /* QuartzCore.framework */; }; 32BDEBC3173A46A900513A7C /* eye_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 32BDEBC2173A46A900513A7C /* eye_icon.png */; }; 32D86505173A4555009C724B /* eye_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 32D86503173A4555009C724B /* eye_icon@2x.png */; }; + 636C388F1ABCB1B7004DECCF /* ATZScreenshotsStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 636C388E1ABCB1B7004DECCF /* ATZScreenshotsStorage.m */; }; 64C28A5518136FF30025C0B1 /* toolbar_colors.png in Resources */ = {isa = PBXBuildFile; fileRef = 64C28A4918136FF30025C0B1 /* toolbar_colors.png */; }; 64C28A5618136FF30025C0B1 /* toolbar_colors@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 64C28A4A18136FF30025C0B1 /* toolbar_colors@2x.png */; }; 64C28A5918136FF30025C0B1 /* toolbar_plugins.png in Resources */ = {isa = PBXBuildFile; fileRef = 64C28A4D18136FF30025C0B1 /* toolbar_plugins.png */; }; @@ -83,6 +84,8 @@ 0C7AF64F186B4E890064EE7B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 32BDEBC2173A46A900513A7C /* eye_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = eye_icon.png; sourceTree = ""; }; 32D86503173A4555009C724B /* eye_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "eye_icon@2x.png"; sourceTree = ""; }; + 636C388D1ABCB1B7004DECCF /* ATZScreenshotsStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZScreenshotsStorage.h; sourceTree = ""; }; + 636C388E1ABCB1B7004DECCF /* ATZScreenshotsStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATZScreenshotsStorage.m; sourceTree = ""; }; 6449530218CE826C009494BD /* ATZVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZVersion.h; sourceTree = ""; }; 64C28A4918136FF30025C0B1 /* toolbar_colors.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = toolbar_colors.png; sourceTree = ""; }; 64C28A4A18136FF30025C0B1 /* toolbar_colors@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "toolbar_colors@2x.png"; sourceTree = ""; }; @@ -353,6 +356,8 @@ 8917DA171726B63B00F0B2D2 /* ATZShell.m */, 89B4F2BC172FF5AC001FD2E3 /* ATZPBXProjParser.h */, 89B4F2BD172FF5AC001FD2E3 /* ATZPBXProjParser.m */, + 636C388D1ABCB1B7004DECCF /* ATZScreenshotsStorage.h */, + 636C388E1ABCB1B7004DECCF /* ATZScreenshotsStorage.m */, ); path = Helpers; sourceTree = ""; @@ -509,6 +514,7 @@ 8917D9F31726B4EE00F0B2D2 /* ATZColorScheme.m in Sources */, 8917D9F41726B4EE00F0B2D2 /* ATZFileTemplate.m in Sources */, 8917D9F51726B4EE00F0B2D2 /* ATZPackage.m in Sources */, + 636C388F1ABCB1B7004DECCF /* ATZScreenshotsStorage.m in Sources */, 8917D9F61726B4EE00F0B2D2 /* ATZPlugin.m in Sources */, 8ADC22341A2AD5B800DB7BCA /* ATZPreviewImageButton.m in Sources */, 8917D9F71726B4EE00F0B2D2 /* ATZProjectTemplate.m in Sources */, diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.h b/Alcatraz/Controllers/ATZPackageTableViewDelegate.h index 30b1db2..9d4d705 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.h +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.h @@ -31,4 +31,7 @@ - (void)filterUsingPredicate:(NSPredicate*)predicate; @property (nonatomic, strong, readonly) NSArray* packages; + +- (void)loadImagesForRowsInRange:(NSRange)range inTableView:(NSTableView *)tableView; + @end diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m index 2a03264..35d74c2 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m @@ -32,6 +32,7 @@ #import "ATZColorScheme.h" #import "ATZDownloader.h" #import "NSColor+Alcatraz.h" +#import "ATZScreenshotsStorage.h" @interface ATZPackageTableViewDelegate () @@ -90,18 +91,8 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn BOOL hasImage = package.screenshotPath != nil; [view.previewButton setFullSize:hasImage]; [view.previewButton setHidden:!hasImage]; - if (package.screenshotPath) { - [view.previewButton setImage:[[self class] cachedImageForPackage:package]]; - if (!view.previewButton.image) { - __block NSButton* imageButton = view.previewButton; - [[self class] fetchAndCacheImageForPackage:package progress:NULL completion:^(NSImage *image) { - imageButton.image = image; - [tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]]; - }]; - } - } else { - [view.previewButton setImage:nil]; - } + view.screenshotPath = package.screenshotPath; + view.previewButton.image = nil; ATZFillableButton* installButton = (ATZFillableButton*)view.installButton; [installButton setButtonBorderStyle:ATZFillableButtonTypeInstall]; [installButton setFillRatio:([package isInstalled] ? 100 : 0) animated:NO]; @@ -188,41 +179,27 @@ - (NSImage *)selectionTemplateImageNamed:(NSString *)imageName { return copiedImage; } -#pragma mark - Image Previews - -+ (NSCache *)imageCache { - static NSCache* cache = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - cache = [[NSCache alloc] init]; - }); - return cache; +- (void)loadImagesForRowsInRange:(NSRange)range inTableView:(NSTableView *)tableView { + for (NSInteger row = range.location; row < range.location + range.length; ++row) { + ATZPackageListTableCellView *view = [tableView viewAtColumn:0 row:row makeIfNecessary:NO]; + ATZPackage *package = self.filteredPackages[row]; + + if (package.screenshotPath) { + [view.previewButton setImage:[ATZScreenshotsStorage cachedImageForPackage:package]]; + if (!view.previewButton.image) { + __block NSButton* imageButton = view.previewButton; + [ATZScreenshotsStorage fetchAndCacheImageForPackage:package progress:NULL completion:^(ATZPackage *pkg, NSImage *image) { + if ([view.titleField.stringValue isEqualToString:pkg.name]) { + imageButton.image = image; + [tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]]; + } + }]; + } + } else { + [view.previewButton setImage:nil]; + } + } } -+ (NSImage *)cachedImageForPackage:(ATZPackage*)package { - return [[self imageCache] objectForKey:package.name]; -} - -+ (void)cacheImage:(NSImage *)image forPackage:(ATZPackage *)package { - [[self imageCache] setObject:image forKey:package.name]; -} - -+ (void)fetchAndCacheImageForPackage:(ATZPackage*)package progress:(void(^)(CGFloat))progress completion:(void(^)(NSImage *))completion { - ATZDownloader *downloader = [ATZDownloader new]; - [downloader downloadFileFromPath:package.screenshotPath - progress:progress - completion:^(NSData *responseData, NSError *error) { - if (error) - return; - - NSImage *image = [[NSImage alloc] initWithData:responseData]; - if (!image) - return; - - [self cacheImage:image forPackage:package]; - if (completion) - completion(image); - }]; -} @end diff --git a/Alcatraz/Controllers/ATZPluginWindowController.m b/Alcatraz/Controllers/ATZPluginWindowController.m index 6be8a64..a860fb9 100644 --- a/Alcatraz/Controllers/ATZPluginWindowController.m +++ b/Alcatraz/Controllers/ATZPluginWindowController.m @@ -1,5 +1,5 @@ // PluginWindowController.m -// +// // Copyright (c) 2014 Marin Usalj | supermar.in // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -8,10 +8,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -55,6 +55,10 @@ @interface ATZPluginWindowController () @implementation ATZPluginWindowController +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + - (id)init { @throw [NSException exceptionWithName:@"There's a better initializer" reason:@"Use -initWithNibName:inBundle:" userInfo:nil]; } @@ -73,8 +77,15 @@ - (id)initWithBundle:(NSBundle *)bundle { - (void)windowDidLoad { [super windowDidLoad]; [self addVersionToWindow]; - if ([self.window respondsToSelector:@selector(setTitleVisibility:)]) + + typeof(self) __weak wSelf = self; + [[NSNotificationCenter defaultCenter] addObserverForName:NSScrollViewDidEndLiveScrollNotification object:self.tableView.enclosingScrollView queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + [wSelf loadImagesInVisibleRows]; + }]; + + if ([self.window respondsToSelector:@selector(setTitleVisibility:)]) { self.window.titleVisibility = NSWindowTitleHidden; + } } - (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { @@ -89,7 +100,7 @@ - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentN - (IBAction)installPressed:(ATZFillableButton *)button { ATZPackage *package = [self.tableViewDelegate tableView:self.tableView objectValueForTableColumn:0 row:[self.tableView rowForView:button]]; - + if (package.isInstalled) [self removePackage:package andUpdateControl:button]; else @@ -174,7 +185,6 @@ - (void)reloadTableView { self.tableView.dataSource = self.tableViewDelegate; [self.tableViewDelegate configureTableView:self.tableView]; [self updatePredicate]; - [self.tableView reloadData]; } #pragma mark - Private @@ -209,7 +219,7 @@ - (void)installPackage:(ATZPackage *)package andUpdateControl:(ATZFillableButton - (void)postNotificationForInstalledPackage:(ATZPackage *)package { if (![NSUserNotificationCenter class] || !package.isInstalled) return; - + NSUserNotification *notification = [NSUserNotification new]; notification.title = [NSString stringWithFormat:@"%@ installed", package.type]; NSString *restartText = package.requiresRestart ? @" Please restart Xcode to use it." : @""; @@ -237,6 +247,11 @@ - (void)updatePredicate { [self.tableViewDelegate filterUsingPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]]; [self.tableView reloadData]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // wait next run loop, otherwise there are no rows yet + [self loadImagesInVisibleRows]; + }); } - (void)updatePackages { @@ -250,7 +265,7 @@ - (void)openWebsite:(NSString *)address { } - (void)displayScreenshotWithPath:(NSString *)screenshotPath withTitle:(NSString *)title { - + [self.previewPanel.animator setAlphaValue:0.f]; self.previewPanel.title = title; [self retrieveImageViewForScreenshot:screenshotPath @@ -276,22 +291,27 @@ - (void)displayImage:(NSImage *)image withTitle:(NSString*)title { } - (void)retrieveImageViewForScreenshot:(NSString *)screenshotPath progress:(void (^)(CGFloat))downloadProgress completion:(void (^)(NSImage *))completion { - + ATZDownloader *downloader = [ATZDownloader new]; [downloader downloadFileFromPath:screenshotPath progress:^(CGFloat progress) { downloadProgress(progress); } completion:^(NSData *responseData, NSError *error) { - + NSImage *image = [[NSImage alloc] initWithData:responseData]; completion(image); }]; - + } - (void)addVersionToWindow { self.versionTextField.stringValue = @(ATZ_VERSION); } +- (void)loadImagesInVisibleRows { + NSRange visibleRows = [self.tableView rowsInRect:self.tableView.visibleRect]; + [self.tableViewDelegate loadImagesForRowsInRange:visibleRows inTableView:self.tableView]; +} + @end diff --git a/Alcatraz/Helpers/ATZScreenshotsStorage.h b/Alcatraz/Helpers/ATZScreenshotsStorage.h new file mode 100644 index 0000000..c74daca --- /dev/null +++ b/Alcatraz/Helpers/ATZScreenshotsStorage.h @@ -0,0 +1,21 @@ +// +// ATZScreenshotsStorage.h +// Alcatraz +// +// Created by Alex Antonyuk on 3/20/15. +// Copyright (c) 2015 supermar.in. All rights reserved. +// + +#import + +@class ATZPackage; + +typedef void(^ATZImagesStorageCompletion)(ATZPackage *pkg, NSImage *image); + +@interface ATZScreenshotsStorage : NSObject + ++ (NSImage *)cachedImageForPackage:(ATZPackage*)package; ++ (void)cacheImage:(NSImage *)image forPackage:(ATZPackage *)package; ++ (void)fetchAndCacheImageForPackage:(ATZPackage*)package progress:(void(^)(CGFloat))progress completion:(ATZImagesStorageCompletion)completion; + +@end diff --git a/Alcatraz/Helpers/ATZScreenshotsStorage.m b/Alcatraz/Helpers/ATZScreenshotsStorage.m new file mode 100644 index 0000000..4708c4e --- /dev/null +++ b/Alcatraz/Helpers/ATZScreenshotsStorage.m @@ -0,0 +1,53 @@ +// +// ATZScreenshotsStorage.m +// Alcatraz +// +// Created by Alex Antonyuk on 3/20/15. +// Copyright (c) 2015 supermar.in. All rights reserved. +// + +#import "ATZScreenshotsStorage.h" +#import +#import "ATZDownloader.h" +#import "ATZPackage.h" + +@implementation ATZScreenshotsStorage + +#pragma mark - Image Previews + ++ (NSCache *)imageCache { + static NSCache* cache = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + cache = [[NSCache alloc] init]; + }); + return cache; +} + ++ (NSImage *)cachedImageForPackage:(ATZPackage*)package { + return [[self imageCache] objectForKey:package.name]; +} + ++ (void)cacheImage:(NSImage *)image forPackage:(ATZPackage *)package { + [[self imageCache] setObject:image forKey:package.name]; +} + ++ (void)fetchAndCacheImageForPackage:(ATZPackage*)package progress:(void(^)(CGFloat))progress completion:(ATZImagesStorageCompletion)completion { + ATZDownloader *downloader = [ATZDownloader new]; + [downloader downloadFileFromPath:package.screenshotPath + progress:progress + completion:^(NSData *responseData, NSError *error) { + if (error) + return; + + NSImage *image = [[NSImage alloc] initWithData:responseData]; + if (!image) + return; + + [self cacheImage:image forPackage:package]; + if (completion) + completion(package, image); + }]; +} + +@end diff --git a/Alcatraz/Views/ATZPackageListTableCellView.h b/Alcatraz/Views/ATZPackageListTableCellView.h index 9e3ce11..d27aee8 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.h +++ b/Alcatraz/Views/ATZPackageListTableCellView.h @@ -31,4 +31,6 @@ @property (nonatomic, weak) IBOutlet NSButton* installButton; @property (nonatomic, weak) IBOutlet ATZPreviewImageButton* previewButton; @property (nonatomic, weak) IBOutlet NSImageView* typeImageView; +@property (nonatomic, copy) NSString *screenshotPath; + @end From 538f20ac39c423c125bc239dbad31e3fa9e9b543 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Fri, 20 Mar 2015 23:15:49 +0200 Subject: [PATCH 02/11] - fixed images loading on mouse wheel scrolling - show cached images right away --- Alcatraz/Controllers/ATZPackageTableViewDelegate.h | 2 +- Alcatraz/Controllers/ATZPackageTableViewDelegate.m | 7 +++++-- Alcatraz/Controllers/ATZPluginWindowController.m | 11 +++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.h b/Alcatraz/Controllers/ATZPackageTableViewDelegate.h index 9d4d705..16014bd 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.h +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.h @@ -32,6 +32,6 @@ @property (nonatomic, strong, readonly) NSArray* packages; -- (void)loadImagesForRowsInRange:(NSRange)range inTableView:(NSTableView *)tableView; +- (void)loadImagesForVisibleRowsInTableView:(NSTableView *)tableView; @end diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m index 35d74c2..37e2589 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m @@ -92,7 +92,9 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn [view.previewButton setFullSize:hasImage]; [view.previewButton setHidden:!hasImage]; view.screenshotPath = package.screenshotPath; - view.previewButton.image = nil; + if (package.screenshotPath) { + [view.previewButton setImage:[ATZScreenshotsStorage cachedImageForPackage:package]]; + } ATZFillableButton* installButton = (ATZFillableButton*)view.installButton; [installButton setButtonBorderStyle:ATZFillableButtonTypeInstall]; [installButton setFillRatio:([package isInstalled] ? 100 : 0) animated:NO]; @@ -179,7 +181,8 @@ - (NSImage *)selectionTemplateImageNamed:(NSString *)imageName { return copiedImage; } -- (void)loadImagesForRowsInRange:(NSRange)range inTableView:(NSTableView *)tableView { +- (void)loadImagesForVisibleRowsInTableView:(NSTableView *)tableView { + NSRange range = [tableView rowsInRect:tableView.visibleRect]; for (NSInteger row = range.location; row < range.location + range.length; ++row) { ATZPackageListTableCellView *view = [tableView viewAtColumn:0 row:row makeIfNecessary:NO]; ATZPackage *package = self.filteredPackages[row]; diff --git a/Alcatraz/Controllers/ATZPluginWindowController.m b/Alcatraz/Controllers/ATZPluginWindowController.m index a860fb9..7c25816 100644 --- a/Alcatraz/Controllers/ATZPluginWindowController.m +++ b/Alcatraz/Controllers/ATZPluginWindowController.m @@ -51,6 +51,8 @@ typedef NS_ENUM(NSInteger, ATZFilterSegment) { @interface ATZPluginWindowController () @property (nonatomic, assign) NSView *hoverButtonsContainer; @property (nonatomic, strong) ATZPackageTableViewDelegate* tableViewDelegate; +@property (nonatomic, strong) NSTimer *loadImagesTimer; + @end @implementation ATZPluginWindowController @@ -79,8 +81,10 @@ - (void)windowDidLoad { [self addVersionToWindow]; typeof(self) __weak wSelf = self; - [[NSNotificationCenter defaultCenter] addObserverForName:NSScrollViewDidEndLiveScrollNotification object:self.tableView.enclosingScrollView queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - [wSelf loadImagesInVisibleRows]; + [[NSNotificationCenter defaultCenter] addObserverForName:NSScrollViewDidLiveScrollNotification object:self.tableView.enclosingScrollView queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + [wSelf.loadImagesTimer invalidate]; + wSelf.loadImagesTimer = [NSTimer timerWithTimeInterval:0.2 target:wSelf selector:@selector(loadImagesInVisibleRows) userInfo:nil repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:self.loadImagesTimer forMode:NSRunLoopCommonModes]; }]; if ([self.window respondsToSelector:@selector(setTitleVisibility:)]) { @@ -310,8 +314,7 @@ - (void)addVersionToWindow { } - (void)loadImagesInVisibleRows { - NSRange visibleRows = [self.tableView rowsInRect:self.tableView.visibleRect]; - [self.tableViewDelegate loadImagesForRowsInRange:visibleRows inTableView:self.tableView]; + [self.tableViewDelegate loadImagesForVisibleRowsInTableView:self.tableView]; } @end From 56eba94dbe3ea9db60e7b8aaeb3a8959fa52194f Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Sat, 21 Mar 2015 00:37:29 +0200 Subject: [PATCH 03/11] - added overlay NSImageView for displaying screenshot previews. fix #230 --- .../Controllers/ATZPackageTableViewDelegate.m | 56 +++---------------- Alcatraz/Views/ATZPackageListTableCellView.h | 2 +- .../Views/ATZPackageListTableCellView.xib | 15 ++++- Alcatraz/Views/ATZPreviewImageButton.m | 24 -------- 4 files changed, 22 insertions(+), 75 deletions(-) diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m index 37e2589..86295b2 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m @@ -86,14 +86,13 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn [view.descriptionField setStringValue:package.summary]; [view.linkButton setImage:[self tableView:tableView websiteImageForTableColumn:tableColumn row:row]]; [view.linkButton setTitle:[self tableView:tableView displayWebsiteForTableColumn:tableColumn row:row]]; - [view.typeImageView setImage:[self tableView:tableView packageTypeImageForTableColumn:tableColumn row:row]]; [view.installButton setTitle:([package isInstalled] ? @"REMOVE" : @"INSTALL")]; BOOL hasImage = package.screenshotPath != nil; [view.previewButton setFullSize:hasImage]; [view.previewButton setHidden:!hasImage]; view.screenshotPath = package.screenshotPath; if (package.screenshotPath) { - [view.previewButton setImage:[ATZScreenshotsStorage cachedImageForPackage:package]]; + view.screenshotImageView.image = [ATZScreenshotsStorage cachedImageForPackage:package]; } ATZFillableButton* installButton = (ATZFillableButton*)view.installButton; [installButton setButtonBorderStyle:ATZFillableButtonTypeInstall]; @@ -149,57 +148,20 @@ - (NSImage *)tableView:(NSTableView*)tableView websiteImageForTableColumn:(NSTab return [[Alcatraz sharedPlugin].bundle imageForResource:websiteImageName]; } -- (NSImage *)tableView:(NSTableView*)tableView packageTypeImageForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { - NSString* typeImageName = nil; - ATZPackage* package = [self tableView:tableView objectValueForTableColumn:tableColumn row:row]; - if ([package isKindOfClass:[ATZPlugin class]]) { - typeImageName = @"740-gear"; - } else if ([package isKindOfClass:[ATZTemplate class]]) { - typeImageName = @"808-documents"; - } else if ([package isKindOfClass:[ATZColorScheme class]]) { - typeImageName = @"837-palette"; - } else { - return nil; - } - if ([package isInstalled]) - typeImageName = [NSString stringWithFormat:@"%@-selected", typeImageName]; - - return [self selectionTemplateImageNamed:typeImageName]; -} - -- (NSImage *)selectionTemplateImageNamed:(NSString *)imageName { - NSImage *template = [[Alcatraz sharedPlugin].bundle imageForResource:imageName]; - NSSize size = [template size]; - - NSImage *copiedImage = [template copy]; - [copiedImage setTemplate:NO]; - [copiedImage lockFocus]; - [[NSColor selectedItemColor] set]; - NSRectFillUsingOperation(NSMakeRect(0, 0, size.width, size.height), NSCompositeSourceAtop); - [copiedImage unlockFocus]; - - return copiedImage; -} - - (void)loadImagesForVisibleRowsInTableView:(NSTableView *)tableView { NSRange range = [tableView rowsInRect:tableView.visibleRect]; for (NSInteger row = range.location; row < range.location + range.length; ++row) { ATZPackageListTableCellView *view = [tableView viewAtColumn:0 row:row makeIfNecessary:NO]; ATZPackage *package = self.filteredPackages[row]; - if (package.screenshotPath) { - [view.previewButton setImage:[ATZScreenshotsStorage cachedImageForPackage:package]]; - if (!view.previewButton.image) { - __block NSButton* imageButton = view.previewButton; - [ATZScreenshotsStorage fetchAndCacheImageForPackage:package progress:NULL completion:^(ATZPackage *pkg, NSImage *image) { - if ([view.titleField.stringValue isEqualToString:pkg.name]) { - imageButton.image = image; - [tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]]; - } - }]; - } - } else { - [view.previewButton setImage:nil]; + if (package.screenshotPath && !view.screenshotImageView.image) { + NSImageView __weak *imageView = view.screenshotImageView; + [ATZScreenshotsStorage fetchAndCacheImageForPackage:package progress:NULL completion:^(ATZPackage *pkg, NSImage *image) { + if ([view.titleField.stringValue isEqualToString:pkg.name]) { + imageView.image = image; + [tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]]; + } + }]; } } } diff --git a/Alcatraz/Views/ATZPackageListTableCellView.h b/Alcatraz/Views/ATZPackageListTableCellView.h index d27aee8..b98dcd1 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.h +++ b/Alcatraz/Views/ATZPackageListTableCellView.h @@ -30,7 +30,7 @@ @property (nonatomic, weak) IBOutlet NSButton* linkButton; @property (nonatomic, weak) IBOutlet NSButton* installButton; @property (nonatomic, weak) IBOutlet ATZPreviewImageButton* previewButton; -@property (nonatomic, weak) IBOutlet NSImageView* typeImageView; @property (nonatomic, copy) NSString *screenshotPath; +@property (nonatomic, weak) IBOutlet NSImageView *screenshotImageView; @end diff --git a/Alcatraz/Views/ATZPackageListTableCellView.xib b/Alcatraz/Views/ATZPackageListTableCellView.xib index 2e3cc8a..25eae39 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.xib +++ b/Alcatraz/Views/ATZPackageListTableCellView.xib @@ -1,8 +1,8 @@ - + - + @@ -58,19 +58,25 @@ + + + + + + @@ -78,9 +84,11 @@ + + @@ -88,6 +96,7 @@ + diff --git a/Alcatraz/Views/ATZPreviewImageButton.m b/Alcatraz/Views/ATZPreviewImageButton.m index b284e82..53df8c6 100644 --- a/Alcatraz/Views/ATZPreviewImageButton.m +++ b/Alcatraz/Views/ATZPreviewImageButton.m @@ -40,25 +40,6 @@ - (instancetype)initWithCoder:(NSCoder *)coder { return self; } -- (void)drawRect:(NSRect)dirtyRect { - if (!self.image) - return; - NSSize imageSize = self.image.size; - CGFloat x, y, width, height; - if (imageSize.width >= self.bounds.size.width) { - width = imageSize.width; - height = imageSize.height; - } else { - width = self.bounds.size.width; - height = (width/imageSize.width) * imageSize.height; - } - x = (self.bounds.size.width - width)/2; - y = (ATZPreviewImageHeight - height)/2; - NSRect imageRect = NSMakeRect(x, y, width, height); - [self.image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeDestinationAtop - fraction:1.f respectFlipped:YES hints:nil]; -} - - (NSSize)intrinsicContentSize { if (self.image || [self isFullSize]) return NSMakeSize(self.bounds.size.width, ATZPreviewImageHeight); @@ -66,9 +47,4 @@ - (NSSize)intrinsicContentSize { return NSZeroSize; } -- (void)setImage:(NSImage *)image { - [image lockFocusFlipped:YES]; - [super setImage:image]; -} - @end From 5a6cb14e1a57c3c3c6eb46021d8832b8a42b8d9c Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Sat, 21 Mar 2015 22:21:31 +0200 Subject: [PATCH 04/11] now it clears out previous image from ImageView --- Alcatraz/Controllers/ATZPackageTableViewDelegate.m | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m index 37e2589..c726e4f 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m @@ -92,9 +92,7 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn [view.previewButton setFullSize:hasImage]; [view.previewButton setHidden:!hasImage]; view.screenshotPath = package.screenshotPath; - if (package.screenshotPath) { - [view.previewButton setImage:[ATZScreenshotsStorage cachedImageForPackage:package]]; - } + [view.previewButton setImage:[ATZScreenshotsStorage cachedImageForPackage:package]]; ATZFillableButton* installButton = (ATZFillableButton*)view.installButton; [installButton setButtonBorderStyle:ATZFillableButtonTypeInstall]; [installButton setFillRatio:([package isInstalled] ? 100 : 0) animated:NO]; From 91fd767ba3a396c58e738e2cb667231e51a0e041 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Fri, 27 Mar 2015 20:57:18 +0200 Subject: [PATCH 05/11] enabled animations (.gif) in previews --- Alcatraz/ATZPluginWindowController.xib | 10 +++++----- Alcatraz/Views/ATZPackageListTableCellView.xib | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Alcatraz/ATZPluginWindowController.xib b/Alcatraz/ATZPluginWindowController.xib index 9dc0c5e..6694d48 100644 --- a/Alcatraz/ATZPluginWindowController.xib +++ b/Alcatraz/ATZPluginWindowController.xib @@ -1,8 +1,8 @@ - + - + @@ -23,7 +23,7 @@ - + @@ -228,14 +228,14 @@ - + - + diff --git a/Alcatraz/Views/ATZPackageListTableCellView.xib b/Alcatraz/Views/ATZPackageListTableCellView.xib index 25eae39..321c15b 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.xib +++ b/Alcatraz/Views/ATZPackageListTableCellView.xib @@ -1,5 +1,5 @@ - + @@ -67,7 +67,7 @@ - + From d6519201ae156cc064912aa3487b4e3e7ab8bbf0 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Mon, 30 Mar 2015 10:35:21 +0300 Subject: [PATCH 06/11] added missed braces --- Alcatraz/Helpers/ATZScreenshotsStorage.m | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Alcatraz/Helpers/ATZScreenshotsStorage.m b/Alcatraz/Helpers/ATZScreenshotsStorage.m index 4708c4e..d748428 100644 --- a/Alcatraz/Helpers/ATZScreenshotsStorage.m +++ b/Alcatraz/Helpers/ATZScreenshotsStorage.m @@ -37,16 +37,19 @@ + (void)fetchAndCacheImageForPackage:(ATZPackage*)package progress:(void(^)(CGFl [downloader downloadFileFromPath:package.screenshotPath progress:progress completion:^(NSData *responseData, NSError *error) { - if (error) + if (error) { return; + } NSImage *image = [[NSImage alloc] initWithData:responseData]; - if (!image) + if (!image) { return; + } [self cacheImage:image forPackage:package]; - if (completion) + if (completion) { completion(package, image); + } }]; } From 5cfaa99ba623aaacf742db2f84a9b2eecab33f00 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Mon, 30 Mar 2015 22:03:21 +0300 Subject: [PATCH 07/11] changed scaling of previews to fill full width --- .../Views/ATZPackageListTableCellView.xib | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Alcatraz/Views/ATZPackageListTableCellView.xib b/Alcatraz/Views/ATZPackageListTableCellView.xib index 321c15b..62ba24f 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.xib +++ b/Alcatraz/Views/ATZPackageListTableCellView.xib @@ -65,30 +65,39 @@ - + - - + + + + + + + + + + + - - + - + - + + From c002e919211341f9d3a61e5cd453e7ee20371ad5 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Tue, 31 Mar 2015 06:03:43 +0300 Subject: [PATCH 08/11] tab into spaces --- .../Controllers/ATZPackageTableViewDelegate.m | 30 +++++------ .../Controllers/ATZPluginWindowController.m | 28 +++++----- Alcatraz/Helpers/ATZScreenshotsStorage.m | 52 +++++++++---------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m index b194a2d..6ab020f 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m @@ -147,21 +147,21 @@ - (NSImage *)tableView:(NSTableView*)tableView websiteImageForTableColumn:(NSTab } - (void)loadImagesForVisibleRowsInTableView:(NSTableView *)tableView { - NSRange range = [tableView rowsInRect:tableView.visibleRect]; - for (NSInteger row = range.location; row < range.location + range.length; ++row) { - ATZPackageListTableCellView *view = [tableView viewAtColumn:0 row:row makeIfNecessary:NO]; - ATZPackage *package = self.filteredPackages[row]; - - if (package.screenshotPath && !view.screenshotImageView.image) { - NSImageView __weak *imageView = view.screenshotImageView; - [ATZScreenshotsStorage fetchAndCacheImageForPackage:package progress:NULL completion:^(ATZPackage *pkg, NSImage *image) { - if ([view.titleField.stringValue isEqualToString:pkg.name]) { - imageView.image = image; - [tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]]; - } - }]; - } - } + NSRange range = [tableView rowsInRect:tableView.visibleRect]; + for (NSInteger row = range.location; row < range.location + range.length; ++row) { + ATZPackageListTableCellView *view = [tableView viewAtColumn:0 row:row makeIfNecessary:NO]; + ATZPackage *package = self.filteredPackages[row]; + + if (package.screenshotPath && !view.screenshotImageView.image) { + NSImageView __weak *imageView = view.screenshotImageView; + [ATZScreenshotsStorage fetchAndCacheImageForPackage:package progress:NULL completion:^(ATZPackage *pkg, NSImage *image) { + if ([view.titleField.stringValue isEqualToString:pkg.name]) { + imageView.image = image; + [tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]]; + } + }]; + } + } } diff --git a/Alcatraz/Controllers/ATZPluginWindowController.m b/Alcatraz/Controllers/ATZPluginWindowController.m index 7c25816..d88770b 100644 --- a/Alcatraz/Controllers/ATZPluginWindowController.m +++ b/Alcatraz/Controllers/ATZPluginWindowController.m @@ -58,7 +58,7 @@ @interface ATZPluginWindowController () @implementation ATZPluginWindowController - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (id)init { @@ -80,16 +80,16 @@ - (void)windowDidLoad { [super windowDidLoad]; [self addVersionToWindow]; - typeof(self) __weak wSelf = self; - [[NSNotificationCenter defaultCenter] addObserverForName:NSScrollViewDidLiveScrollNotification object:self.tableView.enclosingScrollView queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - [wSelf.loadImagesTimer invalidate]; - wSelf.loadImagesTimer = [NSTimer timerWithTimeInterval:0.2 target:wSelf selector:@selector(loadImagesInVisibleRows) userInfo:nil repeats:NO]; - [[NSRunLoop mainRunLoop] addTimer:self.loadImagesTimer forMode:NSRunLoopCommonModes]; - }]; + typeof(self) __weak wSelf = self; + [[NSNotificationCenter defaultCenter] addObserverForName:NSScrollViewDidLiveScrollNotification object:self.tableView.enclosingScrollView queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + [wSelf.loadImagesTimer invalidate]; + wSelf.loadImagesTimer = [NSTimer timerWithTimeInterval:0.2 target:wSelf selector:@selector(loadImagesInVisibleRows) userInfo:nil repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:self.loadImagesTimer forMode:NSRunLoopCommonModes]; + }]; - if ([self.window respondsToSelector:@selector(setTitleVisibility:)]) { + if ([self.window respondsToSelector:@selector(setTitleVisibility:)]) { self.window.titleVisibility = NSWindowTitleHidden; - } + } } - (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { @@ -252,10 +252,10 @@ - (void)updatePredicate { [self.tableViewDelegate filterUsingPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]]; [self.tableView reloadData]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - // wait next run loop, otherwise there are no rows yet - [self loadImagesInVisibleRows]; - }); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // wait next run loop, otherwise there are no rows yet + [self loadImagesInVisibleRows]; + }); } - (void)updatePackages { @@ -314,7 +314,7 @@ - (void)addVersionToWindow { } - (void)loadImagesInVisibleRows { - [self.tableViewDelegate loadImagesForVisibleRowsInTableView:self.tableView]; + [self.tableViewDelegate loadImagesForVisibleRowsInTableView:self.tableView]; } @end diff --git a/Alcatraz/Helpers/ATZScreenshotsStorage.m b/Alcatraz/Helpers/ATZScreenshotsStorage.m index d748428..bc366eb 100644 --- a/Alcatraz/Helpers/ATZScreenshotsStorage.m +++ b/Alcatraz/Helpers/ATZScreenshotsStorage.m @@ -16,41 +16,41 @@ @implementation ATZScreenshotsStorage #pragma mark - Image Previews + (NSCache *)imageCache { - static NSCache* cache = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - cache = [[NSCache alloc] init]; - }); - return cache; + static NSCache* cache = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + cache = [[NSCache alloc] init]; + }); + return cache; } + (NSImage *)cachedImageForPackage:(ATZPackage*)package { - return [[self imageCache] objectForKey:package.name]; + return [[self imageCache] objectForKey:package.name]; } + (void)cacheImage:(NSImage *)image forPackage:(ATZPackage *)package { - [[self imageCache] setObject:image forKey:package.name]; + [[self imageCache] setObject:image forKey:package.name]; } + (void)fetchAndCacheImageForPackage:(ATZPackage*)package progress:(void(^)(CGFloat))progress completion:(ATZImagesStorageCompletion)completion { - ATZDownloader *downloader = [ATZDownloader new]; - [downloader downloadFileFromPath:package.screenshotPath - progress:progress - completion:^(NSData *responseData, NSError *error) { - if (error) { - return; - } - - NSImage *image = [[NSImage alloc] initWithData:responseData]; - if (!image) { - return; - } - - [self cacheImage:image forPackage:package]; - if (completion) { - completion(package, image); - } - }]; + ATZDownloader *downloader = [ATZDownloader new]; + [downloader downloadFileFromPath:package.screenshotPath + progress:progress + completion:^(NSData *responseData, NSError *error) { + if (error) { + return; + } + + NSImage *image = [[NSImage alloc] initWithData:responseData]; + if (!image) { + return; + } + + [self cacheImage:image forPackage:package]; + if (completion) { + completion(package, image); + } + }]; } @end From 7359256d184923282c84e123245926248e620d40 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Wed, 1 Apr 2015 20:54:52 +0300 Subject: [PATCH 09/11] fixed preview image misplaced constraints --- Alcatraz/Views/ATZPackageListTableCellView.xib | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Alcatraz/Views/ATZPackageListTableCellView.xib b/Alcatraz/Views/ATZPackageListTableCellView.xib index 62ba24f..2e01ac4 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.xib +++ b/Alcatraz/Views/ATZPackageListTableCellView.xib @@ -73,8 +73,8 @@ - - + + From d739506c53954b643b5fd0e82c4d2e6b8f2ecb90 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Thu, 9 Apr 2015 09:48:40 +0300 Subject: [PATCH 10/11] Okay Xcode, as you wish --- Alcatraz/Views/ATZPackageListTableCellView.xib | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Alcatraz/Views/ATZPackageListTableCellView.xib b/Alcatraz/Views/ATZPackageListTableCellView.xib index 2e01ac4..a68b2f6 100644 --- a/Alcatraz/Views/ATZPackageListTableCellView.xib +++ b/Alcatraz/Views/ATZPackageListTableCellView.xib @@ -1,8 +1,8 @@ - + - + @@ -69,6 +69,7 @@ + From 277ade92bc6cea072dbaa7cba2b040ad51279752 Mon Sep 17 00:00:00 2001 From: Alex Antonyuk Date: Thu, 16 Apr 2015 23:33:05 +0300 Subject: [PATCH 11/11] missed a few tabs, all glory to the spaces --- Alcatraz/Controllers/ATZPackageTableViewDelegate.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m index 6ab020f..8f33cae 100644 --- a/Alcatraz/Controllers/ATZPackageTableViewDelegate.m +++ b/Alcatraz/Controllers/ATZPackageTableViewDelegate.m @@ -90,8 +90,8 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn BOOL hasImage = package.screenshotPath != nil; [view.previewButton setFullSize:hasImage]; [view.previewButton setHidden:!hasImage]; - view.screenshotPath = package.screenshotPath; - view.screenshotImageView.image = [ATZScreenshotsStorage cachedImageForPackage:package]; + view.screenshotPath = package.screenshotPath; + view.screenshotImageView.image = [ATZScreenshotsStorage cachedImageForPackage:package]; ATZFillableButton* installButton = (ATZFillableButton*)view.installButton; [installButton setButtonBorderStyle:ATZFillableButtonTypeInstall]; [installButton setFillRatio:([package isInstalled] ? 100 : 0) animated:NO];