NSView, NSScrollView, NSClipView: IMReallyImpressed

I’ve just started working on the graphics part of my program and thus far I’ve been massively impressed by Cocoa’s offerings in this area. Admittedly, I haven’t done a whole lot — I’m currently just drawing using NSString’s drawInRect:withAttributes: (from AppKit’s NSString additions) and some NSBezierPath methods.

The largest source of awe so far has been just how easy it is to place an NSView subclass inside an NSScrollView. This is a task that involves no code whatsoever — one simply has to select the “Make subviews of > Scrollview” command in Interface Builder and your custom view is now scrollable.

I think the most impressive facet of this set up is the elegance of the view hierarchy. Your custom NSView subclass effectively forms a canvas, only a portion of which is displayed in the scroll view. The visible part of the view is generally referred to as the content view (and is an instance of NSClipView) and that’s pretty much it — the scroll view provides the scroll bars and resizes them as the size of the “canvas” changes (I’m using NSView’s setFrameSize: and setFrameOrigin: methods to obtain the desired stretching of my view in response to an NSSlider.) Here’s how it’s looking at the moment:

GFF Viewer window

NSTableView delegate and data source

I’ve just successfully implemented my first “delegate” (and indeed datasource) object in Cocoa, so this post is mostly a result of my excitement for actually making something work. However, making this work is actually not very impressive at all, but I’m still happy, especially when I consider that I didn’t know what a delegate was until last week :)

There’s a great article here that describes what a delegate is, that is:

A delegate is an object which is able to influence the behavior of another object by responding to delegate messages. A class that uses a delegate has a “delegate” instance variable and defines a number of “delegate methods”. An instance of that class will then send delegate messages to its delegate for help on deciding how to behave.

In other words, delegation allows for one object to ask another object to do something on its behalf (much like a delegate in real life). Delegation can, therefore, be a simple alternative to subclassing — rather than implementing a whole new class to customise an object’s behaviour, simply have a delegate object sign up to be invoked when the custom behaviour is required.

The delegate object in this case was my view controller, which needs to respond to the user selecting a different line in my NSTableView. The way to do this involves only 2 steps:

  1. implementing the method – (void) tableViewSelectionDidChange:­(NSNotification *)­notification
  2. connecting up the controller object as the delegate in Interface Builder

In my case, the first stage did literally involve just adding the following code (for now) to my view controller class:
- (void) tableViewSelectionDidChange:(NSNotification *)notification {
int currentRow = [motifList selectedRow];
if (currentRow == -1) {
return;
}
[motifName setTitle:[self tableView:motifList objectValueForTableColumn:motifNameColumn row:currentRow]];
}

The only vaguely interesting bit here is that I send the message tableView:­objectValueForTableColumn:­row: to self. This is because my view controller is also the datasource for the very same NSTableView. motifName, in case you’re wondering is an NSBox.

The second stage is even simpler and involves control-dragging from the NSTableView to the controller object in Interface Builder and selecting the delegate outlet, as shown here:
NSTableView delegation

Implementing the same object as the NSTableView datasource is even simpler, involving only the addition of the following two methods from the (appropriately-named) NSTableDataSource class:

  • – (int)numberOfRowsInTableView:(NSTableView *)theTableView
  • – (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)theColumn row:(int)theRow

In my case (where I’m pulling values from an array) it’s just a case of returning [array count] and [array objectAtIndex:theRow] respectively for those methods. That’s all for now!

BASHing biology

Just a quick post from work… I’ve recently been using UNIX stalwarts sed, tr and grep quite regularly to manipulate DNA sequence files, so I thought I’d post a few handy little commands for your perusal.

To strip out all the annotations in a FASTA file, leaving just the bare, unseparated sequences:
grep -v '^>' sequence.fasta | tr -d "[:space:]"
To then output the total length of the sequences, simply append | wc -c.

To calculate the total number of sequences contained in a FASTA file:
grep '>' sequence.fasta | wc -l

To read out a DNA sequence, capitalise it and group the bases into threes (i.e. codons):
cat sequence.seq | sed s/.../\&\ /g | tr "[:lower:]" "[:upper:]"

To obtain the complement of a sequence, use tr as follows:
cat sequence.seq | tr TACGtacg ATGCATGC
For the reverse complement, append | rev.

I’ve also found the pbcopy and pbpaste utilities to be particularly useful. To grab the reverse complement of a sequence copied from, say, a web page, just type the following:
pbpaste | tr TACGtacg ATGCATGC | rev | pbcopy
This takes the sequence currently on the clipboard and replaces it with its reverse complement. There’s a caveat here, which is that rev only reverses each line of the input, not the entire input. As such, if you’ve copied a sequence containing line breaks, you’ll need to add a tr -d “[:space:]” to remove the white space before invoking rev.