Refactoring refresh interval handling
This commit is contained in:
24
baRSS/Helper/NSDate+Ext.h
Normal file
24
baRSS/Helper/NSDate+Ext.h
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
typedef int32_t Interval;
|
||||
typedef NS_ENUM(int32_t, TimeUnitType) {
|
||||
TimeUnitSeconds = 1,
|
||||
TimeUnitMinutes = 60,
|
||||
TimeUnitHours = 60 * 60,
|
||||
TimeUnitDays = 24 * 60 * 60,
|
||||
TimeUnitWeeks = 7 * 24 * 60 * 60,
|
||||
TimeUnitYears = 365 * 24 * 60 * 60
|
||||
};
|
||||
|
||||
@interface NSDate (Ext)
|
||||
+ (nonnull NSString*)stringForInterval:(Interval)intv rounded:(BOOL)flag;
|
||||
@end
|
||||
|
||||
|
||||
@interface NSDate (RefreshControlsUI)
|
||||
+ (Interval)intervalForPopup:(NSPopUpButton*)unit andField:(NSTextField*)value;
|
||||
+ (void)setInterval:(Interval)intv forPopup:(NSPopUpButton*)popup andField:(NSTextField*)field;
|
||||
+ (void)populateUnitsMenu:(NSPopUpButton*)popup selected:(TimeUnitType)unit;
|
||||
@end
|
||||
101
baRSS/Helper/NSDate+Ext.m
Normal file
101
baRSS/Helper/NSDate+Ext.m
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
#import "NSDate+Ext.h"
|
||||
|
||||
static const char _shortnames[] = {'y','w','d','h','m','s'};
|
||||
static const char *_names[] = {"Years", "Weeks", "Days", "Hours", "Minutes", "Seconds"};
|
||||
static const TimeUnitType _values[] = {
|
||||
TimeUnitYears,
|
||||
TimeUnitWeeks,
|
||||
TimeUnitDays,
|
||||
TimeUnitHours,
|
||||
TimeUnitMinutes,
|
||||
TimeUnitSeconds,
|
||||
};
|
||||
|
||||
|
||||
@implementation NSDate (Ext)
|
||||
|
||||
+ (nonnull NSString*)stringForInterval:(Interval)intv rounded:(BOOL)flag {
|
||||
if (flag) {
|
||||
unsigned short i = [self floatUnitIndexForInterval:abs(intv)];
|
||||
return [NSString stringWithFormat:@"%1.1f%c", intv / (float)_values[i], _shortnames[i]];
|
||||
}
|
||||
unsigned short i = [self exactUnitIndexForInterval:abs(intv)];
|
||||
return [NSString stringWithFormat:@"%d%c", intv / _values[i], _shortnames[i]];
|
||||
}
|
||||
|
||||
/// @return Highest non-zero unit ( @c flag=YES ). Or highest integer-dividable unit ( @c flag=NO ).
|
||||
+ (TimeUnitType)unitForInterval:(Interval)intv rounded:(BOOL)flag {
|
||||
if (flag) {
|
||||
return _values[[self floatUnitIndexForInterval:abs(intv)]];
|
||||
}
|
||||
return _values[[self exactUnitIndexForInterval:abs(intv)]];
|
||||
}
|
||||
|
||||
/// @return Highest unit type that allows integer division. E.g., '61 minutes'.
|
||||
+ (unsigned short)exactUnitIndexForInterval:(Interval)intv {
|
||||
for (unsigned short i = 0; i < 5; i++)
|
||||
if (intv % _values[i] == 0) return i;
|
||||
return 5; // seconds
|
||||
}
|
||||
|
||||
/// @return Highest non-zero unit type. Can be used with fractions e.g., '1.1 hours'.
|
||||
+ (unsigned short)floatUnitIndexForInterval:(Interval)intv {
|
||||
for (unsigned short i = 0; i < 5; i++)
|
||||
if (intv > _values[i]) return i;
|
||||
return 5; // seconds
|
||||
}
|
||||
/* NOT USED
|
||||
/// Convert any unit to the next smaller one. Unit does not have to be exact.
|
||||
+ (TimeUnitType)smallerUnit:(TimeUnitType)unit {
|
||||
if (unit <= TimeUnitHours) return TimeUnitSeconds;
|
||||
if (unit <= TimeUnitDays) return TimeUnitMinutes; // > hours
|
||||
if (unit <= TimeUnitWeeks) return TimeUnitHours; // > days
|
||||
if (unit <= TimeUnitYears) return TimeUnitDays; // > weeks
|
||||
return TimeUnitWeeks; // > years
|
||||
}
|
||||
|
||||
/// @return Formatted string from @c timeIntervalSinceNow.
|
||||
- (nonnull NSString*)intervalStringWithDecimal:(BOOL)flag {
|
||||
return [NSDate stringForInterval:(Interval)[self timeIntervalSinceNow] rounded:flag];
|
||||
}
|
||||
|
||||
/// @return Highest non-zero unit ( @c flag=YES ). Or highest integer-dividable unit ( @c flag=NO ).
|
||||
- (TimeUnitType)unitWithDecimal:(BOOL)flag {
|
||||
Interval absIntv = abs((Interval)[self timeIntervalSinceNow]);
|
||||
if (flag) {
|
||||
return _values[ [NSDate floatUnitIndexForInterval:absIntv] ];
|
||||
}
|
||||
return _values[ [NSDate exactUnitIndexForInterval:absIntv] ];
|
||||
}
|
||||
*/
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSDate (RefreshControlsUI)
|
||||
|
||||
/// @return Interval by multiplying the text field value with the currently selected popup unit.
|
||||
+ (Interval)intervalForPopup:(NSPopUpButton*)unit andField:(NSTextField*)value {
|
||||
return value.intValue * (Interval)unit.selectedTag;
|
||||
}
|
||||
|
||||
/// Configure both @c NSControl elements based on the provided interval @c intv.
|
||||
+ (void)setInterval:(Interval)intv forPopup:(NSPopUpButton*)popup andField:(NSTextField*)field {
|
||||
TimeUnitType unit = [self unitForInterval:intv rounded:NO];
|
||||
[popup selectItemWithTag:unit];
|
||||
field.intValue = (int)(intv / unit);
|
||||
}
|
||||
|
||||
/// Insert all @c TimeUnitType items into popup button. Save unit value into @c tag attribute.
|
||||
+ (void)populateUnitsMenu:(NSPopUpButton*)popup selected:(TimeUnitType)unit {
|
||||
[popup removeAllItems];
|
||||
for (NSUInteger i = 0; i < 6; i++) {
|
||||
[popup addItemWithTitle:[NSString stringWithUTF8String:_names[i]]];
|
||||
NSMenuItem *item = popup.lastItem;
|
||||
[item setKeyEquivalent:[[NSString stringWithFormat:@"%c", _shortnames[i]] uppercaseString]];
|
||||
item.tag = _values[i];
|
||||
}
|
||||
[popup selectItemWithTag:unit];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user