Things I’ve learned while playing with AppKit

Every framework I have ever encountered, every API, Toolkit, or whatever, consists of (a) a specification, (2) an implementation, and (3) a whole bunch of bugs which require experience to understand and work around. In many ways one could say that the difference between one who is just learning a framework and one who understands the framework is in part measured by how many bugs one “just knows how to work around.”

Here is what I’ve learned so far about Apple’s AppKit:

(1) If you want to make Apple’s synchronized scrolling hint work, you need to make sure the document views across the different scroll windows have the same frame origin. In order to guarantee this, the following snippet of code seems to work for me:

- (id)initWithFrame:(NSRect)frame 
{
	/* Kludge: Modify the origin to be 0. This forces the value to be 0 so
	 * we can do synchronized scrolling across multiple desparate objects.
	 * Otherwise, we don't have a common origin, so things don't synchronize
	 * as the value of the origin is essentially random from the nib.
	 */
	
	frame.origin.y = 0;
	frame.origin.x = 0;
	
    self = [super initWithFrame:frame];
    if (self) {
         ... the rest of your initialization goes here ...
    }
    return self;
}

(2) (And the subject of my last rant post) If you embed a your own custom view within an NSScrollView, if your view implements either -(NSView *)headerView or -(NSView *)cornerView, you’ll get either a horizontal header or a corner view a’la the NSTableView’s documentation on both of these methods. (In other words, NSScrollView handles and manages the NSClipView for the table view by seeing if the document implements these methods.) Handy if you need a custom header along the top of your document view–though honestly, if you’re creating a table or a drawing program, you’re better off using the built-in NSTableHeaderView or NSRulerView classes instead.

For example:

- (NSView *)headerView
{
	if (fRuler == nil) {
		NSRect r;
		
		r.origin.x = 0;
		r.origin.y = 0;
		r.size.width = 320; // default width; resize frame with correct width as frame resizes
		r.size.height = 16;
		
		fRuler = [[ResourceRulerView alloc] initWithFrame:r];
	}
	return fRuler;
}

(3) Oh, and to answer the off-asked question how do you get your content view document to grow from top down rather than from bottom up, and how to stick to the top:

(a) Implement -(BOOL)isFlipped in your custom view. Return YES. Yes, this flips the coordinate system so the upper left corner is the origin, instead of the lower left corner. No, I don’t know how to do this without flipping the coordinate system: I’m new to this whole thing. 🙂

(b) Make sure you flip the autosize parameters as shown below:

Disclamer: All of these things seemed to work for me. However, I reserve the right (as always) to be a complete idiot and get the details wrong.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s