Objective-J is based on Objective-C and is fun. When I learned Javascript some years ago, I could not manage to write a line of JavaScript. What a mess to have just animation in web browser. And at that time, no debugger was available. On the desktop, I could play with the Cocoa framework and Objective C to solve real problems, not just animations.
Latest version of browsers (Firefox or Safari 4) have changed the landscape, we now have a good debugger to solve the typos and bugs. Now Objective-J and the Cappuccino framework enable us to have the same feel of developping application for the desktop but in a browser. This changes everything. I am now waiting improvments and polishing of Cappuccino. I the mean time, we can start using Cappuccino to be ready when next version arrives.
I have included the class Person that was used in the tutorial about Ojective-J. One small addition is the method -(CPString) description. This enable us to have a better reporting when debugging the program. You will see that in few minutes.
@implementation Person : CPObject
{
CPString name;
CPString jobTitle;
CPString company;
}
+ (id)personWithName:(CPString)aName
{
return [[self alloc] initWithName:aName];
}
- (id)initWithName:(CPString)aName
{
self = [super init];
if (self)
{
name = aName;
jobTitle = @"";
company = @"";
}
return self;
}
- (void)setName:(CPString)aName
{
name = aName;
}
- (CPString)name
{
return name;
}
- (void)setJobTitle:(CPString)aJobTitle company:(CPString)aCompany
{
jobTitle = aJobTitle;
company = aCompany;
}
-(CPString) description
{
return [[CPString alloc] initWithFormat:@"name: %@ jobTitle: %@ company: %@", name, jobTitle, company];
}
@end
Well, the fundation framework contains non GUI objects. We will use all of them : CPArray, CPDictionary, CPNull, CPData, CPDate, CPNumber, CPString. Just create a small application containg a centered button.
We will put the code in the method - (void)playWithArray:(id)sender that is triggered by a click on the button.
[button setTarget:self];
[button setAction:@selector(playWithArray:)];
Another interesting code is CPLogRegister(CPLogPopup) which enable us to see the output of CPLog.trace(message).
@import
@import "Person.j"
@implementation AppController : CPObject
{
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
/* Enable Logging (DEBUG) */
CPLogRegister(CPLogPopup);
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
contentView = [theWindow contentView];
var button = [[CPButton alloc] initWithFrame: CGRectMake(CGRectGetWidth([contentView bounds])/2.0 - 40, CGRectGetHeight([contentView bounds])/2.0 - 9, 80, 18)];
[button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin];
[button setTitle:"Play with array"];
[button setTarget:self];
[button setAction:@selector(playWithArray:)];
[contentView addSubview:button];
[theWindow orderFront:self];
}
You should read the tutorial on debugging Ojective-J programs. You need to know how to enable the debugger in Firefox 3 or Safari 4. When it is done, you can use the debugger command to stop the execution of your code. This enable you to check the content of your variables (and the stack frame).
- (void)playWithArray:(id)sender
{
debugger;
We start to play with the Person class by creating two objects (john and joe). We also use CPString object and chain message calls [[object message1] message2]. We now use our description method to see our object easely : CPLog.trace([joe description]).
var john = [[Person alloc] initWithName:@"dummy"];
var name = [[CPString alloc] initWithString:@"Jo"];
name = [[name stringByAppendingFormat:@"%@", @"hn"] uppercaseString];
[john setName:name];
[john setJobTitle:@"Engineer" company:@"Best sofware Inc."];
var joe = [Person personWithName:"Joe"];
[joe setJobTitle:@"Funder" company:@"Even better sofware Co."];
CPLog.trace([joe description]);
Now it is time to play with CPArray, CPDictionary, CPNull, CPData, CPDate, CPNumber, CPString. A dictionary is the standard way of passing around key-value pairs in the Cappuccino framework. It is similar to the Java map interface, except all keys are CPStrings and values can be any Cappuccino or JavaScript object. If you are familiar with dictionaries in Cocoa, you'll notice that there is no CPMutableDictionary class. The regular CPDictionary has setObject: and removeObjectForKey: methods. In Cappuccino there is no distinction between immutable and mutable classes. They are all mutable.
We reuse our Person objects and add them in the CPDictionary object. The method description of Person object will be called by [dict description].
var keys = [CPArray arrayWithObjects:@"key1", @"key2", @"John", @"Joe", nil];
var objects = [CPArray arrayWithObjects:@"value1", [CPNumber numberWithBool:NO], john, joe, nil];
var dict = [CPDictionary dictionaryWithObjects:objects forKeys:keys];
[dict setObject:[CPNumber numberWithDouble:9.9] forKey:@"key3"];
[dict removeObjectForKey:@"key1"];
CPLog.trace("dict : " + [dict description]);
var myNull = [CPNull null];
var data = [CPData dataWithString:@"Cappuccino"];
var date = [CPDate date];
var number = [CPNumber numberWithBool:YES];
var array = [CPArray arrayWithObjects:@"string1", @"string2", myNull, date, number, data, dict, nil];
var mutableArray = [CPArray arrayWithCapacity:10];
[mutableArray addObjectsFromArray:array];
[mutableArray addObject:@"new one"];
CPLog.trace("dict : " + [mutableArray description]);
CPLog.trace("end");
}
@end
Now that we have seen the objects available in Fundation, we will play with the GUI part of Cappuccino : AppKit.
If you'd like to see the complete code listing from the tutorial, you can download it all in a single file: Tutorial1.zip. The web application is available online: Tutorial1