aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/views/mac/SkOptionsTableView.mm
blob: 51d4864833077a8d9d63b86740c6a79c9ab94009 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

/*
 * 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<SkOSMenu*>*)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<SkOSMenu *>(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<SkString[]> 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