Calling given Cocoa Method from applescript

Hey guys,

im struggling with a little problem over here. I got a cocoa method to draw a badge on an icon with numbers to get a visual feedback of a progress. i cant use the simple method provided for 10.6 and higher because this needs to run on a 10.4 machine.

Im good at applescript but not good with cocoa and the calling of methods. Heres the .m and .h file.
How do a call this method from applescript correctly? Any help aprreciated!

IconImageCounterController.h


#import <Cocoa/Cocoa.h>

@interface IconImageCounterController : NSObject {

    NSImage *iconImageBuffer;
    NSImage *originalIcon;
    NSTimer *timer;
    NSDictionary *attributes;
    int count;
}
- (void)drawCountdownIcon:(int)number;
- (void)timerAction:(NSTimer *)_timer;

@end

IconImageCounterController.m


#import "IconImageCounterController.h"


@implementation IconImageCounterController

- (void)awakeFromNib {
    if (timer) return;
    originalIcon = [[NSApp applicationIconImage] copy];
    iconImageBuffer = [originalIcon copy];
    timer = [[NSTimer scheduledTimerWithTimeInterval:1
											  target:self
											selector:@selector(timerAction:)
											userInfo:nil
											 repeats:YES] retain];
    attributes = [[NSDictionary alloc] initWithObjectsAndKeys:
				  [NSFont fontWithName:@"Helvetica-Bold" size:26], NSFontAttributeName,
				  [NSColor whiteColor], NSForegroundColorAttributeName, nil];
	
    count = 20;
}

- (void)dealloc {
    [originalIcon release];
    [iconImageBuffer release];
    [attributes release];
    [super dealloc];
}

- (void)timerAction:(NSTimer *)_timer {
    if (count < 0 && timer == _timer) {[timer invalidate]; [timer release]; timer = nil; return;}
    [self drawCountdownIcon:count--];
    
}

- (void)drawCountdownIcon:(int)number {
    
    NSString *countdown = [NSString stringWithFormat:@"%i", number];
    NSSize numSize = [countdown sizeWithAttributes:attributes];
    NSSize iconSize = [originalIcon size];
    if (number) {
        [iconImageBuffer lockFocus];
        [originalIcon drawAtPoint:NSMakePoint(0, 0)
						 fromRect:NSMakeRect(0, 0, iconSize.width, iconSize.height) 
						operation:NSCompositeSourceOver 
						 fraction:1.0f];
        float max = (numSize.width > numSize.height) ? numSize.width : numSize.height;
        max += 16;
        NSRect circleRect = NSMakeRect(iconSize.width - max, iconSize.height - max, max, max);
        NSBezierPath *bp = [NSBezierPath bezierPathWithOvalInRect:circleRect];
        [[NSColor colorWithCalibratedRed:0.8f green:0.0f blue:0.0f alpha:1.0f] set];
        [bp fill];
        [countdown drawAtPoint:NSMakePoint(NSMidX(circleRect) - numSize.width / 2.0f, 
										   NSMidY(circleRect) - numSize.height / 2.0f + 2.0f) 
				withAttributes:attributes];
        
        [iconImageBuffer unlockFocus];
        [NSApp setApplicationIconImage:iconImageBuffer];
    }
    else [NSApp setApplicationIconImage:originalIcon];
    
}

@end


i tried this here on an awake from nib (testwise), but nothing happens:


call method "drawCountdownIcon" of class "IconImageCounterController" with parameters {10}

Hi,

you can call methods of custom classes directly from AppleScript Studio only if they are class methods (starting with plus sign).

The other way is to create an instance of the class with the usual alloc/init methods


set iconImageCounterControllerInstance to (call method "init" of (call method "alloc" of class "IconImageCounterController"))
call method "drawCountdownIcon" of iconImageCounterControllerInstance with parameter 10

don’t forget to release the instance object after having finished with it


call method "release" of iconImageCounterControllerInstance

Hi StefanK

Thank you for your answer. I tried what you told me but still nothing happens.
I think there might be a problem with the call i do.

As far as i understand the methods, i have to call the “drawCountdownIcon” method to draw a badge with the parameter (10) , but thaht might be completely wrong. Im still working on my cocoa skills (actually started with basics),but want to finish this applescript app. So could you please have a look at the method to figure out how to call it correctly? I’d aprreciate that.

EDIT: Additional question: As more as i get into the cocoa, the more i understand it. With the code you gave me, you created an instance of the object “iconImageCounterController”. But how do you pass the variables (iconImageBuffer,originalIcon,timer,attributes,count?) from applescript?

Greetings
Jonathan

is the awakeFromNib handler be called at all in the Cocoa class?
It’s important, because in this handler the main variables are set.

I haven’t used AppleScript Studio for a long time,
as far as I remember you have to add a custom object (blue cube) in Interface Builder,
change the class name to your custom class and connect the delegate to files’s owner

The parameter call should work as written.

Ah!
It works with Awake from nib connected in IB. First Sunlight at the end of the darkness!
But…

I rewrote the cocoa a little - it works if i use awake from nib to declare the vars, but i want to launch it from applescript. so i removed the awake from nib and build a new method “setbadge” where i declare the vars except of the number i want to display.
Everything works and is tested. Onliest thing that doesnt work is to call the method setBadge from Applescript like you mentionend in your second post.

IconImageCounterController.h file



#import <Cocoa/Cocoa.h>


@interface IconImageCounterController : NSObject {

    NSImage *iconImageBuffer;
    NSImage *originalIcon;
    NSTimer *timer;
    NSDictionary *attributes;
    //int count;
}
- (void)setBadge:(int)count;
- (void)drawIcon:(int)number;


@end


IconImageCounterController.m file


#import "IconImageCounterController.h"


@implementation IconImageCounterController

- (void)setBadge:(int)count {    
    originalIcon = [[NSApp applicationIconImage] copy];
    iconImageBuffer = [originalIcon copy];
	
    attributes = [[NSDictionary alloc] initWithObjectsAndKeys:
				  [NSFont fontWithName:@"Helvetica-Bold" size:26], NSFontAttributeName,
				  [NSColor whiteColor], NSForegroundColorAttributeName, nil];	
   
	[self drawIcon:count];
}

- (void)dealloc {
    [originalIcon release];
    [iconImageBuffer release];
    [attributes release];
    [super dealloc];
}


- (void)drawIcon:(int)number {
    
    NSString *countdown = [NSString stringWithFormat:@"%i", number];
    NSSize numSize = [countdown sizeWithAttributes:attributes];
    NSSize iconSize = [originalIcon size];
    if (number) {
        [iconImageBuffer lockFocus];
        [originalIcon drawAtPoint:NSMakePoint(0, 0)
						 fromRect:NSMakeRect(0, 0, iconSize.width, iconSize.height) 
						operation:NSCompositeSourceOver 
						 fraction:1.0f];
        float max = (numSize.width > numSize.height) ? numSize.width : numSize.height;
        max += 16;
        NSRect circleRect = NSMakeRect(iconSize.width - max, iconSize.height - max, max, max);
        NSBezierPath *bp = [NSBezierPath bezierPathWithOvalInRect:circleRect];
        [[NSColor colorWithCalibratedRed:0.8f green:0.0f blue:0.0f alpha:1.0f] set];
        [bp fill];
        [countdown drawAtPoint:NSMakePoint(NSMidX(circleRect) - numSize.width / 2.0f, 
										   NSMidY(circleRect) - numSize.height / 2.0f + 2.0f) 
				withAttributes:attributes];
        
        [iconImageBuffer unlockFocus];
        [NSApp setApplicationIconImage:iconImageBuffer];
    }
    else [NSApp setApplicationIconImage:originalIcon];
    
}

@end


leaned onto your script, i try this, doesnt work


on awake from nib theObject
	log "awake..." --handler works!
	try
		set iconImageCounterControllerInstance to (call method "init" of (call method "alloc" of class "IconImageCounterController"))		
		call method "setBadge" of iconImageCounterControllerInstance with parameter 10
		call method "release" of iconImageCounterControllerInstance
	on error err
		log err
	end try
	
end awake from nib


sorry, I forgot, if the method has parameter(s), you have to add the appropriate colons


 call method "setBadge:" of iconImageCounterControllerInstance with parameter 10

Thats it!!!

Thank you very much! :slight_smile:

last question:

when im done with what i need to do, do i need to to call the method “dealloc”?


- (void)dealloc {
    [originalIcon release];
    [iconImageBuffer release];
    [attributes release];
    [super dealloc];
}

No, never call dealloc in custom methods.
The method will be called from the parent class automatically after releasing the object

Everything works! Thank you very much!