diff options
Diffstat (limited to 'combobox_darwin.m')
| -rw-r--r-- | combobox_darwin.m | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/combobox_darwin.m b/combobox_darwin.m new file mode 100644 index 0000000..5c88b07 --- /dev/null +++ b/combobox_darwin.m @@ -0,0 +1,122 @@ +// 17 may 2014 + +#include "objc_darwin.h" + +// see delegateuitask_darwin.m +// in this case, NSPopUpButton.h and NSComboBox.h includes NSApplication.h +#import <AppKit/NSArrayController.h> + +#ifdef MAC_OS_X_VERSION_10_7 +#undef MAC_OS_X_VERSION_MIN_REQUIRED +#undef MAC_OS_X_VERSION_MAX_ALLOWED +#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_7 +#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_7 +#endif +#import <AppKit/NSApplication.h> +#undef MAC_OS_X_VERSION_MIN_REQUIRED +#undef MAC_OS_X_VERSION_MAX_ALLOWED +#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6 +#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_6 + +#import <AppKit/NSPopUpButton.h> +#import <AppKit/NSComboBox.h> +#import <AppKit/NSArrayController.h> + +/* +Cocoa doesn't have combo boxes in the sense that other systems do. NSPopUpButton is not editable and technically behaves like a menu on a menubar. NSComboBox is editable and is the more traditional combo box, but the edit field and list are even more separated than they are on other platforms. + +Unfortunately, their default internal storage mechanisms exhibit the automatic selection behavior I DON'T want, so we're going to have to do that ourselves. + +The NSArrayController we use in our Listboxes already behaves the way we want. Consequently, you'll notice a bunch of functions here call functions in listbox_darwin.m. How convenient =P (TODO separate into objc_darwin.m?) + +TODO should we use NSComboBox's dataSource feature? +*/ + +extern NSRect dummyRect; + +#define to(T, x) ((T *) (x)) +#define toNSPopUpButton(x) to(NSPopUpButton, (x)) +#define toNSComboBox(x) to(NSComboBox, (x)) + +#define toNSInteger(x) ((NSInteger) (x)) +#define fromNSInteger(x) ((intptr_t) (x)) + +#define COMBOBOXKEY @"cbitem" +static NSString *comboboxKey = COMBOBOXKEY; +static NSString *comboboxBinding = @"contentValues"; +static NSString *comboboxKeyPath = @"arrangedObjects." COMBOBOXKEY; + +id makeCombobox(BOOL editable) +{ + NSArrayController *ac; + + ac = makeListboxArray(); +#define BIND bind:comboboxBinding toObject:ac withKeyPath:comboboxKeyPath options:nil +// for NSPopUpButton, we need a little extra work to make it respect the NSArrayController's selection behavior properties +// thanks to stevesliva (http://stackoverflow.com/questions/23715275/cocoa-how-do-i-suppress-nspopupbutton-automatic-selection-synchronization-nsar) +// TODO where in the docs does it say that NSArrayController has a keyPath of selectionIndex? it's not in the Cocoa Bindings Reference +#define BINDSEL bind:@"selectedIndex" toObject:ac withKeyPath:@"selectionIndex" options:nil + + if (!editable) { + NSPopUpButton *pb; + + pb = [[NSPopUpButton alloc] + initWithFrame:dummyRect + pullsDown:NO]; + [pb BIND]; + [pb BINDSEL]; + return pb; + } + + NSComboBox *cb; + + cb = [[NSComboBox alloc] + initWithFrame:dummyRect]; + [cb setUsesDataSource:NO]; + [cb BIND]; + // no need to bind selection + return cb; +} + +id comboboxText(id c, BOOL editable) +{ + if (!editable) + return [toNSPopUpButton(c) titleOfSelectedItem]; + return [toNSComboBox(c) stringValue]; +} + +void comboboxAppend(id c, BOOL editable, id str) +{ + id ac; + + ac = boundListboxArray(c, comboboxBinding); + listboxArrayAppend(ac, toListboxItem(comboboxKey, str)); +} + +void comboboxInsertBefore(id c, BOOL editable, id str, intptr_t before) +{ + id ac; + + ac = boundListboxArray(c, comboboxBinding); + listboxArrayInsertBefore(ac, toListboxItem(comboboxKey, str), before); +} + +intptr_t comboboxSelectedIndex(id c) +{ + // both satisfy the selector + return fromNSInteger([toNSPopUpButton(c) indexOfSelectedItem]); +} + +void comboboxDelete(id c, intptr_t index) +{ + id ac; + + ac = boundListboxArray(c, comboboxBinding); + listboxArrayDelete(ac, index); +} + +intptr_t comboboxLen(id c) +{ + // both satisfy the selector + return fromNSInteger([toNSPopUpButton(c) numberOfItems]); +} |
