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