From 265879b272e49101e8be1f2408734bb5ff6fa332 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Fri, 21 Aug 2015 21:03:50 -0400 Subject: [PATCH] Really implemented uiSpinbox on OS X. --- redo/reredo/darwin/spinbox.m | 138 +++++++++++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 6 deletions(-) diff --git a/redo/reredo/darwin/spinbox.m b/redo/reredo/darwin/spinbox.m index c541ced1..776aaf0e 100644 --- a/redo/reredo/darwin/spinbox.m +++ b/redo/reredo/darwin/spinbox.m @@ -1,27 +1,148 @@ // 14 august 2015 #import "uipriv_darwin.h" +@interface libui_spinbox : NSView { + NSTextField *tf; + NSNumberFormatter *formatter; + NSStepper *stepper; + + NSInteger value; + NSInteger minimum; + NSInteger maximum; + + uiSpinbox *spinbox; +} +- (id)initWithFrame:(NSRect)r spinbox:(uiSpinbox *)sb; +// see https://github.com/andlabs/ui/issues/82 +- (NSInteger)libui_value; +- (void)libui_setValue:(NSInteger)val; +- (void)setMinimum:(NSInteger)min; +- (void)setMaximum:(NSInteger)max; +- (IBAction)stepperClicked:(id)sender; +- (void)controlTextDidChange:(NSNotification *)note; +@end + struct uiSpinbox { uiDarwinControl c; - NSTextField *dummy; + libui_spinbox *spinbox; void (*onChanged)(uiSpinbox *, void *); void *onChangedData; }; +@implementation libui_spinbox + +- (id)initWithFrame:(NSRect)r spinbox:(uiSpinbox *)sb +{ + NSDictionary *views; + + self = [super initWithFrame:r]; + if (self) { + self->tf = newEditableTextField(); + [self->tf setTranslatesAutoresizingMaskIntoConstraints:NO]; + + self->formatter = [NSNumberFormatter new]; + [self->formatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; + [self->formatter setLocalizesFormat:NO]; + [self->formatter setUsesGroupingSeparator:NO]; + [self->formatter setHasThousandSeparators:NO]; + [self->formatter setAllowsFloats:NO]; + [self->tf setFormatter:self->formatter]; + + self->stepper = [[NSStepper alloc] initWithFrame:NSZeroRect]; + [self->stepper setIncrement:1]; + [self->stepper setValueWraps:NO]; + [self->stepper setAutorepeat:YES]; // hold mouse button to step repeatedly + [self->stepper setTranslatesAutoresizingMaskIntoConstraints:NO]; + + [self->tf setDelegate:self]; + [self->stepper setTarget:self]; + [self->stepper setAction:@selector(stepperClicked:)]; + + [self addSubview:self->tf]; + [self addSubview:self->stepper]; + views = [NSDictionary + dictionaryWithObjectsAndKeys:self->tf, @"textfield", + self->stepper, @"stepper", + nil]; + addConstraint(self, @"H:|[textfield]-[stepper]|", nil, views); + addConstraint(self, @"V:|[textfield]|", nil, views); + addConstraint(self, @"V:|[stepper]|", nil, views); + + self->spinbox = sb; + } + return self; +} + +- (void)dealloc +{ + [self->tf setDelegate:nil]; + [self->tf removeFromSuperview]; + [self->tf release]; + [self->formatter release]; + [self->stepper setTarget:nil]; + [self->stepper removeFromSuperview]; + [self->stepper release]; + [super dealloc]; +} + +- (NSInteger)libui_value +{ + return self->value; +} + +- (void)libui_setValue:(NSInteger)val +{ + self->value = val; + if (self->value < self->minimum) + self->value = self->minimum; + if (self->value > self->maximum) + self->value = self->maximum; + [self->tf setIntegerValue:self->value]; + [self->stepper setIntegerValue:self->value]; +} + +- (void)setMinimum:(NSInteger)min +{ + self->minimum = min; + [self->formatter setMinimum:[NSNumber numberWithInteger:self->minimum]]; + [self->stepper setMinValue:((double) (self->minimum))]; +} + +- (void)setMaximum:(NSInteger)max +{ + self->maximum = max; + [self->formatter setMaximum:[NSNumber numberWithInteger:self->maximum]]; + [self->stepper setMaxValue:((double) (self->maximum))]; +} + +- (IBAction)stepperClicked:(id)sender +{ + [self libui_setValue:[self->stepper integerValue]]; + (*(self->spinbox->onChanged))(self->spinbox, self->spinbox->onChangedData); +} + +- (void)controlTextDidChange:(NSNotification *)note +{ + [self libui_setValue:[self->tf integerValue]]; + (*(self->spinbox->onChanged))(self->spinbox, self->spinbox->onChangedData); +} + +@end + uiDarwinDefineControl( uiSpinbox, // type name uiSpinboxType, // type function - dummy // handle + spinbox // handle ) intmax_t uiSpinboxValue(uiSpinbox *s) { - return PUT_CODE_HERE; + return [s->spinbox libui_value]; } void uiSpinboxSetValue(uiSpinbox *s, intmax_t value) { - // TODO + [s->spinbox libui_setValue:value]; } void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *, void *), void *data) @@ -39,10 +160,15 @@ uiSpinbox *uiNewSpinbox(intmax_t min, intmax_t max) { uiSpinbox *s; + if (min >= max) + complain("error: min >= max in uiNewSpinbox()"); + s = (uiSpinbox *) uiNewControl(uiSpinboxType()); - s->dummy = [[NSTextField alloc] initWithFrame:NSZeroRect]; - [s->dummy setStringValue:@"TODO uiSpinbox not implemented"]; + s->spinbox = [[libui_spinbox alloc] initWithFrame:NSZeroRect spinbox:s]; + [s->spinbox setMinimum:min]; + [s->spinbox setMaximum:max]; + [s->spinbox libui_setValue:min]; uiSpinboxOnChanged(s, defaultOnChanged, NULL);