diff options
Diffstat (limited to 'src/libui_sdl/libui/darwin/entry.m')
-rw-r--r-- | src/libui_sdl/libui/darwin/entry.m | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/darwin/entry.m b/src/libui_sdl/libui/darwin/entry.m new file mode 100644 index 0000000..219d080 --- /dev/null +++ b/src/libui_sdl/libui/darwin/entry.m @@ -0,0 +1,251 @@ +// 14 august 2015 +#import "uipriv_darwin.h" + +// Text fields for entering text have no intrinsic width; we'll use the default Interface Builder width for them. +#define textfieldWidth 96 + +@interface libui_intrinsicWidthNSTextField : NSTextField +@end + +@implementation libui_intrinsicWidthNSTextField + +- (NSSize)intrinsicContentSize +{ + NSSize s; + + s = [super intrinsicContentSize]; + s.width = textfieldWidth; + return s; +} + +@end + +// TODO does this have one on its own? +@interface libui_intrinsicWidthNSSecureTextField : NSSecureTextField +@end + +@implementation libui_intrinsicWidthNSSecureTextField + +- (NSSize)intrinsicContentSize +{ + NSSize s; + + s = [super intrinsicContentSize]; + s.width = textfieldWidth; + return s; +} + +@end + +// TODO does this have one on its own? +@interface libui_intrinsicWidthNSSearchField : NSSearchField +@end + +@implementation libui_intrinsicWidthNSSearchField + +- (NSSize)intrinsicContentSize +{ + NSSize s; + + s = [super intrinsicContentSize]; + s.width = textfieldWidth; + return s; +} + +@end + +struct uiEntry { + uiDarwinControl c; + NSTextField *textfield; + void (*onChanged)(uiEntry *, void *); + void *onChangedData; +}; + +static BOOL isSearchField(NSTextField *tf) +{ + return [tf isKindOfClass:[NSSearchField class]]; +} + +@interface entryDelegateClass : NSObject<NSTextFieldDelegate> { + struct mapTable *entries; +} +- (void)controlTextDidChange:(NSNotification *)note; +- (IBAction)onSearch:(id)sender; +- (void)registerEntry:(uiEntry *)e; +- (void)unregisterEntry:(uiEntry *)e; +@end + +@implementation entryDelegateClass + +- (id)init +{ + self = [super init]; + if (self) + self->entries = newMap(); + return self; +} + +- (void)dealloc +{ + mapDestroy(self->entries); + [super dealloc]; +} + +- (void)controlTextDidChange:(NSNotification *)note +{ + [self onSearch:[note object]]; +} + +- (IBAction)onSearch:(id)sender +{ + uiEntry *e; + + e = (uiEntry *) mapGet(self->entries, sender); + (*(e->onChanged))(e, e->onChangedData); +} + +- (void)registerEntry:(uiEntry *)e +{ + mapSet(self->entries, e->textfield, e); + if (isSearchField(e->textfield)) { + [e->textfield setTarget:self]; + [e->textfield setAction:@selector(onSearch:)]; + } else + [e->textfield setDelegate:self]; +} + +- (void)unregisterEntry:(uiEntry *)e +{ + if (isSearchField(e->textfield)) + [e->textfield setTarget:nil]; + else + [e->textfield setDelegate:nil]; + mapDelete(self->entries, e->textfield); +} + +@end + +static entryDelegateClass *entryDelegate = nil; + +uiDarwinControlAllDefaultsExceptDestroy(uiEntry, textfield) + +static void uiEntryDestroy(uiControl *c) +{ + uiEntry *e = uiEntry(c); + + [entryDelegate unregisterEntry:e]; + [e->textfield release]; + uiFreeControl(uiControl(e)); +} + +char *uiEntryText(uiEntry *e) +{ + return uiDarwinNSStringToText([e->textfield stringValue]); +} + +void uiEntrySetText(uiEntry *e, const char *text) +{ + [e->textfield setStringValue:toNSString(text)]; + // don't queue the control for resize; entry sizes are independent of their contents +} + +void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) +{ + e->onChanged = f; + e->onChangedData = data; +} + +int uiEntryReadOnly(uiEntry *e) +{ + return [e->textfield isEditable] == NO; +} + +void uiEntrySetReadOnly(uiEntry *e, int readonly) +{ + BOOL editable; + + editable = YES; + if (readonly) + editable = NO; + [e->textfield setEditable:editable]; +} + +static void defaultOnChanged(uiEntry *e, void *data) +{ + // do nothing +} + +// these are based on interface builder defaults; my comments in the old code weren't very good so I don't really know what talked about what, sorry :/ +void finishNewTextField(NSTextField *t, BOOL isEntry) +{ + uiDarwinSetControlFont(t, NSRegularControlSize); + + // THE ORDER OF THESE CALLS IS IMPORTANT; CHANGE IT AND THE BORDERS WILL DISAPPEAR + [t setBordered:NO]; + [t setBezelStyle:NSTextFieldSquareBezel]; + [t setBezeled:isEntry]; + + // we don't need to worry about substitutions/autocorrect here; see window_darwin.m for details + + [[t cell] setLineBreakMode:NSLineBreakByClipping]; + [[t cell] setScrollable:YES]; +} + +static NSTextField *realNewEditableTextField(Class class) +{ + NSTextField *tf; + + tf = [[class alloc] initWithFrame:NSZeroRect]; + [tf setSelectable:YES]; // otherwise the setting is masked by the editable default of YES + finishNewTextField(tf, YES); + return tf; +} + +NSTextField *newEditableTextField(void) +{ + return realNewEditableTextField([libui_intrinsicWidthNSTextField class]); +} + +static uiEntry *finishNewEntry(Class class) +{ + uiEntry *e; + + uiDarwinNewControl(uiEntry, e); + + e->textfield = realNewEditableTextField(class); + + if (entryDelegate == nil) { + entryDelegate = [[entryDelegateClass new] autorelease]; + [delegates addObject:entryDelegate]; + } + [entryDelegate registerEntry:e]; + uiEntryOnChanged(e, defaultOnChanged, NULL); + + return e; +} + +uiEntry *uiNewEntry(void) +{ + return finishNewEntry([libui_intrinsicWidthNSTextField class]); +} + +uiEntry *uiNewPasswordEntry(void) +{ + return finishNewEntry([libui_intrinsicWidthNSSecureTextField class]); +} + +uiEntry *uiNewSearchEntry(void) +{ + uiEntry *e; + NSSearchField *s; + + e = finishNewEntry([libui_intrinsicWidthNSSearchField class]); + s = (NSSearchField *) (e->textfield); + // TODO these are only on 10.10 +// [s setSendsSearchStringImmediately:NO]; +// [s setSendsWholeSearchString:NO]; + [s setBordered:NO]; + [s setBezelStyle:NSTextFieldRoundedBezel]; + [s setBezeled:YES]; + return e; +} |