/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #import "SkOptionsTableView.h" #import "SkTextFieldCell.h" @implementation SkOptionItem @synthesize fCell, fItem; - (void)dealloc { [fCell release]; [super dealloc]; } @end @implementation SkOptionsTableView @synthesize fItems; - (id)initWithCoder:(NSCoder*)coder { if ((self = [super initWithCoder:coder])) { self.dataSource = self; self.delegate = self; fMenus = NULL; fShowKeys = YES; [self setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone]; self.fItems = [NSMutableArray array]; } return self; } - (void)dealloc { self.fItems = nil; [super dealloc]; } - (void) view:(SkNSView*)view didAddMenu:(const SkOSMenu*)menu {} - (void) view:(SkNSView*)view didUpdateMenu:(const SkOSMenu*)menu { [self updateMenu:menu]; } - (IBAction)toggleKeyEquivalents:(id)sender { fShowKeys = !fShowKeys; NSMenuItem* item = (NSMenuItem*)sender; [item setState:fShowKeys]; [self reloadData]; } - (void)registerMenus:(const SkTDArray*)menus { fMenus = menus; for (int i = 0; i < fMenus->count(); ++i) { [self loadMenu:(*fMenus)[i]]; } } - (void)updateMenu:(const SkOSMenu*)menu { // the first menu is always assumed to be the static, the second is // repopulated every time over and over again // seems pretty weird that we have to get rid of the const'ness here, // but trying to propagate the const'ness through all the way to the fMenus // vector was a non-starter. int menuIndex = fMenus->find(const_cast(menu)); if (menuIndex >= 0 && menuIndex < fMenus->count()) { NSUInteger first = 0; for (int i = 0; i < menuIndex; ++i) { first += (*fMenus)[i]->getCount(); } [fItems removeObjectsInRange:NSMakeRange(first, [fItems count] - first)]; [self loadMenu:menu]; } [self reloadData]; } - (NSCellStateValue)triStateToNSState:(SkOSMenu::TriState)state { if (SkOSMenu::kOnState == state) return NSOnState; else if (SkOSMenu::kOffState == state) return NSOffState; else return NSMixedState; } - (void)loadMenu:(const SkOSMenu*)menu { const SkOSMenu::Item* menuitems[menu->getCount()]; menu->getItems(menuitems); for (int i = 0; i < menu->getCount(); ++i) { const SkOSMenu::Item* item = menuitems[i]; SkOptionItem* option = [[SkOptionItem alloc] init]; option.fItem = item; if (SkOSMenu::kList_Type == item->getType()) { int index = 0, count = 0; SkOSMenu::FindListItemCount(*item->getEvent(), &count); NSMutableArray* optionstrs = [[NSMutableArray alloc] initWithCapacity:count]; std::unique_ptr ada(new SkString[count]); SkString* options = ada.get(); SkOSMenu::FindListItems(*item->getEvent(), options); for (int i = 0; i < count; ++i) [optionstrs addObject:[NSString stringWithUTF8String:options[i].c_str()]]; SkOSMenu::FindListIndex(*item->getEvent(), item->getSlotName(), &index); option.fCell = [self createList:optionstrs current:index]; [optionstrs release]; } else { bool state = false; SkString str; SkOSMenu::TriState tristate; switch (item->getType()) { case SkOSMenu::kAction_Type: option.fCell = [self createAction]; break; case SkOSMenu::kSlider_Type: SkScalar min, max, value; SkOSMenu::FindSliderValue(*item->getEvent(), item->getSlotName(), &value); SkOSMenu::FindSliderMin(*item->getEvent(), &min); SkOSMenu::FindSliderMax(*item->getEvent(), &max); option.fCell = [self createSlider:value min:min max:max]; break; case SkOSMenu::kSwitch_Type: SkOSMenu::FindSwitchState(*item->getEvent(), item->getSlotName(), &state); option.fCell = [self createSwitch:(BOOL)state]; break; case SkOSMenu::kTriState_Type: SkOSMenu::FindTriState(*item->getEvent(), item->getSlotName(), &tristate); option.fCell = [self createTriState:[self triStateToNSState:tristate]]; break; case SkOSMenu::kTextField_Type: SkOSMenu::FindText(*item->getEvent(),item->getSlotName(), &str); option.fCell = [self createTextField:[NSString stringWithUTF8String:str.c_str()]]; break; default: break; } } [fItems addObject:option]; [option release]; } } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return [self.fItems count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]]; if (columnIndex == 0) { const SkOSMenu::Item* item = ((SkOptionItem*)[fItems objectAtIndex:row]).fItem; NSString* label = [NSString stringWithUTF8String:item->getLabel()]; if (fShowKeys) return [NSString stringWithFormat:@"%@ (%c)", label, item->getKeyEquivalent()]; else return label; } else return nil; } - (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { if (tableColumn) { NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]]; if (columnIndex == 1) return [((SkOptionItem*)[fItems objectAtIndex:row]).fCell copy]; else return [[[SkTextFieldCell alloc] init] autorelease]; } return nil; } - (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]]; if (columnIndex == 1) { SkOptionItem* option = (SkOptionItem*)[self.fItems objectAtIndex:row]; NSCell* storedCell = option.fCell; const SkOSMenu::Item* item = option.fItem; switch (item->getType()) { case SkOSMenu::kAction_Type: break; case SkOSMenu::kList_Type: [cell selectItemAtIndex:[(NSPopUpButtonCell*)storedCell indexOfSelectedItem]]; break; case SkOSMenu::kSlider_Type: [cell setFloatValue:[storedCell floatValue]]; break; case SkOSMenu::kSwitch_Type: [cell setState:[(NSButtonCell*)storedCell state]]; break; case SkOSMenu::kTextField_Type: if ([[storedCell stringValue] length] > 0) [cell setStringValue:[storedCell stringValue]]; break; case SkOSMenu::kTriState_Type: [cell setState:[(NSButtonCell*)storedCell state]]; break; default: break; } } else { [(SkTextFieldCell*)cell setEditable:NO]; } } - (void)tableView:(NSTableView *)tableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]]; if (columnIndex == 1) { SkOptionItem* option = (SkOptionItem*)[self.fItems objectAtIndex:row]; NSCell* cell = option.fCell; const SkOSMenu::Item* item = option.fItem; switch (item->getType()) { case SkOSMenu::kAction_Type: item->postEvent(); break; case SkOSMenu::kList_Type: [(NSPopUpButtonCell*)cell selectItemAtIndex:[anObject intValue]]; item->setInt([anObject intValue]); break; case SkOSMenu::kSlider_Type: [cell setFloatValue:[anObject floatValue]]; item->setScalar([anObject floatValue]); break; case SkOSMenu::kSwitch_Type: [cell setState:[anObject boolValue]]; item->setBool([anObject boolValue]); break; case SkOSMenu::kTextField_Type: if ([anObject length] > 0) { [cell setStringValue:anObject]; item->setString([anObject UTF8String]); } break; case SkOSMenu::kTriState_Type: [cell setState:[anObject intValue]]; item->setTriState((SkOSMenu::TriState)[anObject intValue]); break; default: break; } item->postEvent(); } } - (NSCell*)createAction{ NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease]; [cell setTitle:@""]; [cell setButtonType:NSMomentaryPushInButton]; [cell setBezelStyle:NSSmallSquareBezelStyle]; return cell; } - (NSCell*)createList:(NSArray*)items current:(int)index { NSPopUpButtonCell* cell = [[[NSPopUpButtonCell alloc] init] autorelease]; [cell addItemsWithTitles:items]; [cell selectItemAtIndex:index]; [cell setArrowPosition:NSPopUpArrowAtBottom]; [cell setBezelStyle:NSSmallSquareBezelStyle]; return cell; } - (NSCell*)createSlider:(float)value min:(float)min max:(float)max { NSSliderCell* cell = [[[NSSliderCell alloc] init] autorelease]; [cell setFloatValue:value]; [cell setMinValue:min]; [cell setMaxValue:max]; return cell; } - (NSCell*)createSwitch:(BOOL)state { NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease]; [cell setState:state]; [cell setTitle:@""]; [cell setButtonType:NSSwitchButton]; return cell; } - (NSCell*)createTextField:(NSString*)placeHolder { SkTextFieldCell* cell = [[[SkTextFieldCell alloc] init] autorelease]; [cell setEditable:YES]; [cell setStringValue:@""]; [cell setPlaceholderString:placeHolder]; return cell; } - (NSCell*)createTriState:(NSCellStateValue)state { NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease]; [cell setAllowsMixedState:TRUE]; [cell setTitle:@""]; [cell setState:(NSInteger)state]; [cell setButtonType:NSSwitchButton]; return cell; } @end