Blame client/iOS/Views/AdvancedKeyboardView.m

Packit 1fb8d4
/*
Packit 1fb8d4
 Advanced keyboard view interface
Packit 1fb8d4
 
Packit 1fb8d4
 Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
Packit 1fb8d4
 
Packit 1fb8d4
 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 
Packit 1fb8d4
 If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
#import "AdvancedKeyboardView.h"
Packit 1fb8d4
#include <freerdp/locale/keyboard.h>
Packit 1fb8d4
Packit 1fb8d4
// helper struct to define button layouts/settings
Packit 1fb8d4
struct ButtonItem
Packit 1fb8d4
{
Packit 1fb8d4
    NSString* title;
Packit 1fb8d4
    int tag;
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
@interface AdvancedKeyboardView (Private)
Packit 1fb8d4
- (UIView*)keyboardViewForItems:(struct ButtonItem*)items columns:(int)columns rows:(int)rows;
Packit 1fb8d4
@end
Packit 1fb8d4
Packit 1fb8d4
@implementation AdvancedKeyboardView
Packit 1fb8d4
Packit 1fb8d4
@synthesize delegate = _delegate;
Packit 1fb8d4
Packit 1fb8d4
// defines for the different views
Packit 1fb8d4
#define KEY_SHOW_FUNCVIEW    0x1000
Packit 1fb8d4
#define KEY_SHOW_CURSORVIEW  0x1001
Packit 1fb8d4
#define KEY_SHOW_NUMPADVIEW  0x1002
Packit 1fb8d4
#define KEY_SKIP             0x8000
Packit 1fb8d4
#define KEY_MERGE_COLUMN     0x8001
Packit 1fb8d4
Packit 1fb8d4
#define KEYCODE_UNICODE      0x80000000
Packit 1fb8d4
Packit 1fb8d4
struct ButtonItem functionKeysItems[24] = 
Packit 1fb8d4
{
Packit 1fb8d4
    { @"F1", VK_F1 },
Packit 1fb8d4
    { @"F2", VK_F2 },
Packit 1fb8d4
    { @"F3", VK_F3 },
Packit 1fb8d4
    { @"F4", VK_F4 },
Packit 1fb8d4
    { @"F5", VK_F5 },
Packit 1fb8d4
    { @"F6", VK_F6 },
Packit 1fb8d4
    { @"F7", VK_F7 },
Packit 1fb8d4
    { @"F8", VK_F8 },
Packit 1fb8d4
    { @"F9", VK_F9 },
Packit 1fb8d4
    { @"F10", VK_F10 },
Packit 1fb8d4
    { @"F11", VK_F11 },
Packit 1fb8d4
    { @"F12", VK_F12 },
Packit 1fb8d4
    
Packit 1fb8d4
    { @"img:icon_key_arrows", KEY_SHOW_CURSORVIEW },
Packit 1fb8d4
    { @"Tab", VK_TAB },
Packit 1fb8d4
    { @"Ins", VK_INSERT | KBDEXT },
Packit 1fb8d4
    { @"Home", VK_HOME | KBDEXT },
Packit 1fb8d4
    { @"PgUp", VK_PRIOR | KBDEXT },
Packit 1fb8d4
    { @"img:icon_key_win", VK_LWIN | KBDEXT },
Packit 1fb8d4
Packit 1fb8d4
    { @"123", KEY_SHOW_NUMPADVIEW },
Packit 1fb8d4
    { @"Print", VK_PRINT },
Packit 1fb8d4
    { @"Del", VK_DELETE | KBDEXT },
Packit 1fb8d4
    { @"End", VK_END | KBDEXT },
Packit 1fb8d4
    { @"PgDn", VK_NEXT | KBDEXT },
Packit 1fb8d4
    { @"img:icon_key_menu", VK_APPS | KBDEXT }
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
struct ButtonItem numPadKeysItems[24] = 
Packit 1fb8d4
{
Packit 1fb8d4
    { @"(", KEYCODE_UNICODE | 40 },
Packit 1fb8d4
    { @")", KEYCODE_UNICODE | 41 },
Packit 1fb8d4
    { @"7", VK_NUMPAD7 },
Packit 1fb8d4
    { @"8", VK_NUMPAD8 },
Packit 1fb8d4
    { @"9", VK_NUMPAD9 },
Packit 1fb8d4
    { @"-", VK_SUBTRACT },
Packit 1fb8d4
Packit 1fb8d4
    { @"/", VK_DIVIDE | KBDEXT },
Packit 1fb8d4
    { @"*", VK_MULTIPLY },
Packit 1fb8d4
    { @"4", VK_NUMPAD4 },
Packit 1fb8d4
    { @"5", VK_NUMPAD5 },
Packit 1fb8d4
    { @"6", VK_NUMPAD6 },
Packit 1fb8d4
    { @"+", VK_ADD },
Packit 1fb8d4
Packit 1fb8d4
    { @"Fn", KEY_SHOW_FUNCVIEW },
Packit 1fb8d4
    { @"Num", VK_NUMLOCK },
Packit 1fb8d4
    { @"1", VK_NUMPAD1 },
Packit 1fb8d4
    { @"2", VK_NUMPAD2 },
Packit 1fb8d4
    { @"3", VK_NUMPAD3 },
Packit 1fb8d4
    { @"img:icon_key_backspace", VK_BACK },
Packit 1fb8d4
Packit 1fb8d4
    { @"img:icon_key_arrows", KEY_SHOW_CURSORVIEW },
Packit 1fb8d4
    { @"=", KEYCODE_UNICODE | 61 },
Packit 1fb8d4
    { @"", KEY_MERGE_COLUMN },
Packit 1fb8d4
    { @"0", VK_NUMPAD0 },
Packit 1fb8d4
    { @".", VK_DECIMAL },
Packit 1fb8d4
    { @"img:icon_key_return", VK_RETURN | KBDEXT }
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
struct ButtonItem cursorKeysItems[24] = 
Packit 1fb8d4
{
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"img:icon_key_arrow_up", VK_UP | KBDEXT },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    
Packit 1fb8d4
    { @"Fn", KEY_SHOW_FUNCVIEW },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"img:icon_key_arrow_left", VK_LEFT | KBDEXT },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"img:icon_key_arrow_right", VK_RIGHT | KBDEXT },
Packit 1fb8d4
    { @"img:icon_key_backspace", VK_BACK },
Packit 1fb8d4
    
Packit 1fb8d4
    { @"123", KEY_SHOW_NUMPADVIEW },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"img:icon_key_arrow_down", VK_DOWN | KBDEXT },
Packit 1fb8d4
    { @"", KEY_SKIP },
Packit 1fb8d4
    { @"img:icon_key_return", VK_RETURN | KBDEXT }
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
- (void)initFunctionKeysView
Packit 1fb8d4
{
Packit 1fb8d4
    _function_keys_view = [[self keyboardViewForItems:functionKeysItems columns:6 rows:4] retain];
Packit 1fb8d4
    [self addSubview:_function_keys_view];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)initNumPadKeysView
Packit 1fb8d4
{
Packit 1fb8d4
    _numpad_keys_view = [[self keyboardViewForItems:numPadKeysItems columns:6 rows:4] retain];
Packit 1fb8d4
    [self addSubview:_numpad_keys_view];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)initCursorKeysView
Packit 1fb8d4
{
Packit 1fb8d4
    _cursor_keys_view = [[self keyboardViewForItems:cursorKeysItems columns:6 rows:4] retain];
Packit 1fb8d4
    [self addSubview:_cursor_keys_view];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
- (id)initWithFrame:(CGRect)frame delegate:(NSObject<AdvancedKeyboardDelegate>*)delegate
Packit 1fb8d4
{
Packit 1fb8d4
    self = [super initWithFrame:frame];
Packit 1fb8d4
    if (self) 
Packit 1fb8d4
    {
Packit 1fb8d4
        _delegate = delegate;
Packit 1fb8d4
        
Packit 1fb8d4
        self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
Packit 1fb8d4
        self.backgroundColor = [UIColor blackColor];
Packit 1fb8d4
        // Initialization code
Packit 1fb8d4
        
Packit 1fb8d4
        [self initCursorKeysView];
Packit 1fb8d4
        [self initNumPadKeysView];
Packit 1fb8d4
        [self initFunctionKeysView];
Packit 1fb8d4
        
Packit 1fb8d4
        // set function keys view to the initial view and hide others
Packit 1fb8d4
        _cur_view = _function_keys_view;
Packit 1fb8d4
        [_numpad_keys_view setHidden:YES];
Packit 1fb8d4
        [_cursor_keys_view setHidden:YES];
Packit 1fb8d4
    }
Packit 1fb8d4
    return self;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
/*
Packit 1fb8d4
// Only override drawRect: if you perform custom drawing.
Packit 1fb8d4
// An empty implementation adversely affects performance during animation.
Packit 1fb8d4
- (void)drawRect:(CGRect)rect
Packit 1fb8d4
{
Packit 1fb8d4
    // Drawing code
Packit 1fb8d4
}
Packit 1fb8d4
*/
Packit 1fb8d4
Packit 1fb8d4
- (void)drawRect:(CGRect)rect 
Packit 1fb8d4
{
Packit 1fb8d4
    // draw a nice background gradient
Packit 1fb8d4
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
Packit 1fb8d4
    
Packit 1fb8d4
    CGGradientRef glossGradient;
Packit 1fb8d4
    CGColorSpaceRef rgbColorspace;
Packit 1fb8d4
    size_t num_locations = 2;
Packit 1fb8d4
    CGFloat locations[2] = { 0.0, 1.0 };
Packit 1fb8d4
    CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35,  // Start color
Packit 1fb8d4
                              1.0, 1.0, 1.0, 0.06 }; // End color
Packit 1fb8d4
    
Packit 1fb8d4
    rgbColorspace = CGColorSpaceCreateDeviceRGB();
Packit 1fb8d4
    glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
Packit 1fb8d4
    
Packit 1fb8d4
    CGRect currentBounds = self.bounds;
Packit 1fb8d4
    CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
Packit 1fb8d4
    CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), currentBounds.size.height);
Packit 1fb8d4
    CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);
Packit 1fb8d4
    
Packit 1fb8d4
    CGGradientRelease(glossGradient);
Packit 1fb8d4
    CGColorSpaceRelease(rgbColorspace); 
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
- (void)dealloc
Packit 1fb8d4
{
Packit 1fb8d4
    [_function_keys_view autorelease];
Packit 1fb8d4
    [_numpad_keys_view autorelease];
Packit 1fb8d4
    [_cursor_keys_view autorelease];
Packit 1fb8d4
    [super dealloc];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark button events
Packit 1fb8d4
Packit 1fb8d4
-(IBAction)keyPressed:(id)sender
Packit 1fb8d4
{
Packit 1fb8d4
    UIButton* btn = (UIButton*)sender;
Packit 1fb8d4
    switch([btn tag])
Packit 1fb8d4
    {
Packit 1fb8d4
        case KEY_SHOW_CURSORVIEW:
Packit 1fb8d4
            // switch to cursor view
Packit 1fb8d4
            [_cur_view setHidden:YES];
Packit 1fb8d4
            [_cursor_keys_view setHidden:NO];
Packit 1fb8d4
            _cur_view = _cursor_keys_view;
Packit 1fb8d4
            break;
Packit 1fb8d4
            
Packit 1fb8d4
        case KEY_SHOW_NUMPADVIEW:
Packit 1fb8d4
            // switch to numpad view
Packit 1fb8d4
            [_cur_view setHidden:YES];
Packit 1fb8d4
            [_numpad_keys_view setHidden:NO];
Packit 1fb8d4
            _cur_view = _numpad_keys_view;
Packit 1fb8d4
            break;
Packit 1fb8d4
            
Packit 1fb8d4
        case KEY_SHOW_FUNCVIEW:
Packit 1fb8d4
            // switch to function keys view
Packit 1fb8d4
            [_cur_view setHidden:YES];
Packit 1fb8d4
            [_function_keys_view setHidden:NO];
Packit 1fb8d4
            _cur_view = _function_keys_view;
Packit 1fb8d4
            break;
Packit 1fb8d4
            
Packit 1fb8d4
        default:
Packit 1fb8d4
            if([btn tag] & KEYCODE_UNICODE)
Packit 1fb8d4
            {                                        
Packit 1fb8d4
                if ([[self delegate] respondsToSelector:@selector(advancedKeyPressedUnicode:)])
Packit 1fb8d4
                    [[self delegate] advancedKeyPressedUnicode:([btn tag] & ~KEYCODE_UNICODE)];
Packit 1fb8d4
            }
Packit 1fb8d4
            else
Packit 1fb8d4
            {
Packit 1fb8d4
                if ([[self delegate] respondsToSelector:@selector(advancedKeyPressedVKey:)])
Packit 1fb8d4
                    [[self delegate] advancedKeyPressedVKey:[btn tag]];
Packit 1fb8d4
            }
Packit 1fb8d4
            break;
Packit 1fb8d4
    }
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
@end
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
@implementation AdvancedKeyboardView (Private)
Packit 1fb8d4
    
Packit 1fb8d4
- (UIView*)keyboardViewForItems:(struct ButtonItem*)items columns:(int)columns rows:(int)rows
Packit 1fb8d4
{
Packit 1fb8d4
    UIView* result_view = [[[UIView alloc] initWithFrame:self.bounds] autorelease];
Packit 1fb8d4
    result_view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
Packit 1fb8d4
    
Packit 1fb8d4
    // calculate maximum button size
Packit 1fb8d4
    int max_btn_width = result_view.bounds.size.width / ((columns * 2) + 1);
Packit 1fb8d4
    int max_btn_height = result_view.bounds.size.height / ((rows * 2) + 1);
Packit 1fb8d4
    
Packit 1fb8d4
    // ensure minimum button size
Packit 1fb8d4
    CGSize btn_size = CGSizeMake(45, 30);
Packit 1fb8d4
    if(btn_size.width < max_btn_width)
Packit 1fb8d4
        btn_size.width = max_btn_width;
Packit 1fb8d4
    if(btn_size.height < max_btn_height)
Packit 1fb8d4
        btn_size.height = max_btn_height;
Packit 1fb8d4
    
Packit 1fb8d4
    // calc distance width and height between buttons
Packit 1fb8d4
    int dist_width = (result_view.bounds.size.width - (columns * btn_size.width)) / (columns + 1);
Packit 1fb8d4
    int dist_height = (result_view.bounds.size.height - (rows * btn_size.height)) / (rows + 1);
Packit 1fb8d4
    
Packit 1fb8d4
	UIImage* btn_background_img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"keyboard_button_background" ofType:@"png"]];
Packit 1fb8d4
    for(int j = 0; j < rows; j++)
Packit 1fb8d4
    {
Packit 1fb8d4
        for(int i = 0; i < columns; i++)
Packit 1fb8d4
        {
Packit 1fb8d4
            struct ButtonItem* curItem = &items[j * columns + i];
Packit 1fb8d4
            
Packit 1fb8d4
            // skip this spot?
Packit 1fb8d4
            if(curItem->tag == KEY_SKIP)
Packit 1fb8d4
                continue;
Packit 1fb8d4
            
Packit 1fb8d4
            // create button, set autoresizing mask and add action handler
Packit 1fb8d4
            UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
Packit 1fb8d4
            [btn setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
Packit 1fb8d4
            [btn addTarget:self action:@selector(keyPressed:) forControlEvents:UIControlEventTouchUpInside];
Packit 1fb8d4
            
Packit 1fb8d4
            // if merge is specified we merge this button's position with the next one
Packit 1fb8d4
            if(curItem->tag == KEY_MERGE_COLUMN)
Packit 1fb8d4
            {
Packit 1fb8d4
                // calc merged frame
Packit 1fb8d4
                [btn setFrame:CGRectMake(dist_width + (i * dist_width) + (i * btn_size.width), 
Packit 1fb8d4
                                         dist_height + (j * dist_height) + (j * btn_size.height), 
Packit 1fb8d4
                                         btn_size.width * 2 + dist_width, btn_size.height)];
Packit 1fb8d4
                
Packit 1fb8d4
                // proceed to the next column item
Packit 1fb8d4
                i++;    
Packit 1fb8d4
                curItem = &items[j * columns + i];
Packit 1fb8d4
            }
Packit 1fb8d4
            else
Packit 1fb8d4
            {
Packit 1fb8d4
                [btn setFrame:CGRectMake(dist_width + (i * dist_width) + (i * btn_size.width), 
Packit 1fb8d4
                                         dist_height + (j * dist_height) + (j * btn_size.height), 
Packit 1fb8d4
                                         btn_size.width, btn_size.height)];
Packit 1fb8d4
            }
Packit 1fb8d4
            
Packit 1fb8d4
            // set button text or image parameters
Packit 1fb8d4
            if([curItem->title hasPrefix:@"img:"] == YES)
Packit 1fb8d4
            {
Packit 1fb8d4
                UIImage* btn_image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[curItem->title substringFromIndex:4] ofType:@"png"]];
Packit 1fb8d4
                [btn setImage:btn_image forState:UIControlStateNormal];
Packit 1fb8d4
            }
Packit 1fb8d4
            else
Packit 1fb8d4
            {
Packit 1fb8d4
                [btn setTitle:curItem->title forState:UIControlStateNormal];
Packit 1fb8d4
                [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];                
Packit 1fb8d4
            }
Packit 1fb8d4
            
Packit 1fb8d4
            [btn setBackgroundImage:btn_background_img forState:UIControlStateNormal];    
Packit 1fb8d4
            [btn setTag:curItem->tag];
Packit 1fb8d4
            
Packit 1fb8d4
            // add button to view
Packit 1fb8d4
            [result_view addSubview:btn];
Packit 1fb8d4
        }
Packit 1fb8d4
    }
Packit 1fb8d4
    
Packit 1fb8d4
    return result_view;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
@end