188 lines
5.9 KiB
Objective-C
188 lines
5.9 KiB
Objective-C
//
|
|
// KBKeyboardLayoutConfig.m
|
|
// CustomKeyboard
|
|
//
|
|
|
|
#import "KBKeyboardLayoutConfig.h"
|
|
#import <MJExtension/MJExtension.h>
|
|
#import "KBConfig.h"
|
|
|
|
static NSString * const kKBKeyboardLayoutConfigFileName = @"kb_keyboard_layout_config";
|
|
|
|
@implementation KBKeyboardLayoutMetrics
|
|
@end
|
|
|
|
@implementation KBKeyboardLayoutFonts
|
|
@end
|
|
|
|
@implementation KBKeyboardKeyDef
|
|
@end
|
|
|
|
@implementation KBKeyboardRowItem
|
|
|
|
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
|
|
return @{ @"itemId": @"id" };
|
|
}
|
|
|
|
+ (NSArray<KBKeyboardRowItem *> *)itemsFromRawArray:(NSArray *)raw {
|
|
if (![raw isKindOfClass:[NSArray class]] || raw.count == 0) {
|
|
return @[];
|
|
}
|
|
NSMutableArray<KBKeyboardRowItem *> *items = [NSMutableArray arrayWithCapacity:raw.count];
|
|
for (id obj in raw) {
|
|
if ([obj isKindOfClass:[NSString class]]) {
|
|
KBKeyboardRowItem *item = [KBKeyboardRowItem new];
|
|
item.itemId = (NSString *)obj;
|
|
[items addObject:item];
|
|
continue;
|
|
}
|
|
if ([obj isKindOfClass:[NSDictionary class]]) {
|
|
KBKeyboardRowItem *item = [KBKeyboardRowItem mj_objectWithKeyValues:obj];
|
|
if (item.itemId.length == 0) {
|
|
NSString *fallback = ((NSDictionary *)obj)[@"id"];
|
|
if ([fallback isKindOfClass:[NSString class]]) {
|
|
item.itemId = fallback;
|
|
}
|
|
}
|
|
if (item.itemId.length > 0) {
|
|
[items addObject:item];
|
|
}
|
|
}
|
|
}
|
|
return items.copy;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation KBKeyboardRowSegments
|
|
|
|
- (NSArray<KBKeyboardRowItem *> *)leftItems {
|
|
return [KBKeyboardRowItem itemsFromRawArray:self.left ?: @[]];
|
|
}
|
|
|
|
- (NSArray<KBKeyboardRowItem *> *)centerItems {
|
|
return [KBKeyboardRowItem itemsFromRawArray:self.center ?: @[]];
|
|
}
|
|
|
|
- (NSArray<KBKeyboardRowItem *> *)rightItems {
|
|
return [KBKeyboardRowItem itemsFromRawArray:self.right ?: @[]];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation KBKeyboardRowConfig
|
|
|
|
- (NSArray<KBKeyboardRowItem *> *)resolvedItems {
|
|
return [KBKeyboardRowItem itemsFromRawArray:self.items ?: @[]];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation KBKeyboardLayout
|
|
|
|
+ (NSDictionary *)mj_objectClassInArray {
|
|
return @{ @"rows": [KBKeyboardRowConfig class] };
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation KBKeyboardLayoutConfig
|
|
|
|
+ (instancetype)sharedConfig {
|
|
static KBKeyboardLayoutConfig *config = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
NSString *path = [[NSBundle mainBundle] pathForResource:kKBKeyboardLayoutConfigFileName ofType:@"json"];
|
|
NSData *data = path.length ? [NSData dataWithContentsOfFile:path] : nil;
|
|
config = data ? [KBKeyboardLayoutConfig configFromJSONData:data] : nil;
|
|
});
|
|
return config;
|
|
}
|
|
|
|
+ (instancetype)configFromJSONData:(NSData *)data {
|
|
if (data.length == 0) { return nil; }
|
|
NSError *error = nil;
|
|
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
|
|
if (error || ![json isKindOfClass:[NSDictionary class]]) {
|
|
return nil;
|
|
}
|
|
NSDictionary *dict = (NSDictionary *)json;
|
|
KBKeyboardLayoutConfig *config = [KBKeyboardLayoutConfig mj_objectWithKeyValues:dict];
|
|
|
|
NSDictionary *keyDefsRaw = dict[@"keyDefs"];
|
|
if ([keyDefsRaw isKindOfClass:[NSDictionary class]]) {
|
|
NSMutableDictionary<NSString *, KBKeyboardKeyDef *> *defs = [NSMutableDictionary dictionaryWithCapacity:keyDefsRaw.count];
|
|
[keyDefsRaw enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
|
if (![key isKindOfClass:[NSString class]] || ![obj isKindOfClass:[NSDictionary class]]) {
|
|
return;
|
|
}
|
|
KBKeyboardKeyDef *def = [KBKeyboardKeyDef mj_objectWithKeyValues:obj];
|
|
if (def) {
|
|
defs[key] = def;
|
|
}
|
|
}];
|
|
config.keyDefs = defs.copy;
|
|
}
|
|
|
|
NSDictionary *layoutsRaw = dict[@"layouts"];
|
|
if ([layoutsRaw isKindOfClass:[NSDictionary class]]) {
|
|
NSMutableDictionary<NSString *, KBKeyboardLayout *> *layouts = [NSMutableDictionary dictionaryWithCapacity:layoutsRaw.count];
|
|
[layoutsRaw enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
|
if (![key isKindOfClass:[NSString class]] || ![obj isKindOfClass:[NSDictionary class]]) {
|
|
return;
|
|
}
|
|
KBKeyboardLayout *layout = [KBKeyboardLayout mj_objectWithKeyValues:obj];
|
|
if (layout) {
|
|
layouts[key] = layout;
|
|
}
|
|
}];
|
|
config.layouts = layouts.copy;
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
- (CGFloat)scaledValue:(CGFloat)designValue {
|
|
CGFloat baseWidth = (self.designWidth > 0.0) ? self.designWidth : KB_DESIGN_WIDTH;
|
|
CGFloat scale = KBScreenWidth() / baseWidth;
|
|
return designValue * scale;
|
|
}
|
|
|
|
- (CGFloat)keyboardAreaDesignHeight {
|
|
KBKeyboardLayout *layout = [self layoutForName:@"letters"] ?: self.layouts.allValues.firstObject;
|
|
NSUInteger rowCount = layout.rows.count;
|
|
if (rowCount == 0) { return 0.0; }
|
|
|
|
CGFloat rowSpacing = self.metrics.rowSpacing.doubleValue;
|
|
CGFloat topInset = self.metrics.topInset.doubleValue;
|
|
CGFloat bottomInset = self.metrics.bottomInset.doubleValue;
|
|
|
|
CGFloat total = topInset + bottomInset + rowSpacing * (rowCount - 1);
|
|
for (KBKeyboardRowConfig *row in layout.rows) {
|
|
CGFloat height = row.height.doubleValue;
|
|
if (height <= 0.0) {
|
|
height = self.metrics.keyHeight.doubleValue;
|
|
}
|
|
if (height <= 0.0) { height = 40.0; }
|
|
total += height;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
- (CGFloat)keyboardAreaScaledHeight {
|
|
CGFloat designHeight = [self keyboardAreaDesignHeight];
|
|
return designHeight > 0.0 ? [self scaledValue:designHeight] : 0.0;
|
|
}
|
|
|
|
- (KBKeyboardLayout *)layoutForName:(NSString *)name {
|
|
if (name.length == 0) { return nil; }
|
|
return self.layouts[name];
|
|
}
|
|
|
|
- (KBKeyboardKeyDef *)keyDefForIdentifier:(NSString *)identifier {
|
|
if (identifier.length == 0) { return nil; }
|
|
return self.keyDefs[identifier];
|
|
}
|
|
|
|
@end
|