Logo Search packages:      
Sourcecode: addresses-for-gnustep version File versions  Download package

ADPersonPropertyView+Private.m

// ADPersonPropertyView+Private.m (this is -*- ObjC -*-)
// 
// \author: Björn Giesler <giesler@ira.uka.de>
// 
// Address Book Application for GNUstep
// 
// $Author: rmottola $
// $Locker:  $
// $Revision: 1.1 $
// $Date: 2007/03/29 22:36:04 $

/* system includes */
/* (none) */

/* my includes */
#include "ADPersonPropertyView.h"

@implementation ADPersonPropertyView (Private)
- (ADPersonPropertyCell*) addCellWithValue: (NSString*) val
                            inRect: (NSRect*) rect
                          editable: (BOOL) yesno
                              font: (NSFont*) font
                         alignment: (NSTextAlignment) alignment
                           details: (id) details
{
  ADPersonPropertyCell *cell;
  NSSize s;

  cell = [[[ADPersonPropertyCell alloc] init] autorelease];
  [cell setEditable: yesno];
  [cell setStringValue: val];
  [cell setFont: font];
  [cell setAlignment: alignment];

  if(details) [cell setDetails: details];

  s = [cell cellSize];
  rect->size.width = MAX(rect->size.width, s.width);
  rect->size.height = MAX(rect->size.height, s.height);

  [cell setRect: *rect];
  [_cells addObject: cell];

  return cell;
}
  
- (ADPersonPropertyCell*) addValueCellForValue: (NSString*) val
                              inRect: (NSRect*) rect
                               details: (id) details
{
  ADPersonPropertyCell *cell;

  cell = [self addCellWithValue: val
             inRect: rect
             editable: YES
             font: [self font]
             alignment: NSLeftTextAlignment
             details: details];
  
  if(_delegate &&
     [_delegate respondsToSelector: _clickSel] &&
     [_delegate canPerformClickForProperty: _property] &&
     !_editable)
    [cell setTextColor: [NSColor blueColor]];
  else if(_editable)
    [cell setTextColor: [NSColor darkGrayColor]];
  else
    [cell setTextColor: [NSColor blackColor]];
  return cell;
}

- (ADPersonPropertyCell*) addValueCellForValue: (NSString*) val
                              inRect: (NSRect*) rect
{
  return [self addValueCellForValue: val
             inRect: rect
             details: nil];
}

- (ADPersonPropertyCell*) addLabelCellForLabel: (NSString*) label
                              inRect: (NSRect*) rect
{
  NSString *str;
  NSFont *font;
  int w;

  str = ADLocalizedPropertyOrLabel(label);
  font = [self boldFont];
  w = [font widthOfString: str];
  
  _neededLabelWidth = MAX(_neededLabelWidth, w);
  str = [str stringByAbbreviatingToFitWidth: _maxLabelWidth
           inFont: font];
  
  rect->size.width = [self maxLabelWidth];
  
  return [self addCellWithValue: str
             inRect: rect
             editable: NO
             font: font
             alignment: NSRightTextAlignment
             details: nil];
}

- (ADPersonPropertyCell*) addConstantCellForString: (NSString*) str
                                  inRect: (NSRect*) rect
{
  NSFont *font = [self font];
  rect->size.width = [font widthOfString: str];
  
  return [self addCellWithValue: str
             inRect: rect
             editable: NO
             font: font
             alignment: NSRightTextAlignment
             details: nil];
}

- (ADPersonActionCell*) addActionCellWithType: (ADActionType) t
                               inRect: (NSRect*) rect
                              details: (id) details
{
  id cell;
  NSSize cellSize; NSPoint cellOrigin;

  cell = [[[ADPersonActionCell alloc] init] autorelease];
  switch(t)
    {
    case ADAddAction:
      [cell setImage: _addImg];
      break;
    case ADRemoveAction:
      [cell setImage: _rmvImg];
      break;
    case ADChangeAction:
      [cell setImage: _chgImg];
      break;
    default:
      NSLog(@"Unknown action type %d\n", t);
    }

  cellSize = [cell rect].size;
  cellOrigin = rect->origin;
  if(rect->size.height > cellSize.height)
    cellOrigin.y += (rect->size.height - cellSize.height)/2 + 2;
  [cell setOrigin: cellOrigin];

  rect->size = [cell rect].size;
  [cell setDetails: details];
  [cell setActionType: t];

  [_cells addObject: cell];
  return cell;
}

- (NSArray*) layoutDictionary: (NSDictionary*) dict
                withLabel: (NSString*) label
           forDisplayInRect: (NSRect*) rect
{
  NSArray *layout, *row;
  NSString *field;
  NSEnumerator *rowEnumerator, *fieldEnumerator;
  ADPersonPropertyCell *labelCell;
  NSSize rowSize; NSRect rowRect; float labelX;
  BOOL firstRow;
  NSMutableArray *cells;
  
  layout = [self layoutRuleForValue: dict];
  cells = [NSMutableArray array];

  labelCell = [self addLabelCellForLabel: label inRect: rect];
  rect->origin.x += rect->size.width + 5; labelX = rect->origin.x;
  rect->size.width += 5;
  
  rowRect = *rect;
  rowSize = rect->size;
  firstRow = YES;
  
  rowEnumerator = [layout objectEnumerator];
  while((row = [rowEnumerator nextObject]))
    {
      // do we have to layout anything in this row at all?
      fieldEnumerator = [row objectEnumerator];
      while((field = [fieldEnumerator nextObject]))
      {
        if([field hasPrefix: @"$"] ||
           ![dict objectForKey: field]) continue;
        break;
      }
      
      if(!field) continue;
      
      fieldEnumerator = [row objectEnumerator];
      while((field = [fieldEnumerator nextObject]))
      {
        NSString *str;
        id cell;
        
        if([field hasPrefix: @"$"])
          str = [field substringFromIndex: 1];
        else
          str = [dict objectForKey: field];
        if(!str || [str length] == 0)
          continue;
        
        rowRect.size = NSMakeSize(0, 0);

        cell = [self addConstantCellForString: str inRect: &rowRect];
        [cells addObject: cell];
        
        rowRect.origin.x += rowRect.size.width + 5;
        rowSize.width += rowRect.size.width + 5;
        rowSize.height = MAX(rowSize.height,
                         rowRect.size.height);
      }

      // add +1 to compensate tiny GNUstep bug
      rect->size.width = MAX(rect->size.width, rowSize.width+1);
      if(!firstRow)
      rect->size.height += rowSize.height+1;
      firstRow = NO;
      
      rowRect.origin.x = rect->origin.x;
      rowRect.origin.y += rowRect.size.height;
      rowSize = NSMakeSize(labelX, 0);
    }

  return [NSArray arrayWithArray: cells];
}

- (NSArray*) layoutDictionary: (NSDictionary*) dict
                withLabel: (NSString*) label
                  details: (NSDictionary*) details
                  buttons: (BOOL) buttons
            forEditInRect: (NSRect*) rect
{
  NSArray *layout, *row;
  NSString *field;
  NSEnumerator *rowEnumerator, *fieldEnumerator;
  ADPersonPropertyCell *labelCell;
  NSSize rowSize; NSRect rowRect; float labelX;
  BOOL firstRow, showsDefault;
  NSMutableArray *cells;
  
  layout = [self layoutRuleForValue: dict];
  cells = [NSMutableArray array];

  labelCell = [self addLabelCellForLabel: label inRect: rect];
  rect->origin.x += rect->size.width + 5;
  rect->size.width += 5;
  
  rowSize = rect->size;

  if(buttons)
    {
      rect->size.height = rowSize.height;
      [self addActionCellWithType: ADChangeAction
          inRect: rect
          details: details];
      rect->origin.x += rect->size.width + 5;
      rowSize.width += rect->size.width + 5;
      rowSize.height = MAX(rowSize.height, rect->size.height);
      
      rect->size.height = rowSize.height;
      [self addActionCellWithType: ADRemoveAction
          inRect: rect
          details: details];
      rect->origin.x += rect->size.width + 5;
      rowSize.width += rect->size.width + 5;
      rowSize.height = MAX(rowSize.height, rect->size.height);
    }
  
  labelX = rect->origin.x;

  rowRect = *rect;
  firstRow = YES;

  rowEnumerator = [layout objectEnumerator];
  while((row = [rowEnumerator nextObject]))
    {
      fieldEnumerator = [row objectEnumerator];
      while((field = [fieldEnumerator nextObject]))
      {
        NSString *str; BOOL label;

        label = NO; showsDefault = NO;
        if([field hasPrefix: @"$"])
          {
            str = [field substringFromIndex: 1];
            label = YES;
          }
        else
          str = [dict objectForKey: field];
        if(!str)
          {
            str = [NSString stringWithFormat: @"[%@]",
                        ADLocalizedPropertyOrLabel(field)];
            showsDefault = YES;
          }
        
        rowRect.size = NSMakeSize(0, 0);
        if(label)
          {
            ADPersonPropertyCell *cell =
            [self addConstantCellForString: str inRect: &rowRect];
            [cells addObject: cell];
          }
        else
          {
            ADPersonPropertyCell *cell;

            NSMutableDictionary *myDetails =
            [NSMutableDictionary dictionaryWithDictionary: details];
            [myDetails setObject: field forKey: @"Key"];
            cell = [self addValueCellForValue: str
                     inRect: &rowRect
                     details: myDetails];
            if(showsDefault) [cell setTextColor: [NSColor lightGrayColor]];
            [cells addObject: cell];
          }
        rowRect.origin.x += rowRect.size.width + 5;
        rowSize.width += rowRect.size.width + 5;
        rowSize.height = MAX(rowSize.height,
                         rowRect.size.height);
      }
      rect->size.width = MAX(rect->size.width, rowSize.width+1);
      if(!firstRow)
      rect->size.height += rowSize.height+1;
      firstRow = NO;
      
      rowRect.origin.x = rect->origin.x;
      rowRect.origin.y += rowRect.size.height;
      rowSize = NSMakeSize(labelX, 0);
    }

  return [NSArray arrayWithArray: cells];
}

- (void) layoutForEdit
{
  id val;
  id cell;
  ADPropertyType type;
  NSRect r; NSSize allSize; 
  int i; BOOL showsDefault;

  if(!_property || !_person) return;

  val = [_person valueForProperty: _property];

  type = [_person typeOfProperty: _property];

  r = NSMakeRect(0, 0, 0, 0); allSize = NSMakeSize(0, 0);

  // convert types
  if(val)
    switch(type)
      {
      case ADStringProperty: break;
      case ADIntegerProperty:
      val = [NSString stringWithFormat: @"%d", [val intValue]];
      break;
      case ADRealProperty:
      val = [NSString stringWithFormat: @"%f", [val floatValue]];
      break;
      case ADDateProperty:
      case ADArrayProperty:
      case ADDictionaryProperty:
      case ADDataProperty:
      case ADErrorInProperty:
      NSLog(@"Can't layout object of type %d\n", type);
      return;
      default:
      break;
      }

  // layout single-cell values
  if(!(type & ADMultiValueMask))
    {
      if(_displaysLabel)
      {
        [self addLabelCellForLabel: _property inRect: &r];
        r.origin.x += r.size.width + 5;
        allSize.width = r.size.width + 5;
        allSize.width += r.size.width + 5;
        r.size = NSMakeSize(0, 0);
      }

      showsDefault = NO;
      if(!val)
      {
        val = [self emptyValue];
        showsDefault = YES;
      }
      cell = [self addValueCellForValue: val
               inRect: &r];
      if(showsDefault)
      [cell setTextColor: [NSColor lightGrayColor]];
      allSize.width += r.size.width;
      allSize.height = MAX(allSize.height, r.size.height);
    }

  else if(type == ADMultiStringProperty)
    {
      if(![val count])
      {
        ADPersonPropertyCell *labelCell, *valueCell;
        NSString *label, *value;
        NSDictionary *details;

        label = [self defaultLabel];

        details = [NSDictionary dictionaryWithObjectsAndKeys:
                            label, @"Label",
                          nil];
        
        labelCell = [self addLabelCellForLabel: label inRect: &r];
        [labelCell setDetails: details];
        r.origin.x += r.size.width + 5;
        allSize.width = r.size.width + 5;
        allSize.height = r.size.height;

        r.size = NSMakeSize(0, 0);
        value = [self emptyValue];
        valueCell = [self addValueCellForValue: value inRect: &r];
        [valueCell setTextColor: [NSColor lightGrayColor]];
        [valueCell setDetails: details];

        allSize.width += r.size.width;
        allSize.height = MAX(allSize.height, r.size.height);
      }
      else
      {
        for(i=0; i<[val count]; i++)
          {
            ADPersonPropertyCell *labelCell, *valueCell;
            NSString *label, *identifier, *value;
            NSDictionary *details;
            NSSize rowSize;
            
            label = [val labelAtIndex: i];
            identifier = [val identifierAtIndex: i];
            value = [val valueAtIndex: i];
            
            details = [NSDictionary dictionaryWithObjectsAndKeys:
                              identifier, @"Identifier",
                              label, @"Label",
                              nil];
            
            labelCell = [self addLabelCellForLabel: label inRect: &r];
            [labelCell setDetails: details];
            r.origin.x += r.size.width + 5; 
            rowSize.width = r.size.width + 5;
            rowSize.height = r.size.height;

            r.size.height = rowSize.height;
            [self addActionCellWithType: ADChangeAction
                inRect: &r
                details: details];
            r.origin.x += r.size.width + 5;
            rowSize.width += r.size.width + 5;
            rowSize.height = MAX(rowSize.height, r.size.height);

            r.size.height = rowSize.height;
            [self addActionCellWithType: ADRemoveAction
                inRect: &r
                details: details];
            r.origin.x += r.size.width + 5;
            rowSize.width += r.size.width + 5;
            rowSize.height = MAX(rowSize.height, r.size.height);

            r.size = NSMakeSize(0, 0);
            valueCell = [self addValueCellForValue: value inRect: &r];
            [valueCell setDetails: details];
            if([value isEqualToString: [self emptyValue]])
            [valueCell setTextColor: [NSColor lightGrayColor]];
            else
            [valueCell setTextColor: [NSColor darkGrayColor]];

            rowSize.width += r.size.width;
            rowSize.height = MAX(rowSize.height, r.size.height);
            r.size = NSMakeSize(0, 0);
            r.origin.x = 0;
            r.origin.y += rowSize.height;
            
            allSize.width = MAX(allSize.width, rowSize.width);
            allSize.height += rowSize.height;
          }

        r.origin.x = _maxLabelWidth + 5 + [_chgImg size].width + 5;
        r.origin.y += 5;
        [self addActionCellWithType: ADAddAction
            inRect: &r
            details: nil];
        allSize.height += r.size.height + 5;
      }
    }

  else if(type == ADMultiDictionaryProperty)
    {
      NSRect rect = NSZeroRect;
      
      if(![val count])
      {
        NSDictionary *details;
        NSString *label; NSMutableDictionary *value;

        label = [self defaultLabel];
        value = [self emptyValue];
        details = [NSDictionary dictionaryWithObjectsAndKeys:
                            label, @"Label",
                          nil];

        [self layoutDictionary: value
            withLabel: label
            details: details
            buttons: NO
            forEditInRect: &rect];
        allSize = rect.size;
      }
      else
      {
        for(i=0; i<[val count]; i++)
          {
            NSString *label, *value, *identifier;
            NSDictionary *details;
            
            label = [val labelAtIndex: i];
            value = [val valueAtIndex: i];
            identifier = [val identifierAtIndex: i];

            details =
            [NSDictionary dictionaryWithObjectsAndKeys:
                        identifier, @"Identifier",
                        label, @"Label",
                        nil];
            
            [self layoutDictionary: [val valueAtIndex: i]
                withLabel: [val labelAtIndex: i]
                details: details
                buttons: YES
                forEditInRect: &rect];
            allSize.width = MAX(allSize.width, rect.size.width);
            allSize.height += rect.size.height;
            rect.origin.x = 0; rect.origin.y += rect.size.height;
            rect.size = NSZeroSize;
          }
        
        rect.origin.x = _maxLabelWidth + 5 + [_chgImg size].width + 5;
        rect.origin.y += 5;
        [self addActionCellWithType: ADAddAction
            inRect: &rect
            details: nil];
        allSize.height += rect.size.height + 5;
      }
    }

  else NSLog(@"Can't layout values of type %d yet\n", type);

  _requiredSize = allSize;
  [self setFrameSize: _requiredSize];
}


- (void) layoutForDisplay
{
  NSRect r; NSSize allSize; 
  int i;
  id cell;
  id val;
  ADPropertyType type;

  if(!_property || !_person) return;

  val = [_person valueForProperty: _property];

  type = [_person typeOfProperty: _property];

  r = NSMakeRect(0, 0, 0, 0); allSize = NSMakeSize(0, 0);

  if(!val) return;

  // convert types
  switch(type)
    {
    case ADStringProperty: break;
    case ADIntegerProperty:
      val = [NSString stringWithFormat: @"%d", [val intValue]];
      break;
    case ADRealProperty:
      val = [NSString stringWithFormat: @"%f", [val floatValue]];
      break;
    case ADDateProperty:
    case ADArrayProperty:
    case ADDictionaryProperty:
    case ADDataProperty:
    case ADErrorInProperty:
      NSLog(@"Can't layout object of type %d\n", type);
      return;
    default:
      break;
    }

  // layout single-cell values
  if(!(type & ADMultiValueMask))
    {
      if(_displaysLabel)
      {
        [self addLabelCellForLabel: _property inRect: &r];
        allSize.width += r.size.width + 5;
        allSize.height = r.size.height;
        r.origin.x += r.size.width + 5; r.size = NSMakeSize(0, 0);
      }

      cell = [self addValueCellForValue: val inRect: &r];
      allSize.width += r.size.width;
      allSize.height = MAX(allSize.height, r.size.height);
    }

  // layout multi-cell values; multi-string only this far
  else if(type == ADMultiStringProperty)
    {
      for(i=0; i<[val count]; i++)
      {
        ADPersonPropertyCell *labelCell, *valueCell;
        NSString *label, *value, *identifier;
        NSSize rowSize;
        NSDictionary *details;

        label = [val labelAtIndex: i];
        value = [val valueAtIndex: i];
        identifier = [val identifierAtIndex: i];

        details =
          [NSDictionary dictionaryWithObjectsAndKeys:
                      identifier, @"Identifier",
                    label, @"Label",
                    nil];

        labelCell = [self addLabelCellForLabel: label
                      inRect: &r];
        r.origin.x += r.size.width + 5; 
        rowSize.width = r.size.width + 5;
        rowSize.height = r.size.height;
        r.size = NSMakeSize(0, 0);
            
        valueCell = [self addValueCellForValue: value
                      inRect: &r
                      details: details];
            
        rowSize.width += r.size.width;
        rowSize.height = MAX(rowSize.height, r.size.height);
        r.size = NSMakeSize(0, 0);
        r.origin.x = 0;
        r.origin.y += rowSize.height;
        
        allSize.width = MAX(allSize.width, rowSize.width);
        allSize.height += rowSize.height;
      }
    }

  // layout dictionaries
  else if(type == ADMultiDictionaryProperty)
    {
      NSRect rect = NSZeroRect;
      for(i=0; i<[val count]; i++)
      {
        NSArray *cells; NSDictionary *details;
        NSString *identifier, *label; int j;

        label = [val labelAtIndex: i];
        identifier = [val identifierAtIndex: i];

        details =
          [NSDictionary dictionaryWithObjectsAndKeys:
                      identifier, @"Identifier",
                    label, @"Label",
                    nil];

        cells = [self layoutDictionary: [val valueAtIndex: i]
                  withLabel: [val labelAtIndex: i]
                  forDisplayInRect: &rect];
        for(j=0; j<[cells count]; j++)
          [[cells objectAtIndex: j] setDetails: details];
        
        allSize.width = MAX(allSize.width, rect.size.width);
        allSize.height += rect.size.height;
        rect.origin.x = 0; rect.origin.y += rect.size.height;
        rect.size = NSZeroSize;
      }
    }

  else
    NSLog(@"Can't layout values of type %d yet\n", type);

  _requiredSize = allSize;
  [self setFrameSize: _requiredSize];
}

- (void) layout
{
  float heightBefore, heightAfter;

  _neededLabelWidth = 0;

  // clear everything
  [_cells release]; _cells = [[NSMutableArray alloc] init];

  heightBefore = [self frame].size.height;
  if([self isEditable])
    [self layoutForEdit];
  else
    [self layoutForDisplay];
  heightAfter = [self frame].size.height;

  if((heightBefore != heightAfter) &&
     (_delegate != nil) &&
     [_delegate respondsToSelector: @selector(view:changedHeightFrom:to:)])
    [_delegate view: self changedHeightFrom: heightBefore to: heightAfter];

  [self setNeedsDisplay: YES];
}
@end


Generated by  Doxygen 1.6.0   Back to index