Home | History | Annotate | Download | only in mac
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #import "SkOptionsTableView.h"
     10 #import "SkTextFieldCell.h"
     11 @implementation SkOptionItem
     12 @synthesize fCell, fItem;
     13 - (void)dealloc {
     14     [fCell release];
     15     [super dealloc];
     16 }
     17 @end
     18 
     19 @implementation SkOptionsTableView
     20 @synthesize fItems;
     21 
     22 - (id)initWithCoder:(NSCoder*)coder {
     23     if ((self = [super initWithCoder:coder])) {
     24         self.dataSource = self;
     25         self.delegate = self;
     26         fMenus = NULL;
     27         fShowKeys = YES;
     28         [self setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];
     29         self.fItems = [NSMutableArray array];
     30     }
     31     return self;
     32 }
     33 
     34 - (void)dealloc {
     35     self.fItems = nil;
     36     [super dealloc];
     37 }
     38 
     39 - (void) view:(SkNSView*)view didAddMenu:(const SkOSMenu*)menu {}
     40 - (void) view:(SkNSView*)view didUpdateMenu:(const SkOSMenu*)menu {
     41     [self updateMenu:menu];
     42 }
     43 
     44 - (IBAction)toggleKeyEquivalents:(id)sender {
     45     fShowKeys = !fShowKeys;
     46     NSMenuItem* item = (NSMenuItem*)sender;
     47     [item setState:fShowKeys];
     48     [self reloadData];
     49 }
     50 
     51 - (void)registerMenus:(const SkTDArray<SkOSMenu*>*)menus {
     52     fMenus = menus;
     53     for (int i = 0; i < fMenus->count(); ++i) {
     54         [self loadMenu:(*fMenus)[i]];
     55     }
     56 }
     57 
     58 - (void)updateMenu:(const SkOSMenu*)menu {
     59     // the first menu is always assumed to be the static, the second is
     60     // repopulated every time over and over again
     61 
     62     // seems pretty weird that we have to get rid of the const'ness here,
     63     // but trying to propagate the const'ness through all the way to the fMenus
     64     // vector was a non-starter.
     65 
     66     int menuIndex = fMenus->find(const_cast<SkOSMenu *>(menu));
     67     if (menuIndex >= 0 && menuIndex < fMenus->count()) {
     68         NSUInteger first = 0;
     69         for (int i = 0; i < menuIndex; ++i) {
     70             first += (*fMenus)[i]->getCount();
     71         }
     72         [fItems removeObjectsInRange:NSMakeRange(first, [fItems count] - first)];
     73         [self loadMenu:menu];
     74     }
     75     [self reloadData];
     76 }
     77 
     78 - (NSCellStateValue)triStateToNSState:(SkOSMenu::TriState)state {
     79     if (SkOSMenu::kOnState == state)
     80         return NSOnState;
     81     else if (SkOSMenu::kOffState == state)
     82         return NSOffState;
     83     else
     84         return NSMixedState;
     85 }
     86 
     87 - (void)loadMenu:(const SkOSMenu*)menu {
     88     const SkOSMenu::Item* menuitems[menu->getCount()];
     89     menu->getItems(menuitems);
     90     for (int i = 0; i < menu->getCount(); ++i) {
     91         const SkOSMenu::Item* item = menuitems[i];
     92         SkOptionItem* option = [[SkOptionItem alloc] init];
     93         option.fItem = item;
     94 
     95         if (SkOSMenu::kList_Type == item->getType()) {
     96             int index = 0, count = 0;
     97             SkOSMenu::FindListItemCount(*item->getEvent(), &count);
     98             NSMutableArray* optionstrs = [[NSMutableArray alloc] initWithCapacity:count];
     99             SkAutoTDeleteArray<SkString> ada(new SkString[count]);
    100             SkString* options = ada.get();
    101             SkOSMenu::FindListItems(*item->getEvent(), options);
    102             for (int i = 0; i < count; ++i)
    103                 [optionstrs addObject:[NSString stringWithUTF8String:options[i].c_str()]];
    104             SkOSMenu::FindListIndex(*item->getEvent(), item->getSlotName(), &index);
    105             option.fCell = [self createList:optionstrs current:index];
    106             [optionstrs release];
    107         }
    108         else {
    109             bool state = false;
    110             SkString str;
    111             SkOSMenu::TriState tristate;
    112             switch (item->getType()) {
    113                 case SkOSMenu::kAction_Type:
    114                     option.fCell = [self createAction];
    115                     break;
    116                 case SkOSMenu::kSlider_Type:
    117                     SkScalar min, max, value;
    118                     SkOSMenu::FindSliderValue(*item->getEvent(), item->getSlotName(), &value);
    119                     SkOSMenu::FindSliderMin(*item->getEvent(), &min);
    120                     SkOSMenu::FindSliderMax(*item->getEvent(), &max);
    121                     option.fCell = [self createSlider:value
    122                                                   min:min
    123                                                   max:max];
    124                     break;
    125                 case SkOSMenu::kSwitch_Type:
    126                     SkOSMenu::FindSwitchState(*item->getEvent(), item->getSlotName(), &state);
    127                     option.fCell = [self createSwitch:(BOOL)state];
    128                     break;
    129                 case SkOSMenu::kTriState_Type:
    130                     SkOSMenu::FindTriState(*item->getEvent(), item->getSlotName(), &tristate);
    131                     option.fCell = [self createTriState:[self triStateToNSState:tristate]];
    132                     break;
    133                 case SkOSMenu::kTextField_Type:
    134                     SkOSMenu::FindText(*item->getEvent(),item->getSlotName(), &str);
    135                     option.fCell = [self createTextField:[NSString stringWithUTF8String:str.c_str()]];
    136                     break;
    137                 default:
    138                     break;
    139             }
    140         }
    141         [fItems addObject:option];
    142         [option release];
    143     }
    144 }
    145 
    146 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    147     return [self.fItems count];
    148 }
    149 
    150 - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    151     NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
    152     if (columnIndex == 0) {
    153         const SkOSMenu::Item* item = ((SkOptionItem*)[fItems objectAtIndex:row]).fItem;
    154         NSString* label = [NSString stringWithUTF8String:item->getLabel()];
    155         if (fShowKeys)
    156             return [NSString stringWithFormat:@"%@ (%c)", label, item->getKeyEquivalent()];
    157         else
    158             return label;
    159     }
    160     else
    161         return nil;
    162 }
    163 
    164 - (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    165     if (tableColumn) {
    166         NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
    167         if (columnIndex == 1)
    168             return [((SkOptionItem*)[fItems objectAtIndex:row]).fCell copy];
    169         else
    170             return [[[SkTextFieldCell alloc] init] autorelease];
    171     }
    172     return nil;
    173 }
    174 
    175 - (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    176     NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
    177     if (columnIndex == 1) {
    178         SkOptionItem* option = (SkOptionItem*)[self.fItems objectAtIndex:row];
    179         NSCell* storedCell = option.fCell;
    180         const SkOSMenu::Item* item = option.fItem;
    181         switch (item->getType()) {
    182             case SkOSMenu::kAction_Type:
    183                 break;
    184             case SkOSMenu::kList_Type:
    185                 [cell selectItemAtIndex:[(NSPopUpButtonCell*)storedCell indexOfSelectedItem]];
    186                 break;
    187             case SkOSMenu::kSlider_Type:
    188                 [cell setFloatValue:[storedCell floatValue]];
    189                 break;
    190             case SkOSMenu::kSwitch_Type:
    191                 [cell setState:[(NSButtonCell*)storedCell state]];
    192                 break;
    193             case SkOSMenu::kTextField_Type:
    194                 if ([[storedCell stringValue] length] > 0)
    195                     [cell setStringValue:[storedCell stringValue]];
    196                 break;
    197             case SkOSMenu::kTriState_Type:
    198                 [cell setState:[(NSButtonCell*)storedCell state]];
    199                 break;
    200             default:
    201                 break;
    202         }
    203     }
    204     else {
    205         [(SkTextFieldCell*)cell setEditable:NO];
    206     }
    207 }
    208 
    209 - (void)tableView:(NSTableView *)tableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    210     NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
    211     if (columnIndex == 1) {
    212         SkOptionItem* option = (SkOptionItem*)[self.fItems objectAtIndex:row];
    213         NSCell* cell = option.fCell;
    214         const SkOSMenu::Item* item = option.fItem;
    215         switch (item->getType()) {
    216             case SkOSMenu::kAction_Type:
    217                 item->postEvent();
    218                 break;
    219             case SkOSMenu::kList_Type:
    220                 [(NSPopUpButtonCell*)cell selectItemAtIndex:[anObject intValue]];
    221                 item->setInt([anObject intValue]);
    222                 break;
    223             case SkOSMenu::kSlider_Type:
    224                 [cell setFloatValue:[anObject floatValue]];
    225                 item->setScalar([anObject floatValue]);
    226                 break;
    227             case SkOSMenu::kSwitch_Type:
    228                 [cell setState:[anObject boolValue]];
    229                 item->setBool([anObject boolValue]);
    230                 break;
    231             case SkOSMenu::kTextField_Type:
    232                 if ([anObject length] > 0) {
    233                     [cell setStringValue:anObject];
    234                     item->setString([anObject UTF8String]);
    235                 }
    236                 break;
    237             case SkOSMenu::kTriState_Type:
    238                 [cell setState:[anObject intValue]];
    239                 item->setTriState((SkOSMenu::TriState)[anObject intValue]);
    240                 break;
    241             default:
    242                 break;
    243         }
    244         item->postEvent();
    245     }
    246 }
    247 
    248 - (NSCell*)createAction{
    249     NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease];
    250     [cell setTitle:@""];
    251     [cell setButtonType:NSMomentaryPushInButton];
    252     [cell setBezelStyle:NSSmallSquareBezelStyle];
    253     return cell;
    254 }
    255 
    256 - (NSCell*)createList:(NSArray*)items current:(int)index {
    257     NSPopUpButtonCell* cell = [[[NSPopUpButtonCell alloc] init] autorelease];
    258     [cell addItemsWithTitles:items];
    259     [cell selectItemAtIndex:index];
    260     [cell setArrowPosition:NSPopUpArrowAtBottom];
    261     [cell setBezelStyle:NSSmallSquareBezelStyle];
    262     return cell;
    263 }
    264 
    265 - (NSCell*)createSlider:(float)value min:(float)min max:(float)max {
    266     NSSliderCell* cell = [[[NSSliderCell alloc] init] autorelease];
    267     [cell setFloatValue:value];
    268     [cell setMinValue:min];
    269     [cell setMaxValue:max];
    270     return cell;
    271 }
    272 
    273 - (NSCell*)createSwitch:(BOOL)state {
    274     NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease];
    275     [cell setState:state];
    276     [cell setTitle:@""];
    277     [cell setButtonType:NSSwitchButton];
    278     return cell;
    279 }
    280 
    281 - (NSCell*)createTextField:(NSString*)placeHolder {
    282     SkTextFieldCell* cell = [[[SkTextFieldCell alloc] init] autorelease];
    283     [cell setEditable:YES];
    284     [cell setStringValue:@""];
    285     [cell setPlaceholderString:placeHolder];
    286     return cell;
    287 }
    288 
    289 - (NSCell*)createTriState:(NSCellStateValue)state {
    290     NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease];
    291     [cell setAllowsMixedState:TRUE];
    292     [cell setTitle:@""];
    293     [cell setState:(NSInteger)state];
    294     [cell setButtonType:NSSwitchButton];
    295     return cell;
    296 }
    297 @end
    298