ftp.nice.ch/pub/next/database/apps/Stopwatch.2.5.s.tar.gz#/Stopwatch2.5/BrowserViewMgr.m

This is BrowserViewMgr.m in view mode; [Download] [Up]

/*
 * For legal stuff see the file COPYRIGHT
 */
#import "BrowserViewMgr.h"
#import "ClientInspector.h"
#import "Controller.h"
#import "ColCell.h"
#import "SessionEditor.h"	/* later, this should be the abstract superclass... */

@implementation BrowserViewMgr

- awakeFromNib
{
  [browser setCellClass:[ColCell class]];
  [browser setTarget:self];
  [browser setAction:@selector(browserClick:)];
  [browser setDoubleAction:@selector(browserDoubleClick:)];
  selectedCells = [[List alloc] init];
  return self;
}

- mgrShow:(ClientInspector *)inspector
{
  [self displayTitle];		/* we do this in our own text field */
  [browser loadColumnZero];
  [self displaySummary];
  return self;
}

/*
 * On a double-click in the main client browser, add a new
 * item for the selected client.
 */
- (BOOL)mgrDoubleClick:(ClientInspector *)inspector
{
  return [self mgrAdd:inspector];
}

/*
 * Assumes the cells in the browsers respond to cellData method.
 */
- (void)selectCellWithItem:item
{
  Matrix *matrix = [browser matrixInColumn:0];
  List *list = [matrix cellList];
  ColCell *cell;
  int i, count = [list count];

  for ( i = 0; i < count; i++ ) {
    cell = [list objectAt:i];
    if ( [cell cellData] == item ) {
      //[matrix highlightCellAt:i :0 lit:YES];
      [matrix selectCell:cell];
      [matrix scrollCellToVisible:i :0];
    }
  }
}

/*
 * Allow the user to fill in a new item manually.
 */
- (BOOL)mgrAdd:(ClientInspector *)inspector
{
  ClientInfo *info = [inspector selectedClient];
  id item = [[self itemEditor] editItem:nil]; /* new method: editItem */

  if ( item == nil )
    return NO;

  [info perform:[self addMethod] with:item];
  [self mgrShow:inspector];
  [self selectCellWithItem:item];
  return YES;
}

/*
 * Delete the selected expense, saving it on the undelete list
 */
- (BOOL)mgrDelete:(ClientInspector *)inspector
{
  ClientInfo *info = [inspector selectedClient];
  int i, count;
  id item;
  Matrix *matrix;

  [selectedCells empty];
  [browser getSelectedCells:selectedCells];

  if ( (count = [selectedCells count]) == 0 )
    return NO;

  for ( i = 0; i < count; i++ ) {
    item = [[selectedCells objectAt:i] cellData];
    [info perform:[self deleteMethod] with:item];
    [self saveDeletedItem:item];
  }

  [self mgrShow:inspector];

  /* Select the first cell, for lack of anything better... */
  matrix = [browser matrixInColumn:0];
  [matrix scrollCellToVisible:0 :0];
  [matrix selectCellAt:0 :0];

  return YES;
}

- (BOOL)mgrUndelete:(ClientInspector *)inspector
{
  id item = [self getDeletedItem];
  ClientInfo *info = [inspector selectedClient];

  if ( item ) {
    [info perform:[self addMethod] with:item];
    // Select the added item!
    [self mgrShow:inspector];
    [self selectCellWithItem:item];
    return YES;
  }

  return NO;			/* indicate that no save is required */
}

/*
 * Modify the selected expense.
 */
- (BOOL)mgrModify:(ClientInspector *)inspector
{
  ClientInfo *info = [inspector selectedClient];
  id item = [self selectedItem];

  if ( item == nil || [[self itemEditor] editItem:item] == nil )
    return NO;

  [info perform:[self sortMethod]];
  [info computeTotalMins];
  [self mgrShow:inspector];
  [self selectCellWithItem:item];
  return YES;
}

- (BOOL)canAdd
{
  return YES;
}

/*
 * We can use the modify only if there is exactly one
 * item selected.
 */
- (BOOL)canModify
{
  [selectedCells empty];
  [browser getSelectedCells:selectedCells];

  return ([selectedCells count] == 1 ? YES : NO);
}

/*
 * We can use the delete button if there are any items selected.
 */
- (BOOL)canDelete
{
  return [[browser matrixInColumn:0] selectedCell] ? YES : NO;
}

- (SEL)addMethod
{
  [self subclassResponsibility:_cmd];
  return (SEL)0;
}

- (SEL)deleteMethod
{
  [self subclassResponsibility:_cmd];
  return (SEL)0;
}

- (SEL)sortMethod
{
  [self subclassResponsibility:_cmd];
  return (SEL)0;
}

- itemEditor
{
  [self subclassResponsibility:_cmd];
  return self;
}

/*
 * This must be implemented per subclass, so the right list is accessed
 */
- info:(ClientInfo *)info itemAt:(int)position
{
  [self subclassResponsibility:_cmd];
  return self;
}

/*
 * Must be implemented per subclass
 */
- (int)itemCount:(ClientInfo *)info
{
  [self subclassResponsibility:_cmd];
  return 0;
}

- (void)displayTitle
{
  [self subclassResponsibility:_cmd];
}


@implementation BrowserViewMgr(PRIVATE)

- (int)selectedRow
{
  return [[browser matrixInColumn:0] selectedRow];
}

- selectedItem
{
  ClientInfo *info = [[ClientInspector sharedInstance] selectedClient];

  return [self info:info itemAt:[self selectedRow]];
}

- (void)displaySummary
{
  [self subclassResponsibility:_cmd];
}

- selectAll:sender
{
  id result = [browser selectAll:sender];
  [ClientInspector updateButtons];
  return result;
}

- browserClick:sender
{
  [ClientInspector updateButtons];
  return self;
}

- browserDoubleClick:sender
{
  /*
   * Since the cell is still activated, make this happen next event pass. This
   * seems to be a bug in NXBrowser, since this only is necessary if multiple
   * select is enabled...
   */
  [[ClientInspector sharedInstance] perform:@selector(performModify)
 	with:nil afterDelay:1 cancelPrevious:YES];

  return nil;
}

- (int)browser:sender fillMatrix:matrix inColumn:(int)column
{
  ClientInfo *info = [[ClientInspector sharedInstance] selectedClient];
  int i, count = [self itemCount:info];
  ColCell *cell;
  id item;

  [matrix renewRows:0 cols:0];

  for ( i = 0; i < count; i++ ) {
    [matrix addRow];
    item = [self info:info itemAt:i];
    cell = [matrix cellAt:i :0];
    [cell setCellData:item];		/* our custom cell draws multi-column */
    [cell setLoaded:YES];
    [cell setLeaf:YES];
  }

  return count ;
}

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.