How to get theIcon (continued)

So I’ve got no reaction to my question (Tue Jul 20, 2004 )
But I keep trying. The code below is from someone of Applescript engineering. He wrote that he has tested it himself and got it to work. But I don’t. Whatever I try.

I made a window “main” with image View “image” and a button to choose a file; I wrote this code:

set thePath to (choose file)
set iconImage to call method “iconForFile:” of (call method “sharedWorkspace” of class “NSWorkspace”) with parameter thePath
log iconImage
set image of image view “iconxxx” of window “main” to load image iconImage

This is the result:

image id 4
*** -[NSUniqueIDSpecifier length]: selector not recognized

The call method seems to work ok, the log gives no error but the set image keeps giving this error message:

“NSInternalScriptError (8)”

So I am asking again. Is there anyone who knows what I am doing wrong?
Is there anyone who has been able to make this work. I would appreciate this very much.
I just can’t imagine that a BASIC thing like getting the icon could not be done in AS studio.
I am running Jaguar. Could it be done in Panther maybe?
Sorry for the bad english.

I am just about to get desperate with this icon thing.

John dh

First, doing ANYTHING with icons is a recognized and admitted weakness of applescript. There is no direct support via applescript, standard additions, finder, etc. There may be an osax out there, but your best and likely only bet will be to use obj-c…as you’ve tried already. The “NSInternalScriptError (8 )” errors you’re getting probably mean that your applescript version simply isn’t capable of doing what you’re trying to do the way you’re trying to do it.

I’m running panther, so I can’t guarantee this will work in jag but here’s what works for me…
I have a basic app with an image view, a text field, and a button. Note that the button will not be able to send messages to any applescript code, because a cocoa connection supercedes any applescript calls, and any handlers (such as a clicked handler) connected to the button will never be called. This is something I’ve been trying to work around by creating a custom class that responds to call method calls, but I’m not obj-c savy enough to work that out yet. You can provide an AS name for the image view and the text field and control their contents with AS, but the button will only respond to cocoa once it’s connected.

  1. Create the image view, a text field, and a button. Make sure to set the image view to something about 150x150 pixels, so it has room to display a full-size 128x128 icon. The text field will provide the path to the file you want the icon of. You may want to connect some AS code to another button that will set the value of the text field like…
set contents of text field "text" of window "main" to (choose file)
  1. In IB, click on the “Classes” pane in the nib window. Select NSObject (at the root of the classes). In the “Classes” menu in the IB main menu, select “Subclass NSObject”. A new subclass will be created to the right…name it “Controller”.

  2. Select the new “Controller” subclass, and then go to ‘attributes’ pane of the IB info window. Select ‘Outlets’, then click ‘Add’ (at the bottom). Name the new outlet “theFilePath”. Add another outlet and name it “theImageView”. Then, click on ‘Action’, and create an action named “setImageViewContents” in the same way.

  3. In the IB “Classes” main menu, select “Instantiate Controller”, and then select “Create Files For Controller”. This will create an IB object called “Controller” in the nib window, and will create “Controller.h” and “Controller.m” in your project.

  4. In IB, hold the ‘control’ key, and drag from your button to the ‘Controller’ object in the nib window. Under ‘Target/Action’, you should find “setImageViewContents:” as an option. Select it, and click “Connect” at the bottom. Now whenever the button is pushed, it will execute the code we provide soon in the “setImageViewContents” method.

  5. Again in IB, while holding ‘Control’, drag from the ‘Controller’ object to the image view. Under ‘Outlets’ select “theImageView” and then click ‘Connect’. Repeat this proces for the text field, connecting it to the “theTextField” outlet.

  6. In xcode (or project builder) go into the “Controller.h” file we created, where you should see something very similar to this…

/* Controller */

#import <Cocoa/Cocoa.h>

@interface Controller : NSObject
{
    IBOutlet id theFilePath;
    IBOutlet id theImageView;
}
- (IBAction)setImageViewContents:(id)sender;
@end

8.) Then go into the “Controller.m” file, where you’ll find a default implementation. Add any of the following code necessary to make the file look like this…

#import "Controller.h"

@implementation Controller

- (IBAction)setImageViewContents:(id)sender
{
NSImage* img = [ [ NSWorkspace sharedWorkspace ] iconForFile : [ theFilePath stringValue ] ];
// Make the icon it's full 128x128 pixel size; otherwise it's 32x32 //
[ img setSize:NSMakeSize(128.0,128.0)];
[ theImageView setImage: img ];
}

@end
  1. Unless I forgot something, you should now be able to build and run the app. The text field contains the path to the file you want the icon for. So, if you enter “/”, it should display the icon for the HD. If you enter “/Applications/” you’ll get the icon for your applications folder. You should be able to get the icon for anything you provide a valid posix path for.

From here you’ll have to figure out a way to put your path into the text field. If this doesn’t fit your exact needs, post what your exact configuration is and we can try to hammer it out. Also, there’s a lot more code you could put into this, like error-checking and such that I’m just not capable of doing in obj-c.

Good luck, hope this helps…
j

Thank you for your clear explanation.
It works perfect!

John dh

As I said, it works great with a button.

I wonder if it is possible to connect a table column to the Controller.
What I am trying to accomplish is:

  1. I have a table view and one of the columns contains the POSIX path.
  2. When the user clicks a row, the icon should be displayed
    from the contents of the matching column that contains the POSIX path.

Is there a way to get this working?

I tried myself but can’t get it to work.

Regards

John dh

Forgive for coming back to this Icon issue but I am still having a problem.
Sofar, I have successfully connected my table view to the Controller dataSource. So now the icon is automatically displayed when I click on a row.
The problem are the up/down arrow keys to scroll trough the table. These keys make the selection scroll but the image view does not change with it.

it would be perfect if the icon is also automatically displayed when you scroll trough the table using the arrow keys.

Could this be done or am I asking for the impossible?

Thank you and best regards

John dh

What I really need is to display the icon from a handler, but whatever I try, it does not work. I keep trying something like:

tell…
call method “iconForFile:” …
end tell

best regards

John dh

I am sorry to be so persistent and probably getting boring but I really need your help for the syntax of the call statement I would like to use.

I have been trying to figure this out myself for weeks but I just can’t get it to work.
the whole project succeeds or fails with this one issue.

The problem is that I cannot display the icon with a button. It must be done from within a handler (selection changed, the item from which the icon must be displayed is part of a table view)
So the question is: can I display the icon from within a handler? I have tried a great number of variations of the syntax of the call statement to get the icon. For example this one:

tell image view “iconImage” of window “main”
call method “setImageViewContents:” of object it
end tell

Finally I gave up, I just don’t have the knowledge of obj-C.
Could you please help me with the syntax of this statement.

On forehand thanks,

John dh

Assuming that you want to only use the direct call method, and not the IB actions to trigger your icon insert, scrap the IB connections and the “Controller” class, and use the following instead.

Create a new class named “IconController”, and only create the “IconController.m” file. In it, insert this…

#import <Cocoa/Cocoa.h>
#import <AppKit/AppKit.h>

@interface IconController : NSObject

+(void)displayIconInImageView:(NSImageView *)theImageView forFileIconAtPath:(NSString *)theFilePath;

@end

@implementation IconController

+(void)displayIconInImageView:(NSImageView *)theImageView forFileIconAtPath:(NSString *)theFilePath {
	NSImage* img = [[NSWorkspace sharedWorkspace] iconForFile:theFilePath];
	[img setSize:NSMakeSize(128.0,128.0)];
	[theImageView setImage:img];
}
@end

In your script call the method using…

set theFilePath to "/" --> Insert your code here to get the posix path to the file
set theImageView to (image view "image" of window "main") --> The image view to display the icon in
call method "displayIconInImageView:forFileIconAtPath:" of class "IconController" with parameters {theImageView, theFilePath}

That should do it for you…
j

Thank you Jobu, it works perfect.
There is just one little thing:
After I have cleaned the target and recompile, the IB generates the sytax error: illigal expression found ‘unknown’ on the call statement.
However, everything works fine.
Should I worry about this or just leave it the way it is?

Best Regards,

Johndh

If you’re working in the original project and deleted the old class, and are now using only the new class, this error may be because there is still a connection to the old one that the IB cannot find the method for. Go through your nib and make sure all the old connections are gone. I tend to get ambitous and try wild ideas on my main project which in the end only leads to the corruption of my nib. I now will usually create a test file on the desktop to test just one specific challenge and then cut/paste the code from it into my good project once I get it working bug-free. Then I can easily pitch the test project from the desktop. This seems to save me time in the end, as I don’t have to go back and totally re-create my project (as often) because of random corruptions caused by my continuous trial and error testing in my main project.

Glad it’s working, though…
j

Dear Jobu,

In order to test if my NIB is corrupt I made an entire new project with one button(choose file) and one image view(icon) and no connections. I carefully pasted the code to get the icon and compiled. I was surprised to see that the same warnings and error(s) occurred as shown below.


LOG....
IconController.m:1: warning: could not use precompiled header '/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa-gcc3.p', because:
IconController.m:1: warning: 'AvailabilityMacros.h' has different date than in precomp
/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h:12: warning: could not use precompiled header '/System/Library/Frameworks/Foundation.framework/Headers/Foundation-gcc3.p', because:
/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h:12: warning: 'AvailabilityMacros.h' has different date than in precomp
/System/Library/Frameworks/Foundation.framework/Headers/NSAppleEventDescriptor.h:8: warning: could not use precompiled header '/System/Library/Frameworks/ApplicationServices.framework/Headers/ApplicationServices-gcc3.p', because:
/System/Library/Frameworks/Foundation.framework/Headers/NSAppleEventDescriptor.h:8: warning: 'AvailabilityMacros.h' has different date than in precomp
/System/Library/Frameworks/ApplicationServices.framework/Headers/ApplicationServices.h:20: warning: could not use precompiled header '/System/Library/Frameworks/CoreServices.framework/Headers/CoreServices-gcc3.p', because:
/System/Library/Frameworks/ApplicationServices.framework/Headers/ApplicationServices.h:20: warning: 'AvailabilityMacros.h' has different date than in precomp
/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h:13: warning: could not use precompiled header '/System/Library/Frameworks/AppKit.framework/Headers/AppKit-gcc3.p', because:
/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h:13: warning: 'AvailabilityMacros.h' has different date than in precomp
IconController.m:13: illegal expression, found `unknown'
IconController.m:14: illegal expression, found `unknown'
IconController.m:15: illegal expression, found `unknown'
cpp-precomp: warning: errors during smart preprocessing, retrying in basic mode
......LOG

However, again it works perfect. yet I still am a bit worried about this.
What is smart preprocessing and basic mode?

best Regards,

John

Hope I am not intruding into your post, but I have been following this topic because I am looking at doing something very similar. I used the code from Jobu’s post on August 03 and it worked perfectly. I would like to take the icon graphic loaded into the image view and save it as a graphics file on my computer (to import into FileMaker). If I try to use Applescript to access the icon graphic I recieve errors. My test script tries to set a new image view “image2” to the contents of image view “image” as follows:

I can successfully load the contents of a graphics file on my computer into the image view “image2”, but cannot load the contents of the image view “image” into “image2”. I had made the assumption that once image view “image” had an icon file in it that AppleScript could handle this as it would handle any graphics file on my hard drive - evidently I am mistaken. Any ideas on where I am going wrong?

Thanks for your time,
jON bEEBE