Merged back combobox_darwin.m, rewrote it to use boundListboxArray() instead of creating a whole new object, and implemented what appears to be a fix for NSPopUpButton selection. Will delete the unneeded select(-1) code later and test again...
This commit is contained in:
parent
e3edc7e0c3
commit
4baa9397e6
|
@ -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]);
|
||||||
|
}
|
|
@ -1,156 +0,0 @@
|
||||||
// 17 may 2014
|
|
||||||
|
|
||||||
#include "objc_darwin.h"
|
|
||||||
#include <AppKit/NSPopUpButton.h>
|
|
||||||
#include <AppKit/NSComboBox.h>
|
|
||||||
#include <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.
|
|
||||||
|
|
||||||
You will notice that a bunch of functions here call functions in listbox_darwin.m. How convenient =P
|
|
||||||
*/
|
|
||||||
|
|
||||||
@interface combobox : NSObject {
|
|
||||||
@public
|
|
||||||
NSPopUpButton *pb;
|
|
||||||
NSComboBox *cb;
|
|
||||||
NSArrayController *ac;
|
|
||||||
}
|
|
||||||
// and these are so we can use a combobox like a reegular control
|
|
||||||
- (void)setHidden:(BOOL)hidden;
|
|
||||||
- (void)setFont:(NSFont *)font;
|
|
||||||
- (void)setFrame:(NSRect)r;
|
|
||||||
- (NSRect)frame;
|
|
||||||
- (void)sizeToFit;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation combobox
|
|
||||||
|
|
||||||
#define OVERRIDE(sig, msg) \
|
|
||||||
sig \
|
|
||||||
{ \
|
|
||||||
if (pb != nil) { \
|
|
||||||
[pb msg]; \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
[cb msg]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
OVERRIDE(- (void)setHidden:(BOOL)hidden, setHidden:hidden)
|
|
||||||
OVERRIDE(- (void)setFont:(NSFont *)font, setFont:font)
|
|
||||||
OVERRIDE(- (void)setFrame:(NSRect)r, setFrame:r)
|
|
||||||
|
|
||||||
- (NSRect)frame
|
|
||||||
{
|
|
||||||
if (pb != nil)
|
|
||||||
return [pb frame];
|
|
||||||
return [cb frame];
|
|
||||||
}
|
|
||||||
|
|
||||||
OVERRIDE(- (void)sizeToFit, sizeToFit)
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
extern NSRect dummyRect;
|
|
||||||
|
|
||||||
#define to(T, x) ((T *) (x))
|
|
||||||
#define tocombobox(x) to(combobox, (x))
|
|
||||||
|
|
||||||
#define toNSInteger(x) ((NSInteger) (x))
|
|
||||||
#define fromNSInteger(x) ((intptr_t) (x))
|
|
||||||
|
|
||||||
#define COMBOBOXKEY @"cbitem"
|
|
||||||
static NSString *comboboxKey = COMBOBOXKEY;
|
|
||||||
static NSString *comboboxKeyPath = @"arrangedObjects." COMBOBOXKEY;
|
|
||||||
|
|
||||||
id makeCombobox(BOOL editable)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = [combobox new];
|
|
||||||
c->pb = nil;
|
|
||||||
c->cb = nil;
|
|
||||||
c->ac = makeListboxArray();
|
|
||||||
#define BIND bind:@"contentValues" toObject:c->ac withKeyPath:comboboxKeyPath options:nil
|
|
||||||
if (!editable) {
|
|
||||||
c->pb = [[NSPopUpButton alloc]
|
|
||||||
initWithFrame:dummyRect
|
|
||||||
pullsDown:NO];
|
|
||||||
[c->pb BIND];
|
|
||||||
} else {
|
|
||||||
c->cb = [[NSComboBox alloc]
|
|
||||||
initWithFrame:dummyRect];
|
|
||||||
[c->cb setUsesDataSource:NO];
|
|
||||||
[c->cb BIND];
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addCombobox(id parentWindow, id cbox)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
if (c->pb != nil) {
|
|
||||||
addControl(parentWindow, c->pb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addControl(parentWindow, c->cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
id comboboxText(id cbox, BOOL editable)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
if (!editable)
|
|
||||||
return [c->pb titleOfSelectedItem];
|
|
||||||
return [c->cb stringValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxAppend(id cbox, BOOL editable, id str)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
listboxArrayAppend(c->ac, toListboxItem(comboboxKey, str));
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxInsertBefore(id cbox, BOOL editable, id str, intptr_t before)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
listboxArrayInsertBefore(c->ac, toListboxItem(comboboxKey, str), before);
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t comboboxSelectedIndex(id cbox)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
if (c->pb != nil)
|
|
||||||
return fromNSInteger([c->pb indexOfSelectedItem]);
|
|
||||||
return fromNSInteger([c->cb indexOfSelectedItem]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxDelete(id cbox, intptr_t index)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
listboxArrayDelete(c->ac, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t comboboxLen(id cbox)
|
|
||||||
{
|
|
||||||
combobox *c;
|
|
||||||
|
|
||||||
c = tocombobox(cbox);
|
|
||||||
if (c->pb != nil)
|
|
||||||
return fromNSInteger([c->pb numberOfItems]);
|
|
||||||
return fromNSInteger([c->cb numberOfItems]);
|
|
||||||
}
|
|
|
@ -103,13 +103,6 @@ extern void buttonSetTargetAction(id, id);
|
||||||
extern void buttonSetText(id, id);
|
extern void buttonSetText(id, id);
|
||||||
extern id buttonText(id);
|
extern id buttonText(id);
|
||||||
extern id makeCheckbox(void);
|
extern id makeCheckbox(void);
|
||||||
extern id makeCombobox(BOOL);
|
|
||||||
extern id comboboxText(id, BOOL);
|
|
||||||
extern void comboboxAppend(id, BOOL, id);
|
|
||||||
extern void comboboxInsertBefore(id, BOOL, id, intptr_t);
|
|
||||||
extern intptr_t comboboxSelectedIndex(id);
|
|
||||||
extern void comboboxDelete(id, intptr_t);
|
|
||||||
extern intptr_t comboboxLen(id);
|
|
||||||
extern void comboboxSelectIndex(id, BOOL, intptr_t);
|
extern void comboboxSelectIndex(id, BOOL, intptr_t);
|
||||||
extern id makeLineEdit(BOOL);
|
extern id makeLineEdit(BOOL);
|
||||||
extern void lineeditSetText(id, id);
|
extern void lineeditSetText(id, id);
|
||||||
|
@ -122,4 +115,13 @@ extern void windowSetContentSize(id, intptr_t, intptr_t);
|
||||||
extern void setProgress(id, intptr_t);
|
extern void setProgress(id, intptr_t);
|
||||||
extern void setAreaSize(id, intptr_t, intptr_t);
|
extern void setAreaSize(id, intptr_t, intptr_t);
|
||||||
|
|
||||||
|
/* combobox_darwin.m */
|
||||||
|
extern id makeCombobox(BOOL);
|
||||||
|
extern id comboboxText(id, BOOL);
|
||||||
|
extern void comboboxAppend(id, BOOL, id);
|
||||||
|
extern void comboboxInsertBefore(id, BOOL, id, intptr_t);
|
||||||
|
extern intptr_t comboboxSelectedIndex(id);
|
||||||
|
extern void comboboxDelete(id, intptr_t);
|
||||||
|
extern intptr_t comboboxLen(id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#import <AppKit/NSFont.h>
|
#import <AppKit/NSFont.h>
|
||||||
#import <AppKit/NSControl.h>
|
#import <AppKit/NSControl.h>
|
||||||
#import <AppKit/NSButton.h>
|
#import <AppKit/NSButton.h>
|
||||||
#import <AppKit/NSPopUpButton.h>
|
|
||||||
#import <AppKit/NSComboBox.h>
|
|
||||||
#import <AppKit/NSTextField.h>
|
#import <AppKit/NSTextField.h>
|
||||||
#import <AppKit/NSSecureTextField.h>
|
#import <AppKit/NSSecureTextField.h>
|
||||||
#import <AppKit/NSProgressIndicator.h>
|
#import <AppKit/NSProgressIndicator.h>
|
||||||
|
@ -39,8 +37,6 @@ extern NSRect dummyRect;
|
||||||
#define toNSView(x) to(NSView, (x))
|
#define toNSView(x) to(NSView, (x))
|
||||||
#define toNSControl(x) to(NSControl, (x))
|
#define toNSControl(x) to(NSControl, (x))
|
||||||
#define toNSButton(x) to(NSButton, (x))
|
#define toNSButton(x) to(NSButton, (x))
|
||||||
#define toNSPopUpButton(x) to(NSPopUpButton, (x))
|
|
||||||
#define toNSComboBox(x) to(NSComboBox, (x))
|
|
||||||
#define toNSTextField(x) to(NSTextField, (x))
|
#define toNSTextField(x) to(NSTextField, (x))
|
||||||
#define toNSProgressIndicator(x) to(NSProgressIndicator, (x))
|
#define toNSProgressIndicator(x) to(NSProgressIndicator, (x))
|
||||||
#define toNSScrollView(x) to(NSScrollView, (x))
|
#define toNSScrollView(x) to(NSScrollView, (x))
|
||||||
|
@ -143,89 +139,9 @@ id makeCheckbox(void)
|
||||||
return checkbox;
|
return checkbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
id makeCombobox(BOOL editable)
|
|
||||||
{
|
|
||||||
if (!editable) {
|
|
||||||
NSPopUpButton *combobox;
|
|
||||||
|
|
||||||
combobox = [[NSPopUpButton alloc]
|
|
||||||
initWithFrame:dummyRect
|
|
||||||
pullsDown:NO];
|
|
||||||
return combobox;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSComboBox *combobox;
|
|
||||||
|
|
||||||
combobox = [[NSComboBox alloc]
|
|
||||||
initWithFrame:dummyRect];
|
|
||||||
[combobox setUsesDataSource:NO];
|
|
||||||
return combobox;
|
|
||||||
}
|
|
||||||
|
|
||||||
id comboboxText(id combobox, BOOL editable)
|
|
||||||
{
|
|
||||||
if (!editable)
|
|
||||||
return [toNSPopUpButton(combobox) titleOfSelectedItem];
|
|
||||||
return [toNSComboBox(combobox) stringValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxAppend(id combobox, BOOL editable, id str)
|
|
||||||
{
|
|
||||||
if (!editable) {
|
|
||||||
[toNSPopUpButton(combobox) addItemWithTitle:str];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[toNSComboBox(combobox) addItemWithObjectValue:str];
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxInsertBefore(id combobox, BOOL editable, id str, intptr_t before)
|
|
||||||
{
|
|
||||||
if (!editable) {
|
|
||||||
[toNSPopUpButton(combobox) insertItemWithTitle:str atIndex:toNSInteger(before)];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[toNSComboBox(combobox) insertItemWithObjectValue:str atIndex:toNSInteger(before)];
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t comboboxSelectedIndex(id combobox)
|
|
||||||
{
|
|
||||||
// works the same for both NSPopUpButton and NSComboBox
|
|
||||||
return fromNSInteger([toNSPopUpButton(combobox) indexOfSelectedItem]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxDelete(id combobox, intptr_t index)
|
|
||||||
{
|
|
||||||
// works the same for both NSPopUpButton and NSComboBox
|
|
||||||
[toNSPopUpButton(combobox) removeItemAtIndex:toNSInteger(index)];
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t comboboxLen(id combobox)
|
|
||||||
{
|
|
||||||
// works the same for both NSPopUpButton and NSComboBox
|
|
||||||
return fromNSInteger([toNSPopUpButton(combobox) numberOfItems]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void comboboxSelectIndex(id combobox, BOOL editable, intptr_t index)
|
void comboboxSelectIndex(id combobox, BOOL editable, intptr_t index)
|
||||||
{
|
{
|
||||||
NSInteger i;
|
// TODO remove
|
||||||
NSInteger selected;
|
|
||||||
NSComboBox *c;
|
|
||||||
|
|
||||||
i = toNSInteger(index);
|
|
||||||
// NSPopUpButton documents -1 as deselecting, so we can just use selectItemAtindex: directly
|
|
||||||
if (!editable) {
|
|
||||||
[toNSPopUpButton(combobox) selectItemAtIndex:i];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// NSComboBox, on the other hand, does not, so to be safe, we do things the long way
|
|
||||||
c = toNSComboBox(combobox);
|
|
||||||
if (i == -1) { // deselect
|
|
||||||
selected = [c indexOfSelectedItem];
|
|
||||||
if (selected != -1)
|
|
||||||
[c deselectItemAtIndex:selected];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[c selectItemAtIndex:i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id makeLineEdit(BOOL password)
|
id makeLineEdit(BOOL password)
|
||||||
|
|
Loading…
Reference in New Issue