unison

Fork of Unison, a bi-directional file synchronization tool
git clone git://git.laack.co/unison.git
Log | Files | Refs | README | LICENSE

ReconTableView.m (7716B)


      1 //
      2 //  ReconTableView.m
      3 //  Unison
      4 //
      5 //  Created by Trevor Jim on Wed Aug 27 2003.
      6 //  Copyright (c) 2003, 2016.  See file COPYING for details.
      7 //
      8 
      9 #import "ReconTableView.h"
     10 #import "ReconItem.h"
     11 #import "MyController.h"
     12 
     13 @implementation NSOutlineView (_UnisonExtras)
     14 
     15 - (NSArray *)selectedObjects
     16 {
     17         NSMutableArray *result = [NSMutableArray array];
     18   NSIndexSet *set = [self selectedRowIndexes];
     19   NSUInteger index = [set firstIndex];
     20   while (index != NSNotFound) {
     21     [result addObject:[self itemAtRow:index]];
     22     index = [set indexGreaterThanIndex: index];
     23   }
     24   return result;
     25 }
     26 
     27 - (void)setSelectedObjects:(NSArray *)selectedObjects
     28 {
     29         NSMutableIndexSet *set = [NSMutableIndexSet indexSet];
     30         NSUInteger i = [selectedObjects count];
     31         while (i--) {
     32                 NSInteger index = [self rowForItem:[selectedObjects objectAtIndex:i]];
     33                 if (index >= 0)	[set addIndex:index];
     34         }
     35         [self selectRowIndexes:set byExtendingSelection:NO];
     36 }
     37 
     38 - (NSEnumerator *)selectedObjectEnumerator
     39 {
     40         return [[self selectedObjects] objectEnumerator];
     41 }
     42 
     43 - (int)rowCapacityWithoutScrolling
     44 {
     45         float bodyHeight = [self visibleRect].size.height;
     46         bodyHeight -=  [[self headerView] visibleRect].size.height;
     47         return bodyHeight / ([self rowHeight] + 2.0);
     48 }
     49 
     50 - (BOOL)_canAcceptRowCountWithoutScrolling:(NSInteger)rows
     51 {
     52         return ([self numberOfRows] + rows) <= [self rowCapacityWithoutScrolling];
     53 }
     54 
     55 - (BOOL)_expandChildrenIfSpace:(id)parent level:(int)level
     56 {
     57         BOOL didExpand = NO;
     58         id dataSource = [self dataSource];
     59         NSInteger count = [dataSource outlineView:self numberOfChildrenOfItem:parent];
     60         if (level == 0) {
     61                 if (count && ([self isItemExpanded:parent] || [self _canAcceptRowCountWithoutScrolling:count])) {
     62                         [self expandItem:parent expandChildren:NO];
     63                         didExpand = YES;
     64                 }
     65         } else {
     66                 // try expanding each of our children.  If all expand, then return YES,
     67                 // indicating that it may be worth trying the next level
     68                 int i;
     69                 for (i=0; i < count; i++) {
     70                         id child = [dataSource outlineView:self child:i ofItem:parent];
     71                         didExpand = [self _expandChildrenIfSpace:child level:level-1] || didExpand;
     72                 }
     73         }
     74 
     75         return didExpand;
     76 }
     77 
     78 - (void)expandChildrenIfSpace
     79 {
     80         int level = 1;
     81         while ([self _expandChildrenIfSpace:nil level:level]) level++;
     82 }
     83 
     84 @end
     85 
     86 @implementation ReconTableView
     87 
     88 - (BOOL)editable
     89 {
     90     return editable;
     91 }
     92 
     93 - (void)setEditable:(BOOL)x
     94 {
     95     editable = x;
     96 }
     97 
     98 - (BOOL)validateItem:(SEL) action
     99 {
    100     if (action == @selector(selectAll:)
    101         || action == @selector(selectConflicts:)
    102         || action == @selector(copyLR:)
    103         || action == @selector(copyRL:)
    104         || action == @selector(leaveAlone:)
    105         || action == @selector(forceNewer:)
    106         || action == @selector(forceOlder:)
    107         || action == @selector(revert:)
    108         || action == @selector(ignorePath:)
    109         || action == @selector(ignoreExt:)
    110         || action == @selector(ignoreName:))
    111         return editable;
    112     else if (action == @selector(merge:)) {
    113         if (!editable) return NO;
    114         else return [self canDiffSelection];
    115     }
    116     else if (action == @selector(showDiff:)) {
    117         if ((!editable) || (!([self numberOfSelectedRows]==1)))
    118             return NO;
    119         else return [self canDiffSelection];
    120     }
    121     else return YES;
    122 }
    123 
    124 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
    125 {
    126         return [self validateItem:[menuItem action]];
    127 }
    128 
    129 - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
    130 {
    131        return [self validateItem:[toolbarItem action]];
    132 }
    133 
    134 - (void)doIgnore:(unichar)c
    135 {
    136     NSEnumerator *e = [self selectedObjectEnumerator];
    137         ReconItem *item, *last = nil;
    138     while (item = [e nextObject]) {
    139         [item doIgnore:c];
    140                 last = item;
    141     }
    142     if (last) { // something was selected
    143         MyController* controller = (MyController*) [self dataSource];
    144         last = [controller updateForIgnore:last];
    145         [self selectRowIndexes:[NSIndexSet indexSetWithIndex:[self rowForItem:last]] byExtendingSelection:NO];
    146         [self reloadData];
    147     }
    148 }
    149 
    150 - (IBAction)ignorePath:(id)sender
    151 {
    152     [self doIgnore:'I'];
    153 }
    154 
    155 - (IBAction)ignoreExt:(id)sender
    156 {
    157     [self doIgnore:'E'];
    158 }
    159 
    160 - (IBAction)ignoreName:(id)sender
    161 {
    162     [self doIgnore:'N'];
    163 }
    164 
    165 - (void)doAction:(unichar)c
    166 {
    167     int numSelected = 0;
    168     NSEnumerator *e = [self selectedObjectEnumerator];
    169         ReconItem *item, *last = nil;
    170     while (item = [e nextObject]) {
    171         numSelected++;
    172         [item doAction:c];
    173                 last = item;
    174     }
    175     if (numSelected>0) {
    176                 long nextRow = [self rowForItem:last] + 1;
    177         if (numSelected == 1 && [self numberOfRows] > nextRow && c!='d') {
    178             // Move to next row, unless already at last row, or if more than one row selected
    179             [self selectRowIndexes:[NSIndexSet indexSetWithIndex:nextRow] byExtendingSelection:NO];
    180             [self scrollRowToVisible:nextRow];
    181         }
    182         [self reloadData];
    183     }
    184 }
    185 
    186 - (IBAction)copyLR:(id)sender
    187 {
    188     [self doAction:'>'];
    189 }
    190 
    191 - (IBAction)copyRL:(id)sender
    192 {
    193     [self doAction:'<'];
    194 }
    195 
    196 - (IBAction)leaveAlone:(id)sender
    197 {
    198     [self doAction:'/'];
    199 }
    200 
    201 - (IBAction)forceOlder:(id)sender
    202 {
    203     [self doAction:'-'];
    204 }
    205 
    206 - (IBAction)forceNewer:(id)sender
    207 {
    208     [self doAction:'+'];
    209 }
    210 
    211 - (IBAction)selectConflicts:(id)sender
    212 {
    213     [self deselectAll:self];
    214     MyController* controller = (MyController*) [self dataSource];
    215     NSMutableArray *reconItems = [controller reconItems];
    216     int i = 0;
    217     for (; i < [reconItems count]; i++) {
    218                 ReconItem *item = [reconItems objectAtIndex:i];
    219         if ([item isConflict])
    220             [self selectRowIndexes:[NSIndexSet indexSetWithIndex:[self rowForItem:item]] byExtendingSelection:YES];
    221     }
    222 }
    223 
    224 - (IBAction)revert:(id)sender
    225 {
    226     [self doAction:'R'];
    227 }
    228 
    229 - (IBAction)merge:(id)sender
    230 {
    231     [self doAction:'m'];
    232 }
    233 
    234 - (IBAction)showDiff:(id)sender
    235 {
    236     [self doAction:'d'];
    237 }
    238 
    239 /* There are menu commands for these, but we add some shortcuts so you don't
    240    have to press the Command key */
    241 - (void)keyDown:(NSEvent *)event
    242 {
    243     /* some keys return zero-length strings */
    244     if ([[event characters] length] == 0) {
    245         [super keyDown:event];
    246         return;
    247     }
    248 
    249     /* actions are disabled when when menu items are */
    250     if (!editable) {
    251         [super keyDown:event];
    252         return;
    253     }
    254 
    255     unichar c = [[event characters] characterAtIndex:0];
    256     switch (c) {
    257     case '>':
    258     case NSRightArrowFunctionKey:
    259         [self doAction:'>'];
    260         break;
    261     case '<':
    262     case NSLeftArrowFunctionKey:
    263         [self doAction:'<'];
    264         break;
    265     case '?':
    266     case '/':
    267         [self doAction:'/'];
    268         break;
    269     default:
    270         [super keyDown:event];
    271         break;
    272     }
    273 }
    274 
    275 - (BOOL)canDiffSelection
    276 {
    277     BOOL canDiff = YES;
    278     NSEnumerator *e = [self selectedObjectEnumerator];
    279         ReconItem *item;
    280     while (item = [e nextObject]) {
    281         if (![item canDiff]) canDiff= NO;
    282     }
    283     return canDiff;
    284 }
    285 
    286 /* Override default highlight colour because it's hard to see the
    287    conflict/resolution icons */
    288 - (id)_highlightColorForCell:(NSCell *)cell
    289 {
    290     if(([[self window] firstResponder] == self) &&
    291         [[self window] isMainWindow] &&
    292         [[self window] isKeyWindow])
    293 
    294         return [NSColor colorWithCalibratedRed:0.7 green:0.75 blue:0.8 alpha:1.0];
    295     else return [NSColor colorWithCalibratedRed:0.8 green:0.8 blue:0.8 alpha:1.0];
    296 }
    297 
    298 @end