我设法在Mac Os Finder中将Icon Overlay(如Dropbox)与SIMBL插件集成在一起! 我使用swizzle方法覆盖一些finder函数。
这是我的混合方法:
void PluginSwizzleInstanceMethod(Class cls, SEL oldSel, SEL newSel)
{
Method mnew = class_getInstanceMethod(cls, newSel);
Method mold = class_getInstanceMethod(cls, oldSel);
method_exchangeImplementations(mnew, mold);
}
所以暂时我覆盖了drawWithFrame方法,如下所示:
Class cls = NSClassFromString(@"TIconAndTextCell");
SEL oldSel = @selector(drawWithFrame:inView:);
SEL newSel = @selector(PluginDrawWithFrame:inView:);
PluginSwizzleInstanceMethod(cls, oldSel, newSel);
我的所有图标都显示但不在我的桌面上或显示项目为图标的视图上... 为什么?
谢谢,
答案 0 :(得分:2)
我只是设法为桌面做了一些事情,所以我会发帖,以防仍然与某人有关:
正如您所经历的那样,Finder在桌面上绘制的图标有所不同 一个负责的课程是 TDesktopIcon 例如,可以通过覆盖drawIconInContext:方法来更改图标,并将thumbnailImage属性设置为他喜欢的任何NSImage *。
- (void) FO_drawIconInContext:(struct CGContext *)arg1 {
NSImage *image;
// set image...
[(TDesktopIcon*)self setThumbnailImage:image];
[self FO_drawIconInContext:arg1];
}
获取每个项目的网址并不像TIconAndTextCell或IKImageBrowserCell那样简单。
要获取URL,您需要覆盖 TDesktopViewController 的prepareToDrawNode:方法。 您从arg1获取URL如下:
- (void) FO_prepareToDrawNode:(const struct TFENode *)arg1 {
struct OpaqueNodeRef *opr = arg1->fNodeRef;
struct FINode *fiNode = [FINode nodeFromNodeRef:opr];
NSURL *url = [fiNode previewItemURL];
// save url somewhere (I use NSUserDefaults)
[self FO_prepareToDrawNode:arg1];
}
也许有更好的方法,但这就是我想出来的......
答案 1 :(得分:2)
知道了! (这个代码仅适用于10.7)我遇到了问题,因为在最终图像渲染到缩略图图像之前绘制了图标....所以我得到了原始图标丢失的这些文物......但是覆盖总是在那里......这是我错误的绘制操作的顺序......!
我甚至有目标节点的名称......您需要TFENodeHelper类将TFENode转换为filePath ...
//
// DesktopViewIconOverlay.h
// FinderIconOverlayExample
//
// Created by Orbitus007 on 2/20/13.
//
//
#import <Foundation/Foundation.h>
#import <Quartz/Quartz.h>
#import "Finder.h"
@interface DesktopViewIconOverlay : NSObject
+ (void)pluginLoad;
- (void) FO_prepareToDrawNode:(const struct TFENode *)arg1;
- (void) FO_drawIconInContext:(struct CGContext *)arg1;
@end
//
// DesktopViewIconOverlay.m
// FinderIconOverlayExample
//
// Created by Orbitus007 on 2/20/13.
//
//
#import "DesktopViewIconOverlay.h"
#import "FinderIconOverlayExample.h"
#include <objc/objc.h>
#include <objc/runtime.h>
#import <Quartz/Quartz.h>
#import "TFENodeHelper.h"
static TFENodeHelper *gNodeHelper;
@implementation DesktopViewIconOverlay
+ (void)pluginLoad
{
// Create helper object
gNodeHelper = [[TFENodeHelper alloc] init];
if (gNodeHelper == nil) {
NSLog(@"Failed to instantiate 'TFENodeHelper' class");
return;
}
Method old, new;
Class self_class = [self class];
Class finder_class = [objc_getClass("TDesktopIcon") class];
class_addMethod(finder_class, @selector(FO_drawIconInContext:),
class_getMethodImplementation(self_class, @selector(FO_drawIconInContext:)),"v@:@");
old = class_getInstanceMethod(finder_class, @selector(drawIconInContext:));
new = class_getInstanceMethod(finder_class, @selector(FO_drawIconInContext:));
method_exchangeImplementations(old, new);
finder_class = [objc_getClass("TDesktopViewController") class];
class_addMethod(finder_class, @selector(FO_prepareToDrawNode:),
class_getMethodImplementation(self_class, @selector(FO_prepareToDrawNode:)),"v@:@");
old = class_getInstanceMethod(finder_class, @selector(prepareToDrawNode:));
new = class_getInstanceMethod(finder_class, @selector(FO_prepareToDrawNode:));
method_exchangeImplementations(old, new);
}
- (void) FO_prepareToDrawNode:(const struct TFENode *)arg1 {
NSString *path = [gNodeHelper pathForNode:arg1];
NSLog(@"Path = %@", path);
[[NSUserDefaults standardUserDefaults] setValue:path forKey:@"TDesktopIconURL"];
//struct OpaqueNodeRef *opr = arg1->fNodeRef;
//NSLog(@"path = %@", [[FINode nodeWithFENode:arg1] fullPath]);
//id fiNode = [FINode nodeFromNodeRef:opr];
//NSURL *url = [fiNode previewItemURL];
//[[NSUserDefaults standardUserDefaults] setValue:[url path] forKey:@"TDesktopIconURL"];
//NSLog(@"sending ", arg1->fNodeRef);
// save url somewhere (I use NSUserDefaults)
[self FO_prepareToDrawNode:arg1];
}
- (void) FO_drawIconInContext:(struct CGContext *)arg1
{
[self FO_drawIconInContext:arg1];
NSString *iconPath = [[NSUserDefaults standardUserDefaults] valueForKey:@"TDesktopIconURL"];
NSLog(@"recieved %@", iconPath);
if (![iconPath isEqualToString:@"/Users/h0xff/Desktop/Restart Finder.app"])
return;
NSString *imagePath = @"/Users/h0xff/Desktop/020513_icons/128_synced_green.png";
NSImage *overlay = [[NSImage alloc] initWithContentsOfFile:imagePath];
NSImage *mainImage = [(TDesktopIcon*)self thumbnailImage];
float width = 256.0;
float height = 256.0;
NSImage *finalImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
[finalImage lockFocus];
// draw the base image
[mainImage drawInRect:NSMakeRect(0, 0, width, height)
fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
// draw the overlay image at some offset point
[overlay drawInRect:NSMakeRect(0, 0, [overlay size].width/1.5, [overlay size].height/1.5)
fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[finalImage unlockFocus];
// set image...
[(TDesktopIcon*)self setThumbnailImage:finalImage];
[self FO_drawIconInContext:arg1];
}
@end
此代码源自Alexey Zhuchkov及其他许多人......如果您有任何问题,请提出问题!
//
// TFENodeHelper.h
// FinderMenu
//
// Helper class to get full path from TFENode
//
// Created by Alexey Zhuchkov on 11/4/12.
// Copyright (c) 2012 InfiniteLabs. All rights reserved.
//
#import <Foundation/Foundation.h>
// Forward declarations
struct TFENode;
typedef enum {
TFENodeCtorTypeUnknown,
TFENodeCtorTypeNodeWithFENode, // nodeWithFENode
TFENodeCtorTypeNodeFromNodeRef, // nodeFromNodeRef
} TFENodeCtorType;
typedef enum {
TFENodePathMethodTypeUnknown,
TFENodePathMethodTypeFullPath, // fullPath
TFENodePathMethodTypePreviewItemURL, // previewItemURL
} TFENodePathMethodType;
@interface TFENodeHelper : NSObject {
@private
Class _class;
TFENodeCtorType _ctorType;
TFENodePathMethodType _pathMethodType;
}
- (NSString *)pathForNode:(const struct TFENode *)node;
@end
//
// TFENodeHelper.m
// FinderMenu
//
// Created by Alexey Zhuchkov on 11/4/12.
// Copyright (c) 2012 InfiniteLabs. All rights reserved.
//
#import "TFENodeHelper.h"
#import <objc/runtime.h>
#import "Finder.h"
@implementation TFENodeHelper
- (id)init {
self = [super init];
if (self) {
_class = NSClassFromString(@"FINode");
_ctorType = TFENodeCtorTypeUnknown;
_pathMethodType = TFENodePathMethodTypeUnknown;
if (_class) {
if (class_getClassMethod(_class, @selector(nodeWithFENode:))) {
_ctorType = TFENodeCtorTypeNodeWithFENode;
} else if (class_getClassMethod(_class, @selector(nodeFromNodeRef:))) {
_ctorType = TFENodeCtorTypeNodeFromNodeRef;
}
if (class_getInstanceMethod(_class, @selector(fullPath))) {
_pathMethodType = TFENodePathMethodTypeFullPath;
} else if (class_getInstanceMethod(_class, @selector(previewItemURL))) {
_pathMethodType = TFENodePathMethodTypePreviewItemURL;
}
}
if (!_class
|| (_ctorType == TFENodePathMethodTypeUnknown)
|| (_pathMethodType == TFENodePathMethodTypeUnknown)) {
[self release];
return nil;
}
}
return self;
}
- (NSString *)pathForNode:(const struct TFENode *)node {
FINode *fiNode = nil;
NSString *path = nil;
switch (_ctorType) {
case TFENodeCtorTypeNodeWithFENode:
fiNode = [_class nodeWithFENode:node];
break;
case TFENodeCtorTypeNodeFromNodeRef:
fiNode = [_class nodeFromNodeRef:node->fNodeRef];
break;
default:
break;
}
NSURL *url;
if (fiNode) {
switch (_pathMethodType) {
case TFENodePathMethodTypeFullPath:
path = [fiNode fullPath];
break;
case TFENodePathMethodTypePreviewItemURL:
url = [fiNode previewItemURL];
path = [url path];
default:
break;
}
}
return path;
}
@end