ref: uint-formatter on NSView+Ext
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
544F5A752E30EFC700674F81 /* style.css in Resources */ = {isa = PBXBuildFile; fileRef = 544F5A722E30EFC700674F81 /* style.css */; };
|
544F5A752E30EFC700674F81 /* style.css in Resources */ = {isa = PBXBuildFile; fileRef = 544F5A722E30EFC700674F81 /* style.css */; };
|
||||||
544F5A762E30EFC700674F81 /* opml-lib.m in Sources */ = {isa = PBXBuildFile; fileRef = 544F5A702E30EFC700674F81 /* opml-lib.m */; };
|
544F5A762E30EFC700674F81 /* opml-lib.m in Sources */ = {isa = PBXBuildFile; fileRef = 544F5A702E30EFC700674F81 /* opml-lib.m */; };
|
||||||
54501010230E9C8600F0B165 /* FeedDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 5450100F230E9C8600F0B165 /* FeedDownload.m */; };
|
54501010230E9C8600F0B165 /* FeedDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 5450100F230E9C8600F0B165 /* FeedDownload.m */; };
|
||||||
|
545EB5DA2EE8622200FABBE0 /* StrictUIntFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 545EB5D92EE8622200FABBE0 /* StrictUIntFormatter.m */; };
|
||||||
5469E13C2EA90C6C00D46CE7 /* NotifyEndpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 5469E13B2EA90C6C00D46CE7 /* NotifyEndpoint.m */; };
|
5469E13C2EA90C6C00D46CE7 /* NotifyEndpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 5469E13B2EA90C6C00D46CE7 /* NotifyEndpoint.m */; };
|
||||||
546A6A2922C583390034E806 /* SettingsGeneralView.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D857D122802309001BA1C8 /* SettingsGeneralView.m */; };
|
546A6A2922C583390034E806 /* SettingsGeneralView.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D857D122802309001BA1C8 /* SettingsGeneralView.m */; };
|
||||||
546A6A2C22C584AF0034E806 /* SettingsAppearanceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 546A6A2A22C584AF0034E806 /* SettingsAppearanceView.m */; };
|
546A6A2C22C584AF0034E806 /* SettingsAppearanceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 546A6A2A22C584AF0034E806 /* SettingsAppearanceView.m */; };
|
||||||
@@ -150,6 +151,8 @@
|
|||||||
544F5A722E30EFC700674F81 /* style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = style.css; sourceTree = "<group>"; };
|
544F5A722E30EFC700674F81 /* style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = style.css; sourceTree = "<group>"; };
|
||||||
5450100E230E9C8600F0B165 /* FeedDownload.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FeedDownload.h; sourceTree = "<group>"; };
|
5450100E230E9C8600F0B165 /* FeedDownload.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FeedDownload.h; sourceTree = "<group>"; };
|
||||||
5450100F230E9C8600F0B165 /* FeedDownload.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FeedDownload.m; sourceTree = "<group>"; };
|
5450100F230E9C8600F0B165 /* FeedDownload.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FeedDownload.m; sourceTree = "<group>"; };
|
||||||
|
545EB5D62EE8620300FABBE0 /* StrictUIntFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StrictUIntFormatter.h; sourceTree = "<group>"; };
|
||||||
|
545EB5D92EE8622200FABBE0 /* StrictUIntFormatter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StrictUIntFormatter.m; sourceTree = "<group>"; };
|
||||||
5469E13A2EA90C6C00D46CE7 /* NotifyEndpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotifyEndpoint.h; sourceTree = "<group>"; };
|
5469E13A2EA90C6C00D46CE7 /* NotifyEndpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotifyEndpoint.h; sourceTree = "<group>"; };
|
||||||
5469E13B2EA90C6C00D46CE7 /* NotifyEndpoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotifyEndpoint.m; sourceTree = "<group>"; };
|
5469E13B2EA90C6C00D46CE7 /* NotifyEndpoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotifyEndpoint.m; sourceTree = "<group>"; };
|
||||||
546A6A2A22C584AF0034E806 /* SettingsAppearanceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsAppearanceView.m; sourceTree = "<group>"; };
|
546A6A2A22C584AF0034E806 /* SettingsAppearanceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsAppearanceView.m; sourceTree = "<group>"; };
|
||||||
@@ -515,6 +518,8 @@
|
|||||||
54910066233A4D4000858AE2 /* URLScheme.m */,
|
54910066233A4D4000858AE2 /* URLScheme.m */,
|
||||||
54229F532E02491A0019ACB0 /* TinySVG.h */,
|
54229F532E02491A0019ACB0 /* TinySVG.h */,
|
||||||
54229F542E02491A0019ACB0 /* TinySVG.m */,
|
54229F542E02491A0019ACB0 /* TinySVG.m */,
|
||||||
|
545EB5D62EE8620300FABBE0 /* StrictUIntFormatter.h */,
|
||||||
|
545EB5D92EE8622200FABBE0 /* StrictUIntFormatter.m */,
|
||||||
);
|
);
|
||||||
path = Helper;
|
path = Helper;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -732,6 +737,7 @@
|
|||||||
546FC43D21188AD5007CC3A3 /* SettingsFeeds.m in Sources */,
|
546FC43D21188AD5007CC3A3 /* SettingsFeeds.m in Sources */,
|
||||||
54253C952C49BFE400742695 /* RegexConverterView.m in Sources */,
|
54253C952C49BFE400742695 /* RegexConverterView.m in Sources */,
|
||||||
548C6D0A230C33DE003A1AAF /* NSURL+Ext.m in Sources */,
|
548C6D0A230C33DE003A1AAF /* NSURL+Ext.m in Sources */,
|
||||||
|
545EB5DA2EE8622200FABBE0 /* StrictUIntFormatter.m in Sources */,
|
||||||
54E88320211B509D00064188 /* ModalFeedEdit.m in Sources */,
|
54E88320211B509D00064188 /* ModalFeedEdit.m in Sources */,
|
||||||
54195883218A061100581B79 /* Feed+Ext.m in Sources */,
|
54195883218A061100581B79 /* Feed+Ext.m in Sources */,
|
||||||
5469E13C2EA90C6C00D46CE7 /* NotifyEndpoint.m in Sources */,
|
5469E13C2EA90C6C00D46CE7 /* NotifyEndpoint.m in Sources */,
|
||||||
|
|||||||
4
baRSS/Helper/StrictUIntFormatter.h
Normal file
4
baRSS/Helper/StrictUIntFormatter.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
@import Cocoa;
|
||||||
|
|
||||||
|
@interface StrictUIntFormatter : NSFormatter
|
||||||
|
@end
|
||||||
23
baRSS/Helper/StrictUIntFormatter.m
Normal file
23
baRSS/Helper/StrictUIntFormatter.m
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#import "StrictUIntFormatter.h"
|
||||||
|
|
||||||
|
@implementation StrictUIntFormatter
|
||||||
|
/// Display object as integer formatted string.
|
||||||
|
- (NSString *)stringForObjectValue:(id)obj {
|
||||||
|
return [NSString stringWithFormat:@"%d", [[NSString stringWithFormat:@"%@", obj] intValue]];
|
||||||
|
}
|
||||||
|
/// 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];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
/// Only digits, no other character allowed
|
||||||
|
- (BOOL)isPartialStringValid:(NSString *__autoreleasing _Nonnull *)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString *__autoreleasing _Nullable *)error {
|
||||||
|
for (NSUInteger i = 0; i < [*partialStringPtr length]; i++) {
|
||||||
|
unichar c = [*partialStringPtr characterAtIndex:i];
|
||||||
|
if (c < '0' || c > '9')
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
@@ -36,6 +36,7 @@ static inline CGFloat NSMaxWidth(NSView *a, NSView *b) { return Max(NSWidth(a.fr
|
|||||||
// UI: TextFields
|
// UI: TextFields
|
||||||
+ (NSTextField*)label:(NSString*)text;
|
+ (NSTextField*)label:(NSString*)text;
|
||||||
+ (NSTextField*)inputField:(NSString*)placeholder width:(CGFloat)w;
|
+ (NSTextField*)inputField:(NSString*)placeholder width:(CGFloat)w;
|
||||||
|
+ (NSTextField*)integerField:(NSUInteger)placeholder width:(CGFloat)w;
|
||||||
+ (NSView*)labelColumn:(NSArray<NSString*>*)labels rowHeight:(CGFloat)h padding:(CGFloat)pad;
|
+ (NSView*)labelColumn:(NSArray<NSString*>*)labels rowHeight:(CGFloat)h padding:(CGFloat)pad;
|
||||||
// UI: Buttons
|
// UI: Buttons
|
||||||
+ (NSButton*)button:(NSString*)text;
|
+ (NSButton*)button:(NSString*)text;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#import "NSView+Ext.h"
|
#import "NSView+Ext.h"
|
||||||
|
#import "StrictUIntFormatter.h"
|
||||||
|
|
||||||
@implementation NSView (Ext)
|
@implementation NSView (Ext)
|
||||||
|
|
||||||
@@ -27,6 +28,13 @@
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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];
|
||||||
|
input.formatter = [StrictUIntFormatter new];
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create view with @c NSTextField subviews with right-aligned and row-centered text from @c labels.
|
/// Create view with @c NSTextField subviews with right-aligned and row-centered text from @c labels.
|
||||||
+ (NSView*)labelColumn:(NSArray<NSString*>*)labels rowHeight:(CGFloat)h padding:(CGFloat)pad {
|
+ (NSView*)labelColumn:(NSArray<NSString*>*)labels rowHeight:(CGFloat)h padding:(CGFloat)pad {
|
||||||
CGFloat w = 0, y = 0;
|
CGFloat w = 0, y = 0;
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
#import "NSView+Ext.h"
|
#import "NSView+Ext.h"
|
||||||
#import "Constants.h"
|
#import "Constants.h"
|
||||||
|
|
||||||
@interface StrictUIntFormatter : NSFormatter
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ModalFeedEditView
|
@implementation ModalFeedEditView
|
||||||
|
|
||||||
@@ -34,7 +32,7 @@
|
|||||||
self.name = [[[NSView inputField:NSLocalizedString(@"Example Title", nil) width:0] placeIn:self x:x yTop:rowHeight] sizeToRight:PAD_S + 18];
|
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];
|
self.spinnerName = [[NSView activitySpinner] placeIn:self xRight:1 yTop:rowHeight + 2.5];
|
||||||
// 3. row
|
// 3. row
|
||||||
self.refreshNum = [[NSView inputField:@"30" width:85] placeIn:self x:x yTop:2*rowHeight];
|
self.refreshNum = [[NSView integerField:30 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.refreshUnit = [[NSView popupButton:120] placeIn:self x:NSMaxX(self.refreshNum.frame) + PAD_M yTop:2*rowHeight];
|
||||||
self.regexConverterButton = [[[[NSView buttonIcon:RSSImageRegexIcon size:19]
|
self.regexConverterButton = [[[[NSView buttonIcon:RSSImageRegexIcon size:19]
|
||||||
action:@selector(openRegexConverter) target:controller]
|
action:@selector(openRegexConverter) target:controller]
|
||||||
@@ -48,7 +46,6 @@
|
|||||||
self.url.delegate = controller;
|
self.url.delegate = controller;
|
||||||
self.warningButton.hidden = YES;
|
self.warningButton.hidden = YES;
|
||||||
self.regexConverterButton.hidden = YES;
|
self.regexConverterButton.hidden = YES;
|
||||||
self.refreshNum.formatter = [StrictUIntFormatter new]; // see below ...
|
|
||||||
[self prepareWarningPopover];
|
[self prepareWarningPopover];
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -67,29 +64,3 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - StrictUIntFormatter -
|
|
||||||
|
|
||||||
|
|
||||||
@implementation StrictUIntFormatter
|
|
||||||
/// Display object as integer formatted string.
|
|
||||||
- (NSString *)stringForObjectValue:(id)obj {
|
|
||||||
return [NSString stringWithFormat:@"%d", [[NSString stringWithFormat:@"%@", obj] intValue]];
|
|
||||||
}
|
|
||||||
/// 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];
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
/// Only digits, no other character allowed
|
|
||||||
- (BOOL)isPartialStringValid:(NSString *__autoreleasing _Nonnull *)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString *__autoreleasing _Nullable *)error {
|
|
||||||
for (NSUInteger i = 0; i < [*partialStringPtr length]; i++) {
|
|
||||||
unichar c = [*partialStringPtr characterAtIndex:i];
|
|
||||||
if (c < '0' || c > '9')
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user