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 id buttonText(id);
|
||||
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 id makeLineEdit(BOOL);
|
||||
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 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
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#import <AppKit/NSFont.h>
|
||||
#import <AppKit/NSControl.h>
|
||||
#import <AppKit/NSButton.h>
|
||||
#import <AppKit/NSPopUpButton.h>
|
||||
#import <AppKit/NSComboBox.h>
|
||||
#import <AppKit/NSTextField.h>
|
||||
#import <AppKit/NSSecureTextField.h>
|
||||
#import <AppKit/NSProgressIndicator.h>
|
||||
|
@ -39,8 +37,6 @@ extern NSRect dummyRect;
|
|||
#define toNSView(x) to(NSView, (x))
|
||||
#define toNSControl(x) to(NSControl, (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 toNSProgressIndicator(x) to(NSProgressIndicator, (x))
|
||||
#define toNSScrollView(x) to(NSScrollView, (x))
|
||||
|
@ -143,89 +139,9 @@ id makeCheckbox(void)
|
|||
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)
|
||||
{
|
||||
NSInteger i;
|
||||
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];
|
||||
// TODO remove
|
||||
}
|
||||
|
||||
id makeLineEdit(BOOL password)
|
||||
|
|
Loading…
Reference in New Issue