mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-06 00:45:32 +00:00
400 lines
18 KiB
Objective-C
400 lines
18 KiB
Objective-C
//
|
|
// KMKeyboardMenuView.m
|
|
// KeymanEngine
|
|
//
|
|
// Created by Serkan Kurt on 18/03/2015.
|
|
// Copyright (c) 2017 SIL International. All rights reserved.
|
|
//
|
|
|
|
#import "KMKeyboardMenuView.h"
|
|
#import "KMManager+Internal.h"
|
|
|
|
static CGFloat borderRadius = 5.0; // 4.0;
|
|
static CGFloat strokeWidth = 0.75;
|
|
|
|
@interface KMKeyboardMenuView ()
|
|
@property (assign) CGRect menuFrame;
|
|
@property (assign) CGRect keyFrame;
|
|
@property (assign) CGFloat rowHeight;
|
|
@property (assign) CGFloat fontSize;
|
|
@property (assign) CGFloat xLength;
|
|
@property (assign) CGFloat adjX;
|
|
@property (assign) CGFloat topBarHeight;
|
|
@property (nonatomic, strong) UIColor *borderColor;
|
|
@property (nonatomic, strong) UIColor *bgColor;
|
|
@property (nonatomic, strong) UIColor *bgColor2;
|
|
@property (nonatomic, strong) UITableView *tableView;
|
|
@property (nonatomic, strong) NSMutableArray *tableList;
|
|
@property (nonatomic, strong) NSString *closeButtonTitle;
|
|
@property (nonatomic, weak) KMInputViewController *inputViewController;
|
|
@end
|
|
|
|
@implementation KMKeyboardMenuView
|
|
@synthesize tableView = _tableView;
|
|
@synthesize menuFrame, keyFrame, rowHeight, fontSize, xLength, adjX, topBarHeight;
|
|
@synthesize bgColor, bgColor2, borderColor;
|
|
@synthesize tableList = _tableList;
|
|
|
|
- (id)initWithKeyFrame:(CGRect)frame inputViewController:(KMInputViewController *)inputViewController closeButtonTitle:(NSString *)closeButtonTitle {
|
|
BOOL isSystemKeyboard = [KMManager isKeymanSystemKeyboard];
|
|
BOOL isPortrait = YES;
|
|
if (isSystemKeyboard)
|
|
isPortrait = [KMInputViewController isPortrait];
|
|
else {
|
|
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
|
|
isPortrait = UIInterfaceOrientationIsPortrait(orientation);
|
|
}
|
|
|
|
_inputViewController = inputViewController;
|
|
_closeButtonTitle = closeButtonTitle;
|
|
topBarHeight = [[KMManager sharedInstance] isSystemKeyboardTopBarEnabled]?[KMInputViewController topBarHeight]:0;
|
|
keyFrame = CGRectInset(frame, 0, 0); // CGRectInset(frame, 2, 2);
|
|
rowHeight = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)?30:60;
|
|
fontSize = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)?14:21;
|
|
xLength = keyFrame.size.width*(isPortrait?1.1:0.6);
|
|
|
|
CGFloat screenWidth;
|
|
CGRect screenRect = [[UIScreen mainScreen] bounds];
|
|
int iosVersion = [[[UIDevice currentDevice] systemVersion] intValue];
|
|
if (iosVersion >= 8)
|
|
screenWidth = screenRect.size.width;
|
|
else {
|
|
if (isPortrait)
|
|
screenWidth = screenRect.size.width;
|
|
else
|
|
screenWidth = screenRect.size.height;
|
|
}
|
|
|
|
CGFloat maxWidth = [self getMaxWidth];
|
|
if (maxWidth > screenWidth)
|
|
maxWidth = screenWidth;
|
|
CGFloat baseHeight = keyFrame.size.height;
|
|
CGFloat containerWidth = maxWidth - strokeWidth*2;
|
|
CGFloat containerHeight = self.tableList.count*rowHeight;
|
|
CGFloat vHeight = [KMManager keyboardHeight] + ([[KMManager sharedInstance] isSystemKeyboardTopBarEnabled]?[KMInputViewController topBarHeight]:0);
|
|
CGFloat bY = [KMManager keyboardHeight] - (keyFrame.origin.y + baseHeight);
|
|
|
|
if ((containerHeight + baseHeight ) > (vHeight - bY)) {
|
|
int maxRows = (vHeight - baseHeight - bY)/rowHeight;
|
|
containerHeight = maxRows*rowHeight;
|
|
}
|
|
|
|
CGRect containerFrame = CGRectMake(strokeWidth, strokeWidth, containerWidth, containerHeight);
|
|
|
|
CGFloat viewWidth = maxWidth;
|
|
CGFloat viewHeight = baseHeight + containerHeight + strokeWidth;
|
|
CGFloat viewPosX = keyFrame.origin.x - (viewWidth - keyFrame.size.width)/2.0;
|
|
CGFloat viewPosY = (keyFrame.origin.y + topBarHeight) - (viewHeight - keyFrame.size.height);
|
|
|
|
adjX = 0;
|
|
if (viewPosX < 0) {
|
|
if ((keyFrame.origin.x - borderRadius*1.0 /* 2 */) < 0) {
|
|
adjX = keyFrame.origin.x - viewPosX;
|
|
viewPosX = keyFrame.origin.x;
|
|
}
|
|
else {
|
|
adjX = -viewPosX;
|
|
viewPosX = 0;
|
|
}
|
|
}
|
|
else if ((viewPosX + viewWidth) > screenWidth) {
|
|
if (((keyFrame.origin.x + keyFrame.size.width) + borderRadius*1.0 /* 2 */) > screenWidth) {
|
|
adjX = viewPosX - keyFrame.origin.x;
|
|
viewPosX = keyFrame.origin.x + 2*adjX;
|
|
}
|
|
else {
|
|
adjX = (screenWidth - viewWidth) - viewPosX;
|
|
viewPosX = adjX + viewPosX;
|
|
}
|
|
}
|
|
|
|
CGRect mainFrame = self.inputViewController.view.frame;
|
|
if (CGRectEqualToRect(mainFrame, CGRectZero))
|
|
mainFrame = [KMManager inputView].frame;
|
|
self = [super initWithFrame:mainFrame];
|
|
if (self) {
|
|
super.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.25];
|
|
self.tag = 1;
|
|
self.userInteractionEnabled = YES;
|
|
bgColor = [[UIColor alloc] initWithRed:255.0/255.0
|
|
green:255.0/255.0
|
|
blue:255.0/255.0
|
|
alpha:1.0];
|
|
bgColor2 = [[UIColor alloc] initWithRed:255.0/255.0
|
|
green:255.0/255.0
|
|
blue:255.0/255.0
|
|
alpha:1.0];
|
|
borderColor = [[UIColor alloc] initWithRed:134.0/255.0 green:137.0/255.0 blue:139.0/255.0 alpha:1.0];
|
|
|
|
menuFrame = CGRectMake(viewPosX, viewPosY, viewWidth, viewHeight);
|
|
UIView *menuView = [[UIView alloc] initWithFrame:menuFrame];
|
|
[menuView setTag:2];
|
|
[menuView setBackgroundColor:[UIColor clearColor]];
|
|
|
|
_tableView = [[UITableView alloc] initWithFrame:containerFrame];
|
|
[_tableView setDelegate:self];
|
|
[_tableView setDataSource:self];
|
|
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
|
|
[_tableView setBackgroundColor:[UIColor clearColor]];
|
|
[_tableView.layer setCornerRadius:(borderRadius*1.0 /* 2 */ - strokeWidth)];
|
|
[menuView addSubview:_tableView];
|
|
[self addSubview:menuView];
|
|
|
|
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
|
|
[tapGesture setDelegate:self];
|
|
[tapGesture setNumberOfTapsRequired:1];
|
|
[tapGesture setNumberOfTouchesRequired:1];
|
|
[self addGestureRecognizer:tapGesture];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)drawRect:(CGRect)rect {
|
|
CGFloat keyWidth = keyFrame.size.width;
|
|
CGFloat keyHeight = keyFrame.size.height;
|
|
CGFloat viewWidth = menuFrame.size.width;
|
|
CGFloat viewHeight = menuFrame.size.height;
|
|
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
UIGraphicsPushContext(context);
|
|
CGContextSetLineJoin(context, kCGLineJoinRound);
|
|
CGContextSetLineWidth(context, strokeWidth*2);
|
|
CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
|
|
CGContextSetFillColorWithColor(context, bgColor.CGColor);
|
|
//CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
|
|
CGFloat keyLeft = menuFrame.origin.x + (viewWidth - keyWidth)/2.0 + strokeWidth - adjX;
|
|
CGFloat keyRight = menuFrame.origin.x + (viewWidth - keyWidth)/2.0 + keyWidth - strokeWidth - adjX;
|
|
keyLeft = ceilf(keyLeft*10)/10;
|
|
keyRight = floorf(keyRight*10)/10;
|
|
|
|
CGFloat midY = menuFrame.origin.y + viewHeight - keyHeight;
|
|
CGFloat viewLeft = menuFrame.origin.x + strokeWidth;
|
|
CGFloat viewRight = menuFrame.origin.x + viewWidth - strokeWidth;
|
|
CGFloat viewTop = menuFrame.origin.y + strokeWidth;
|
|
CGFloat viewBottom = menuFrame.origin.y + viewHeight - strokeWidth*1.25;
|
|
CGFloat viewMid = menuFrame.origin.x + viewWidth/2.0;
|
|
CGFloat r = borderRadius - strokeWidth;
|
|
CGFloat r2 = borderRadius*1.0 /* 2 */ - strokeWidth;
|
|
CGFloat r3 = borderRadius*1.0 /* 2 */ - strokeWidth;
|
|
|
|
CGContextBeginPath(context);
|
|
CGContextMoveToPoint(context, viewMid, viewTop);
|
|
CGContextAddArcToPoint(context, viewLeft, viewTop, viewLeft, midY, r2);
|
|
CGContextAddArcToPoint(context, viewLeft, midY, keyLeft, midY, r2);
|
|
CGContextAddArcToPoint(context, keyLeft, midY, keyLeft, viewBottom, r3);
|
|
CGContextAddArcToPoint(context, keyLeft, viewBottom, keyRight, viewBottom, r);
|
|
CGContextAddArcToPoint(context, keyRight, viewBottom, keyRight, midY, r);
|
|
CGContextAddArcToPoint(context, keyRight, midY, viewRight, midY, r3);
|
|
CGContextAddArcToPoint(context, viewRight, midY, viewRight, viewTop, r2);
|
|
CGContextAddArcToPoint(context, viewRight, viewTop, viewMid, viewTop, r2);
|
|
CGContextClosePath(context);
|
|
CGContextDrawPath(context, kCGPathStroke);
|
|
|
|
CGContextBeginPath(context);
|
|
CGContextMoveToPoint(context, viewMid, viewTop);
|
|
CGContextAddArcToPoint(context, viewLeft, viewTop, viewLeft, midY, r2);
|
|
CGContextAddArcToPoint(context, viewLeft, midY, keyLeft, midY, r2);
|
|
CGContextAddArcToPoint(context, keyLeft, midY, keyLeft, viewBottom, r3);
|
|
CGContextAddArcToPoint(context, keyLeft, viewBottom, keyRight, viewBottom, r);
|
|
CGContextAddArcToPoint(context, keyRight, viewBottom, keyRight, midY, r);
|
|
CGContextAddArcToPoint(context, keyRight, midY, viewRight, midY, r3);
|
|
CGContextAddArcToPoint(context, viewRight, midY, viewRight, viewTop, r2);
|
|
CGContextAddArcToPoint(context, viewRight, viewTop, viewMid, viewTop, r2);
|
|
CGContextClosePath(context);
|
|
CGContextClip(context);
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
NSArray *gradientColors = [NSArray arrayWithObjects:(id)bgColor.CGColor, bgColor2.CGColor, nil];
|
|
CGFloat gradientLocations[] = {0, 1};
|
|
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) gradientColors, gradientLocations);
|
|
|
|
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
|
|
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
|
|
|
|
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
|
|
CGGradientRelease(gradient);
|
|
CGColorSpaceRelease(colorSpace);
|
|
UIGraphicsPopContext();
|
|
}
|
|
|
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
|
CGPoint point = [gestureRecognizer locationInView:gestureRecognizer.view];
|
|
UIView *view = [gestureRecognizer.view hitTest:point withEvent:nil];
|
|
if (view.tag > 0)
|
|
return YES;
|
|
|
|
return NO;
|
|
}
|
|
|
|
- (void)tapAction:(UITapGestureRecognizer *)sender {
|
|
[[KMManager sharedInstance] dismissKeyboardMenu];
|
|
}
|
|
|
|
- (NSMutableArray *)tableList {
|
|
if (_tableList == nil) {
|
|
NSUserDefaults *userData = [[KMManager sharedInstance] activeUserDefaults];
|
|
NSMutableArray *keyboardList = [[userData arrayForKey:kKeymanUserKeyboardsListKey] mutableCopy];
|
|
|
|
NSString *titleCloseButton;
|
|
if (self.closeButtonTitle != nil)
|
|
titleCloseButton = self.closeButtonTitle;
|
|
else {
|
|
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
|
titleCloseButton = [NSString stringWithFormat:@"Close %@", appName];
|
|
}
|
|
|
|
if (keyboardList == nil) {
|
|
NSString *kbVersion = [[KMManager sharedInstance] latestKeyboardFileVersionWithID:kKeymanDefaultKeyboardID];
|
|
_tableList = [[NSMutableArray alloc] initWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
kKeymanDefaultKeyboardID, kKeymanKeyboardIdKey,
|
|
kKeymanDefaultLanguageID, kKeymanLanguageIdKey,
|
|
kKeymanDefaultKeyboardName, kKeymanKeyboardNameKey,
|
|
kKeymanDefaultLanguageName, kKeymanLanguageNameKey,
|
|
kbVersion, kKeymanKeyboardVersionKey,
|
|
kKeymanDefaultKeyboardRTL, kKeymanKeyboardRTLKey,
|
|
kKeymanDefaultKeyboardFont, kKeymanFontKey,
|
|
nil], nil];
|
|
[_tableList addObject:titleCloseButton];
|
|
}
|
|
else {
|
|
_tableList = [[NSMutableArray alloc] initWithArray:keyboardList];
|
|
/*
|
|
_tableList = [[NSMutableArray alloc] initWithCapacity:keyboardList.count];
|
|
int startIndex = 0;
|
|
for (int i = 0; i < keyboardList.count; i++) {
|
|
NSString *languageID = [[keyboardList objectAtIndex:i] objectForKey:kKeymanLanguageIdKey];
|
|
NSString *keyboardID = [[keyboardList objectAtIndex:i] objectForKey:kKeymanKeyboardIdKey];
|
|
if ([[KMManager sharedInstance].languageID isEqualToString:languageID] && [[KMManager sharedInstance].keyboardID isEqualToString:keyboardID]) {
|
|
startIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int i = startIndex; i < keyboardList.count; i++) {
|
|
[_tableList addObject:[keyboardList objectAtIndex:i]];
|
|
}
|
|
|
|
for (int i = 0; i < startIndex; i++) {
|
|
[_tableList addObject:[keyboardList objectAtIndex:i]];
|
|
}
|
|
*/
|
|
|
|
[_tableList addObject:titleCloseButton];
|
|
}
|
|
}
|
|
|
|
return _tableList;
|
|
}
|
|
|
|
#pragma mark - Table view data source
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
|
return 1;
|
|
}
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
|
return [self.tableList count];
|
|
}
|
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
static NSString *cellIdentifier = @"Cell";
|
|
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
|
|
if (!cell) {
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
|
|
UIView *selectionColor = [[UIView alloc] init];
|
|
[selectionColor setBackgroundColor:[UIColor colorWithRed:74.0/255.0 green:186.0/255.0 blue:208.0/255.0 alpha:1.0]];
|
|
[cell setSelectedBackgroundView:selectionColor];
|
|
}
|
|
|
|
return cell;
|
|
}
|
|
|
|
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
|
|
//
|
|
}
|
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
return rowHeight;
|
|
}
|
|
|
|
#pragma mark - Table view delegate
|
|
|
|
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
[cell.textLabel setTextColor:[UIColor darkGrayColor]];
|
|
[cell.textLabel setTextAlignment:NSTextAlignmentLeft];
|
|
[cell.textLabel setFont:[UIFont systemFontOfSize:fontSize]];
|
|
[cell setSelectionStyle:UITableViewCellSelectionStyleDefault];
|
|
[cell setBackgroundColor:[UIColor clearColor]];
|
|
if (indexPath.row == (self.tableList.count - 1)) {
|
|
cell.textLabel.text = [self.tableList objectAtIndex:indexPath.row];
|
|
cell.tag = indexPath.row;
|
|
[cell.textLabel setTextColor:[UIColor grayColor]];
|
|
[cell.textLabel setTextAlignment:NSTextAlignmentRight];
|
|
[cell setSelected:NO];
|
|
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
|
|
}
|
|
else {
|
|
NSString *languageID = [[self.tableList objectAtIndex:indexPath.row] objectForKey:kKeymanLanguageIdKey];
|
|
NSString *keyboardID = [[self.tableList objectAtIndex:indexPath.row] objectForKey:kKeymanKeyboardIdKey];
|
|
cell.textLabel.text = [[self.tableList objectAtIndex:indexPath.row] objectForKey:kKeymanKeyboardNameKey];
|
|
cell.tag = indexPath.row;
|
|
if ([[KMManager sharedInstance].languageID isEqualToString:languageID] && [[KMManager sharedInstance].keyboardID isEqualToString:keyboardID]) {
|
|
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
|
|
[cell setSelected:YES];
|
|
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
|
|
}
|
|
else {
|
|
[cell setSelected:NO];
|
|
[cell setAccessoryType:UITableViewCellAccessoryNone];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
[self switchKeyboard:indexPath.row];
|
|
[[KMManager sharedInstance] dismissKeyboardMenu];
|
|
}
|
|
|
|
- (CGFloat)getMaxWidth {
|
|
CGFloat w = 0;
|
|
for (id obj in self.tableList) {
|
|
NSString *text = nil;
|
|
if ([obj isKindOfClass:[NSDictionary class]]) {
|
|
NSDictionary *kb = (NSDictionary *)obj;
|
|
text = [kb objectForKey:kKeymanKeyboardNameKey];
|
|
}
|
|
else {
|
|
text = (NSString *)obj;
|
|
}
|
|
|
|
CGFloat tw = [self getTextWidth:text];
|
|
if (tw > w)
|
|
w = tw;
|
|
}
|
|
|
|
return w + (([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)?75:150);
|
|
}
|
|
|
|
- (CGFloat)getTextWidth:(NSString *)text {
|
|
return [text sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]}].width;
|
|
}
|
|
|
|
- (void)switchKeyboard:(NSInteger)index {
|
|
if (index == (self.tableList.count - 1)) {
|
|
[self.inputViewController advanceToNextInputMode];
|
|
}
|
|
else {
|
|
NSString *langID = [[self.tableList objectAtIndex:index] objectForKey:kKeymanLanguageIdKey];
|
|
NSString *kbID = [[self.tableList objectAtIndex:index] objectForKey:kKeymanKeyboardIdKey];
|
|
NSString *langName = [[self.tableList objectAtIndex:index] objectForKey:kKeymanLanguageNameKey];
|
|
NSString *kbName = [[self.tableList objectAtIndex:index] objectForKey:kKeymanKeyboardNameKey];
|
|
NSString *font = [[self.tableList objectAtIndex:index] objectForKey:kKeymanFontKey];
|
|
NSString *oskFont = [[self.tableList objectAtIndex:index] objectForKey:kKeymanOskFontKey];
|
|
|
|
if ([[KMManager sharedInstance] setKeyboardWithID:kbID languageID:langID keyboardName:kbName languageName:langName font:font oskFont:oskFont])
|
|
[self.tableView reloadData];
|
|
}
|
|
}
|
|
|
|
@end
|