Skip to content
This repository has been archived by the owner on Sep 4, 2018. It is now read-only.

Some fixes #246

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions Alcatraz.xcodeproj/project.pbxproj
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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 = "<group>"; };
32D86503173A4555009C724B /* eye_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "eye_icon@2x.png"; sourceTree = "<group>"; };
636C388D1ABCB1B7004DECCF /* ATZScreenshotsStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZScreenshotsStorage.h; sourceTree = "<group>"; };
636C388E1ABCB1B7004DECCF /* ATZScreenshotsStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATZScreenshotsStorage.m; sourceTree = "<group>"; };
6449530218CE826C009494BD /* ATZVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZVersion.h; sourceTree = "<group>"; };
64C28A4918136FF30025C0B1 /* toolbar_colors.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = toolbar_colors.png; sourceTree = "<group>"; };
64C28A4A18136FF30025C0B1 /* toolbar_colors@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "toolbar_colors@2x.png"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -353,6 +356,8 @@
8917DA171726B63B00F0B2D2 /* ATZShell.m */,
89B4F2BC172FF5AC001FD2E3 /* ATZPBXProjParser.h */,
89B4F2BD172FF5AC001FD2E3 /* ATZPBXProjParser.m */,
636C388D1ABCB1B7004DECCF /* ATZScreenshotsStorage.h */,
636C388E1ABCB1B7004DECCF /* ATZScreenshotsStorage.m */,
);
path = Helpers;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down
10 changes: 5 additions & 5 deletions Alcatraz/ATZPluginWindowController.xib
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6751" systemVersion="14C1514" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6751"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ATZPluginWindowController">
Expand All @@ -23,7 +23,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" unifiedTitleAndToolbar="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="545" height="449"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="545" height="449"/>
<autoresizingMask key="autoresizingMask"/>
Expand Down Expand Up @@ -228,14 +228,14 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" utility="YES" HUD="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="139" y="81" width="276" height="378"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="WQe-dv-pdE">
<rect key="frame" x="0.0" y="0.0" width="276" height="378"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="47h-q5-ax2">
<rect key="frame" x="0.0" y="0.0" width="276" height="378"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="Pbz-gX-fEe"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" animates="YES" imageScaling="proportionallyDown" id="Pbz-gX-fEe"/>
</imageView>
</subviews>
<constraints>
Expand Down
3 changes: 3 additions & 0 deletions Alcatraz/Controllers/ATZPackageTableViewDelegate.h
Expand Up @@ -31,4 +31,7 @@
- (void)filterUsingPredicate:(NSPredicate*)predicate;

@property (nonatomic, strong, readonly) NSArray* packages;

- (void)loadImagesForVisibleRowsInTableView:(NSTableView *)tableView;

@end
96 changes: 18 additions & 78 deletions Alcatraz/Controllers/ATZPackageTableViewDelegate.m
Expand Up @@ -32,6 +32,7 @@
#import "ATZColorScheme.h"
#import "ATZDownloader.h"
#import "NSColor+Alcatraz.h"
#import "ATZScreenshotsStorage.h"

@interface ATZPackageTableViewDelegate ()

Expand Down Expand Up @@ -85,23 +86,12 @@ - (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];
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.screenshotImageView.image = [ATZScreenshotsStorage cachedImageForPackage:package];
ATZFillableButton* installButton = (ATZFillableButton*)view.installButton;
[installButton setButtonBorderStyle:ATZFillableButtonTypeInstall];
[installButton setFillRatio:([package isInstalled] ? 100 : 0) animated:NO];
Expand Down Expand Up @@ -156,73 +146,23 @@ - (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;
- (void)loadImagesForVisibleRowsInTableView:(NSTableView *)tableView {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor here appreciated (try to have max 3 levels of indentation)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh...actually I deleted these lines, as they were unused 😮
I don't like to keep dead code in project.

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]];
}
}];
}
}
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;
}

#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:(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
45 changes: 34 additions & 11 deletions 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
Expand All @@ -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
Expand Down Expand Up @@ -51,10 +51,16 @@ 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

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (id)init {
@throw [NSException exceptionWithName:@"There's a better initializer" reason:@"Use -initWithNibName:inBundle:" userInfo:nil];
}
Expand All @@ -73,8 +79,17 @@ - (id)initWithBundle:(NSBundle *)bundle {
- (void)windowDidLoad {
[super windowDidLoad];
[self addVersionToWindow];
if ([self.window respondsToSelector:@selector(setTitleVisibility:)])

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:)]) {
self.window.titleVisibility = NSWindowTitleHidden;
}
}

- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
Expand All @@ -89,7 +104,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
Expand Down Expand Up @@ -174,7 +189,6 @@ - (void)reloadTableView {
self.tableView.dataSource = self.tableViewDelegate;
[self.tableViewDelegate configureTableView:self.tableView];
[self updatePredicate];
[self.tableView reloadData];
}

#pragma mark - Private
Expand Down Expand Up @@ -209,7 +223,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." : @"";
Expand Down Expand Up @@ -237,6 +251,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 {
Expand All @@ -250,7 +269,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
Expand All @@ -276,22 +295,26 @@ - (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 {
[self.tableViewDelegate loadImagesForVisibleRowsInTableView:self.tableView];
}

@end
21 changes: 21 additions & 0 deletions 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 <Foundation/Foundation.h>

@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