Thursday, February 25, 2010

TimeLine view - header

I have been working on the timeline header view. In Cello this is called the FrameView as it contains details of fime frames. I have just got the selection working. The selection normally shows a single frame - the current frame, but it is possible to select a contiguous strip of frames as well.

Before starting work on the selection I once again had a look at CocoaTron NSTableView to see how the mouse down - and shift selection was handled. The code was less liftable - but studying someone else's code is always useful.

Selection of a Single Frame

Selection of Multiple Frames

Friday, February 19, 2010

Drag resizable columns in a headerless NSTableView

Currently table headers are responsible for handling the dynamic resizing of table columns. I have needed to make it possible to resize table columns from within the table - so the idea is that you will be able to:
  • move your mouse to the divider between two columns
  • the cursor will change to indicate that you can resize the column
  • click and drag and your column will resize.
I already have a NSTableView sublclass that has modest, general, enrichments for the very few enhancements I need to NSTableView - so my aim is to enhance this a little.

As a start point I looked at the CocoaTron code for the NSTableHeader. My thought was the CocoaTron NSTableHeader will be much like the cocoa table header, it handles resizing so will in the least be a reasonable template for implementing my own table. As it happens I was able to more-or-less copy/paste the code for the following key methods into my NSTableView.

-(void)resetCursorRects;
-(void)resizeWithOldSuperviewSize:(NSSize)size;
-(void)mouseDown:(NSEvent *)theEvent;

Of course there is a little more to it than this - but it is small beer and this small piece of CocoaTron proved an excellent starting - and indeed took me most of the way.

Wednesday, February 17, 2010

Synchronizing the selection in two NSTableViews

I have been looking at a problem of synchronizing the selection across two NSTableViews. It took a few attempts to come to a solution that worked as I wanted it to. The idea is to have two table views with the same number of elements - as soon as you make a selection in one the other one updates to show the same items selected.

My first port of call was to hook into the tableViewSelectionDidChange notification. Then when one selection changes you just change the other. This works - but there is a lag. Click in one table the selection changes, the window updates and then the second selection changes.

The solution was to override selectRowIndexes and to use that to trigger the selection in the paired table. This works fine and produces the required results. I was able to 'hack' this in as a proof of concept fairly quickley.

Implementing it 'properly' or rather 'as I wanted it' I dod not want my two tables to carry references to each other - insead I wanted to have this in the controller class. I did this my adding a new protocol to my subclass of the table:

- (void)selectedRowIndexes:(NSIndexSet *)indexes forTableView:(NSTableView *)tableView byExtendingSelection:(BOOL)extend;

Then, by implementing this protocol, I can add the synchronization logic to the controller which is where I want it.

Monday, February 15, 2010

Interface Builder

Working with an application framework has a few parts - there is the first staggering steps of familiarity and the kind of awkwardness you have because of the difference between what you knew before and what you are looking at. Then there is the familiarity when you know more-or-less how to do what you did before and then there is that time a while later when you sort of "get it". This part is the most exciting part as that is when you can work with the flow and get the benefits of the good current.

I think have had something of a slow burn Eureka moment with interface builder. It goes like this - any class member that is declared with the magic IBOutlet in front of it can be connected up in interface builder. It is difficult to kick off in Cocoa (I started with Aaron Hillegass' book) without seeing that this is the way you connect up views and controllers - but you can connect up other things as well. If you have a table and you need to deal with the columns you can do it in two ways. You can give each column an Identifier and loop through the columns until you find the column that you want - or you can pick out the columns you want, add them to your controller with a IBOutlet - and hook them up in Interface builder. The anything part of this is quite powerful - if you need to set attributes on the NSCell derivative that powers the drawing of your column - you can hook this up as well - and so it goes on.

Thursday, February 4, 2010

BWToolKit

I have downloaded and built BWToolKit by Brandon Walkin. This is a framework that extends the existing components that are available in Inerface Builder. It is of particular interest to me at the moment as it contains an improved splitter. The BWSplitView is a subclass of the NSSplitView that handles improvements like the splitter collapsing, max min sizes etc. BWToolKit comes with interface builder plugin so you can drag out Brandon Walkin's carefully crafted goodies just as if they were a piece of appkit. BWToolKit is available under the New-BSD licence. I downloaded the code and built it myself as I feel insecure if I don't have the source code.

Sunday, January 17, 2010

Moving MFC icons to Cocoa

Working my way through the timeline MFC to Cocoa conversion I have once again bumped up against graphic resources. Various components in the UI have graphic resources (icons). Back when I was getting the basic engine to work I compiled out all things of this ilk with a huge amount of other things with a

#define _NO_UI.

A part of my approach is that the structure of the new UI follows the PC version very closely so I am bumping into the way that Icons are handled within Cello as a whole. Basically this I am gradually working my way through some of these #if _NO_UI blocks.

Existing graphic resources in the PC version are stored as .bmp files. Each file typically has a number of icons. The various components that comprise the system (such as the 20-30 effects) have factory functions that specify a name for the component, and a bitmap resource with an offset as an icon. This is achieved by all the components inheriting from a base class that maintains this. The upshot is that I have to tackle this base class and bring it into line, and because I hit the constructor, I also have to attend to the many sub-classes that use icons.

In the OSX version of Cello I use NSImage to represent an icon - and as an alternative to specifying an icon resource and offset simply specify a name. This name is the name is nothing more than the filename that of the icon that appears in the bundle. I have written a really simple wrapper based on boost intrusive_ptr that wraps the NSImage for use in C++. The existing icons are appropriate to Windows and will look really out of place in OSX but that is a problem for another day and a problem that I hope to hand over to an icon designer. For place-holder icons I take the existing icons bring them to my old Power-PC and use an old copy of Photoshop to turn them into individual PNG files.

Monday, January 11, 2010

Mutating MFC to Cocoa

I am making progress converting the view hierarchy of the timeline to cocoa. In the about face I am working through the classes and interfaces that are defined in MFC and attempting a mechanical conversion where possible. In my first cut I do the following:
  • Mutate the all 'interface' definitions to protocols.
  • Mutate all pure virtual base classes into protocols.
  • Mutate all other classes as objective C classes.
  • Where a class is based on multiple inheritance of a C++ class (typically mix-in classes) this is expressed as a protocol and I write a subclass of the mix-in class that funnels calls to an object of that protocol.
  • Comment out what is obviously not needed for a first cut.
I do the conversion bit by bit getting the compiler to guide me. It is a relentless, tireless guide. At best I get logic and code that is very close to what I need at worst I get a fill-in-the-dots template. Importantly the code dovetails in nicely into the existing code.