Ignore:
Timestamp:
11/18/02 08:57:41 (21 years ago)
Author:
Nicholas Riley
Message:

Alarms.nib: Removed horizontal scroll bar. Turned on grid. Set delegate to NJRTableDelegate instead of PSAlarmSetController.

NJRTableDelegate: In general, made functional (was previously unused). Fixed MyCompanyName. Changed ORDER_BY_CONTEXT to use key-value coding instead of assuming data consists of a dictionary of dictionaries. Added sorting support (reorderedData, replaces oData) with autosave support for sort context. Added _positionTypeSelectDisplay, which adjusts position and justification of type select display control based on the current sort column. Added support for reverse sorting in type select string. Use table data source instead of sorted data so text matches as displayed (this will break with non-text cells...).

NJRTableView: Adapted from iTableView (Jaguar table alternate table background color), TableTester (most everything else) and NJROutlineView (keyDown, moveToBeginning/EndOfDocument). Support for type selection, delete shortcut for row deletion, and iTunes-alike background colors and frame.

NSCharacterSet-NJRExtensions: Moved _typeSelectSet from NJROutlineView as it's now shared with NJRTableView. Still need to factor NJROutlineView as embedded in HostLauncher some day.

PSAlarm: Reorganized, renamed and categorized methods. Added time accessor for the benefit of sorting. Renamed compare: to compareDate: for clarity. Added compareMessage:, though it's currently unused. Renamed cancel to cancelTimer for clarity.

PSAlarmSetController: More fun with initial first responder on window show/hide; still need to work around bug properly (subclass NSComboBox?) and fix it for real. As is, works for OS X 10.1.

PSAlarms: Added alarms accessor, returning alarm array. Fixed memory leak on successful alarm removal (oops). Added removeAlarms:, needed with sorted alarm list.

PSAlarmsController: Set window resize increment. Changes to table delegate methods to use reordered alarm list. Register for NSTableViewSelectionDidChangeNotification now we're no longer the table view delegate. Fixed autoselection in alarmsChanged by using data reordering support in NJRTableView. Implement NJRTableViewDataSource to permit deletion from table view.

Pester.pbproj: Added new files.

Read Me.rtfd: Added TableTester/iTableView acknowledgements. Updated release notes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Cocoa/Pester/Source/NJRTableDelegate.m

    r34 r51  
    44//
    55//  Created by Nicholas Riley on Sun Oct 27 2002.
    6 //  Copyright (c) 2002 __MyCompanyName__. All rights reserved.
     6//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
    77//
    88
     
    1414typedef struct { NSString *key; BOOL descending; } SortContext;
    1515
    16 // Sort array of itemNums, by looking up the itemNum in the dictionary of dictionaries.
     16// Sort array of itemNums, by looking up the itemNum in the dictionary of objects.
    1717// based on code of Ondra Cada <ocs@ocs.cz> on cocoa-dev list
    1818
     
    2525
    2626        if (context->descending) {
    27             first  = [right objectForKey: key];
    28             second = [left  objectForKey: key];
     27            first  = [right valueForKey: key];
     28            second = [left  valueForKey: key];
    2929        } else {
    30             first  = [left  objectForKey: key];
    31             second = [right objectForKey: key];
     30            first  = [left  valueForKey: key];
     31            second = [right valueForKey: key];
    3232        }
    3333
     
    4141}
    4242
     43@interface NJRTableDelegate (Private)
     44
     45- (void)_positionTypeSelectDisplay;
     46- (void)_sortByColumn:(NSTableColumn *)inTableColumn;
     47
     48@end
     49
    4350@implementation NJRTableDelegate
    4451
    4552#pragma mark initialize-release
    4653
     54- (void)awakeFromNib;
     55{
     56    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_positionTypeSelectDisplay) name: NSViewFrameDidChangeNotification object: tableView];
     57}
     58
    4759- (void)dealloc
    4860{
     61    [[NSNotificationCenter defaultCenter] removeObserver: self];
    4962    [sortingColumn release];
    5063    [sortingKey release];
     64    [reorderedData release];
    5165    [super dealloc];
    5266}
     
    6882}
    6983
     84#pragma mark sorting
     85
     86- (NSString *)_sortContextDefaultKey;
     87{
     88    NSString *autosaveName = [tableView autosaveName];
     89    if (autosaveName != nil)
     90        return [NSString stringWithFormat: @"NJRTableDelegate SortContext %@", autosaveName];
     91    else
     92        return nil;
     93}
     94
     95- (void)_sortData;
     96{
     97    SortContext ctxt = { sortingKey, sortDescending };
     98    NSString *sortContextKey = [self _sortContextDefaultKey];
     99
     100    if (sortContextKey != nil) {
     101        [[NSUserDefaults standardUserDefaults] setObject:
     102            [NSDictionary dictionaryWithObjectsAndKeys: sortingKey, @"sortingKey", [NSNumber numberWithBool: sortDescending], @"sortDescending", nil]
     103                                                    forKey: [self _sortContextDefaultKey]];
     104    }
     105   
     106    // sort the NSMutableArray
     107    [reorderedData sortUsingFunction: ORDER_BY_CONTEXT context: &ctxt];
     108    [tableView reloadData];
     109}
     110
     111- (void)_sortByColumn:(NSTableColumn *)inTableColumn;
     112{
     113    NSSet *oldSelection = [self selectedItems];
     114    if (sortingColumn == inTableColumn) {
     115        // User clicked same column, change sort order
     116        sortDescending = !sortDescending;
     117        // Possible optimization: Don't actually re-sort if you just change the sorting direction; instead, just display either the nth item or the (count-1-n)th item depending on ascending/descending.)
     118    } else {
     119        // User clicked new column, change old/new column headers, save new sorting column, and re-sort the array.
     120        if (sortingColumn != nil) {
     121            [tableView setIndicatorImage: nil inTableColumn: sortingColumn];
     122            sortDescending = NO; // on initial sort, preserve previous sort order
     123        }
     124        [self setSortingKey: [inTableColumn identifier]];
     125        [self setSortingColumn: inTableColumn];
     126        [tableView setHighlightedTableColumn: inTableColumn];
     127    }
     128    [tableView setIndicatorImage: (sortDescending ? [NSTableView descendingSortIndicator] : [NSTableView ascendingSortIndicator]) inTableColumn: inTableColumn];
     129    [self _positionTypeSelectDisplay];
     130    // Actually sort the data
     131    [self _sortData];
     132    [self selectItems: oldSelection];
     133}
     134
     135- (void)_initialSortData;
     136{
     137    NSString *sortContextKey = [self _sortContextDefaultKey];
     138    NSDictionary *sortContext;
     139    NSString *key;
     140    NSTableColumn *column;
     141
     142    if (sortContextKey == nil) goto noContext;
     143    if ( (sortContext = [[NSUserDefaults standardUserDefaults] dictionaryForKey: sortContextKey]) == nil) goto noContext;
     144    if ( (key = [sortContext objectForKey: @"sortingKey"]) == nil) goto noContext;
     145    if ( (column = [tableView tableColumnWithIdentifier: key]) == nil) goto noContext;
     146    sortDescending = [[sortContext objectForKey: @"sortDescending"] boolValue];
     147    [self _sortByColumn: column];
     148    return;
     149   
     150noContext:
     151    sortDescending = NO;
     152    [self _sortByColumn: [[tableView tableColumns] objectAtIndex: 0]];
     153}
     154
     155- (NSMutableArray *)reorderedDataForData:(NSArray *)data;
     156{
     157    if (reorderedData == nil) {
     158        reorderedData = [data mutableCopy];
     159        [self _initialSortData];
     160    } else {
     161        NSSet *oldSelection = [self selectedItems];
     162        [reorderedData release]; reorderedData = nil;
     163        reorderedData = [data mutableCopy];
     164        [self _sortData];
     165        [self selectItems: oldSelection];
     166    }
     167    return reorderedData;
     168}
     169
     170#pragma mark type selection
     171
     172- (void)_positionTypeSelectDisplay;
     173{
     174    [tableView resetTypeSelect]; // avoid extraneous matching
     175    if ([tableView typeSelectDisplay] != nil && sortingColumn != nil) {
     176        NSControl *typeSelectControl = [tableView typeSelectDisplay];
     177        if ([typeSelectControl isKindOfClass: [NSControl class]]) {
     178            NSView *superview = [typeSelectControl superview];
     179            NSRect columnRect = [superview convertRect: [tableView rectOfColumn: [tableView columnWithIdentifier: sortingKey]] fromView: tableView];
     180            // XXX support horizontal scroll bar/clipping (not for Pester, but eventually)
     181            NSRect tableScrollFrame = [[tableView enclosingScrollView] frame];
     182            NSRect selectFrame = [typeSelectControl frame];
     183            [superview setNeedsDisplayInRect: selectFrame]; // fix artifacts caused by moving view
     184            selectFrame.origin.x = columnRect.origin.x;
     185            selectFrame.size.width = columnRect.size.width;
     186            [typeSelectControl setAlignment: [[sortingColumn dataCell] alignment]];
     187            [typeSelectControl setFrame: selectFrame];
     188        }
     189    }
     190}
     191
    70192#pragma mark saving/restoring selection
    71193
     
    77199
    78200    while ( (rowNum = [e nextObject]) != nil) {
    79         id item = [oData objectAtIndex: [rowNum intValue]];
     201        id item = [reorderedData objectAtIndex: [rowNum intValue]];
    80202        [result addObject: item];
    81203    }
     
    92214
    93215    while ( (item = [e nextObject]) != nil ) {
    94         int row = [oData indexOfObjectIdenticalTo: item];
     216        int row = [reorderedData indexOfObjectIdenticalTo: item];
    95217        if (row != NSNotFound) {
    96218            [tableView selectRow: row byExtendingSelection: YES];
     
    101223}
    102224
    103 // ----------------------------------------------------------------------------------------
    104 // Sorting
    105 // ----------------------------------------------------------------------------------------
    106 
    107 - (void)sortData
    108 {
    109     SortContext ctxt = { sortingKey, sortDescending };
    110     NSSet *oldSelection = [self selectedItems];
    111 
    112     // sort the NSMutableArray
    113     [oData sortUsingFunction: ORDER_BY_CONTEXT context: &ctxt];
    114 
    115     [tableView reloadData];
    116     [self selectItems: oldSelection];
    117 }
    118 
    119 - (void)sortByColumn:(NSTableColumn *)inTableColumn;
    120 {
    121     if (sortingColumn == inTableColumn) {
    122         // User clicked same column, change sort order
    123         sortDescending = !sortDescending;
    124         // Possible optimization: Don't actually re-sort if you just change the sorting direction;
    125         // instead, just display either the nth item or the (count-1-n)th item depending on ascending/descending.)
     225@end
     226
     227@implementation NJRTableDelegate (NJRTableViewDelegate)
     228
     229- (void)tableView:(NSTableView *)aTableView didClickTableColumn:(NSTableColumn *)inTableColumn
     230{
     231    [[tableView window] makeFirstResponder: aTableView];
     232    [self _sortByColumn: inTableColumn];
     233}
     234
     235- (void)tableViewColumnDidResize:(NSNotification *)notification;
     236{
     237    [self _positionTypeSelectDisplay];
     238}
     239
     240- (void)tableViewColumnDidMove:(NSNotification *)notification;
     241{
     242    [self _positionTypeSelectDisplay];
     243}
     244
     245- (void)tableView:(NSTableView *)aTableView selectRowMatchingString:(NSString *)matchString;
     246{
     247    // Look for a highlighted column, presuming we are sorted by that column, and search its values.
     248    NSTableColumn *col = [aTableView highlightedTableColumn];
     249    id dataSource = [aTableView dataSource];
     250    int i, rowCount = [reorderedData count];
     251    if (nil == col) return;
     252    if (sortDescending) {
     253        for ( i = rowCount - 1 ; i >= 0 ; i-- ) {
     254            NSComparisonResult order = [matchString caseInsensitiveCompare:
     255                [dataSource tableView: aTableView objectValueForTableColumn: col row: i]];
     256            if (order != NSOrderedDescending) break;
     257        }
     258        if (i < 0) i = 0;
    126259    } else {
    127         // User clicked new column, change old/new column headers,
    128         // save new sorting column, and re-sort the array.
    129         sortDescending = NO;
    130         if (nil != sortingColumn) {
    131             [tableView setIndicatorImage: nil inTableColumn: sortingColumn];
    132         }
    133         [self setSortingKey: [inTableColumn identifier]];
    134         [self setSortingColumn: inTableColumn];
    135         [tableView setHighlightedTableColumn: inTableColumn];
    136     }
    137     [tableView setIndicatorImage: (sortDescending ? [NSTableView descendingSortIndicator] : [NSTableView ascendingSortIndicator]) inTableColumn: inTableColumn];
    138     // Actually sort the data
    139     [self sortData];
    140 }
    141 
    142 //      Sort by whatever column was clicked upon
    143 - (void)tableView:(NSTableView*)aTableView didClickTableColumn:(NSTableColumn *)inTableColumn
    144 {
    145     [[tableView window] makeFirstResponder: aTableView]; // help make this tableView be first responder
    146     [self sortByColumn:inTableColumn];
    147 }
    148 
    149 // ----------------------------------------------------------------------------------------
    150 // Alphabetic Type Ahead
    151 // ----------------------------------------------------------------------------------------
    152 
    153 - (void) typeAheadString:(NSString *)inString;
    154 {
    155     // This general sample looks for a highlighted column, presuming that is that column we are sorted by, and uses that as the lookup key.
    156     NSTableColumn *col = [tableView highlightedTableColumn];
    157     if (nil != col) {
    158         NSString *key = [col identifier];
    159         int i;
    160         for ( i = 0 ; i < [oData count] ; i++ ) {
    161             NSDictionary *rowDict = [oData objectAtIndex:i];
    162             NSString *compareTo = [rowDict objectForKey:key];
    163             NSComparisonResult order = [inString caseInsensitiveCompare:compareTo];
     260        for ( i = 0 ; i < rowCount ; i++ ) {
     261            NSComparisonResult order = [matchString caseInsensitiveCompare:
     262                [dataSource tableView: aTableView objectValueForTableColumn: col row: i]];
    164263            if (order != NSOrderedDescending) break;
    165264        }
    166         // Make sure we're not overflowing the row count.
    167         if (i >= [oData count]) {
    168             i = [oData count] - 1;
    169         }
    170         // Now select row i -- either the one we found, or the last row if not found.
    171         [tableView selectRow:i byExtendingSelection:NO];
    172         [tableView scrollRowToVisible:i];
    173     }
     265        if (i >= rowCount) i = rowCount - 1;
     266    }
     267    // Now select row i -- either the one we found, or the first/last row if not found.
     268    [aTableView selectRow: i byExtendingSelection: NO];
     269    [aTableView scrollRowToVisible: i];
    174270}
    175271
Note: See TracChangeset for help on using the changeset viewer.