From 5427cb58ee8118e7389d27a8ac9bcbd8e3110d60 Mon Sep 17 00:00:00 2001 From: relikd Date: Thu, 11 Dec 2025 15:09:14 +0100 Subject: [PATCH] feat: uint formatter with units --- baRSS/Helper/StrictUIntFormatter.h | 2 ++ baRSS/Helper/StrictUIntFormatter.m | 21 +++++++++++++++++-- baRSS/NSCategories/NSView+Ext.h | 2 +- baRSS/NSCategories/NSView+Ext.m | 6 ++++-- .../Preferences/Feeds Tab/ModalFeedEditView.m | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/baRSS/Helper/StrictUIntFormatter.h b/baRSS/Helper/StrictUIntFormatter.h index 49e1bd6..70c3a9d 100644 --- a/baRSS/Helper/StrictUIntFormatter.h +++ b/baRSS/Helper/StrictUIntFormatter.h @@ -1,4 +1,6 @@ @import Cocoa; @interface StrictUIntFormatter : NSFormatter +/// Note: must contain `%ld` and is used as formatter string. +@property (nullable, copy) NSString *unit; @end diff --git a/baRSS/Helper/StrictUIntFormatter.m b/baRSS/Helper/StrictUIntFormatter.m index 7e81a10..bd86832 100644 --- a/baRSS/Helper/StrictUIntFormatter.m +++ b/baRSS/Helper/StrictUIntFormatter.m @@ -3,11 +3,28 @@ @implementation StrictUIntFormatter /// Display object as integer formatted string. - (NSString *)stringForObjectValue:(id)obj { - return [NSString stringWithFormat:@"%d", [[NSString stringWithFormat:@"%@", obj] intValue]]; + NSString *str = [NSString stringWithFormat:@"%@", obj]; + if (str.length == 0) + return @""; + if (self.unit) + return [NSString stringWithFormat:self.unit, [str integerValue]]; + return [NSString stringWithFormat:@"%ld", [str integerValue]]; } + +- (NSString *)editingStringForObjectValue:(id)obj { + NSString *str = [NSString stringWithFormat:@"%@", obj]; + if (str.length == 0) + return @""; + return [NSString stringWithFormat:@"%ld", [str integerValue]]; +} + /// Parse any pasted input as integer. - (BOOL)getObjectValue:(out id _Nullable __autoreleasing *)obj forString:(NSString *)string errorDescription:(out NSString *__autoreleasing _Nullable *)error { - *obj = [[NSNumber numberWithInt:[string intValue]] stringValue]; + if (string.length == 0) { + *obj = @""; + } else { + *obj = [[NSNumber numberWithInt:[string intValue]] stringValue]; + } return YES; } /// Only digits, no other character allowed diff --git a/baRSS/NSCategories/NSView+Ext.h b/baRSS/NSCategories/NSView+Ext.h index b330268..794e030 100644 --- a/baRSS/NSCategories/NSView+Ext.h +++ b/baRSS/NSCategories/NSView+Ext.h @@ -36,7 +36,7 @@ static inline CGFloat NSMaxWidth(NSView *a, NSView *b) { return Max(NSWidth(a.fr // UI: TextFields + (NSTextField*)label:(NSString*)text; + (NSTextField*)inputField:(NSString*)placeholder width:(CGFloat)w; -+ (NSTextField*)integerField:(NSUInteger)placeholder width:(CGFloat)w; ++ (NSTextField*)integerField:(NSString*)placeholder unit:(nullable NSString*)unit width:(CGFloat)w; + (NSView*)labelColumn:(NSArray*)labels rowHeight:(CGFloat)h padding:(CGFloat)pad; // UI: Buttons + (NSButton*)button:(NSString*)text; diff --git a/baRSS/NSCategories/NSView+Ext.m b/baRSS/NSCategories/NSView+Ext.m index 32a9f09..17ef32e 100644 --- a/baRSS/NSCategories/NSView+Ext.m +++ b/baRSS/NSCategories/NSView+Ext.m @@ -29,9 +29,11 @@ } /// Create input text field which only accepts integer values. (calls `inputField`) `21px` height. -+ (NSTextField*)integerField:(NSUInteger)placeholder width:(CGFloat)w { - NSTextField *input = [self inputField:[NSString stringWithFormat:@"%ld", placeholder] width:w]; +/// `field.formatter` is of type `StrictUIntFormatter`. ++ (NSTextField*)integerField:(NSString*)placeholder unit:(nullable NSString*)unit width:(CGFloat)w { + NSTextField *input = [self inputField:placeholder width:w]; input.formatter = [StrictUIntFormatter new]; + ((StrictUIntFormatter*)input.formatter).unit = unit; return input; } diff --git a/baRSS/Preferences/Feeds Tab/ModalFeedEditView.m b/baRSS/Preferences/Feeds Tab/ModalFeedEditView.m index f9b199d..0412650 100644 --- a/baRSS/Preferences/Feeds Tab/ModalFeedEditView.m +++ b/baRSS/Preferences/Feeds Tab/ModalFeedEditView.m @@ -32,7 +32,7 @@ self.name = [[[NSView inputField:NSLocalizedString(@"Example Title", nil) width:0] placeIn:self x:x yTop:rowHeight] sizeToRight:PAD_S + 18]; self.spinnerName = [[NSView activitySpinner] placeIn:self xRight:1 yTop:rowHeight + 2.5]; // 3. row - self.refreshNum = [[NSView integerField:30 width:85] placeIn:self x:x yTop:2*rowHeight]; + self.refreshNum = [[NSView integerField:@"∞" unit:nil width:85] placeIn:self x:x yTop:2*rowHeight]; self.refreshUnit = [[NSView popupButton:120] placeIn:self x:NSMaxX(self.refreshNum.frame) + PAD_M yTop:2*rowHeight]; self.regexConverterButton = [[[[NSView buttonIcon:RSSImageRegexIcon size:19] action:@selector(openRegexConverter) target:controller]