Dynamic objects

i was wondering if it was possible to create dynamic objects with code (panels, buttons, imageviews, etc.). How would you do that?

thanks.

Nope, sorry. With applescript you can only create objects before-hand, and then manipulate them… such as their visibility, value, enabled, state, etc. One psuedo-exception to this is document-based applications which can create a new “instance” of an object (like a window) from a template supplied in your document nib. This is only practical in the case of one specific window object in your app, though.

If you got creative using obj-c, you can instantiate new objects, or copy/clone existing ones, but then you’d have to write all of your code in obj-c. Accessing cocoa-generated objects with applescript can be done, but it’s difficult and could get quite intense in more complex applications…

Another option is creating separate nibs for your hidden objects, and then only loading them when needed. That way they are not loaded into your app’s memory until necessary, and you can keep your main nib clean and simple. Then just use something like { load nib “extrasNib” } and refer to the newly loaded objects as you would any other object.

Ultimately, I think most would agree that creating an object, and then “hiding” it until it is needed is the best applescript studio practice for “simulating” dynamically created objects. You list a broad spectrum of objects in your post (“panels, buttons, imageviews”) so it’s tough to give you any specifics on dealing with this. Windows and panels can be left in the background and accessed using the ‘hide’ and ‘show’, or ‘display’ and ‘close’ commands, respectively. Buttons can be toggled using the ‘visible’ and ‘enabled’ properties. And some objects like text fields and image views can modify their ‘visible’ property, or can simply be set to an empty string or an invisible image to make them “disappear”. Let us know if you need any further clarification or specific examples of some ASS workarounds.

j

in that case, is there a way to use and interact with a cocoa class from applescript that can deal with the copying or instantiating objects. Thanks for the response.

You’ve got to be more specific. Given the right amount of information, just about anything CAN be done. :wink:

Writing obj-c code is not necessarily easy though, especially when using applescript as the front door. Plus, every object has a different way of initializing and defining it, so what you’d use to create a button would not help when creating a window.

So, what is it exactly that your trying to do? How many of the mystery object do you want to create? What do you want to be able to do with it? What happens with it when it’s done being used. I can’t give you a generic bit of code that will do it all, so I have to get some real details.

j

ok. Im trying to be specific here. I’m going to make a konfabulator clone (just for my entertainment). What i need most is basically the ability to create image views at any time and place them in a window that is already loaded from a nib.

AS code…

set contentView to content view of window "myWindow" --> 'myWindow' is the window to insert into
set theImage to load image "myImage" --> The image to put in the image view
set DYNobjects to call method "alloc" of class "DYNobjects"
set newImageView to call method "createImageView:frame:image:" of DYNobjects with parameters {contentView, {0, 0, 200, 200}, theImage}
set name of newImageView to "myImageView" --> Set it's AS name for later reference

Create a new cocoa class, only the ‘.m’ file, and name it “DYNobjects.m”…

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

@interface DYNobjects : NSObject
- (NSImageView *)createImageView:(NSView*)contentView frame:(NSRect)inFrame image:(NSImage*)theImage;
@end

@implementation DYNobjects
- (NSImageView *)createImageView:(NSView*)contentView frame:(NSRect)inFrame image:(NSImage*)theImage
{
	// Create the image view
	NSImageView* imgView = [[NSImageView alloc] initWithFrame:inFrame];
	[imgView setImage];

	// Add the image view to the window
	[contentView addSubview:imgView];  
	[imgView release];
	return imgView;
}
@end

This will dynamically create a new image view, and place it in the window “myWindow”. Cocoa uses a left/bottom/width/height coordinate system, which is what you’ll use to define the size and position of the image in the window. This example puts a 200x200 image view in the bottom left corner of the window. Stacking of objects appears to be chronioligical, so any object you create gets put on top of all others… so your image will block all other content in the window when created. You should be able to tweak that if necessary.

I also have the code to generate a new window and also a button, so let me know if you need them too and I’ll clean them up a bit.

Hope that helps ya,
j

thanks!!
that works really well!!

…now a few more things:
i want to be able to make a new window from a custom window class (CustomWindow.m) and insert dynamic images into that widow. Also, is the dynamic image view “enabled”, because if it is, i need to make it disabled.

thank you sooo much for all your help, jobu!

As far as the image view ‘enabled’ property goes, once you create the image view you can reference it as any other object. Assuming you’ve used the AS code below to create and identify the new window and image view, you should be able to use one of these…

set enabled of newImageView to false
-- OR --
set enabled of image view "myImageView" of window "customWindow" to false

For the custom window, you can’t really call the existing code, as it’s set up as a subclass of the window class, and is intended to be wired up via IB. You can create a whole new object subclass, as you’ve done in the DYNObjects class we created, and add a method to it that creates a new window and uses the same properties as your customwindow class.

AS Code…

set DYNobjects to call method "alloc" of class "DYNobjects"
set customWindow to call method "createCustomWindow:" of DYNobjects with parameters {{200, 200, 480, 360}}
set name of customWindow to "customWindow"
		
set contentView to content view of customWindow
set theImage to load image "myImage"
set newImageView to call method "createImageView:frame:image:" of DYNobjects with parameters {contentView, {10, 10, 200, 200}, theImage}
set name of newImageView to "myImageView" --> Set it's AS name for later reference
		
show customWindow

Add this new method to the “DYNObjects” class…

//--> Add to interface
- (NSWindow *)createCustomWindow:(NSRect)contentRect;

//--> Add to implementation
- (NSWindow *)createCustomWindow:(NSRect)contentRect {
	NSWindow* result = [[NSWindow alloc] initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
	[result setBackgroundColor: [NSColor clearColor]];
	[result setLevel: NSStatusWindowLevel];
	[result setAlphaValue:1.0];
	[result setOpaque:NO];
	[result setHasShadow: YES];
	
	return result;
}

Enjoy,
j

the custom window class i have has that code for handling window dragging…will that still work using the code above?

also, i want to execute an action when you control-click on one of the dynamic image views. i saw you can add the mouse-down function (the control clicking to be added onto this in applescript) from interface builder and “choose” your script as the target, but how would you do this when you create it? is some way to do what interface builder does in applescript?

thanks

are these right?

to createImage(imagefile, targwindow, newname)
	set contentView to content view of window targwindow --> window to insert into 
	set theImage to load image imagefile --> The image to put in the image view 
	set DYNobjects to call method "alloc" of class "DYNobjects"
	set newImageView to call method "createImageView:frame:image:" of DYNobjects with parameters {contentView, {0, 0, 253, 60}, theImage}
	set name of newImageView to newname --> Set it's AS name for later reference
end createImage

to createWindow(winname)
	set DYNobjects to call method "alloc" of class "DYNobjects"
	set customWindow to call method "createCustomWindow:" of DYNobjects with parameters {{200, 200, 480, 360}}
	set name of customWindow to winname
	show customWindow
end createWindow

i get a reciever evaluation script error and i think it might have to do with one (or both) of these. i have everything just the way you said in the DYNobjects file, so im sure its here.

Hi…

Any idea how to adopt this method to create a dynamic date picker control object on a tab view item?

Note: I want the date selection attribute to be none and time selection hour and minute.

Background: inclusion of the date picker in the nib apparently crashes on pre-tiger systems. if I were to load this object onto the interface ONLY IF the user had tiger, would this solve the problem? Or do you think it would still crash?

EDIT:

I tried to create just the original project, and could not compile it. I get this message:

/Users/lryter/Documents/development etc/Project builder projects/createdatepicker/DYNobjects.m:21: fatal error: error writing to -: Broken pipe

the final “@end” in the class code is marked with the red x circle.