// // NumericalArrayDS.h // // Numerical array data sources for NSTableView. Simplifies the binding of // a simple array of numbers (integers and floating point types) to a // Cocoa table. // // This source code is provided as-is, and I provide no warranty as to its // functioning. That being said, I have done a bit of testing with it and // it seems to work fine. // // No explicit licensing is attached to this source code, I merely ask // that you let me know if it was useful to you in your project, and if you // would just make mention in the documentation somewhere that you used // this work. // // Created by Jeffrey Frey on 28 Jan 2007 // Copyright (c) 2007 // #import /*! @protocol NumericalArrayAccess Methods that must be implemented by any numerical array-representing class that wishes to use the NumericalArrayDS for tabular display. */ @protocol NumericalArrayAccess - (int) rows; - (int) columns; - (NSNumberFormatter*) defaultFormatter; - (NSNumber*) valueAtRow:(int)row column:(int)column; - (void) setValue:(id)value atRow:(int)row column:(int)column; @end // // Some pre-defined numerical array represetation classes. // /*! @typedef NumericalArrayType The C type of numerical data in the array. */ typedef enum { NumericalArrayTypeInt = 0, NumericalArrayTypeLong, NumericalArrayTypeLongLong, NumericalArrayTypeFloat, NumericalArrayTypeDouble, NumericalArrayTypeMax } NumericalArrayType; /*! @typedef NumericalArrayOrientation The orientation of the stored data. Column-major implies that the first N bytes represent the first column of an N x M array; row-major implies that the first M bytes represent the first row of an N x M array. */ typedef enum { NumericalArrayOrientationColumnMajor, NumericalArrayOrientationRowMajor } NumericalArrayOrientation; /*! @class NumericalArray Generic wrapper for C numerical arrays. Handles several integer types, floats, and doubles, in both row- and column-major storage formats. Given a 25 x 25 array of float's stored row-major, an appropriate allocation would be:
float             dummy[25 * 25];
NumericalArray*   myArrayRep;

myArrayRep = [[NumericalArray alloc] initWithArrayType:NumericalArrayTypeFloat
               array:dummy
               rows:25
               columns:25
               orientation:NumericalArrayOrientationRowMajor];
  
*/ @interface NumericalArray : NSObject { NumericalArrayType _arrayType; NumericalArrayOrientation _orientation; int _rows,_columns; void* _array; BOOL _freeWhenDone; } /*! @method initWithArrayType:array:rows:columns: Convenience method that calls initWithArrayType:array:rows:columns:orientation: with an orientation of NumericalArrayOrientationColumnMajor. */ - (id) initWithArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns; /*! @method initWithArrayType:array:rows:columns:orientation: Convenience method that calls initWithArrayType:array:rows:columns:orientation:fwd: with fwd set to NO. */ - (id) initWithArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns orientation:(NumericalArrayOrientation)orientation; /*! @method initWithArrayType:array:rows:columns:orientation:freeWhenDone: Designated initializer. The array enters the receiver as a typeless pointer since we internally deal with several different types of atomic numerical data. If array is NULL, then the storage is allocated by this method and will be deallocated when the instance is. If you pass a non-NULL array, then the value of fwd determines whether or not the array should be free'd when the instance is deallocated. */ - (id) initWithArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns orientation:(NumericalArrayOrientation)orientation freeWhenDone:(BOOL)fwd; /*! @method arrayType Returns the NumericalArrayType of the receiver's array. */ - (NumericalArrayType) arrayType; /*! @method orientation Returns the NumericalArrayOrientation of the receiver's array. */ - (NumericalArrayOrientation) orientation; /*! @method array Returns the receiver's array (as a typeless pointer). */ - (void*) array; @end /*! @typedef NumericalArrayTriangular Enumerated constants used to indicate that a numerical array is upper- or lower-triangular. */ typedef enum { NumericalArrayTriangularUpper, NumericalArrayTriangularLower } NumericalArrayTriangular; /*! @class NumericalTrianularArray Generic wrapper for C triangular numerical arrays, implemented as a simple sub-class of the NumericalArray. */ @interface NumericalTrianularArray : NumericalArray { NumericalArrayTriangular _triangularity; } /*! @method initWithUpperTriangularArrayType:array:rows:columns: Convenience method that calls initWithUpperTriangularArrayType:array:rows:columns:orientation: with an orientation of NumericalArrayOrientationColumnMajor. */ - (id) initWithUpperTriangularArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns; /*! @method initWithUpperTriangularArrayType:array:rows:columns:orientation: Designated initializer. The array enters the receiver as a typeless pointer since we internally deal with several different types of atomic numerical data. */ - (id) initWithUpperTriangularArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns orientation:(NumericalArrayOrientation)orientation; /*! @method initWithLowerTriangularArrayType:array:rows:columns: Convenience method that calls initWithLowerTriangularArrayType:array:rows:columns:orientation: with an orientation of NumericalArrayOrientationColumnMajor. */ - (id) initWithLowerTriangularArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns; /*! @method initWithLowerTriangularArrayType:array:rows:columns:orientation: Designated initializer. The array enters the receiver as a typeless pointer since we internally deal with several different types of atomic numerical data. */ - (id) initWithLowerTriangularArrayType:(NumericalArrayType)type array:(void*)array rows:(int)rows columns:(int)columns orientation:(NumericalArrayOrientation)orientation; /*! @method triangularity Triangularity of the receiver's array. */ - (NumericalArrayTriangular) triangularity; @end // // Now for the NSTableView facilitator itself: // /*! @class NumericalArrayDS Facilitates easy reconfiguration of an NSTableView to display a two-dimensional array of numerical values. Instances are immutable and act as the NSTableView data source (hence the 'DS' in the class name) and move data array => NSTableView as well as NSTableView => array -- so you get a simple i/o interface between the UI and your array. The data source must then be bound to an NSTableView in order for the table to be reconfigured to the appropriate number of columns and formatting. You may supply a dictionary of display parameters or allow the binding method to setup default values for you.
NSDictionary*     attrs;

attrs = [NSDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithInt:100],NumericalArrayDSMaximumColumnWidthKey,
            [NSFont userFixedPitchFontOfSize:12.0f],NumericalArrayDSFontKey,
            nil];
[myDS bindToTableView:aTableView displayAttributes:attrs];
  
In this case I specified that the columns of the table should be no larger than 100 pixels and the font should be fixed-pitch, 12.0 points large. */ @interface NumericalArrayDS : NSObject { id _array; } /*! @method initWithNumericalArray: Designated initializer. If array is an object whose class does not conform to the NumericalArrayAccess protocol, nil is returned. Otherwise, array is sent a retain message and the newly initialized instance is returned. */ - (id) initWithNumericalArray:(id)array; /*! @method bindToTableView:displayAttributes: Removes all columns currently in aTable and replaces them with a uniform set of columns configured to display the numerical array. A set of display options may be passed to this method in an NSDictionary: - An NSCell that should act as the template for all columns - The initial, minimum, and maximum widths of the columns Lacking a template NSCell in the dictionary this method will create a default template NSCell. You may override the following default attributes with values in the displayAttributes dictionary: - The font - The NSNumberFormatter used to display the values Once the template NSCell has been constructed and the new columns created for the table, the receiver is set as both the delegate and data source of aTable and aTable is told to reload (and thus redisplay its content). */ - (void) bindToTableView:(NSTableView*)aTable withDisplayAttributes:(NSDictionary*)displayAttributes; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 /*! @method tableView:toolTipForCell:rect:tableColumn:row:mouseLocation: NSTableView delegate method. Displays a tooltip over a table cell -- we merely show the row and column of the cell. */ - (NSString*) tableView:(NSTableView*)tv toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tc row:(int)row mouseLocation:(NSPoint)mouseLocation; #endif /*! @method numberOfRowsInTableView: NSTableDataSource informal protocol method. Returns the number of rows in the table. */ - (int) numberOfRowsInTableView:(NSTableView*)aTableView; /*! @method tableView:objectValueForTableColumn:row: NSTableDataSource informal protocol method. Returns the value (as an NSNumber) of the specified row and column of the table. */ - (id) tableView:(NSTableView*)aTableView objectValueForTableColumn:(NSTableColumn*)aTableColumn row:(int)rowIndex; /*! @method tableView:setObjectValue:forTableColumn:row: NSTableDataSource informal protocol method. Sets the value (as an NSNumber or NSString) of the specified row and column of the table. */ - (void) tableView:(NSTableView*)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn*)aTableColumn row:(int)rowIndex; @end /*! @const NumericalArrayDSCellTemplateKey Keys a pre-constructed NSCell template that should be used by bindToTableView:displayAttributes: when it constructs the NSTableColumn instances. */ APPKIT_EXTERN NSString* NumericalArrayDSCellTemplateKey; /*! @const NumericalArrayDSFontKey Lacking an NSCell template, keys the font that is to be used in the cell template that bindToTableView:displayAttributes: itself constructs. */ APPKIT_EXTERN NSString* NumericalArrayDSFontKey; /*! @const NumericalArrayDSFormatterKey Lacking an NSCell template, keys the NSNumberFormatter that is to be used in the cell template that bindToTableView:displayAttributes: itself constructs. */ APPKIT_EXTERN NSString* NumericalArrayDSFormatterKey; /*! @const NumericalArrayDSInitialColumnWidthKey Keys an NSNumber specifying the initial width of the new columns that bindToTableView:displayAttributes: constructs. Defaults to 25 pixels. */ APPKIT_EXTERN NSString* NumericalArrayDSInitialColumnWidthKey; /*! @const NumericalArrayDSMinimumColumnWidthKey Keys an NSNumber specifying the minimum width of the new columns that bindToTableView:displayAttributes: constructs. Defaults to 50 pixels. */ APPKIT_EXTERN NSString* NumericalArrayDSMinimumColumnWidthKey; /*! @const NumericalArrayDSMaximumColumnWidthKey Keys an NSNumber specifying the maximum width of the new columns that bindToTableView:displayAttributes: constructs. The maximum is unlimited by default. */ APPKIT_EXTERN NSString* NumericalArrayDSMaximumColumnWidthKey;