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