2012-05-07 5 views
4

Мне удается интегрировать значок Overlay как Dropbox в Mac Os Finder с SIMBL-плагином! Я использую метод swizzle для переопределения функции поиска.SIMBL swizzling in 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); 

все мои значки отображаются, но не на моем рабочем столе или на представлении которые показывают элементы как значок ... Почему?

спасибо,

ответ

2

Я только что удалось сделать некоторые вещи для рабочего стола, так что я выложу в случае, если по-прежнему актуальны для кого-то:

Так как вы опытный, Finder рисует иконки по-разному на Desktop.
Один класс, который отвечает за это TDesktopIcon.
Можно, например, сменить значки, переопределив метод drawIconInContext: и установив свойство thumbnailImage для любого NSImage *, который ему нравится.

- (void) FO_drawIconInContext:(struct CGContext *)arg1 { 
    NSImage *image; 
    // set image... 
    [(TDesktopIcon*)self setThumbnailImage:image]; 
    [self FO_drawIconInContext:arg1]; 
} 

Получение URL для каждого элемента был не так прямо вперед, как с TIconAndTextCell или IKImageBrowserCell.

Для получения URL-адресов вам необходимо переопределить метод prepareToDrawNode: TDesktopViewController. Вы получаете URL из arg1 следующим образом:

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

Может быть, есть лучший способ, но вот что я понял ...

+0

Вы видели эффекты этого кода? Его действительно интересно ... похоже, что замена изображения вызывает странные проблемы, когда искатель пишет другие накладки на значок ... Я могу получить половину значков на моем рабочем столе, чтобы правильно нарисовать их оригинальные значки, но все они будут иметь оверлей на их – Orbitus007

+0

Любая идея, как это сделать на Mavericks? – Ali

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:)),"[email protected]:@"); 

    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:)),"[email protected]:@"); 

    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 

Этот код был получен от Алексея Жучков и многие другие .. .. задавайте вопросы, если у вас есть!

// 
// 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 
Смежные вопросы