Sat, 04 Oct 2025 14:52:59 +0200
fix repolist menu button
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2025 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "entry.h" #import <objc/runtime.h> @implementation UiSpinBox - (UiSpinBox*)init { return self; } - (void)valueChanged { float value = _stepper.doubleValue; UiEvent e; e.obj = _obj; e.window = e.obj->window; e.document = e.obj->ctx->document; e.eventdata = NULL; e.eventdatatype = 0; e.intval = (int)value; e.set = ui_get_setop(); if(_onchange) { _onchange(&e, _onchangedata); } if(_observers) { UiObserver *observer = *_observers; ui_notify_evt(observer, &e); } } - (void)stepperChanged:(id)sender { if(_isInteger) { _textfield.integerValue = _stepper.integerValue; } else { _textfield.doubleValue = _stepper.doubleValue; } [self valueChanged]; } - (void) controlTextDidChange:(NSNotification *)obj { if(_isInteger) { _stepper.integerValue = _textfield.integerValue; } else { _stepper.doubleValue = _textfield.doubleValue; } [self valueChanged]; } @end UIWIDGET ui_spinbox_create(UiObject *obj, UiSpinBoxArgs *args) { double min = args->min; double max = args->max != 0 ? args->max : 1000; UiVar *var = NULL; UiVarType vartype = 0; if(args->varname) { var = uic_get_var(obj->ctx, args->varname); if(var) { vartype = var->type; } else { var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, args->varname, UI_VAR_RANGE); vartype = UI_VAR_RANGE; } } if(!var) { if(args->intvalue) { var = uic_widget_var(obj->ctx, obj->ctx, args->intvalue, NULL, UI_VAR_INTEGER); vartype = UI_VAR_INTEGER; } else if(args->doublevalue) { var = uic_widget_var(obj->ctx, obj->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE); vartype = UI_VAR_DOUBLE; } else if(args->rangevalue) { var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, NULL, UI_VAR_RANGE); vartype = UI_VAR_RANGE; } } if(vartype == UI_VAR_RANGE) { UiRange *r = var->value; min = r->min; max = r->max; } if(args->step == 0) { args->step = 1; } // create and setup textfield for number input NSTextField *textfield = [[NSTextField alloc] init]; textfield.translatesAutoresizingMaskIntoConstraints = NO; if(!args->hfill || args->width > 0) { textfield.translatesAutoresizingMaskIntoConstraints = NO; int width = args->width > 0 ? args->width : 100; [[textfield.widthAnchor constraintEqualToConstant:width] setActive:YES]; } NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; formatter.numberStyle = NSNumberFormatterDecimalStyle; formatter.allowsFloats = vartype != UI_VAR_INTEGER; formatter.minimumFractionDigits = args->digits; formatter.maximumFractionDigits = args->digits; textfield.formatter = formatter; // create view containing the textfield and stepper NSView *view = [[NSView alloc]init]; view.translatesAutoresizingMaskIntoConstraints = NO; NSStepper *stepper = [[NSStepper alloc] init]; stepper.translatesAutoresizingMaskIntoConstraints = NO; [view addSubview:textfield]; [view addSubview:stepper]; [NSLayoutConstraint activateConstraints:@[ [textfield.leadingAnchor constraintEqualToAnchor:view.leadingAnchor], [textfield.topAnchor constraintEqualToAnchor:view.topAnchor], [textfield.bottomAnchor constraintEqualToAnchor:view.bottomAnchor], [stepper.trailingAnchor constraintEqualToAnchor:view.trailingAnchor], [stepper.topAnchor constraintEqualToAnchor:view.topAnchor], [stepper.bottomAnchor constraintEqualToAnchor:view.bottomAnchor], [textfield.trailingAnchor constraintEqualToAnchor:stepper.leadingAnchor] ]]; UiLayout layout = UI_INIT_LAYOUT(args); ui_container_add(obj, view, &layout); // create the spinbox object, that handles all textfield and stepper events UiSpinBox *spinbox = [[UiSpinBox alloc]init]; spinbox.obj = obj; spinbox.textfield = textfield; spinbox.stepper = stepper; spinbox.onchange = args->onchange; spinbox.onchangedata = args->onchangedata; spinbox.isInteger = vartype == UI_VAR_INTEGER; objc_setAssociatedObject(stepper, "ui_spinbox", spinbox, OBJC_ASSOCIATION_RETAIN); stepper.minValue = min; stepper.maxValue = max; stepper.increment = args->step; stepper.target = spinbox; stepper.action = @selector(stepperChanged:); textfield.delegate = spinbox; UiObserver **obs = NULL; if(var) { void *varObj = (__bridge void*)spinbox; switch(vartype) { default: break; case UI_VAR_INTEGER: { UiInteger *i = var->value; i->get = ui_spinbutton_getint; i->set = ui_spinbutton_setint; i->obj = varObj; obs = &i->observers; stepper.integerValue = i->value; textfield.integerValue = i->value; break; } case UI_VAR_DOUBLE: { UiDouble *d = var->value; d->get = ui_spinbutton_getdouble; d->set = ui_spinbutton_setdouble; d->obj = varObj; obs = &d->observers; stepper.doubleValue = d->value; textfield.doubleValue = d->value; break; } case UI_VAR_RANGE: { UiRange *r = var->value; r->get = ui_spinbutton_getrangeval; r->set = ui_spinbutton_setrangeval; r->setrange = ui_spinbutton_setrange; r->setextent = ui_spinbutton_setextent; r->obj = varObj; obs = &r->observers; stepper.doubleValue = r->value; textfield.doubleValue = r->value; break; } } } spinbox.observers = obs; return (__bridge void*)textfield; } int64_t ui_spinbutton_getint(UiInteger *i) { UiSpinBox *spinbox = (__bridge UiSpinBox*)i->obj; i->value = spinbox.stepper.integerValue; return i->value; } void ui_spinbutton_setint(UiInteger *i, int64_t val) { UiSpinBox *spinbox = (__bridge UiSpinBox*)i->obj; i->value = val; spinbox.stepper.integerValue = val; spinbox.textfield.integerValue = val; } double ui_spinbutton_getdouble(UiDouble *d) { UiSpinBox *spinbox = (__bridge UiSpinBox*)d->obj; d->value = spinbox.stepper.doubleValue; return d->value; } void ui_spinbutton_setdouble(UiDouble *d, double val) { UiSpinBox *spinbox = (__bridge UiSpinBox*)d->obj; d->value = val; spinbox.stepper.doubleValue = val; spinbox.textfield.doubleValue = val; } double ui_spinbutton_getrangeval(UiRange *r) { UiSpinBox *spinbox = (__bridge UiSpinBox*)r->obj; r->value = spinbox.stepper.doubleValue; return r->value; } void ui_spinbutton_setrangeval(UiRange *r, double val) { UiSpinBox *spinbox = (__bridge UiSpinBox*)r->obj; r->value = val; spinbox.stepper.doubleValue = val; spinbox.textfield.doubleValue = val; } void ui_spinbutton_setrange(UiRange *r, double min, double max) { UiSpinBox *spinbox = (__bridge UiSpinBox*)r->obj; spinbox.stepper.minValue = min; spinbox.stepper.maxValue = max; } void ui_spinbutton_setextent(UiRange *r, double extent) { UiSpinBox *spinbox = (__bridge UiSpinBox*)r->obj; spinbox.stepper.increment = extent; }