Refactoring refresh interval handling

This commit is contained in:
relikd
2019-01-27 04:01:07 +01:00
parent f0258fb246
commit cd0a1a3fd7
15 changed files with 190 additions and 103 deletions

24
baRSS/Helper/NSDate+Ext.h Normal file
View 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
View 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