Reformatted to new style

This commit is contained in:
Armin Novak
2019-11-06 15:24:51 +01:00
parent ba71de6230
commit 72ca88f49c
1335 changed files with 118253 additions and 113607 deletions

View File

@@ -129,18 +129,18 @@ NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
- (NSUInteger)indexForKey:(id)key
{
return [array indexOfObject:key];
return [array indexOfObject:key];
}
- (NSUInteger)indexForValue:(id)value
{
NSArray* keys = [self allKeysForObject:value];
if ([keys count] > 0)
{
return [self indexForKey:[keys objectAtIndex:0]];
}
return NSNotFound;
NSArray *keys = [self allKeysForObject:value];
if ([keys count] > 0)
{
return [self indexForKey:[keys objectAtIndex:0]];
}
return NSNotFound;
}
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
@@ -151,15 +151,14 @@ NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
{
[indentString appendFormat:@" "];
}
NSMutableString *description = [NSMutableString string];
[description appendFormat:@"%@{\n", indentString];
for (NSObject *key in self)
{
[description appendFormat:@"%@ %@ = %@;\n",
indentString,
DescriptionForObject(key, locale, level),
DescriptionForObject([self objectForKey:key], locale, level)];
[description appendFormat:@"%@ %@ = %@;\n", indentString,
DescriptionForObject(key, locale, level),
DescriptionForObject([self objectForKey:key], locale, level)];
}
[description appendFormat:@"%@}\n", indentString];
return description;

View File

@@ -1,10 +1,11 @@
/*
Additions to Cocoa touch classes
Copyright 2013 Thincast Technologies GmbH, Authors: Dorian Johnson, Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@@ -15,9 +16,12 @@
#pragma mark -
@interface NSString (TSXAdditions)
+ (NSString*)stringWithUUID;
- (NSData*)dataFromHexString;
+ (NSString*)hexStringFromData:(const unsigned char *)data ofSize:(unsigned int)size withSeparator:(NSString *)sep afterNthChar:(int)sepnth;
+ (NSString *)stringWithUUID;
- (NSData *)dataFromHexString;
+ (NSString *)hexStringFromData:(const unsigned char *)data
ofSize:(unsigned int)size
withSeparator:(NSString *)sep
afterNthChar:(int)sepnth;
@end
@interface NSDictionary (TSXAdditions)

View File

@@ -1,10 +1,11 @@
/*
Additions to Cocoa touch classes
Copyright 2013 Thincast Technologies GmbH, Authors: Dorian Johnson, Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "TSXAdditions.h"
@@ -21,12 +22,12 @@
- mutableDeepCopy
{
if([self respondsToSelector:@selector(mutableCopyWithZone:)])
return [self mutableCopy];
else if([self respondsToSelector:@selector(copyWithZone:)])
return [self copy];
else
return [self retain];
if ([self respondsToSelector:@selector(mutableCopyWithZone:)])
return [self mutableCopy];
else if ([self respondsToSelector:@selector(copyWithZone:)])
return [self copy];
else
return [self retain];
}
@end
@@ -36,71 +37,88 @@
@implementation NSString (TSXAdditions)
#pragma mark Creation routines
+ (NSString*)stringWithUUID
+ (NSString *)stringWithUUID
{
CFUUIDRef uuidObj = CFUUIDCreate(nil);
NSString* uuidString = (NSString*)CFUUIDCreateString(nil, uuidObj);
NSString *uuidString = (NSString *)CFUUIDCreateString(nil, uuidObj);
CFRelease(uuidObj);
return [uuidString autorelease];
}
/* Code from http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMNSData%2BHex.m?r=344 */
- (NSData*)dataFromHexString
/* Code from
* http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMNSData%2BHex.m?r=344
*/
- (NSData *)dataFromHexString
{
NSData *hexData = [self dataUsingEncoding:NSASCIIStringEncoding];
const char *hexBuf = [hexData bytes];
NSUInteger hexLen = [hexData length];
// This indicates an error converting to ASCII.
if (!hexData)
return nil;
if ((hexLen % 2) != 0) {
return nil;
}
NSMutableData *binaryData = [NSMutableData dataWithLength:(hexLen / 2)];
unsigned char *binaryPtr = [binaryData mutableBytes];
unsigned char value = 0;
for (NSUInteger i = 0; i < hexLen; i++) {
char c = hexBuf[i];
if (!isxdigit(c)) {
return nil;
}
if (isdigit(c)) {
value += c - '0';
} else if (islower(c)) {
value += 10 + c - 'a';
} else {
value += 10 + c - 'A';
}
if (i & 1) {
*binaryPtr++ = value;
value = 0;
} else {
value <<= 4;
}
}
return [NSData dataWithData:binaryData];
NSData *hexData = [self dataUsingEncoding:NSASCIIStringEncoding];
const char *hexBuf = [hexData bytes];
NSUInteger hexLen = [hexData length];
// This indicates an error converting to ASCII.
if (!hexData)
return nil;
if ((hexLen % 2) != 0)
{
return nil;
}
NSMutableData *binaryData = [NSMutableData dataWithLength:(hexLen / 2)];
unsigned char *binaryPtr = [binaryData mutableBytes];
unsigned char value = 0;
for (NSUInteger i = 0; i < hexLen; i++)
{
char c = hexBuf[i];
if (!isxdigit(c))
{
return nil;
}
if (isdigit(c))
{
value += c - '0';
}
else if (islower(c))
{
value += 10 + c - 'a';
}
else
{
value += 10 + c - 'A';
}
if (i & 1)
{
*binaryPtr++ = value;
value = 0;
}
else
{
value <<= 4;
}
}
return [NSData dataWithData:binaryData];
}
+ (NSString*)hexStringFromData:(const unsigned char *)data ofSize:(unsigned int)size withSeparator:(NSString *)sep afterNthChar:(int)sepnth
+ (NSString *)hexStringFromData:(const unsigned char *)data
ofSize:(unsigned int)size
withSeparator:(NSString *)sep
afterNthChar:(int)sepnth
{
int i;
NSMutableString *result;
NSString *immutableResult;
result = [[NSMutableString alloc] init];
for (i = 0; i < size; i++) {
if(i && sep && sepnth && i%sepnth==0)
for (i = 0; i < size; i++)
{
if (i && sep && sepnth && i % sepnth == 0)
[result appendString:sep];
[result appendFormat:@"%02X", data[i]];
}
immutableResult = [NSString stringWithString:result];
[result release];
return immutableResult;
@@ -114,16 +132,16 @@
- mutableDeepCopy
{
NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] init];
NSEnumerator *enumerator = [self keyEnumerator];
id key;
while((key = [enumerator nextObject]))
{
id obj = [[self objectForKey:key] mutableDeepCopy];
[newDictionary setObject:obj forKey:key];
[obj release];
}
return newDictionary;
NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] init];
NSEnumerator *enumerator = [self keyEnumerator];
id key;
while ((key = [enumerator nextObject]))
{
id obj = [[self objectForKey:key] mutableDeepCopy];
[newDictionary setObject:obj forKey:key];
[obj release];
}
return newDictionary;
}
@end
@@ -132,16 +150,16 @@
- mutableDeepCopy
{
NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSEnumerator *enumerator = [self objectEnumerator];
id obj;
while((obj = [enumerator nextObject]))
{
obj = [obj mutableDeepCopy];
[newArray addObject:obj];
[obj release];
}
return newArray;
NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSEnumerator *enumerator = [self objectEnumerator];
id obj;
while ((obj = [enumerator nextObject]))
{
obj = [obj mutableDeepCopy];
[newArray addObject:obj];
[obj release];
}
return newArray;
}
@end
@@ -150,68 +168,71 @@
- mutableDeepCopy
{
NSMutableSet *newSet = [[NSMutableSet alloc] init];
NSEnumerator *enumerator = [self objectEnumerator];
id obj;
while((obj = [enumerator nextObject]))
{
obj = [obj mutableDeepCopy];
[newSet addObject:obj];
[obj release];
}
return newSet;
NSMutableSet *newSet = [[NSMutableSet alloc] init];
NSEnumerator *enumerator = [self objectEnumerator];
id obj;
while ((obj = [enumerator nextObject]))
{
obj = [obj mutableDeepCopy];
[newSet addObject:obj];
[obj release];
}
return newSet;
}
@end
#pragma mark -
/* Code from http://stackoverflow.com/questions/1305225/best-way-to-serialize-a-nsdata-into-an-hexadeximal-string */
/* Code from
* http://stackoverflow.com/questions/1305225/best-way-to-serialize-a-nsdata-into-an-hexadeximal-string
*/
@implementation NSData (TSXAdditions)
#pragma mark - String Conversion
- (NSString *)hexadecimalString {
/* Returns hexadecimal string of NSData. Empty string if data is empty. */
const unsigned char *dataBuffer = (const unsigned char *)[self bytes];
if (!dataBuffer)
return [NSString string];
NSUInteger dataLength = [self length];
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i)
[hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
return [NSString stringWithString:hexString];
- (NSString *)hexadecimalString
{
/* Returns hexadecimal string of NSData. Empty string if data is empty. */
const unsigned char *dataBuffer = (const unsigned char *)[self bytes];
if (!dataBuffer)
return [NSString string];
NSUInteger dataLength = [self length];
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i)
[hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
return [NSString stringWithString:hexString];
}
/* Code from http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html */
- (NSString *)base64EncodedString
{
// Construct an OpenSSL context
BIO *context = BIO_new(BIO_s_mem());
// Tell the context to encode base64
BIO *command = BIO_new(BIO_f_base64());
context = BIO_push(command, context);
BIO_set_flags(context, BIO_FLAGS_BASE64_NO_NL);
// Encode all the data
BIO_write(context, [self bytes], [self length]);
(void)BIO_flush(context);
// Get the data out of the context
char *outputBuffer;
long outputLength = BIO_get_mem_data(context, &outputBuffer);
NSString *encodedString = [[NSString alloc] initWithBytes:outputBuffer length:outputLength encoding:NSASCIIStringEncoding];
BIO_free_all(context);
return encodedString;
// Construct an OpenSSL context
BIO *context = BIO_new(BIO_s_mem());
// Tell the context to encode base64
BIO *command = BIO_new(BIO_f_base64());
context = BIO_push(command, context);
BIO_set_flags(context, BIO_FLAGS_BASE64_NO_NL);
// Encode all the data
BIO_write(context, [self bytes], [self length]);
(void)BIO_flush(context);
// Get the data out of the context
char *outputBuffer;
long outputLength = BIO_get_mem_data(context, &outputBuffer);
NSString *encodedString = [[NSString alloc] initWithBytes:outputBuffer
length:outputLength
encoding:NSASCIIStringEncoding];
BIO_free_all(context);
return encodedString;
}
@end

View File

@@ -1,11 +1,11 @@
/***************************************************************************
Toast+UIView.h
Toast
Version 0.1
Copyright (c) 2011 Charles Scalesse.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
@@ -13,10 +13,10 @@
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -24,9 +24,8 @@
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/
***************************************************************************/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@@ -38,14 +37,24 @@
#define ToastDurationShort 1.0
// each makeToast method creates a view and displays it as toast
-(void)makeToast:(NSString *)message;
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point;
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point title:(NSString *)title;
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point title:(NSString *)title image:(UIImage *)image;
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point image:(UIImage *)image;
- (void)makeToast:(NSString *)message;
- (void)makeToast:(NSString *)message duration:(float)interval position:(id)point;
- (void)makeToast:(NSString *)message
duration:(float)interval
position:(id)point
title:(NSString *)title;
- (void)makeToast:(NSString *)message
duration:(float)interval
position:(id)point
title:(NSString *)title
image:(UIImage *)image;
- (void)makeToast:(NSString *)message
duration:(float)interval
position:(id)point
image:(UIImage *)image;
// the showToast method displays an existing view as toast
-(void)showToast:(UIView *)toast;
-(void)showToast:(UIView *)toast duration:(float)interval position:(id)point;
- (void)showToast:(UIView *)toast;
- (void)showToast:(UIView *)toast duration:(float)interval position:(id)point;
@end

View File

@@ -1,11 +1,11 @@
/***************************************************************************
Toast+UIView.h
Toast
Version 0.1
Copyright (c) 2011 Charles Scalesse.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
@@ -13,10 +13,10 @@
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -24,284 +24,344 @@
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/
#import "Toast+UIView.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
#define kMaxWidth 0.8
#define kMaxHeight 0.8
#define kMaxWidth 0.8
#define kMaxHeight 0.8
#define kHorizontalPadding 10.0
#define kVerticalPadding 10.0
#define kCornerRadius 10.0
#define kOpacity 0.8
#define kFontSize 16.0
#define kMaxTitleLines 999
#define kMaxMessageLines 999
#define kHorizontalPadding 10.0
#define kVerticalPadding 10.0
#define kCornerRadius 10.0
#define kOpacity 0.8
#define kFontSize 16.0
#define kMaxTitleLines 999
#define kMaxMessageLines 999
#define kFadeDuration 0.2
#define kFadeDuration 0.2
#define kDefaultLength 3
#define kDefaultPosition @"bottom"
#define kDefaultLength 3
#define kDefaultPosition @"bottom"
#define kImageWidth 80.0
#define kImageHeight 80.0
#define kImageWidth 80.0
#define kImageHeight 80.0
static NSString *kDurationKey = @"duration";
@interface UIView (ToastPrivate)
-(CGPoint)getPositionFor:(id)position toast:(UIView *)toast;
-(UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image;
- (CGPoint)getPositionFor:(id)position toast:(UIView *)toast;
- (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image;
@end
@implementation UIView (Toast)
#pragma mark -
#pragma mark Toast Methods
-(void)makeToast:(NSString *)message {
[self makeToast:message duration:kDefaultLength position:kDefaultPosition];
- (void)makeToast:(NSString *)message
{
[self makeToast:message duration:kDefaultLength position:kDefaultPosition];
}
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point {
UIView *toast = [self makeViewForMessage:message title:nil image:nil];
[self showToast:toast duration:interval position:point];
- (void)makeToast:(NSString *)message duration:(float)interval position:(id)point
{
UIView *toast = [self makeViewForMessage:message title:nil image:nil];
[self showToast:toast duration:interval position:point];
}
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point title:(NSString *)title {
UIView *toast = [self makeViewForMessage:message title:title image:nil];
[self showToast:toast duration:interval position:point];
- (void)makeToast:(NSString *)message
duration:(float)interval
position:(id)point
title:(NSString *)title
{
UIView *toast = [self makeViewForMessage:message title:title image:nil];
[self showToast:toast duration:interval position:point];
}
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point image:(UIImage *)image {
UIView *toast = [self makeViewForMessage:message title:nil image:image];
[self showToast:toast duration:interval position:point];
- (void)makeToast:(NSString *)message
duration:(float)interval
position:(id)point
image:(UIImage *)image
{
UIView *toast = [self makeViewForMessage:message title:nil image:image];
[self showToast:toast duration:interval position:point];
}
-(void)makeToast:(NSString *)message duration:(float)interval position:(id)point title:(NSString *)title image:(UIImage *)image {
UIView *toast = [self makeViewForMessage:message title:title image:image];
[self showToast:toast duration:interval position:point];
- (void)makeToast:(NSString *)message
duration:(float)interval
position:(id)point
title:(NSString *)title
image:(UIImage *)image
{
UIView *toast = [self makeViewForMessage:message title:title image:image];
[self showToast:toast duration:interval position:point];
}
-(void)showToast:(UIView *)toast {
[self showToast:toast duration:kDefaultLength position:kDefaultPosition];
- (void)showToast:(UIView *)toast
{
[self showToast:toast duration:kDefaultLength position:kDefaultPosition];
}
-(void)showToast:(UIView *)toast duration:(float)interval position:(id)point {
/****************************************************
* *
* Displays a view for a given duration & position. *
* *
****************************************************/
CGPoint toastPoint = [self getPositionFor:point toast:toast];
//use an associative reference to associate the toast view with the display interval
objc_setAssociatedObject (toast, &kDurationKey, [NSNumber numberWithFloat:interval], OBJC_ASSOCIATION_RETAIN);
[toast setCenter:toastPoint];
[toast setAlpha:0.0];
[self addSubview:toast];
[UIView beginAnimations:@"fade_in" context:toast];
[UIView setAnimationDuration:kFadeDuration];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[toast setAlpha:1.0];
[UIView commitAnimations];
- (void)showToast:(UIView *)toast duration:(float)interval position:(id)point
{
/****************************************************
* *
* Displays a view for a given duration & position. *
* *
****************************************************/
CGPoint toastPoint = [self getPositionFor:point toast:toast];
// use an associative reference to associate the toast view with the display interval
objc_setAssociatedObject(toast, &kDurationKey, [NSNumber numberWithFloat:interval],
OBJC_ASSOCIATION_RETAIN);
[toast setCenter:toastPoint];
[toast setAlpha:0.0];
[self addSubview:toast];
[UIView beginAnimations:@"fade_in" context:toast];
[UIView setAnimationDuration:kFadeDuration];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[toast setAlpha:1.0];
[UIView commitAnimations];
}
#pragma mark -
#pragma mark Animation Delegate Method
- (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context {
UIView *toast = (UIView *)context;
// retrieve the display interval associated with the view
float interval = [(NSNumber *)objc_getAssociatedObject(toast, &kDurationKey) floatValue];
if([animationID isEqualToString:@"fade_in"]) {
[UIView beginAnimations:@"fade_out" context:toast];
[UIView setAnimationDelay:interval];
[UIView setAnimationDuration:kFadeDuration];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[toast setAlpha:0.0];
[UIView commitAnimations];
} else if ([animationID isEqualToString:@"fade_out"]) {
[toast removeFromSuperview];
}
- (void)animationDidStop:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
UIView *toast = (UIView *)context;
// retrieve the display interval associated with the view
float interval = [(NSNumber *)objc_getAssociatedObject(toast, &kDurationKey) floatValue];
if ([animationID isEqualToString:@"fade_in"])
{
[UIView beginAnimations:@"fade_out" context:toast];
[UIView setAnimationDelay:interval];
[UIView setAnimationDuration:kFadeDuration];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[toast setAlpha:0.0];
[UIView commitAnimations];
}
else if ([animationID isEqualToString:@"fade_out"])
{
[toast removeFromSuperview];
}
}
#pragma mark -
#pragma mark Private Methods
-(CGPoint)getPositionFor:(id)point toast:(UIView *)toast {
/*************************************************************************************
* *
* Converts string literals @"top", @"bottom", @"center", or any point wrapped in an *
* NSValue object into a CGPoint *
* *
*************************************************************************************/
if([point isKindOfClass:[NSString class]]) {
if( [point caseInsensitiveCompare:@"top"] == NSOrderedSame ) {
return CGPointMake(self.bounds.size.width/2, (toast.frame.size.height / 2) + kVerticalPadding);
} else if( [point caseInsensitiveCompare:@"bottom"] == NSOrderedSame ) {
return CGPointMake(self.bounds.size.width/2, (self.bounds.size.height - (toast.frame.size.height / 2)) - kVerticalPadding);
} else if( [point caseInsensitiveCompare:@"center"] == NSOrderedSame ) {
return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
}
} else if ([point isKindOfClass:[NSValue class]]) {
return [point CGPointValue];
}
NSLog(@"Error: Invalid position for toast.");
return [self getPositionFor:kDefaultPosition toast:toast];
- (CGPoint)getPositionFor:(id)point toast:(UIView *)toast
{
/*************************************************************************************
* *
* Converts string literals @"top", @"bottom", @"center", or any point wrapped in an *
* NSValue object into a CGPoint *
* *
*************************************************************************************/
if ([point isKindOfClass:[NSString class]])
{
if ([point caseInsensitiveCompare:@"top"] == NSOrderedSame)
{
return CGPointMake(self.bounds.size.width / 2,
(toast.frame.size.height / 2) + kVerticalPadding);
}
else if ([point caseInsensitiveCompare:@"bottom"] == NSOrderedSame)
{
return CGPointMake(self.bounds.size.width / 2,
(self.bounds.size.height - (toast.frame.size.height / 2)) -
kVerticalPadding);
}
else if ([point caseInsensitiveCompare:@"center"] == NSOrderedSame)
{
return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
}
}
else if ([point isKindOfClass:[NSValue class]])
{
return [point CGPointValue];
}
NSLog(@"Error: Invalid position for toast.");
return [self getPositionFor:kDefaultPosition toast:toast];
}
-(UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image {
/***********************************************************************************
* *
* Dynamically build a toast view with any combination of message, title, & image. *
* *
***********************************************************************************/
if((message == nil) && (title == nil) && (image == nil)) return nil;
- (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image
{
UILabel *messageLabel = nil;
UILabel *titleLabel = nil;
UIImageView *imageView = nil;
// create the parent view
UIView *wrapperView = [[[UIView alloc] init] autorelease];
[wrapperView.layer setCornerRadius:kCornerRadius];
[wrapperView setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:kOpacity]];
wrapperView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
/***********************************************************************************
* *
* Dynamically build a toast view with any combination of message, title, & image. *
* *
***********************************************************************************/
if(image != nil) {
imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[imageView setFrame:CGRectMake(kHorizontalPadding, kVerticalPadding, kImageWidth, kImageHeight)];
}
float imageWidth, imageHeight, imageLeft;
// the imageView frame values will be used to size & position the other views
if(imageView != nil) {
imageWidth = imageView.bounds.size.width;
imageHeight = imageView.bounds.size.height;
imageLeft = kHorizontalPadding;
} else {
imageWidth = imageHeight = imageLeft = 0;
}
if (title != nil) {
titleLabel = [[[UILabel alloc] init] autorelease];
[titleLabel setNumberOfLines:kMaxTitleLines];
[titleLabel setFont:[UIFont boldSystemFontOfSize:kFontSize]];
[titleLabel setTextAlignment:UITextAlignmentLeft];
[titleLabel setLineBreakMode:UILineBreakModeWordWrap];
[titleLabel setTextColor:[UIColor whiteColor]];
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setAlpha:1.0];
[titleLabel setText:title];
// size the title label according to the length of the text
CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth, self.bounds.size.height * kMaxHeight);
CGSize expectedSizeTitle = [title sizeWithFont:titleLabel.font constrainedToSize:maxSizeTitle lineBreakMode:titleLabel.lineBreakMode];
[titleLabel setFrame:CGRectMake(0, 0, expectedSizeTitle.width, expectedSizeTitle.height)];
}
if (message != nil) {
messageLabel = [[[UILabel alloc] init] autorelease];
[messageLabel setNumberOfLines:kMaxMessageLines];
[messageLabel setFont:[UIFont systemFontOfSize:kFontSize]];
[messageLabel setLineBreakMode:UILineBreakModeWordWrap];
[messageLabel setTextColor:[UIColor whiteColor]];
[messageLabel setTextAlignment:UITextAlignmentCenter];
[messageLabel setBackgroundColor:[UIColor clearColor]];
[messageLabel setAlpha:1.0];
[messageLabel setText:message];
// size the message label according to the length of the text
CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth, self.bounds.size.height * kMaxHeight);
CGSize expectedSizeMessage = [message sizeWithFont:messageLabel.font constrainedToSize:maxSizeMessage lineBreakMode:messageLabel.lineBreakMode];
[messageLabel setFrame:CGRectMake(0, 0, expectedSizeMessage.width, expectedSizeMessage.height)];
}
// titleLabel frame values
float titleWidth, titleHeight, titleTop, titleLeft;
if(titleLabel != nil) {
titleWidth = titleLabel.bounds.size.width;
titleHeight = titleLabel.bounds.size.height;
titleTop = kVerticalPadding;
titleLeft = imageLeft + imageWidth + kHorizontalPadding;
} else {
titleWidth = titleHeight = titleTop = titleLeft = 0;
}
// messageLabel frame values
float messageWidth, messageHeight, messageLeft, messageTop;
if ((message == nil) && (title == nil) && (image == nil))
return nil;
if(messageLabel != nil) {
messageWidth = messageLabel.bounds.size.width;
messageHeight = messageLabel.bounds.size.height;
messageLeft = imageLeft + imageWidth + kHorizontalPadding;
messageTop = titleTop + titleHeight + kVerticalPadding;
} else {
messageWidth = messageHeight = messageLeft = messageTop = 0;
}
// compare the title & message widths and use the longer value to calculate the size of the wrapper width
// the same logic applies to the x value (left)
float longerWidth = (messageWidth < titleWidth) ? titleWidth : messageWidth;
float longerLeft = (messageLeft < titleLeft) ? titleLeft : messageLeft;
// if the image width is larger than longerWidth, use the image width to calculate the wrapper width.
// the same logic applies to the wrapper height
float wrapperWidth = ((longerLeft + longerWidth + kHorizontalPadding) < imageWidth + (kHorizontalPadding * 2)) ? imageWidth + (kHorizontalPadding * 2) : (longerLeft + longerWidth + kHorizontalPadding);
float wrapperHeight = ((messageTop + messageHeight + kVerticalPadding) < imageHeight + (kVerticalPadding * 2)) ? imageHeight + (kVerticalPadding * 2) : (messageTop + messageHeight + kVerticalPadding);
[wrapperView setFrame:CGRectMake(0, 0, wrapperWidth, wrapperHeight)];
if(titleLabel != nil) {
[titleLabel setFrame:CGRectMake(titleLeft, titleTop, titleWidth, titleHeight)];
[wrapperView addSubview:titleLabel];
}
if(messageLabel != nil) {
[messageLabel setFrame:CGRectMake(messageLeft, messageTop, messageWidth, messageHeight)];
[wrapperView addSubview:messageLabel];
}
if(imageView != nil) {
[wrapperView addSubview:imageView];
}
return wrapperView;
UILabel *messageLabel = nil;
UILabel *titleLabel = nil;
UIImageView *imageView = nil;
// create the parent view
UIView *wrapperView = [[[UIView alloc] init] autorelease];
[wrapperView.layer setCornerRadius:kCornerRadius];
[wrapperView setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:kOpacity]];
wrapperView.autoresizingMask =
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
if (image != nil)
{
imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[imageView
setFrame:CGRectMake(kHorizontalPadding, kVerticalPadding, kImageWidth, kImageHeight)];
}
float imageWidth, imageHeight, imageLeft;
// the imageView frame values will be used to size & position the other views
if (imageView != nil)
{
imageWidth = imageView.bounds.size.width;
imageHeight = imageView.bounds.size.height;
imageLeft = kHorizontalPadding;
}
else
{
imageWidth = imageHeight = imageLeft = 0;
}
if (title != nil)
{
titleLabel = [[[UILabel alloc] init] autorelease];
[titleLabel setNumberOfLines:kMaxTitleLines];
[titleLabel setFont:[UIFont boldSystemFontOfSize:kFontSize]];
[titleLabel setTextAlignment:UITextAlignmentLeft];
[titleLabel setLineBreakMode:UILineBreakModeWordWrap];
[titleLabel setTextColor:[UIColor whiteColor]];
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setAlpha:1.0];
[titleLabel setText:title];
// size the title label according to the length of the text
CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth,
self.bounds.size.height * kMaxHeight);
CGSize expectedSizeTitle = [title sizeWithFont:titleLabel.font
constrainedToSize:maxSizeTitle
lineBreakMode:titleLabel.lineBreakMode];
[titleLabel setFrame:CGRectMake(0, 0, expectedSizeTitle.width, expectedSizeTitle.height)];
}
if (message != nil)
{
messageLabel = [[[UILabel alloc] init] autorelease];
[messageLabel setNumberOfLines:kMaxMessageLines];
[messageLabel setFont:[UIFont systemFontOfSize:kFontSize]];
[messageLabel setLineBreakMode:UILineBreakModeWordWrap];
[messageLabel setTextColor:[UIColor whiteColor]];
[messageLabel setTextAlignment:UITextAlignmentCenter];
[messageLabel setBackgroundColor:[UIColor clearColor]];
[messageLabel setAlpha:1.0];
[messageLabel setText:message];
// size the message label according to the length of the text
CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth,
self.bounds.size.height * kMaxHeight);
CGSize expectedSizeMessage = [message sizeWithFont:messageLabel.font
constrainedToSize:maxSizeMessage
lineBreakMode:messageLabel.lineBreakMode];
[messageLabel
setFrame:CGRectMake(0, 0, expectedSizeMessage.width, expectedSizeMessage.height)];
}
// titleLabel frame values
float titleWidth, titleHeight, titleTop, titleLeft;
if (titleLabel != nil)
{
titleWidth = titleLabel.bounds.size.width;
titleHeight = titleLabel.bounds.size.height;
titleTop = kVerticalPadding;
titleLeft = imageLeft + imageWidth + kHorizontalPadding;
}
else
{
titleWidth = titleHeight = titleTop = titleLeft = 0;
}
// messageLabel frame values
float messageWidth, messageHeight, messageLeft, messageTop;
if (messageLabel != nil)
{
messageWidth = messageLabel.bounds.size.width;
messageHeight = messageLabel.bounds.size.height;
messageLeft = imageLeft + imageWidth + kHorizontalPadding;
messageTop = titleTop + titleHeight + kVerticalPadding;
}
else
{
messageWidth = messageHeight = messageLeft = messageTop = 0;
}
// compare the title & message widths and use the longer value to calculate the size of the
// wrapper width the same logic applies to the x value (left)
float longerWidth = (messageWidth < titleWidth) ? titleWidth : messageWidth;
float longerLeft = (messageLeft < titleLeft) ? titleLeft : messageLeft;
// if the image width is larger than longerWidth, use the image width to calculate the wrapper
// width. the same logic applies to the wrapper height
float wrapperWidth =
((longerLeft + longerWidth + kHorizontalPadding) < imageWidth + (kHorizontalPadding * 2))
? imageWidth + (kHorizontalPadding * 2)
: (longerLeft + longerWidth + kHorizontalPadding);
float wrapperHeight =
((messageTop + messageHeight + kVerticalPadding) < imageHeight + (kVerticalPadding * 2))
? imageHeight + (kVerticalPadding * 2)
: (messageTop + messageHeight + kVerticalPadding);
[wrapperView setFrame:CGRectMake(0, 0, wrapperWidth, wrapperHeight)];
if (titleLabel != nil)
{
[titleLabel setFrame:CGRectMake(titleLeft, titleTop, titleWidth, titleHeight)];
[wrapperView addSubview:titleLabel];
}
if (messageLabel != nil)
{
[messageLabel setFrame:CGRectMake(messageLeft, messageTop, messageWidth, messageHeight)];
[wrapperView addSubview:messageLabel];
}
if (imageView != nil)
{
[wrapperView addSubview:imageView];
}
return wrapperView;
}
@end

View File

@@ -1,22 +1,24 @@
/*
App delegate
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@class MainTabBarController;
@interface AppDelegate : NSObject <UIApplicationDelegate> {
@interface AppDelegate : NSObject <UIApplicationDelegate>
{
MainTabBarController* _tabBarController;
MainTabBarController *_tabBarController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet MainTabBarController* tabBarController;
@property(nonatomic, retain) IBOutlet UIWindow *window;
@property(nonatomic, retain) IBOutlet MainTabBarController *tabBarController;
@end

View File

@@ -1,10 +1,11 @@
/*
App delegate
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "AppDelegate.h"
@@ -18,89 +19,109 @@
@implementation AppDelegate
@synthesize window = _window, tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Set default values for most NSUserDefaults
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Defaults" ofType:@"plist"]]];
[[NSUserDefaults standardUserDefaults]
registerDefaults:[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:@"Defaults"
ofType:@"plist"]]];
// init global settings
SetSwapMouseButtonsFlag([[NSUserDefaults standardUserDefaults] boolForKey:@"ui.swap_mouse_buttons"]);
SetInvertScrollingFlag([[NSUserDefaults standardUserDefaults] boolForKey:@"ui.invert_scrolling"]);
// create bookmark view and navigation controller
BookmarkListController* bookmarkListController = [[[BookmarkListController alloc] initWithNibName:@"BookmarkListView" bundle:nil] autorelease];
UINavigationController* bookmarkNavigationController = [[[UINavigationController alloc] initWithRootViewController:bookmarkListController] autorelease];
// init global settings
SetSwapMouseButtonsFlag(
[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.swap_mouse_buttons"]);
SetInvertScrollingFlag(
[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.invert_scrolling"]);
// create app settings view and navigation controller
AppSettingsController* appSettingsController = [[[AppSettingsController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
UINavigationController* appSettingsNavigationController = [[[UINavigationController alloc] initWithRootViewController:appSettingsController] autorelease];
// create help view controller
HelpController* helpViewController = [[[HelpController alloc] initWithNibName:nil bundle:nil] autorelease];
// create bookmark view and navigation controller
BookmarkListController *bookmarkListController =
[[[BookmarkListController alloc] initWithNibName:@"BookmarkListView"
bundle:nil] autorelease];
UINavigationController *bookmarkNavigationController = [[[UINavigationController alloc]
initWithRootViewController:bookmarkListController] autorelease];
// create about view controller
AboutController* aboutViewController = [[[AboutController alloc] initWithNibName:nil bundle:nil] autorelease];
// add tab-bar controller to the main window and display everything
NSArray* tabItems = [NSArray arrayWithObjects:bookmarkNavigationController, appSettingsNavigationController, helpViewController, aboutViewController, nil];
[_tabBarController setViewControllers:tabItems];
if ([_window respondsToSelector:@selector(setRootViewController:)])
[_window setRootViewController:_tabBarController];
else
[_window addSubview:[_tabBarController view]];
[_window makeKeyAndVisible];
// create app settings view and navigation controller
AppSettingsController *appSettingsController =
[[[AppSettingsController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
UINavigationController *appSettingsNavigationController = [[[UINavigationController alloc]
initWithRootViewController:appSettingsController] autorelease];
return YES;
// create help view controller
HelpController *helpViewController = [[[HelpController alloc] initWithNibName:nil
bundle:nil] autorelease];
// create about view controller
AboutController *aboutViewController =
[[[AboutController alloc] initWithNibName:nil bundle:nil] autorelease];
// add tab-bar controller to the main window and display everything
NSArray *tabItems =
[NSArray arrayWithObjects:bookmarkNavigationController, appSettingsNavigationController,
helpViewController, aboutViewController, nil];
[_tabBarController setViewControllers:tabItems];
if ([_window respondsToSelector:@selector(setRootViewController:)])
[_window setRootViewController:_tabBarController];
else
[_window addSubview:[_tabBarController view]];
[_window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
/*
Sent when the application is about to move from active to inactive state. This can occur for
certain types of temporary interruptions (such as an incoming phone call or SMS message) or
when the user quits the application and it begins the transition to the background state. Use
this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates.
Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
/*
Use this method to release shared resources, save user data, invalidate timers, and store
enough application state information to restore your application to its current state in case
it is terminated later. If your application supports background execution, this method is
called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
// cancel disconnect timer
/*
Called as part of the transition from the background to the inactive state; here you can undo
many of the changes made on entering the background.
*/
// cancel disconnect timer
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If
the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
- (void)dealloc
{
[_window release];
[super dealloc];
[_window release];
[super dealloc];
}
@end

View File

@@ -1,19 +1,19 @@
/*
Application info controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface AboutController : UIViewController <UIWebViewDelegate>
{
NSString* last_link_clicked;
UIWebView* webView;
NSString *last_link_clicked;
UIWebView *webView;
}
@end

View File

@@ -1,10 +1,11 @@
/*
Application info controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "AboutController.h"
@@ -13,80 +14,104 @@
@implementation AboutController
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// The designated initializer. Override if you create the controller programmatically and want to
// perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]))
{
// set title and tab-bar image
[self setTitle:NSLocalizedString(@"About", @"About Controller title")];
UIImage* tabBarIcon = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tabbar_icon_about" ofType:@"png"]];
[self setTabBarItem:[[[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"About", @"Tabbar item about") image:tabBarIcon tag:0] autorelease]];
last_link_clicked = nil;
}
return self;
UIImage *tabBarIcon = [UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tabbar_icon_about"
ofType:@"png"]];
[self setTabBarItem:[[[UITabBarItem alloc]
initWithTitle:NSLocalizedString(@"About", @"Tabbar item about")
image:tabBarIcon
tag:0] autorelease]];
last_link_clicked = nil;
}
return self;
}
- (void)dealloc
{
[super dealloc];
[last_link_clicked release];
[super dealloc];
[last_link_clicked release];
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
- (void)loadView
{
webView = [[[UIWebView alloc] initWithFrame:CGRectZero] autorelease];
[webView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[webView
setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[webView setAutoresizesSubviews:YES];
[webView setDelegate:self];
[webView setDataDetectorTypes:UIDataDetectorTypeNone];
[self setView:webView];
[webView setDelegate:self];
[webView setDataDetectorTypes:UIDataDetectorTypeNone];
[self setView:webView];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *filename = (IsPhone() ? @"about_phone" : @"about");
NSString *htmlString = [[[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:filename ofType:@"html" inDirectory:@"about_page"] encoding:NSUTF8StringEncoding error:nil] autorelease];
[webView loadHTMLString:[NSString stringWithFormat:htmlString,
TSXAppFullVersion(),
[[UIDevice currentDevice] systemName],
[[UIDevice currentDevice] systemVersion],
[[UIDevice currentDevice] model]] baseURL:[NSURL fileURLWithPath:[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"about_page"]]];
[super viewDidLoad];
NSString *filename = (IsPhone() ? @"about_phone" : @"about");
NSString *htmlString = [[[NSString alloc]
initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:filename
ofType:@"html"
inDirectory:@"about_page"]
encoding:NSUTF8StringEncoding
error:nil] autorelease];
[webView
loadHTMLString:[NSString stringWithFormat:htmlString, TSXAppFullVersion(),
[[UIDevice currentDevice] systemName],
[[UIDevice currentDevice] systemVersion],
[[UIDevice currentDevice] model]]
baseURL:[NSURL fileURLWithPath:[[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:@"about_page"]]];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark -
#pragma mark UIWebView callbacks
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if([[request URL] isFileURL])
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([[request URL] isFileURL])
return YES;
if(navigationType == UIWebViewNavigationTypeLinkClicked)
{
[last_link_clicked release];
last_link_clicked = [[[request URL] absoluteString] retain];
BlockAlertView *alert = [BlockAlertView alertWithTitle:NSLocalizedString(@"External Link", @"External Link Alert Title")
message:[NSString stringWithFormat:NSLocalizedString(@"Open [%@] in Browser?", @"Open link in browser (with link as parameter)"), last_link_clicked]];
[alert setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil];
[alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK Button") block:^{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:last_link_clicked]];
}];
[alert show];
if (navigationType == UIWebViewNavigationTypeLinkClicked)
{
[last_link_clicked release];
last_link_clicked = [[[request URL] absoluteString] retain];
BlockAlertView *alert = [BlockAlertView
alertWithTitle:NSLocalizedString(@"External Link", @"External Link Alert Title")
message:[NSString stringWithFormat:
NSLocalizedString(
@"Open [%@] in Browser?",
@"Open link in browser (with link as parameter)"),
last_link_clicked]];
[alert setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil];
[alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK Button")
block:^{
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:last_link_clicked]];
}];
[alert show];
return NO;
}
return YES;

View File

@@ -1,10 +1,11 @@
/*
Controller to edit advanced bookmark settings
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -14,12 +15,12 @@
@interface AdvancedBookmarkEditorController : EditorBaseController
{
@private
ComputerBookmark* _bookmark;
ConnectionParams* _params;
@private
ComputerBookmark *_bookmark;
ConnectionParams *_params;
}
// init for the given bookmark
- (id)initWithBookmark:(ComputerBookmark*)bookmark;
- (id)initWithBookmark:(ComputerBookmark *)bookmark;
@end

View File

@@ -1,10 +1,11 @@
/*
Controller to edit advanced bookmark settings
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "AdvancedBookmarkEditorController.h"
@@ -24,48 +25,49 @@
@implementation AdvancedBookmarkEditorController
- (id)initWithBookmark:(ComputerBookmark*)bookmark
- (id)initWithBookmark:(ComputerBookmark *)bookmark
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
// set additional settings state according to bookmark data
_bookmark = [bookmark retain];
_params = [bookmark params];
}
return self;
_params = [bookmark params];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"Advanced Settings", @"Advanced Settings title")];
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"Advanced Settings", @"Advanced Settings title")];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// we need to reload the table view data here to have up-to-date data for the
// advanced settings accessory items (like for resolution/color mode settings)
[[self tableView] reloadData];
[super viewWillAppear:animated];
// we need to reload the table view data here to have up-to-date data for the
// advanced settings accessory items (like for resolution/color mode settings)
[[self tableView] reloadData];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
return YES;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return SECTION_COUNT;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return SECTION_COUNT;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
switch (section)
{
case SECTION_ADVANCED_SETTINGS: // advanced settings
@@ -73,15 +75,14 @@
default:
break;
}
return 0;
}
return 0;
}
// set section headers
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch(section)
switch (section)
{
case SECTION_ADVANCED_SETTINGS:
return NSLocalizedString(@"Advanced", @"'Advanced': advanced settings header");
@@ -89,203 +90,248 @@
return @"unknown";
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the required cell type
NSString* cellType = nil;
switch([indexPath section])
NSString *cellType = nil;
switch ([indexPath section])
{
case SECTION_ADVANCED_SETTINGS: // advanced settings
{
switch([indexPath row])
{
case 0: // Enable/Disable TSG Settings
cellType = TableCellIdentifierYesNo;
break;
case 1: // TS Gateway Settings
cellType = TableCellIdentifierSubEditor;
break;
case 2: // 3G Settings
cellType = TableCellIdentifierYesNo;
break;
case 3: // 3G screen/color depth
cellType = TableCellIdentifierSelection;
break;
case 4: // 3G performance settings
cellType = TableCellIdentifierSubEditor;
break;
case 5: // security mode
cellType = TableCellIdentifierSelection;
break;
case 6: // remote program
case 7: // work dir
cellType = TableCellIdentifierText;
break;
case 8: // console mode
cellType = TableCellIdentifierYesNo;
break;
default:
break;
}
case SECTION_ADVANCED_SETTINGS: // advanced settings
{
switch ([indexPath row])
{
case 0: // Enable/Disable TSG Settings
cellType = TableCellIdentifierYesNo;
break;
case 1: // TS Gateway Settings
cellType = TableCellIdentifierSubEditor;
break;
case 2: // 3G Settings
cellType = TableCellIdentifierYesNo;
break;
case 3: // 3G screen/color depth
cellType = TableCellIdentifierSelection;
break;
case 4: // 3G performance settings
cellType = TableCellIdentifierSubEditor;
break;
case 5: // security mode
cellType = TableCellIdentifierSelection;
break;
case 6: // remote program
case 7: // work dir
cellType = TableCellIdentifierText;
break;
case 8: // console mode
cellType = TableCellIdentifierYesNo;
break;
default:
break;
}
break;
}
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
}
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
// get the table view cell
UITableViewCell *cell = [self tableViewCellFromIdentifier:cellType];
NSAssert(cell, @"Invalid cell");
NSAssert(cell, @"Invalid cell");
// set cell values
switch([indexPath section])
switch ([indexPath section])
{
// advanced settings
// advanced settings
case SECTION_ADVANCED_SETTINGS:
[self initAdvancedSettings:indexPath cell:cell];
break;
default:
break;
}
return cell;
}
return cell;
}
// updates advanced settings in the UI
- (void)initAdvancedSettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initAdvancedSettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
BOOL enable_3G_settings = [_params boolForKey:@"enable_3g_settings"];
switch(indexPath.row)
BOOL enable_3G_settings = [_params boolForKey:@"enable_3g_settings"];
switch (indexPath.row)
{
case 0:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Enable TS Gateway", @"'Enable TS Gateway': Bookmark enable TSG settings")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[_params boolForKey:@"enable_tsg_settings"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
case 1:
{
BOOL enable_tsg_settings = [_params boolForKey:@"enable_tsg_settings"];
EditSubEditTableViewCell* editCell = (EditSubEditTableViewCell*)cell;
[[editCell label] setText:NSLocalizedString(@"TS Gateway Settings", @"'TS Gateway Settings': Bookmark TS Gateway Settings")];
[[editCell label] setEnabled:enable_tsg_settings];
[editCell setSelectionStyle:enable_tsg_settings ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label]
setText:NSLocalizedString(@"Enable TS Gateway",
@"'Enable TS Gateway': Bookmark enable TSG settings")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[_params boolForKey:@"enable_tsg_settings"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
case 1:
{
BOOL enable_tsg_settings = [_params boolForKey:@"enable_tsg_settings"];
EditSubEditTableViewCell *editCell = (EditSubEditTableViewCell *)cell;
[[editCell label]
setText:NSLocalizedString(@"TS Gateway Settings",
@"'TS Gateway Settings': Bookmark TS Gateway Settings")];
[[editCell label] setEnabled:enable_tsg_settings];
[editCell setSelectionStyle:enable_tsg_settings ? UITableViewCellSelectionStyleBlue
: UITableViewCellSelectionStyleNone];
break;
}
case 2:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"3G Settings", @"'3G Settings': Bookmark enable 3G settings")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[_params boolForKey:@"enable_3g_settings"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label]
setText:NSLocalizedString(@"3G Settings",
@"'3G Settings': Bookmark enable 3G settings")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[_params boolForKey:@"enable_3g_settings"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
case 3:
{
EditSelectionTableViewCell* selCell = (EditSelectionTableViewCell*)cell;
[[selCell label] setText:NSLocalizedString(@"3G Screen", @"'3G Screen': Bookmark 3G Screen settings")];
NSString* resolution = ScreenResolutionDescription([_params intForKeyPath:@"settings_3g.screen_resolution_type"], [_params intForKeyPath:@"settings_3g.width"], [_params intForKeyPath:@"settings_3g.height"]);
int colorBits = [_params intForKeyPath:@"settings_3g.colors"];
[[selCell selection] setText:[NSString stringWithFormat:@"%@@%d", resolution, colorBits]];
[[selCell label] setEnabled:enable_3G_settings];
[[selCell selection] setEnabled:enable_3G_settings];
[selCell setSelectionStyle:enable_3G_settings ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone];
break;
}
{
EditSelectionTableViewCell *selCell = (EditSelectionTableViewCell *)cell;
[[selCell label]
setText:NSLocalizedString(@"3G Screen",
@"'3G Screen': Bookmark 3G Screen settings")];
NSString *resolution = ScreenResolutionDescription(
[_params intForKeyPath:@"settings_3g.screen_resolution_type"],
[_params intForKeyPath:@"settings_3g.width"],
[_params intForKeyPath:@"settings_3g.height"]);
int colorBits = [_params intForKeyPath:@"settings_3g.colors"];
[[selCell selection]
setText:[NSString stringWithFormat:@"%@@%d", resolution, colorBits]];
[[selCell label] setEnabled:enable_3G_settings];
[[selCell selection] setEnabled:enable_3G_settings];
[selCell setSelectionStyle:enable_3G_settings ? UITableViewCellSelectionStyleBlue
: UITableViewCellSelectionStyleNone];
break;
}
case 4:
{
EditSubEditTableViewCell* editCell = (EditSubEditTableViewCell*)cell;
[[editCell label] setText:NSLocalizedString(@"3G Performance", @"'3G Performance': Bookmark 3G Performance Settings")];
[[editCell label] setEnabled:enable_3G_settings];
[editCell setSelectionStyle:enable_3G_settings ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone];
break;
}
{
EditSubEditTableViewCell *editCell = (EditSubEditTableViewCell *)cell;
[[editCell label]
setText:NSLocalizedString(@"3G Performance",
@"'3G Performance': Bookmark 3G Performance Settings")];
[[editCell label] setEnabled:enable_3G_settings];
[editCell setSelectionStyle:enable_3G_settings ? UITableViewCellSelectionStyleBlue
: UITableViewCellSelectionStyleNone];
break;
}
case 5:
{
EditSelectionTableViewCell* selCell = (EditSelectionTableViewCell*)cell;
[[selCell label] setText:NSLocalizedString(@"Security", @"'Security': Bookmark protocl security settings")];
[[selCell selection] setText:ProtocolSecurityDescription([_params intForKey:@"security"])];
break;
}
{
EditSelectionTableViewCell *selCell = (EditSelectionTableViewCell *)cell;
[[selCell label]
setText:NSLocalizedString(@"Security",
@"'Security': Bookmark protocl security settings")];
[[selCell selection]
setText:ProtocolSecurityDescription([_params intForKey:@"security"])];
break;
}
case 6:
{
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
[[textCell label] setText:NSLocalizedString(@"Remote Program", @"'Remote Program': Bookmark remote program settings")];
[[textCell textfield] setText:[_params StringForKey:@"remote_program"]];
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[self adjustEditTextTableViewCell:textCell];
break;
}
{
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell label]
setText:NSLocalizedString(@"Remote Program",
@"'Remote Program': Bookmark remote program settings")];
[[textCell textfield] setText:[_params StringForKey:@"remote_program"]];
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[self adjustEditTextTableViewCell:textCell];
break;
}
case 7:
{
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
[[textCell label] setText:NSLocalizedString(@"Working Directory", @"'Working Directory': Bookmark working directory settings")];
[[textCell textfield] setText:[_params StringForKey:@"working_dir"]];
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[self adjustEditTextTableViewCell:textCell];
break;
}
{
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell label]
setText:NSLocalizedString(
@"Working Directory",
@"'Working Directory': Bookmark working directory settings")];
[[textCell textfield] setText:[_params StringForKey:@"working_dir"]];
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[self adjustEditTextTableViewCell:textCell];
break;
}
case 8:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Console Mode", @"'Console Mode': Bookmark console mode settings")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[_params boolForKey:@"console"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label]
setText:NSLocalizedString(@"Console Mode",
@"'Console Mode': Bookmark console mode settings")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[_params boolForKey:@"console"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
default:
NSLog(@"Invalid row index in settings table!");
break;
}
}
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController* viewCtrl = nil;
// determine view
switch ([indexPath row])
{
case 1:
if ([_params boolForKey:@"enable_tsg_settings"])
viewCtrl = [[[BookmarkGatewaySettingsController alloc] initWithBookmark:_bookmark] autorelease];
break;
case 3:
if ([_params boolForKey:@"enable_3g_settings"])
viewCtrl = [[[ScreenSelectionController alloc] initWithConnectionParams:_params keyPath:@"settings_3g"] autorelease];
break;
case 4:
if ([_params boolForKey:@"enable_3g_settings"])
viewCtrl = [[[PerformanceEditorController alloc] initWithConnectionParams:_params keyPath:@"settings_3g"] autorelease];
break;
case 5:
viewCtrl = [[[EditorSelectionController alloc] initWithConnectionParams:_params entries:[NSArray arrayWithObject:@"security"] selections:[NSArray arrayWithObject:SelectionForSecuritySetting()]] autorelease];
break;
default:
break;
}
// display view
if(viewCtrl)
[[self navigationController] pushViewController:viewCtrl animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *viewCtrl = nil;
// determine view
switch ([indexPath row])
{
case 1:
if ([_params boolForKey:@"enable_tsg_settings"])
viewCtrl = [[[BookmarkGatewaySettingsController alloc] initWithBookmark:_bookmark]
autorelease];
break;
case 3:
if ([_params boolForKey:@"enable_3g_settings"])
viewCtrl = [[[ScreenSelectionController alloc]
initWithConnectionParams:_params
keyPath:@"settings_3g"] autorelease];
break;
case 4:
if ([_params boolForKey:@"enable_3g_settings"])
viewCtrl = [[[PerformanceEditorController alloc]
initWithConnectionParams:_params
keyPath:@"settings_3g"] autorelease];
break;
case 5:
viewCtrl = [[[EditorSelectionController alloc]
initWithConnectionParams:_params
entries:[NSArray arrayWithObject:@"security"]
selections:[NSArray arrayWithObject:SelectionForSecuritySetting()]]
autorelease];
break;
default:
break;
}
// display view
if (viewCtrl)
[[self navigationController] pushViewController:viewCtrl animated:YES];
}
#pragma mark -
#pragma mark Text Field delegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
@@ -293,21 +339,21 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
switch(textField.tag)
switch (textField.tag)
{
// update remote program/work dir settings
case GET_TAG(SECTION_ADVANCED_SETTINGS, 6):
{
[_params setValue:[textField text] forKey:@"remote_program"];
break;
}
case GET_TAG(SECTION_ADVANCED_SETTINGS, 7):
{
[_params setValue:[textField text] forKey:@"working_dir"];
break;
}
// update remote program/work dir settings
case GET_TAG(SECTION_ADVANCED_SETTINGS, 6):
{
[_params setValue:[textField text] forKey:@"remote_program"];
break;
}
case GET_TAG(SECTION_ADVANCED_SETTINGS, 7):
{
[_params setValue:[textField text] forKey:@"working_dir"];
break;
}
default:
break;
}
@@ -318,32 +364,44 @@
- (void)toggleSettingValue:(id)sender
{
UISwitch* valueSwitch = (UISwitch*)sender;
switch(valueSwitch.tag)
{
case GET_TAG(SECTION_ADVANCED_SETTINGS, 0):
{
[_params setBool:[valueSwitch isOn] forKey:@"enable_tsg_settings"];
NSArray* indexPaths = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:1 inSection:SECTION_ADVANCED_SETTINGS], [NSIndexPath indexPathForRow:2 inSection:SECTION_ADVANCED_SETTINGS], nil];
[[self tableView] reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
break;
}
UISwitch *valueSwitch = (UISwitch *)sender;
switch (valueSwitch.tag)
{
case GET_TAG(SECTION_ADVANCED_SETTINGS, 0):
{
[_params setBool:[valueSwitch isOn] forKey:@"enable_tsg_settings"];
NSArray *indexPaths =
[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:1
inSection:SECTION_ADVANCED_SETTINGS],
[NSIndexPath indexPathForRow:2
inSection:SECTION_ADVANCED_SETTINGS],
nil];
[[self tableView] reloadRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationNone];
break;
}
case GET_TAG(SECTION_ADVANCED_SETTINGS, 2):
{
[_params setBool:[valueSwitch isOn] forKey:@"enable_3g_settings"];
NSArray* indexPaths = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:SECTION_ADVANCED_SETTINGS], [NSIndexPath indexPathForRow:2 inSection:SECTION_ADVANCED_SETTINGS], nil];
[[self tableView] reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
break;
}
case GET_TAG(SECTION_ADVANCED_SETTINGS, 8):
[_params setBool:[valueSwitch isOn] forKey:@"console"];
break;
default:
break;
}
case GET_TAG(SECTION_ADVANCED_SETTINGS, 2):
{
[_params setBool:[valueSwitch isOn] forKey:@"enable_3g_settings"];
NSArray *indexPaths =
[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3
inSection:SECTION_ADVANCED_SETTINGS],
[NSIndexPath indexPathForRow:2
inSection:SECTION_ADVANCED_SETTINGS],
nil];
[[self tableView] reloadRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationNone];
break;
}
case GET_TAG(SECTION_ADVANCED_SETTINGS, 8):
[_params setBool:[valueSwitch isOn] forKey:@"console"];
break;
default:
break;
}
}
@end

View File

@@ -1,10 +1,11 @@
/*
Controller to specify application wide settings
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"

View File

@@ -1,10 +1,11 @@
/*
Controller to specify application wide settings
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "AppSettingsController.h"
@@ -21,195 +22,224 @@
#pragma mark -
#pragma mark Initialization
- (id)initWithStyle:(UITableViewStyle)style
{
if ((self = [super initWithStyle:style]))
{
UIImage* tabBarIcon = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tabbar_icon_settings" ofType:@"png"]];
[self setTabBarItem:[[[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"Settings", @"Tabbar item settings") image:tabBarIcon tag:0] autorelease]];
}
return self;
if ((self = [super initWithStyle:style]))
{
UIImage *tabBarIcon = [UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tabbar_icon_settings"
ofType:@"png"]];
[self
setTabBarItem:[[[UITabBarItem alloc]
initWithTitle:NSLocalizedString(@"Settings", @"Tabbar item settings")
image:tabBarIcon
tag:0] autorelease]];
}
return self;
}
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
- (void)viewDidLoad
{
[super viewDidLoad];
// set title
[self setTitle:NSLocalizedString(@"Settings", @"App Settings title")];
// set title
[self setTitle:NSLocalizedString(@"Settings", @"App Settings title")];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return SECTION_NUM_SECTIONS;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return SECTION_NUM_SECTIONS;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
switch (section)
{
case SECTION_UI_SETTINGS: // UI settings
return 5;
case SECTION_CERTIFICATE_HANDLING_SETTINGS: // certificate handling settings
return 2;
case SECTION_UI_SETTINGS: // UI settings
return 5;
case SECTION_CERTIFICATE_HANDLING_SETTINGS: // certificate handling settings
return 2;
default:
break;
}
return 0;
}
return 0;
}
// set section headers
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch(section)
switch (section)
{
case SECTION_UI_SETTINGS:
case SECTION_UI_SETTINGS:
return NSLocalizedString(@"User Interface", @"UI settings section title");
case SECTION_CERTIFICATE_HANDLING_SETTINGS:
return NSLocalizedString(@"Server Certificate Handling", @"Server Certificate Handling section title");
default:
case SECTION_CERTIFICATE_HANDLING_SETTINGS:
return NSLocalizedString(@"Server Certificate Handling",
@"Server Certificate Handling section title");
default:
return nil;
}
return @"unknown";
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the required cell type
NSString* cellIdentifier = nil;
switch([indexPath section])
NSString *cellIdentifier = nil;
switch ([indexPath section])
{
case SECTION_UI_SETTINGS:
{
switch([indexPath row])
{
case 0:
case 1:
case 2:
case 3:
case 4:
cellIdentifier = TableCellIdentifierYesNo;
break;
}
break;
}
case SECTION_CERTIFICATE_HANDLING_SETTINGS:
{
switch([indexPath row])
{
case 0:
cellIdentifier = TableCellIdentifierYesNo;
break;
case 1:
cellIdentifier = TableCellIdentifierSubEditor;
break;
}
break;
}
}
NSAssert(cellIdentifier != nil, @"Couldn't determine cell type");
case SECTION_UI_SETTINGS:
{
switch ([indexPath row])
{
case 0:
case 1:
case 2:
case 3:
case 4:
cellIdentifier = TableCellIdentifierYesNo;
break;
}
break;
}
case SECTION_CERTIFICATE_HANDLING_SETTINGS:
{
switch ([indexPath row])
{
case 0:
cellIdentifier = TableCellIdentifierYesNo;
break;
case 1:
cellIdentifier = TableCellIdentifierSubEditor;
break;
}
break;
}
}
NSAssert(cellIdentifier != nil, @"Couldn't determine cell type");
// get the table view cell
UITableViewCell *cell = [self tableViewCellFromIdentifier:cellIdentifier];
NSAssert(cell, @"Invalid cell");
NSAssert(cell, @"Invalid cell");
// set cell values
switch([indexPath section])
{
case SECTION_UI_SETTINGS:
[self initUISettings:indexPath cell:cell];
break;
case SECTION_CERTIFICATE_HANDLING_SETTINGS:
[self initCertificateHandlingSettings:indexPath cell:cell];
break;
switch ([indexPath section])
{
case SECTION_UI_SETTINGS:
[self initUISettings:indexPath cell:cell];
break;
case SECTION_CERTIFICATE_HANDLING_SETTINGS:
[self initCertificateHandlingSettings:indexPath cell:cell];
break;
default:
break;
}
return cell;
}
return cell;
}
#pragma mark - Initialization helpers
// updates UI settings in the UI
- (void)initUISettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initUISettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
switch([indexPath row])
switch ([indexPath row])
{
case 0:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Hide Status Bar", "Show/Hide Phone Status Bar setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_status_bar"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
case 1:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Hide Tool Bar", "Show/Hide Tool Bar setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_tool_bar"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label] setText:NSLocalizedString(@"Hide Status Bar",
"Show/Hide Phone Status Bar setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle]
setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_status_bar"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
}
case 1:
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label]
setText:NSLocalizedString(@"Hide Tool Bar", "Show/Hide Tool Bar setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle]
setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_tool_bar"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
case 2:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Swap Mouse Buttons", "Swap Mouse Button UI setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.swap_mouse_buttons"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label]
setText:NSLocalizedString(@"Swap Mouse Buttons", "Swap Mouse Button UI setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle]
setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.swap_mouse_buttons"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
case 3:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Invert Scrolling", "Invert Scrolling UI setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.invert_scrolling"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label]
setText:NSLocalizedString(@"Invert Scrolling", "Invert Scrolling UI setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle]
setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.invert_scrolling"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
case 4:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Touch Pointer Auto Scroll", "Touch Pointer Auto Scroll UI setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"ui.auto_scroll_touchpointer"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label] setText:NSLocalizedString(@"Touch Pointer Auto Scroll",
"Touch Pointer Auto Scroll UI setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults]
boolForKey:@"ui.auto_scroll_touchpointer"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
default:
NSLog(@"Invalid row index in settings table!");
break;
@@ -217,25 +247,30 @@
}
// updates certificate handling settings in the UI
- (void)initCertificateHandlingSettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initCertificateHandlingSettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
switch([indexPath row])
switch ([indexPath row])
{
case 0:
{
EditFlagTableViewCell* flagCell = (EditFlagTableViewCell*)cell;
[[flagCell label] setText:NSLocalizedString(@"Accept all Certificates", "Accept All Certificates setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"]];
[[flagCell toggle] addTarget:self action:@selector(toggleSettingValue:) forControlEvents:UIControlEventValueChanged];
break;
}
{
EditFlagTableViewCell *flagCell = (EditFlagTableViewCell *)cell;
[[flagCell label] setText:NSLocalizedString(@"Accept all Certificates",
"Accept All Certificates setting")];
[[flagCell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[flagCell toggle] setOn:[[NSUserDefaults standardUserDefaults]
boolForKey:@"security.accept_certificates"]];
[[flagCell toggle] addTarget:self
action:@selector(toggleSettingValue:)
forControlEvents:UIControlEventValueChanged];
break;
}
case 1:
{
EditSubEditTableViewCell* subCell = (EditSubEditTableViewCell*)cell;
[[subCell label] setText:NSLocalizedString(@"Erase Certificate Cache", @"Erase certificate cache button")];
break;
}
{
EditSubEditTableViewCell *subCell = (EditSubEditTableViewCell *)cell;
[[subCell label] setText:NSLocalizedString(@"Erase Certificate Cache",
@"Erase certificate cache button")];
break;
}
default:
NSLog(@"Invalid row index in settings table!");
break;
@@ -245,24 +280,35 @@
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// deselect any row to fake a button-pressed like effect
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// deselect any row to fake a button-pressed like effect
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// ensure everything is stored in our settings before we proceed
[[self view] endEditing:NO];
// clear certificate cache
if([indexPath section] == SECTION_CERTIFICATE_HANDLING_SETTINGS && [indexPath row] == 1)
{
// delete certificates cache
NSError* err;
if ([[NSFileManager defaultManager] removeItemAtPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"/.freerdp"] error:&err])
[[self view] makeToast:NSLocalizedString(@"Certificate Cache cleared!", @"Clear Certificate cache success message") duration:ToastDurationNormal position:@"center"];
else
[[self view] makeToast:NSLocalizedString(@"Error clearing the Certificate Cache!", @"Clear Certificate cache failed message") duration:ToastDurationNormal position:@"center"];
}
// ensure everything is stored in our settings before we proceed
[[self view] endEditing:NO];
// clear certificate cache
if ([indexPath section] == SECTION_CERTIFICATE_HANDLING_SETTINGS && [indexPath row] == 1)
{
// delete certificates cache
NSError *err;
if ([[NSFileManager defaultManager]
removeItemAtPath:[[NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:@"/.freerdp"]
error:&err])
[[self view] makeToast:NSLocalizedString(@"Certificate Cache cleared!",
@"Clear Certificate cache success message")
duration:ToastDurationNormal
position:@"center"];
else
[[self view] makeToast:NSLocalizedString(@"Error clearing the Certificate Cache!",
@"Clear Certificate cache failed message")
duration:ToastDurationNormal
position:@"center"];
}
}
#pragma mark -
@@ -270,40 +316,45 @@
- (void)toggleSettingValue:(id)sender
{
UISwitch* valueSwitch = (UISwitch*)sender;
switch([valueSwitch tag])
{
case GET_TAG(SECTION_UI_SETTINGS, 0):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn] forKey:@"ui.hide_status_bar"];
break;
UISwitch *valueSwitch = (UISwitch *)sender;
switch ([valueSwitch tag])
{
case GET_TAG(SECTION_UI_SETTINGS, 0):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn]
forKey:@"ui.hide_status_bar"];
break;
case GET_TAG(SECTION_UI_SETTINGS, 1):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn] forKey:@"ui.hide_tool_bar"];
break;
case GET_TAG(SECTION_UI_SETTINGS, 1):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn]
forKey:@"ui.hide_tool_bar"];
break;
case GET_TAG(SECTION_UI_SETTINGS, 2):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn] forKey:@"ui.swap_mouse_buttons"];
SetSwapMouseButtonsFlag([valueSwitch isOn]);
break;
case GET_TAG(SECTION_UI_SETTINGS, 2):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn]
forKey:@"ui.swap_mouse_buttons"];
SetSwapMouseButtonsFlag([valueSwitch isOn]);
break;
case GET_TAG(SECTION_UI_SETTINGS, 3):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn] forKey:@"ui.invert_scrolling"];
SetInvertScrollingFlag([valueSwitch isOn]);
break;
case GET_TAG(SECTION_UI_SETTINGS, 3):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn]
forKey:@"ui.invert_scrolling"];
SetInvertScrollingFlag([valueSwitch isOn]);
break;
case GET_TAG(SECTION_UI_SETTINGS, 4):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn] forKey:@"ui.auto_scroll_touchpointer"];
SetInvertScrollingFlag([valueSwitch isOn]);
break;
case GET_TAG(SECTION_UI_SETTINGS, 4):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn]
forKey:@"ui.auto_scroll_touchpointer"];
SetInvertScrollingFlag([valueSwitch isOn]);
break;
case GET_TAG(SECTION_CERTIFICATE_HANDLING_SETTINGS, 0):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn] forKey:@"security.accept_certificates"];
break;
default:
break;
}
case GET_TAG(SECTION_CERTIFICATE_HANDLING_SETTINGS, 0):
[[NSUserDefaults standardUserDefaults] setBool:[valueSwitch isOn]
forKey:@"security.accept_certificates"];
break;
default:
break;
}
}
@end

View File

@@ -1,12 +1,12 @@
/*
Bookmark editor controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
#import "EditorBaseController.h"
@@ -14,27 +14,25 @@
@class ComputerBookmark;
@class ConnectionParams;
@protocol BookmarkEditorDelegate <NSObject>
// bookmark editing finsihed
- (void)commitBookmark:(ComputerBookmark*)bookmark;
- (void)commitBookmark:(ComputerBookmark *)bookmark;
@end
@interface BookmarkEditorController : EditorBaseController
{
@private
ComputerBookmark* _bookmark;
ConnectionParams* _params;
BOOL _display_server_settings;
id<BookmarkEditorDelegate> delegate;
@private
ComputerBookmark *_bookmark;
ConnectionParams *_params;
BOOL _display_server_settings;
id<BookmarkEditorDelegate> delegate;
}
@property (nonatomic, assign) id<BookmarkEditorDelegate> delegate;
@property(nonatomic, assign) id<BookmarkEditorDelegate> delegate;
// init for the given bookmark
- (id)initWithBookmark:(ComputerBookmark*)bookmark;
- (id)initWithBookmark:(ComputerBookmark *)bookmark;
@end

View File

@@ -1,10 +1,11 @@
/*
Bookmark editor controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "BookmarkEditorController.h"
@@ -26,63 +27,74 @@
#define SECTION_COUNT 3
#pragma mark -
#pragma mark Initialization
#pragma mark Initialization
- (id)initWithBookmark:(ComputerBookmark*)bookmark
- (id)initWithBookmark:(ComputerBookmark *)bookmark
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
// set additional settings state according to bookmark data
if ([[bookmark uuid] length] == 0)
_bookmark = [bookmark copy];
else
_bookmark = [bookmark copyWithUUID];
_params = [_bookmark params];
if ([[bookmark uuid] length] == 0)
_bookmark = [bookmark copy];
else
_bookmark = [bookmark copyWithUUID];
_params = [_bookmark params];
_display_server_settings = YES;
}
return self;
_display_server_settings = YES;
}
return self;
}
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
- (void)viewDidLoad {
[super viewDidLoad];
// replace back button with a custom handler that checks if the required bookmark settings were specified
UIBarButtonItem* saveButton = [[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save", @"Save Button title") style:UIBarButtonItemStyleDone target:self action:@selector(handleSave:)] autorelease];
UIBarButtonItem* cancelButton = [[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", @"Cancel Button title") style:UIBarButtonItemStyleBordered target:self action:@selector(handleCancel:)] autorelease];
[[self navigationItem] setLeftBarButtonItem:cancelButton];
[[self navigationItem] setRightBarButtonItem:saveButton];
// replace back button with a custom handler that checks if the required bookmark settings were
// specified
UIBarButtonItem *saveButton =
[[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save", @"Save Button title")
style:UIBarButtonItemStyleDone
target:self
action:@selector(handleSave:)] autorelease];
UIBarButtonItem *cancelButton =
[[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", @"Cancel Button title")
style:UIBarButtonItemStyleBordered
target:self
action:@selector(handleCancel:)] autorelease];
[[self navigationItem] setLeftBarButtonItem:cancelButton];
[[self navigationItem] setRightBarButtonItem:saveButton];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// we need to reload the table view data here to have up-to-date data for the
// advanced settings accessory items (like for resolution/color mode settings)
[[self tableView] reloadData];
// we need to reload the table view data here to have up-to-date data for the
// advanced settings accessory items (like for resolution/color mode settings)
[[self tableView] reloadData];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return SECTION_COUNT;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return SECTION_COUNT;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
switch (section)
{
case SECTION_SERVER: // server settings
@@ -94,18 +106,19 @@
default:
break;
}
return 0;
}
return 0;
}
// set section headers
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch(section)
switch (section)
{
case SECTION_SERVER:
return (_display_server_settings ? NSLocalizedString(@"Host", @"'Host': host settings header") : nil);
return (_display_server_settings
? NSLocalizedString(@"Host", @"'Host': host settings header")
: nil);
case SECTION_CREDENTIALS:
return NSLocalizedString(@"Credentials", @"'Credentials': credentials settings header");
case SECTION_SETTINGS:
@@ -114,56 +127,57 @@
return @"unknown";
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the required cell type
NSString* cellType = nil;
switch([indexPath section])
NSString *cellType = nil;
switch ([indexPath section])
{
case SECTION_SERVER:
cellType = TableCellIdentifierText;
cellType = TableCellIdentifierText;
break;
case SECTION_CREDENTIALS:
cellType = TableCellIdentifierSelection;
break;
case SECTION_SETTINGS: // settings
{
switch([indexPath row])
{
case 0: // screen/color depth
cellType = TableCellIdentifierSelection;
break;
case 1: // performance settings
case 2: // advanced settings
cellType = TableCellIdentifierSubEditor;
break;
default:
break;
}
}
break;
case SECTION_CREDENTIALS:
cellType = TableCellIdentifierSelection;
break;
case SECTION_SETTINGS: // settings
{
switch ([indexPath row])
{
case 0: // screen/color depth
cellType = TableCellIdentifierSelection;
break;
case 1: // performance settings
case 2: // advanced settings
cellType = TableCellIdentifierSubEditor;
break;
default:
break;
}
}
break;
default:
break;
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
default:
break;
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
// get the table view cell
UITableViewCell *cell = [self tableViewCellFromIdentifier:cellType];
NSAssert(cell, @"Invalid cell");
NSAssert(cell, @"Invalid cell");
// set cell values
switch([indexPath section])
switch ([indexPath section])
{
// server settings
case SECTION_SERVER:
[self initServerSettings:indexPath cell:cell];
break;
// credentials
case SECTION_CREDENTIALS:
[self initCredentialSettings:indexPath cell:cell];
@@ -176,50 +190,54 @@
default:
break;
}
return cell;
}
return cell;
}
// updates server settings in the UI
- (void)initServerSettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initServerSettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
switch([indexPath row])
switch ([indexPath row])
{
case 0:
[[textCell label] setText:NSLocalizedString(@"Label", @"'Label': Bookmark label")];
[[textCell textfield] setText:[_bookmark label]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
case 1:
[[textCell label] setText:NSLocalizedString(@"Host", @"'Host': Bookmark hostname")];
[[textCell textfield] setText:[_params StringForKey:@"hostname"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
case 2:
[[textCell label] setText:NSLocalizedString(@"Port", @"'Port': Bookmark port")];
[[textCell textfield] setText:[NSString stringWithFormat:@"%d", [_params intForKey:@"port"]]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
[[textCell textfield]
setText:[NSString stringWithFormat:@"%d", [_params intForKey:@"port"]]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
break;
default:
NSLog(@"Invalid row index in settings table!");
break;
}
}
[self adjustEditTextTableViewCell:textCell];
[self adjustEditTextTableViewCell:textCell];
}
// updates credentials in the UI
- (void)initCredentialSettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initCredentialSettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
EditSelectionTableViewCell* selCell = (EditSelectionTableViewCell*)cell;
switch(indexPath.row)
EditSelectionTableViewCell *selCell = (EditSelectionTableViewCell *)cell;
switch (indexPath.row)
{
case 0:
[[selCell label] setText:NSLocalizedString(@"Credentials", @"'Credentials': Bookmark credentials")];
[[selCell selection] setText:[_params StringForKey:@"username"]];
[[selCell label]
setText:NSLocalizedString(@"Credentials", @"'Credentials': Bookmark credentials")];
[[selCell selection] setText:[_params StringForKey:@"username"]];
break;
default:
NSLog(@"Invalid row index in settings table!");
@@ -228,85 +246,95 @@
}
// updates session settings in the UI
- (void)initSettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
{
switch(indexPath.row)
- (void)initSettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
switch (indexPath.row)
{
case 0:
{
EditSelectionTableViewCell* selCell = (EditSelectionTableViewCell*)cell;
[[selCell label] setText:NSLocalizedString(@"Screen", @"'Screen': Bookmark Screen settings")];
NSString* resolution = ScreenResolutionDescription([_params intForKey:@"screen_resolution_type"], [_params intForKey:@"width"], [_params intForKey:@"height"]);
int colorBits = [_params intForKey:@"colors"];
[[selCell selection] setText:[NSString stringWithFormat:@"%@@%d", resolution, colorBits]];
break;
}
{
EditSelectionTableViewCell *selCell = (EditSelectionTableViewCell *)cell;
[[selCell label]
setText:NSLocalizedString(@"Screen", @"'Screen': Bookmark Screen settings")];
NSString *resolution = ScreenResolutionDescription(
[_params intForKey:@"screen_resolution_type"], [_params intForKey:@"width"],
[_params intForKey:@"height"]);
int colorBits = [_params intForKey:@"colors"];
[[selCell selection]
setText:[NSString stringWithFormat:@"%@@%d", resolution, colorBits]];
break;
}
case 1:
{
EditSubEditTableViewCell* editCell = (EditSubEditTableViewCell*)cell;
[[editCell label] setText:NSLocalizedString(@"Performance", @"'Performance': Bookmark Performance Settings")];
break;
}
{
EditSubEditTableViewCell *editCell = (EditSubEditTableViewCell *)cell;
[[editCell label]
setText:NSLocalizedString(@"Performance",
@"'Performance': Bookmark Performance Settings")];
break;
}
case 2:
{
EditSubEditTableViewCell* editCell = (EditSubEditTableViewCell*)cell;
[[editCell label] setText:NSLocalizedString(@"Advanced", @"'Advanced': Bookmark Advanced Settings")];
break;
}
{
EditSubEditTableViewCell *editCell = (EditSubEditTableViewCell *)cell;
[[editCell label]
setText:NSLocalizedString(@"Advanced", @"'Advanced': Bookmark Advanced Settings")];
break;
}
default:
NSLog(@"Invalid row index in settings table!");
break;
}
}
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController* viewCtrl = nil;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *viewCtrl = nil;
// determine view
switch([indexPath section])
{
case SECTION_CREDENTIALS:
{
if ([indexPath row] == 0)
viewCtrl = [[[CredentialsEditorController alloc] initWithBookmark:_bookmark] autorelease];
break;
}
case SECTION_SETTINGS:
{
switch ([indexPath row])
{
case 0:
viewCtrl = [[[ScreenSelectionController alloc] initWithConnectionParams:_params] autorelease];
break;
case 1:
viewCtrl = [[[PerformanceEditorController alloc] initWithConnectionParams:_params] autorelease];
break;
case 2:
viewCtrl = [[[AdvancedBookmarkEditorController alloc] initWithBookmark:_bookmark] autorelease];
break;
default:
break;
}
break;
}
}
// determine view
switch ([indexPath section])
{
case SECTION_CREDENTIALS:
{
if ([indexPath row] == 0)
viewCtrl =
[[[CredentialsEditorController alloc] initWithBookmark:_bookmark] autorelease];
break;
}
// display view
if(viewCtrl)
[[self navigationController] pushViewController:viewCtrl animated:YES];
case SECTION_SETTINGS:
{
switch ([indexPath row])
{
case 0:
viewCtrl = [[[ScreenSelectionController alloc] initWithConnectionParams:_params]
autorelease];
break;
case 1:
viewCtrl = [[[PerformanceEditorController alloc]
initWithConnectionParams:_params] autorelease];
break;
case 2:
viewCtrl = [[[AdvancedBookmarkEditorController alloc]
initWithBookmark:_bookmark] autorelease];
break;
default:
break;
}
break;
}
}
// display view
if (viewCtrl)
[[self navigationController] pushViewController:viewCtrl animated:YES];
}
#pragma mark -
#pragma mark Text Field delegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
@@ -314,7 +342,7 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
switch(textField.tag)
switch (textField.tag)
{
// update server settings
case GET_TAG(SECTION_SERVER, 0):
@@ -328,7 +356,7 @@
case GET_TAG(SECTION_SERVER, 2):
[_params setInt:[[textField text] intValue] forKey:@"port"];
break;
default:
break;
}
@@ -340,51 +368,60 @@
- (void)handleSave:(id)sender
{
// resign any first responder (so that we finish editing any bookmark parameter that might be currently edited)
[[self view] endEditing:NO];
// verify that bookmark is complete (only for manual bookmarks)
if ([[_bookmark label] length] == 0 || [[_params StringForKey:@"hostname"] length] == 0 || [_params intForKey:@"port"] == 0)
{
BlockAlertView* alertView = [BlockAlertView alertWithTitle:NSLocalizedString(@"Cancel without saving?", @"Incomplete bookmark error title") message:NSLocalizedString(@"Press 'Cancel' to abort!\nPress 'Continue' to specify the required fields!", @"Incomplete bookmark error message")];
[alertView setCancelButtonWithTitle:NSLocalizedString(@"Cancel", @"Cancel Button") block:^{
// cancel bookmark editing and return to previous view controller
[[self navigationController] popViewControllerAnimated:YES];
}];
[alertView addButtonWithTitle:NSLocalizedString(@"Continue", @"Continue Button") block:nil];
[alertView show];
return;
}
// commit bookmark
if ([[self delegate] respondsToSelector:@selector(commitBookmark:)])
[[self delegate] commitBookmark:_bookmark];
// return to previous view controller
[[self navigationController] popViewControllerAnimated:YES];
// resign any first responder (so that we finish editing any bookmark parameter that might be
// currently edited)
[[self view] endEditing:NO];
// verify that bookmark is complete (only for manual bookmarks)
if ([[_bookmark label] length] == 0 || [[_params StringForKey:@"hostname"] length] == 0 ||
[_params intForKey:@"port"] == 0)
{
BlockAlertView *alertView = [BlockAlertView
alertWithTitle:NSLocalizedString(@"Cancel without saving?",
@"Incomplete bookmark error title")
message:NSLocalizedString(@"Press 'Cancel' to abort!\nPress 'Continue' to "
@"specify the required fields!",
@"Incomplete bookmark error message")];
[alertView
setCancelButtonWithTitle:NSLocalizedString(@"Cancel", @"Cancel Button")
block:^{
// cancel bookmark editing and return to previous view controller
[[self navigationController] popViewControllerAnimated:YES];
}];
[alertView addButtonWithTitle:NSLocalizedString(@"Continue", @"Continue Button") block:nil];
[alertView show];
return;
}
// commit bookmark
if ([[self delegate] respondsToSelector:@selector(commitBookmark:)])
[[self delegate] commitBookmark:_bookmark];
// return to previous view controller
[[self navigationController] popViewControllerAnimated:YES];
}
- (void)handleCancel:(id)sender
{
// return to previous view controller
[[self navigationController] popViewControllerAnimated:YES];
// return to previous view controller
[[self navigationController] popViewControllerAnimated:YES];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)dealloc {
[super dealloc];
[_bookmark autorelease];
- (void)dealloc
{
[super dealloc];
[_bookmark autorelease];
}
@end

View File

@@ -1,10 +1,11 @@
/*
Controller to edit ts gateway bookmark settings
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -14,12 +15,12 @@
@interface BookmarkGatewaySettingsController : EditorBaseController
{
@private
ComputerBookmark* _bookmark;
ConnectionParams* _params;
@private
ComputerBookmark *_bookmark;
ConnectionParams *_params;
}
// init for the given bookmark
- (id)initWithBookmark:(ComputerBookmark*)bookmark;
- (id)initWithBookmark:(ComputerBookmark *)bookmark;
@end

View File

@@ -20,54 +20,54 @@
@implementation BookmarkGatewaySettingsController
- (id)initWithBookmark:(ComputerBookmark*)bookmark
- (id)initWithBookmark:(ComputerBookmark *)bookmark
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
// set additional settings state according to bookmark data
_bookmark = [bookmark retain];
_params = [bookmark params];
}
return self;
_params = [bookmark params];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"TS Gateway Settings", @"TS Gateway Settings title")];
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"TS Gateway Settings", @"TS Gateway Settings title")];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// we need to reload the table view data here to have up-to-date data for the
// advanced settings accessory items (like for resolution/color mode settings)
[[self tableView] reloadData];
[super viewWillAppear:animated];
// we need to reload the table view data here to have up-to-date data for the
// advanced settings accessory items (like for resolution/color mode settings)
[[self tableView] reloadData];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
return YES;
}
- (void)dealloc
{
[super dealloc];
[_bookmark release];
[super dealloc];
[_bookmark release];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return SECTION_COUNT;
// Return the number of sections.
return SECTION_COUNT;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
// Return the number of rows in the section.
switch (section)
{
case SECTION_TSGATEWAY_SETTINGS: // ts gateway settings
@@ -75,14 +75,14 @@
default:
break;
}
return 0;
return 0;
}
// set section headers
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch(section)
switch (section)
{
case SECTION_TSGATEWAY_SETTINGS:
return NSLocalizedString(@"TS Gateway", @"'TS Gateway': ts gateway settings header");
@@ -90,112 +90,119 @@
return @"unknown";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the required cell type
NSString* cellType = nil;
switch([indexPath section])
NSString *cellType = nil;
switch ([indexPath section])
{
case SECTION_TSGATEWAY_SETTINGS: // advanced settings
{
switch([indexPath row])
{
case 0: // hostname
case 1: // port
case 2: // username
case 4: // domain
cellType = TableCellIdentifierText;
break;
case 3: // password
cellType = TableCellIdentifierSecretText;
break;
default:
break;
}
case SECTION_TSGATEWAY_SETTINGS: // advanced settings
{
switch ([indexPath row])
{
case 0: // hostname
case 1: // port
case 2: // username
case 4: // domain
cellType = TableCellIdentifierText;
break;
case 3: // password
cellType = TableCellIdentifierSecretText;
break;
default:
break;
}
break;
}
}
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
// get the table view cell
UITableViewCell *cell = [self tableViewCellFromIdentifier:cellType];
NSAssert(cell, @"Invalid cell");
// set cell values
switch([indexPath section])
switch ([indexPath section])
{
// advanced settings
// advanced settings
case SECTION_TSGATEWAY_SETTINGS:
[self initGatewaySettings:indexPath cell:cell];
break;
default:
break;
}
return cell;
return cell;
}
// updates server settings in the UI
- (void)initGatewaySettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initGatewaySettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
switch([indexPath row])
switch ([indexPath row])
{
case 0:
{
{
[[textCell label] setText:NSLocalizedString(@"Host", @"'Host': Bookmark hostname")];
[[textCell textfield] setText:[_params StringForKey:@"tsg_hostname"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
}
case 1:
{
int port = [_params intForKey:@"tsg_port"];
if (port == 0) port = 443;
{
int port = [_params intForKey:@"tsg_port"];
if (port == 0)
port = 443;
[[textCell label] setText:NSLocalizedString(@"Port", @"'Port': Bookmark port")];
[[textCell textfield] setText:[NSString stringWithFormat:@"%d", port]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
break;
}
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
break;
}
case 2:
{
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label] setText:NSLocalizedString(@"Username", @"'Username': Bookmark username")];
{
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label]
setText:NSLocalizedString(@"Username", @"'Username': Bookmark username")];
[[textCell textfield] setText:[_params StringForKey:@"tsg_username"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
}
case 3:
{
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label] setText:NSLocalizedString(@"Password", @"'Password': Bookmark password")];
{
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label]
setText:NSLocalizedString(@"Password", @"'Password': Bookmark password")];
[[textCell textfield] setText:[_params StringForKey:@"tsg_password"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
}
case 4:
{
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
{
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label] setText:NSLocalizedString(@"Domain", @"'Domain': Bookmark domain")];
[[textCell textfield] setText:[_params StringForKey:@"tsg_domain"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
}
default:
NSLog(@"Invalid row index in settings table!");
break;
}
[self adjustEditTextTableViewCell:textCell];
}
[self adjustEditTextTableViewCell:textCell];
}
#pragma mark -
#pragma mark Text Field delegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
@@ -203,34 +210,33 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
switch(textField.tag)
switch (textField.tag)
{
// update server settings
// update server settings
case GET_TAG(SECTION_TSGATEWAY_SETTINGS, 0):
[_params setValue:[textField text] forKey:@"tsg_hostname"];
break;
case GET_TAG(SECTION_TSGATEWAY_SETTINGS, 1):
[_params setInt:[[textField text] intValue] forKey:@"tsg_port"];
break;
case GET_TAG(SECTION_TSGATEWAY_SETTINGS, 2):
[_params setValue:[textField text] forKey:@"tsg_username"];
break;
case GET_TAG(SECTION_TSGATEWAY_SETTINGS, 3):
[_params setValue:[textField text] forKey:@"tsg_password"];
break;
case GET_TAG(SECTION_TSGATEWAY_SETTINGS, 4):
[_params setValue:[textField text] forKey:@"tsg_domain"];
break;
break;
default:
break;
}
return YES;
}
@end

View File

@@ -1,10 +1,11 @@
/*
bookmarks and active session view controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -14,41 +15,42 @@
#import "BookmarkEditorController.h"
#import "Reachability.h"
@interface BookmarkListController : UIViewController <UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource, BookmarkEditorDelegate>
{
@interface BookmarkListController : UIViewController <UISearchBarDelegate, UITableViewDelegate,
UITableViewDataSource, BookmarkEditorDelegate>
{
// custom bookmark and session table cells
BookmarkTableCell* _bmTableCell;
SessionTableCell* _sessTableCell;
BookmarkTableCell *_bmTableCell;
SessionTableCell *_sessTableCell;
// child views
UISearchBar* _searchBar;
UITableView* _tableView;
// array with search results (or nil if no search active)
NSMutableArray* _manual_search_result;
NSMutableArray* _history_search_result;
UISearchBar *_searchBar;
UITableView *_tableView;
// bookmark arrays
NSMutableArray* _manual_bookmarks;
// bookmark star images
UIImage* _star_on_img;
UIImage* _star_off_img;
// array with active sessions
NSMutableArray* _active_sessions;
// array with connection history entries
NSMutableArray* _connection_history;
// temporary bookmark when asking if the user wants to store a bookmark for a session initiated by a quick connect
ComputerBookmark* _temporary_bookmark;
// array with search results (or nil if no search active)
NSMutableArray *_manual_search_result;
NSMutableArray *_history_search_result;
// bookmark arrays
NSMutableArray *_manual_bookmarks;
// bookmark star images
UIImage *_star_on_img;
UIImage *_star_off_img;
// array with active sessions
NSMutableArray *_active_sessions;
// array with connection history entries
NSMutableArray *_connection_history;
// temporary bookmark when asking if the user wants to store a bookmark for a session initiated
// by a quick connect
ComputerBookmark *_temporary_bookmark;
}
@property (nonatomic, retain) IBOutlet UISearchBar* searchBar;
@property (nonatomic, retain) IBOutlet UITableView* tableView;
@property (nonatomic, retain) IBOutlet BookmarkTableCell* bmTableCell;
@property (nonatomic, retain) IBOutlet SessionTableCell* sessTableCell;
@property(nonatomic, retain) IBOutlet UISearchBar *searchBar;
@property(nonatomic, retain) IBOutlet UITableView *tableView;
@property(nonatomic, retain) IBOutlet BookmarkTableCell *bmTableCell;
@property(nonatomic, retain) IBOutlet SessionTableCell *sessTableCell;
@end

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,11 @@
/*
Controller to edit bookmark credentials
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -14,12 +15,12 @@
@interface CredentialsEditorController : EditorBaseController
{
@private
ComputerBookmark* _bookmark;
ConnectionParams* _params;
@private
ComputerBookmark *_bookmark;
ConnectionParams *_params;
}
// init for the given bookmark
- (id)initWithBookmark:(ComputerBookmark*)bookmark;
- (id)initWithBookmark:(ComputerBookmark *)bookmark;
@end

View File

@@ -1,10 +1,11 @@
/*
Controller to edit bookmark credentials
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "CredentialsEditorController.h"
@@ -20,59 +21,60 @@
@implementation CredentialsEditorController
- (id)initWithBookmark:(ComputerBookmark*)bookmark
- (id)initWithBookmark:(ComputerBookmark *)bookmark
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
// set additional settings state according to bookmark data
_bookmark = [bookmark retain];
_params = [bookmark params];
}
return self;
_params = [bookmark params];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"Credentials", @"Credentials title")];
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"Credentials", @"Credentials title")];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// foce any active editing to stop
[[self view] endEditing:NO];
[super viewWillDisappear:animated];
// foce any active editing to stop
[[self view] endEditing:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
return YES;
}
- (void)dealloc
{
[super dealloc];
[_bookmark release];
[super dealloc];
[_bookmark release];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return SECTION_COUNT;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return SECTION_COUNT;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
switch (section)
{
case SECTION_CREDENTIALS: // credentials
@@ -80,15 +82,14 @@
default:
break;
}
return 0;
}
return 0;
}
// set section headers
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch(section)
switch (section)
{
case SECTION_CREDENTIALS:
return NSLocalizedString(@"Credentials", @"'Credentials': credentials settings header");
@@ -96,88 +97,93 @@
return @"unknown";
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the required cell type
NSString* cellType = nil;
switch([indexPath section])
NSString *cellType = nil;
switch ([indexPath section])
{
case SECTION_CREDENTIALS: // credentials
if([indexPath row] == 1)
cellType = TableCellIdentifierSecretText; // password field
else
cellType = TableCellIdentifierText;
if ([indexPath row] == 1)
cellType = TableCellIdentifierSecretText; // password field
else
cellType = TableCellIdentifierText;
break;
default:
break;
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
// get the table view cell
UITableViewCell *cell = [self tableViewCellFromIdentifier:cellType];
NSAssert(cell, @"Invalid cell");
// set cell values
switch([indexPath section])
{
// credentials
case SECTION_CREDENTIALS:
[self initCredentialSettings:indexPath cell:cell];
break;
default:
break;
}
return cell;
}
NSAssert(cellType != nil, @"Couldn't determine cell type");
// get the table view cell
UITableViewCell *cell = [self tableViewCellFromIdentifier:cellType];
NSAssert(cell, @"Invalid cell");
// set cell values
switch ([indexPath section])
{
// credentials
case SECTION_CREDENTIALS:
[self initCredentialSettings:indexPath cell:cell];
break;
default:
break;
}
return cell;
}
// updates credentials in the UI
- (void)initCredentialSettings:(NSIndexPath*)indexPath cell:(UITableViewCell*)cell
- (void)initCredentialSettings:(NSIndexPath *)indexPath cell:(UITableViewCell *)cell
{
switch(indexPath.row)
switch (indexPath.row)
{
case 0:
{
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label] setText:NSLocalizedString(@"Username", @"'Username': Bookmark username")];
{
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label]
setText:NSLocalizedString(@"Username", @"'Username': Bookmark username")];
[[textCell textfield] setText:[_params StringForKey:@"username"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
case 1:
{
EditSecretTextTableViewCell* textCell = (EditSecretTextTableViewCell*)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label] setText:NSLocalizedString(@"Password", @"'Password': Bookmark password")];
[[textCell textfield] setText:[_params StringForKey:@"password"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
}
case 1:
{
EditSecretTextTableViewCell *textCell = (EditSecretTextTableViewCell *)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label]
setText:NSLocalizedString(@"Password", @"'Password': Bookmark password")];
[[textCell textfield] setText:[_params StringForKey:@"password"]];
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
case 2:
{
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
{
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell textfield] setTag:GET_TAG_FROM_PATH(indexPath)];
[[textCell label] setText:NSLocalizedString(@"Domain", @"'Domain': Bookmark domain")];
[[textCell textfield] setText:[_params StringForKey:@"domain"]];
[[textCell textfield] setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
[[textCell textfield]
setPlaceholder:NSLocalizedString(@"not set", @"not set placeholder")];
break;
}
default:
NSLog(@"Invalid row index in settings table!");
break;
}
}
}
#pragma mark -
#pragma mark Text Field delegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
@@ -185,13 +191,13 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
switch(textField.tag)
{
// update credentials settings
switch (textField.tag)
{
// update credentials settings
case GET_TAG(SECTION_CREDENTIALS, 0):
[_params setValue:[textField text] forKey:@"username"];
break;
case GET_TAG(SECTION_CREDENTIALS, 1):
[_params setValue:[textField text] forKey:@"password"];
break;
@@ -199,7 +205,7 @@
case GET_TAG(SECTION_CREDENTIALS, 2):
[_params setValue:[textField text] forKey:@"domain"];
break;
default:
break;
}

View File

@@ -1,10 +1,11 @@
/*
Credentials input controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -13,19 +14,22 @@
@interface CredentialsInputController : UIViewController
{
@private
IBOutlet UITextField* _textfield_username;
IBOutlet UITextField* _textfield_password;
IBOutlet UITextField* _textfield_domain;
IBOutlet UIButton* _btn_login;
IBOutlet UIButton* _btn_cancel;
IBOutlet UIScrollView* _scroll_view;
IBOutlet UILabel* _lbl_message;
RDPSession* _session;
NSMutableDictionary* _params;
@private
IBOutlet UITextField *_textfield_username;
IBOutlet UITextField *_textfield_password;
IBOutlet UITextField *_textfield_domain;
IBOutlet UIButton *_btn_login;
IBOutlet UIButton *_btn_cancel;
IBOutlet UIScrollView *_scroll_view;
IBOutlet UILabel *_lbl_message;
RDPSession *_session;
NSMutableDictionary *_params;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil session:(RDPSession*)session params:(NSMutableDictionary*)params;
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
session:(RDPSession *)session
params:(NSMutableDictionary *)params;
@end

View File

@@ -1,10 +1,11 @@
/*
Credentials input controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "CredentialsInputController.h"
@@ -13,121 +14,147 @@
@implementation CredentialsInputController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil session:(RDPSession *)session params:(NSMutableDictionary *)params
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
session:(RDPSession *)session
params:(NSMutableDictionary *)params
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_session = session;
_params = params;
[self setModalPresentationStyle:UIModalPresentationFormSheet];
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
_session = session;
_params = params;
[self setModalPresentationStyle:UIModalPresentationFormSheet];
// on iphone we have the problem that the buttons are hidden by the keyboard
// we solve this issue by registering keyboard notification handlers and adjusting the scrollview accordingly
if (IsPhone())
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
}
}
return self;
// on iphone we have the problem that the buttons are hidden by the keyboard
// we solve this issue by registering keyboard notification handlers and adjusting the
// scrollview accordingly
if (IsPhone())
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[super viewDidLoad];
// set localized strings
[_lbl_message setText:NSLocalizedString(@"Please provide the missing user information in order to proceed and login.", @"Credentials input view message")];
[_textfield_username setPlaceholder:NSLocalizedString(@"Username", @"Credentials Input Username hint")];
[_textfield_password setPlaceholder:NSLocalizedString(@"Password", @"Credentials Input Password hint")];
[_textfield_domain setPlaceholder:NSLocalizedString(@"Domain", @"Credentials Input Domain hint")];
[_btn_login setTitle:NSLocalizedString(@"Login", @"Login Button") forState:UIControlStateNormal];
[_btn_cancel setTitle:NSLocalizedString(@"Cancel", @"Cancel Button") forState:UIControlStateNormal];
// set localized strings
[_lbl_message
setText:NSLocalizedString(
@"Please provide the missing user information in order to proceed and login.",
@"Credentials input view message")];
[_textfield_username
setPlaceholder:NSLocalizedString(@"Username", @"Credentials Input Username hint")];
[_textfield_password
setPlaceholder:NSLocalizedString(@"Password", @"Credentials Input Password hint")];
[_textfield_domain
setPlaceholder:NSLocalizedString(@"Domain", @"Credentials Input Domain hint")];
[_btn_login setTitle:NSLocalizedString(@"Login", @"Login Button")
forState:UIControlStateNormal];
[_btn_cancel setTitle:NSLocalizedString(@"Cancel", @"Cancel Button")
forState:UIControlStateNormal];
// init scrollview content size
[_scroll_view setContentSize:[_scroll_view frame].size];
// set params in the view
[_textfield_username setText:[_params valueForKey:@"username"]];
[_textfield_password setText:[_params valueForKey:@"password"]];
[_textfield_domain setText:[_params valueForKey:@"domain"]];
// init scrollview content size
[_scroll_view setContentSize:[_scroll_view frame].size];
// set params in the view
[_textfield_username setText:[_params valueForKey:@"username"]];
[_textfield_password setText:[_params valueForKey:@"password"]];
[_textfield_domain setText:[_params valueForKey:@"domain"]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
[super viewDidUnload];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
// set signal
[[_session uiRequestCompleted] signal];
[super viewDidDisappear:animated];
// set signal
[[_session uiRequestCompleted] signal];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
return YES;
}
- (void)dealloc
{
[super dealloc];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark -
#pragma mark iOS Keyboard Notification Handlers
- (void)keyboardWillShow:(NSNotification *)notification
{
CGRect keyboardEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrame = [[self view] convertRect:keyboardEndFrame toView:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
{
CGRect keyboardEndFrame =
[[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrame = [[self view] convertRect:keyboardEndFrame toView:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo]
objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView
setAnimationDuration:[[[notification userInfo]
objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
CGRect frame = [_scroll_view frame];
frame.size.height -= keyboardFrame.size.height;
frame.size.height -= keyboardFrame.size.height;
[_scroll_view setFrame:frame];
[UIView commitAnimations];
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
CGRect keyboardEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrame = [[self view] convertRect:keyboardEndFrame toView:nil];
CGRect keyboardEndFrame =
[[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrame = [[self view] convertRect:keyboardEndFrame toView:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo]
objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView
setAnimationDuration:[[[notification userInfo]
objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
CGRect frame = [_scroll_view frame];
frame.size.height += keyboardFrame.size.height;
frame.size.height += keyboardFrame.size.height;
[_scroll_view setFrame:frame];
[UIView commitAnimations];
[UIView commitAnimations];
}
#pragma mark - Action handlers
- (IBAction)loginPressed:(id)sender
{
// read input back in
[_params setValue:[_textfield_username text] forKey:@"username"];
[_params setValue:[_textfield_password text] forKey:@"password"];
[_params setValue:[_textfield_domain text] forKey:@"domain"];
[_params setValue:[NSNumber numberWithBool:YES] forKey:@"result"];
// read input back in
[_params setValue:[_textfield_username text] forKey:@"username"];
[_params setValue:[_textfield_password text] forKey:@"password"];
[_params setValue:[_textfield_domain text] forKey:@"domain"];
[_params setValue:[NSNumber numberWithBool:YES] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)cancelPressed:(id)sender
{
[_params setValue:[NSNumber numberWithBool:NO] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
[_params setValue:[NSNumber numberWithBool:NO] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
}
@end

View File

@@ -1,12 +1,12 @@
/*
Basic interface for settings editors
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
#import "EditTextTableViewCell.h"
@@ -16,29 +16,29 @@
#import "EditSecretTextTableViewCell.h"
#import "EditButtonTableViewCell.h"
extern NSString* TableCellIdentifierText;
extern NSString* TableCellIdentifierSecretText;
extern NSString* TableCellIdentifierYesNo;
extern NSString* TableCellIdentifierSelection;
extern NSString* TableCellIdentifierSubEditor;
extern NSString* TableCellIdentifierMultiChoice;
extern NSString* TableCellIdentifierButton;
extern NSString *TableCellIdentifierText;
extern NSString *TableCellIdentifierSecretText;
extern NSString *TableCellIdentifierYesNo;
extern NSString *TableCellIdentifierSelection;
extern NSString *TableCellIdentifierSubEditor;
extern NSString *TableCellIdentifierMultiChoice;
extern NSString *TableCellIdentifierButton;
@interface EditorBaseController : UITableViewController <UITextFieldDelegate>
{
@private
IBOutlet EditTextTableViewCell* _textTableViewCell;
IBOutlet EditSecretTextTableViewCell* _secretTextTableViewCell;
IBOutlet EditFlagTableViewCell* _flagTableViewCell;
IBOutlet EditSelectionTableViewCell* _selectionTableViewCell;
IBOutlet EditSubEditTableViewCell* _subEditTableViewCell;
IBOutlet EditButtonTableViewCell* _buttonTableViewCell;
{
@private
IBOutlet EditTextTableViewCell *_textTableViewCell;
IBOutlet EditSecretTextTableViewCell *_secretTextTableViewCell;
IBOutlet EditFlagTableViewCell *_flagTableViewCell;
IBOutlet EditSelectionTableViewCell *_selectionTableViewCell;
IBOutlet EditSubEditTableViewCell *_subEditTableViewCell;
IBOutlet EditButtonTableViewCell *_buttonTableViewCell;
}
// returns one of the requested table view cells
- (UITableViewCell*)tableViewCellFromIdentifier:(NSString*)identifier;
- (UITableViewCell *)tableViewCellFromIdentifier:(NSString *)identifier;
// Adjust text input cells label/textfield widht according to the label's text size
- (void)adjustEditTextTableViewCell:(EditTextTableViewCell*)cell;
- (void)adjustEditTextTableViewCell:(EditTextTableViewCell *)cell;
@end

View File

@@ -1,10 +1,11 @@
/*
Basic interface for settings editors
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -13,96 +14,97 @@
@end
NSString* TableCellIdentifierText = @"cellIdText";
NSString* TableCellIdentifierSecretText = @"cellIdSecretText";
NSString* TableCellIdentifierYesNo = @"cellIdYesNo";
NSString* TableCellIdentifierSelection = @"cellIdSelection";
NSString* TableCellIdentifierSubEditor = @"cellIdSubEditor";
NSString* TableCellIdentifierMultiChoice = @"cellIdMultiChoice";
NSString* TableCellIdentifierButton = @"cellIdButton";
NSString *TableCellIdentifierText = @"cellIdText";
NSString *TableCellIdentifierSecretText = @"cellIdSecretText";
NSString *TableCellIdentifierYesNo = @"cellIdYesNo";
NSString *TableCellIdentifierSelection = @"cellIdSelection";
NSString *TableCellIdentifierSubEditor = @"cellIdSubEditor";
NSString *TableCellIdentifierMultiChoice = @"cellIdMultiChoice";
NSString *TableCellIdentifierButton = @"cellIdButton";
@implementation EditorBaseController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
return YES;
}
#pragma mark - Create table view cells
- (UITableViewCell*)tableViewCellFromIdentifier:(NSString*)identifier
- (UITableViewCell *)tableViewCellFromIdentifier:(NSString *)identifier
{
// try to reuse a cell
UITableViewCell* cell = [[self tableView] dequeueReusableCellWithIdentifier:identifier];
if (cell != nil)
return cell;
// try to reuse a cell
UITableViewCell *cell = [[self tableView] dequeueReusableCellWithIdentifier:identifier];
if (cell != nil)
return cell;
// we have to create a new cell
if ([identifier isEqualToString:TableCellIdentifierText])
{
[[NSBundle mainBundle] loadNibNamed:@"EditTextTableViewCell" owner:self options:nil];
cell = _textTableViewCell;
_textTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierSecretText])
{
[[NSBundle mainBundle] loadNibNamed:@"EditSecretTextTableViewCell" owner:self options:nil];
cell = _secretTextTableViewCell;
_secretTextTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierYesNo])
{
[[NSBundle mainBundle] loadNibNamed:@"EditFlagTableViewCell" owner:self options:nil];
cell = _flagTableViewCell;
_flagTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierSelection])
{
[[NSBundle mainBundle] loadNibNamed:@"EditSelectionTableViewCell" owner:self options:nil];
cell = _selectionTableViewCell;
_selectionTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierSubEditor])
{
[[NSBundle mainBundle] loadNibNamed:@"EditSubEditTableViewCell" owner:self options:nil];
cell = _subEditTableViewCell;
_subEditTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierButton])
{
[[NSBundle mainBundle] loadNibNamed:@"EditButtonTableViewCell" owner:self options:nil];
cell = _buttonTableViewCell;
_buttonTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierMultiChoice])
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier] autorelease];
}
else
{
NSAssert(false, @"Unknown table cell identifier");
}
return cell;
// we have to create a new cell
if ([identifier isEqualToString:TableCellIdentifierText])
{
[[NSBundle mainBundle] loadNibNamed:@"EditTextTableViewCell" owner:self options:nil];
cell = _textTableViewCell;
_textTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierSecretText])
{
[[NSBundle mainBundle] loadNibNamed:@"EditSecretTextTableViewCell" owner:self options:nil];
cell = _secretTextTableViewCell;
_secretTextTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierYesNo])
{
[[NSBundle mainBundle] loadNibNamed:@"EditFlagTableViewCell" owner:self options:nil];
cell = _flagTableViewCell;
_flagTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierSelection])
{
[[NSBundle mainBundle] loadNibNamed:@"EditSelectionTableViewCell" owner:self options:nil];
cell = _selectionTableViewCell;
_selectionTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierSubEditor])
{
[[NSBundle mainBundle] loadNibNamed:@"EditSubEditTableViewCell" owner:self options:nil];
cell = _subEditTableViewCell;
_subEditTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierButton])
{
[[NSBundle mainBundle] loadNibNamed:@"EditButtonTableViewCell" owner:self options:nil];
cell = _buttonTableViewCell;
_buttonTableViewCell = nil;
}
else if ([identifier isEqualToString:TableCellIdentifierMultiChoice])
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:identifier] autorelease];
}
else
{
NSAssert(false, @"Unknown table cell identifier");
}
return cell;
}
#pragma mark - Utility functions
- (void)adjustEditTextTableViewCell:(EditTextTableViewCell*)cell
- (void)adjustEditTextTableViewCell:(EditTextTableViewCell *)cell
{
UILabel* label = [cell label];
UITextField* textField = [cell textfield];
// adjust label
CGFloat width = [[label text] sizeWithFont:[label font]].width;
CGRect frame = [label frame];
CGFloat delta = width - frame.size.width;
frame.size.width = width;
[label setFrame:frame];
// adjust text field
frame = [textField frame];
frame.origin.x += delta;
frame.size.width -= delta;
[textField setFrame:frame];
UILabel *label = [cell label];
UITextField *textField = [cell textfield];
// adjust label
CGFloat width = [[label text] sizeWithFont:[label font]].width;
CGRect frame = [label frame];
CGFloat delta = width - frame.size.width;
frame.size.width = width;
[label setFrame:frame];
// adjust text field
frame = [textField frame];
frame.origin.x += delta;
frame.size.width -= delta;
[textField setFrame:frame];
}
@end

View File

@@ -1,10 +1,11 @@
/*
Generic controller to select a single item from a list of options
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -13,18 +14,21 @@
@interface EditorSelectionController : EditorBaseController
{
ConnectionParams* _params;
ConnectionParams *_params;
// array with entries in connection parameters that are altered
NSArray* _entries;
// array with entries in connection parameters that are altered
NSArray *_entries;
// array with dictionaries containing label/value pairs that represent the available values for each entry
NSArray* _selections;
// current selections
NSMutableArray* _cur_selections;
// array with dictionaries containing label/value pairs that represent the available values for
// each entry
NSArray *_selections;
// current selections
NSMutableArray *_cur_selections;
}
- (id)initWithConnectionParams:(ConnectionParams*)params entries:(NSArray*)entries selections:(NSArray*)selections;
- (id)initWithConnectionParams:(ConnectionParams *)params
entries:(NSArray *)entries
selections:(NSArray *)selections;
@end

View File

@@ -1,10 +1,11 @@
/*
Generic controller to select a single item from a list of options
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorSelectionController.h"
@@ -12,88 +13,92 @@
#import "OrderedDictionary.h"
@interface EditorSelectionController (Private)
- (OrderedDictionary*)selectionForIndex:(int)index;
- (OrderedDictionary *)selectionForIndex:(int)index;
@end
@implementation EditorSelectionController
- (id)initWithConnectionParams:(ConnectionParams*)params entries:(NSArray *)entries selections:(NSArray *)selections
- (id)initWithConnectionParams:(ConnectionParams *)params
entries:(NSArray *)entries
selections:(NSArray *)selections
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
_params = [params retain];
_entries = [entries retain];
_selections = [selections retain];
// allocate and init current selections array
_cur_selections = [[NSMutableArray alloc] initWithCapacity:[_entries count]];
for (int i = 0; i < [entries count]; ++i)
{
NSString* entry = [entries objectAtIndex:i];
if([_params hasValueForKeyPath:entry])
{
NSUInteger idx = [(OrderedDictionary*)[selections objectAtIndex:i] indexForValue:[NSNumber numberWithInt:[_params intForKeyPath:entry]]];
[_cur_selections addObject:[NSNumber numberWithInt:(idx != NSNotFound ? idx : 0)]];
}
else
[_cur_selections addObject:[NSNumber numberWithInt:0]];
}
}
return self;
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
_params = [params retain];
_entries = [entries retain];
_selections = [selections retain];
// allocate and init current selections array
_cur_selections = [[NSMutableArray alloc] initWithCapacity:[_entries count]];
for (int i = 0; i < [entries count]; ++i)
{
NSString *entry = [entries objectAtIndex:i];
if ([_params hasValueForKeyPath:entry])
{
NSUInteger idx = [(OrderedDictionary *)[selections objectAtIndex:i]
indexForValue:[NSNumber numberWithInt:[_params intForKeyPath:entry]]];
[_cur_selections addObject:[NSNumber numberWithInt:(idx != NSNotFound ? idx : 0)]];
}
else
[_cur_selections addObject:[NSNumber numberWithInt:0]];
}
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
[_params autorelease];
[_entries autorelease];
[_selections autorelease];
[_cur_selections autorelease];
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
[_params autorelease];
[_entries autorelease];
[_selections autorelease];
[_cur_selections autorelease];
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
// Return YES for supported orientations
return YES;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [_entries count];
// Return the number of sections.
return [_entries count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[self selectionForIndex:section] count];
// Return the number of rows in the section.
return [[self selectionForIndex:section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableViewCellFromIdentifier:TableCellIdentifierMultiChoice];
// get selection
OrderedDictionary* selection = [self selectionForIndex:[indexPath section]];
// set cell properties
UITableViewCell *cell = [self tableViewCellFromIdentifier:TableCellIdentifierMultiChoice];
// get selection
OrderedDictionary *selection = [self selectionForIndex:[indexPath section]];
// set cell properties
[[cell textLabel] setText:[selection keyAtIndex:[indexPath row]]];
// set default checkmark
if([indexPath row] == [[_cur_selections objectAtIndex:[indexPath section]] intValue])
if ([indexPath row] == [[_cur_selections objectAtIndex:[indexPath section]] intValue])
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
else
[cell setAccessoryType:UITableViewCellAccessoryNone];
return cell;
return cell;
}
#pragma mark - Table view delegate
@@ -101,36 +106,38 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// has selection change?
int cur_selection = [[_cur_selections objectAtIndex:[indexPath section]] intValue];
if([indexPath row] != cur_selection)
int cur_selection = [[_cur_selections objectAtIndex:[indexPath section]] intValue];
if ([indexPath row] != cur_selection)
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSIndexPath* oldIndexPath = [NSIndexPath indexPathForRow:cur_selection inSection:[indexPath section]];
NSIndexPath *oldIndexPath = [NSIndexPath indexPathForRow:cur_selection
inSection:[indexPath section]];
// clear old checkmark
UITableViewCell* old_sel_cell = [tableView cellForRowAtIndexPath:oldIndexPath];
UITableViewCell *old_sel_cell = [tableView cellForRowAtIndexPath:oldIndexPath];
old_sel_cell.accessoryType = UITableViewCellAccessoryNone;
// set new checkmark
UITableViewCell* new_sel_cell = [tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *new_sel_cell = [tableView cellForRowAtIndexPath:indexPath];
new_sel_cell.accessoryType = UITableViewCellAccessoryCheckmark;
// get value from selection dictionary
OrderedDictionary* dict = [self selectionForIndex:[indexPath section]];
int sel_value = [[dict valueForKey:[dict keyAtIndex:[indexPath row]]] intValue];
// get value from selection dictionary
OrderedDictionary *dict = [self selectionForIndex:[indexPath section]];
int sel_value = [[dict valueForKey:[dict keyAtIndex:[indexPath row]]] intValue];
// update selection index and params value
[_cur_selections replaceObjectAtIndex:[indexPath section] withObject:[NSNumber numberWithInt:[indexPath row]]];
[_params setInt:sel_value forKeyPath:[_entries objectAtIndex:[indexPath section]]];
}
[_cur_selections replaceObjectAtIndex:[indexPath section]
withObject:[NSNumber numberWithInt:[indexPath row]]];
[_params setInt:sel_value forKeyPath:[_entries objectAtIndex:[indexPath section]]];
}
}
#pragma mark - Convenience functions
- (OrderedDictionary*)selectionForIndex:(int)index
- (OrderedDictionary *)selectionForIndex:(int)index
{
return (OrderedDictionary*)[_selections objectAtIndex:index];
return (OrderedDictionary *)[_selections objectAtIndex:index];
}
@end

View File

@@ -1,10 +1,11 @@
/*
Password Encryption Controller
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@@ -12,13 +13,13 @@
@interface EncryptionController : NSObject
{
Encryptor* _shared_encryptor;
Encryptor *_shared_encryptor;
}
+ (EncryptionController*)sharedEncryptionController;
+ (EncryptionController *)sharedEncryptionController;
// Return a Encryptor suitable for encrypting or decrypting with the master password
- (Encryptor*)decryptor;
- (Encryptor*)encryptor;
- (Encryptor *)decryptor;
- (Encryptor *)encryptor;
@end

View File

@@ -1,10 +1,11 @@
/*
Password Encryption Controller
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EncryptionController.h"
@@ -13,63 +14,65 @@
@interface EncryptionController (Private)
- (BOOL)verifyPassword:(Encryptor*)decryptor;
- (NSData*)encryptedVerificationData;
- (void)setEncryptedVerificationData:(Encryptor*)encryptor;
- (BOOL)verifyPassword:(Encryptor *)decryptor;
- (NSData *)encryptedVerificationData;
- (void)setEncryptedVerificationData:(Encryptor *)encryptor;
- (NSString*)keychainServerName;
- (NSString*)keychainUsername;
- (void)setKeychainPassword:(NSString*)password;
- (NSString*)keychainPassword;
- (NSString*)keychainDefaultPassword;
- (NSString *)keychainServerName;
- (NSString *)keychainUsername;
- (void)setKeychainPassword:(NSString *)password;
- (NSString *)keychainPassword;
- (NSString *)keychainDefaultPassword;
@end
static EncryptionController* _shared_encryption_controller = nil;
static EncryptionController *_shared_encryption_controller = nil;
#pragma mark -
@implementation EncryptionController
+ (EncryptionController*)sharedEncryptionController
+ (EncryptionController *)sharedEncryptionController
{
@synchronized(self)
{
if (_shared_encryption_controller == nil)
_shared_encryption_controller = [[EncryptionController alloc] init];
_shared_encryption_controller = [[EncryptionController alloc] init];
}
return _shared_encryption_controller;
return _shared_encryption_controller;
}
#pragma mark Getting an encryptor or decryptor
- (Encryptor*)encryptor
- (Encryptor *)encryptor
{
if (_shared_encryptor)
return _shared_encryptor;
NSString* saved_password = [self keychainPassword];
NSString *saved_password = [self keychainPassword];
if (saved_password == nil)
{
saved_password = [self keychainDefaultPassword];
Encryptor* encryptor = [[[Encryptor alloc] initWithPassword:saved_password] autorelease];
[self setEncryptedVerificationData:encryptor];
_shared_encryptor = [encryptor retain];
}
else
{
Encryptor* encryptor = [[[Encryptor alloc] initWithPassword:saved_password] autorelease];
if ([self verifyPassword:encryptor])
_shared_encryptor = [encryptor retain];
}
return _shared_encryptor;
{
saved_password = [self keychainDefaultPassword];
Encryptor *encryptor = [[[Encryptor alloc] initWithPassword:saved_password] autorelease];
[self setEncryptedVerificationData:encryptor];
_shared_encryptor = [encryptor retain];
}
else
{
Encryptor *encryptor = [[[Encryptor alloc] initWithPassword:saved_password] autorelease];
if ([self verifyPassword:encryptor])
_shared_encryptor = [encryptor retain];
}
return _shared_encryptor;
}
// For the current implementation, decryptors and encryptors are equivilant.
- (Encryptor*)decryptor { return [self encryptor]; }
- (Encryptor *)decryptor
{
return [self encryptor];
}
@end
@@ -80,62 +83,73 @@ static EncryptionController* _shared_encryption_controller = nil;
#pragma mark -
#pragma mark Keychain password storage
- (NSString*)keychainServerName
- (NSString *)keychainServerName
{
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
}
- (NSString*)keychainUsername
- (NSString *)keychainUsername
{
return @"master.password";
}
- (void)setKeychainPassword:(NSString*)password
{
NSError* error;
- (void)setKeychainPassword:(NSString *)password
{
NSError *error;
if (password == nil)
{
[SFHFKeychainUtils deleteItemForUsername:[self keychainUsername] andServerName:[self keychainServerName] error:&error];
[SFHFKeychainUtils deleteItemForUsername:[self keychainUsername]
andServerName:[self keychainServerName]
error:&error];
return;
}
[SFHFKeychainUtils storeUsername:[self keychainUsername] andPassword:password forServerName:[self keychainServerName] updateExisting:YES error:&error];
[SFHFKeychainUtils storeUsername:[self keychainUsername]
andPassword:password
forServerName:[self keychainServerName]
updateExisting:YES
error:&error];
}
- (NSString*)keychainPassword
- (NSString *)keychainPassword
{
NSError* error;
return [SFHFKeychainUtils getPasswordForUsername:[self keychainUsername] andServerName:[self keychainServerName] error:&error];
NSError *error;
return [SFHFKeychainUtils getPasswordForUsername:[self keychainUsername]
andServerName:[self keychainServerName]
error:&error];
}
- (NSString*)keychainDefaultPassword
- (NSString *)keychainDefaultPassword
{
NSString* password = [[NSUserDefaults standardUserDefaults] stringForKey:@"UUID"];
if ([password length] == 0)
{
password = [NSString stringWithUUID];
[[NSUserDefaults standardUserDefaults] setObject:password forKey:@"UUID"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"TSXMasterPasswordVerification"];
}
return password;
NSString *password = [[NSUserDefaults standardUserDefaults] stringForKey:@"UUID"];
if ([password length] == 0)
{
password = [NSString stringWithUUID];
[[NSUserDefaults standardUserDefaults] setObject:password forKey:@"UUID"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"TSXMasterPasswordVerification"];
}
return password;
}
#pragma mark -
#pragma mark Verification of encryption key against verification data
- (BOOL)verifyPassword:(Encryptor*)decryptor
- (BOOL)verifyPassword:(Encryptor *)decryptor
{
return [[decryptor plaintextPassword] isEqualToString:[decryptor decryptString:[self encryptedVerificationData]]];
return [[decryptor plaintextPassword]
isEqualToString:[decryptor decryptString:[self encryptedVerificationData]]];
}
- (NSData*)encryptedVerificationData
- (NSData *)encryptedVerificationData
{
return [[NSUserDefaults standardUserDefaults] dataForKey:@"TSXMasterPasswordVerification"];
}
- (void)setEncryptedVerificationData:(Encryptor*)encryptor
- (void)setEncryptedVerificationData:(Encryptor *)encryptor
{
[[NSUserDefaults standardUserDefaults] setObject:[encryptor encryptString:[encryptor plaintextPassword]] forKey:@"TSXMasterPasswordVerification"];
[[NSUserDefaults standardUserDefaults]
setObject:[encryptor encryptString:[encryptor plaintextPassword]]
forKey:@"TSXMasterPasswordVerification"];
}
@end

View File

@@ -1,16 +1,17 @@
/*
Application help controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface HelpController : UIViewController <UIWebViewDelegate>
{
UIWebView* webView;
UIWebView *webView;
}
@end

View File

@@ -1,10 +1,11 @@
/*
Application help controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "HelpController.h"
@@ -14,45 +15,62 @@
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// set title and tab-bar image
[self setTitle:NSLocalizedString(@"Help", @"Help Controller title")];
UIImage* tabBarIcon = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tabbar_icon_help" ofType:@"png"]];
[self setTabBarItem:[[[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"Help", @"Tabbar item help") image:tabBarIcon tag:0] autorelease]];
}
return self;
UIImage *tabBarIcon = [UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tabbar_icon_help"
ofType:@"png"]];
[self setTabBarItem:[[[UITabBarItem alloc]
initWithTitle:NSLocalizedString(@"Help", @"Tabbar item help")
image:tabBarIcon
tag:0] autorelease]];
}
return self;
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
- (void)loadView
{
webView = [[[UIWebView alloc] initWithFrame:CGRectZero] autorelease];
[webView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[webView
setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[webView setAutoresizesSubviews:YES];
[webView setDelegate:self];
[webView setDataDetectorTypes:UIDataDetectorTypeNone];
[webView setDelegate:self];
[webView setDataDetectorTypes:UIDataDetectorTypeNone];
[self setView:webView];
}
- (void)dealloc {
[super dealloc];
- (void)dealloc
{
[super dealloc];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *filename = (IsPhone() ? @"gestures_phone" : @"gestures");
NSString *htmlString = [[[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:filename ofType:@"html" inDirectory:@"help_page"] encoding:NSUTF8StringEncoding error:nil] autorelease];
[webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"help_page"]]];
[super viewDidLoad];
NSString *filename = (IsPhone() ? @"gestures_phone" : @"gestures");
NSString *htmlString = [[[NSString alloc]
initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:filename
ofType:@"html"
inDirectory:@"help_page"]
encoding:NSUTF8StringEncoding
error:nil] autorelease];
[webView
loadHTMLString:htmlString
baseURL:[NSURL fileURLWithPath:[[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:@"help_page"]]];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end

View File

@@ -1,17 +1,18 @@
/*
main tabbar controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface MainTabBarController : UITabBarController {
@interface MainTabBarController : UITabBarController
{
}
@end

View File

@@ -1,20 +1,20 @@
/*
main tabbar controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "MainTabBarController.h"
@implementation MainTabBarController
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
return YES;
}
@end

View File

@@ -1,10 +1,11 @@
/*
controller for performance settings selection
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -13,12 +14,12 @@
@interface PerformanceEditorController : EditorBaseController
{
@private
ConnectionParams* _params;
NSString* _keyPath;
@private
ConnectionParams *_params;
NSString *_keyPath;
}
- (id)initWithConnectionParams:(ConnectionParams*)params;
- (id)initWithConnectionParams:(ConnectionParams*)params keyPath:(NSString*)keyPath;
- (id)initWithConnectionParams:(ConnectionParams *)params;
- (id)initWithConnectionParams:(ConnectionParams *)params keyPath:(NSString *)keyPath;
@end

View File

@@ -4,26 +4,26 @@
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "PerformanceEditorController.h"
#import "ConnectionParams.h"
#import "Utils.h"
@interface PerformanceEditorController(Private)
-(NSString*)keyPathForKey:(NSString*)key;
@interface PerformanceEditorController (Private)
- (NSString *)keyPathForKey:(NSString *)key;
@end
@implementation PerformanceEditorController
- (id)initWithConnectionParams:(ConnectionParams*)params
- (id)initWithConnectionParams:(ConnectionParams *)params
{
return [self initWithConnectionParams:params keyPath:nil];
}
- (id)initWithConnectionParams:(ConnectionParams*)params keyPath:
(NSString*)keyPath;
- (id)initWithConnectionParams:(ConnectionParams *)params keyPath:(NSString *)keyPath;
{
self = [super initWithStyle:UITableViewStyleGrouped];
@@ -48,13 +48,12 @@
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)
interfaceOrientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(NSString*)keyPathForKey:(NSString*)key
- (NSString *)keyPathForKey:(NSString *)key
{
if (_keyPath)
return [_keyPath stringByAppendingFormat:@".%@", key];
@@ -71,124 +70,118 @@
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:
(NSInteger)section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 7;
}
// set section headers
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:
(NSInteger)section
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return NSLocalizedString(@"Performance Settings",
@"'Performance Settings': performance settings header");
}
// Customize the appearance of table view cells.
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:
(NSIndexPath*)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get the table view cell
EditFlagTableViewCell* cell = (EditFlagTableViewCell*)[self
tableViewCellFromIdentifier:TableCellIdentifierYesNo];
EditFlagTableViewCell *cell =
(EditFlagTableViewCell *)[self tableViewCellFromIdentifier:TableCellIdentifierYesNo];
NSAssert(cell, @"Invalid cell");
switch ([indexPath row])
{
case 0:
{
[[cell label] setText:NSLocalizedString(@"RemoteFX",
@"RemoteFX performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_remotefx"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"RemoteFX", @"RemoteFX performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_remotefx"]]];
break;
}
case 1:
{
[[cell label] setText:NSLocalizedString(@"GFX", @"GFX performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_gfx"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"GFX", @"GFX performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_gfx"]]];
break;
}
case 2:
{
[[cell label] setText:NSLocalizedString(@"H264", @"H264 performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_h264"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"H264", @"H264 performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_h264"]]];
break;
}
case 3:
{
[[cell label] setText:NSLocalizedString(@"Desktop Background",
@"Desktop background performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_show_desktop"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"Desktop Background",
@"Desktop background performance setting")];
[[cell toggle]
setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_show_desktop"]]];
break;
}
case 4:
{
[[cell label] setText:NSLocalizedString(@"Font Smoothing",
@"Font smoothing performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_font_smoothing"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"Font Smoothing",
@"Font smoothing performance setting")];
[[cell toggle]
setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_font_smoothing"]]];
break;
}
case 5:
{
[[cell label] setText:NSLocalizedString(@"Desktop Composition",
@"Desktop composition performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_desktop_composition"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"Desktop Composition",
@"Desktop composition performance setting")];
[[cell toggle]
setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_desktop_composition"]]];
break;
}
case 6:
{
[[cell label] setText:NSLocalizedString(@"Window contents while dragging",
@"Window Dragging performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_window_dragging"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"Window contents while dragging",
@"Window Dragging performance setting")];
[[cell toggle]
setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_window_dragging"]]];
break;
}
case 7:
{
[[cell label] setText:NSLocalizedString(@"Menu Animation",
@"Menu Animations performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_menu_animation"]]];
break;
}
{
[[cell label] setText:NSLocalizedString(@"Menu Animation",
@"Menu Animations performance setting")];
[[cell toggle]
setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_menu_animation"]]];
break;
}
case 8:
{
[[cell label] setText:NSLocalizedString(@"Visual Styles",
@"Use Themes performance setting")];
[[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:
@"perf_windows_themes"]]];
break;
}
{
[[cell label]
setText:NSLocalizedString(@"Visual Styles", @"Use Themes performance setting")];
[[cell toggle]
setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_windows_themes"]]];
break;
}
default:
break;
}
[[cell toggle] setTag:GET_TAG_FROM_PATH(indexPath)];
[[cell toggle] addTarget:self action:@selector(togglePerformanceSetting:)
forControlEvents:UIControlEventValueChanged];
[[cell toggle] addTarget:self
action:@selector(togglePerformanceSetting:)
forControlEvents:UIControlEventValueChanged];
return cell;
}
@@ -197,53 +190,50 @@
- (void)togglePerformanceSetting:(id)sender
{
UISwitch* valueSwitch = (UISwitch*)sender;
UISwitch *valueSwitch = (UISwitch *)sender;
switch (valueSwitch.tag)
{
case GET_TAG(0, 0):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_remotefx"]];
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_remotefx"]];
break;
case GET_TAG(0, 1):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_gfx"]];
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_gfx"]];
break;
case GET_TAG(0, 2):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_h264"]];
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_h264"]];
break;
case GET_TAG(0, 3):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_show_desktop"]];
[_params setBool:[valueSwitch isOn]
forKeyPath:[self keyPathForKey:@"perf_show_desktop"]];
break;
case GET_TAG(0, 4):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_font_smoothing"]];
[_params setBool:[valueSwitch isOn]
forKeyPath:[self keyPathForKey:@"perf_font_smoothing"]];
break;
case GET_TAG(0, 5):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_desktop_composition"]];
[_params setBool:[valueSwitch isOn]
forKeyPath:[self keyPathForKey:@"perf_desktop_composition"]];
break;
case GET_TAG(0, 6):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_window_dragging"]];
[_params setBool:[valueSwitch isOn]
forKeyPath:[self keyPathForKey:@"perf_window_dragging"]];
break;
case GET_TAG(0, 7):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_menu_animation"]];
[_params setBool:[valueSwitch isOn]
forKeyPath:[self keyPathForKey:@"perf_menu_animation"]];
break;
case GET_TAG(0, 8):
[_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:
@"perf_windows_themes"]];
[_params setBool:[valueSwitch isOn]
forKeyPath:[self keyPathForKey:@"perf_windows_themes"]];
break;
default:

View File

@@ -1,10 +1,11 @@
/*
RDP Session View Controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -14,57 +15,61 @@
#import "TouchPointerView.h"
#import "AdvancedKeyboardView.h"
@interface RDPSessionViewController : UIViewController <RDPSessionDelegate, TouchPointerDelegate, AdvancedKeyboardDelegate, RDPKeyboardDelegate, UIScrollViewDelegate, UITextFieldDelegate>
@interface RDPSessionViewController
: UIViewController <RDPSessionDelegate, TouchPointerDelegate, AdvancedKeyboardDelegate,
RDPKeyboardDelegate, UIScrollViewDelegate, UITextFieldDelegate>
{
// scrollview that hosts the rdp session view
IBOutlet UIScrollView* _session_scrollview;
// rdp session view
IBOutlet RDPSessionView* _session_view;
IBOutlet UIScrollView *_session_scrollview;
// touch pointer view
IBOutlet TouchPointerView* _touchpointer_view;
BOOL _autoscroll_with_touchpointer;
BOOL _is_autoscrolling;
// rdp session view
IBOutlet RDPSessionView *_session_view;
// touch pointer view
IBOutlet TouchPointerView *_touchpointer_view;
BOOL _autoscroll_with_touchpointer;
BOOL _is_autoscrolling;
// rdp session toolbar
IBOutlet UIToolbar* _session_toolbar;
BOOL _session_toolbar_visible;
IBOutlet UIToolbar *_session_toolbar;
BOOL _session_toolbar_visible;
// dummy text field used to display the keyboard
IBOutlet UITextField* _dummy_textfield;
// connecting view and the controls within that view
IBOutlet UIView* _connecting_view;
IBOutlet UILabel* _lbl_connecting;
IBOutlet UIActivityIndicatorView* _connecting_indicator_view;
IBOutlet UIButton* _cancel_connect_button;
// extended keyboard toolbar
UIToolbar* _keyboard_toolbar;
// rdp session
RDPSession* _session;
BOOL _session_initilized;
IBOutlet UITextField *_dummy_textfield;
// connecting view and the controls within that view
IBOutlet UIView *_connecting_view;
IBOutlet UILabel *_lbl_connecting;
IBOutlet UIActivityIndicatorView *_connecting_indicator_view;
IBOutlet UIButton *_cancel_connect_button;
// extended keyboard toolbar
UIToolbar *_keyboard_toolbar;
// rdp session
RDPSession *_session;
BOOL _session_initilized;
// flag that indicates whether the keyboard is visible or not
BOOL _keyboard_visible;
// flag to switch between left/right mouse button mode
BOOL _toggle_mouse_button;
// keyboard extension view
AdvancedKeyboardView* _advanced_keyboard_view;
BOOL _advanced_keyboard_visible;
BOOL _requesting_advanced_keyboard;
CGFloat _keyboard_last_height;
// delayed mouse move event sending
NSTimer* _mouse_move_event_timer;
int _mouse_move_events_skipped;
CGPoint _prev_long_press_position;
// flag to switch between left/right mouse button mode
BOOL _toggle_mouse_button;
// keyboard extension view
AdvancedKeyboardView *_advanced_keyboard_view;
BOOL _advanced_keyboard_visible;
BOOL _requesting_advanced_keyboard;
CGFloat _keyboard_last_height;
// delayed mouse move event sending
NSTimer *_mouse_move_event_timer;
int _mouse_move_events_skipped;
CGPoint _prev_long_press_position;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil session:(RDPSession*)session;
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
session:(RDPSession *)session;
@end

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,11 @@
/*
controller for screen settings selection
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditorBaseController.h"
@@ -14,20 +15,20 @@
@interface ScreenSelectionController : EditorBaseController
{
@private
NSString* _keyPath;
ConnectionParams* _params;
// avaiable options
OrderedDictionary* _color_options;
NSArray* _resolution_modes;
@private
NSString *_keyPath;
ConnectionParams *_params;
// current selections
int _selection_color;
int _selection_resolution;
// avaiable options
OrderedDictionary *_color_options;
NSArray *_resolution_modes;
// current selections
int _selection_color;
int _selection_resolution;
}
- (id)initWithConnectionParams:(ConnectionParams*)params;
- (id)initWithConnectionParams:(ConnectionParams*)params keyPath:(NSString*)keyPath;
- (id)initWithConnectionParams:(ConnectionParams *)params;
- (id)initWithConnectionParams:(ConnectionParams *)params keyPath:(NSString *)keyPath;
@end

View File

@@ -1,10 +1,11 @@
/*
controller for screen settings selection
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "ScreenSelectionController.h"
@@ -13,197 +14,213 @@
#import "ConnectionParams.h"
@interface ScreenSelectionController (Private)
-(NSString*)keyPathForKey:(NSString*)key;
- (NSString *)keyPathForKey:(NSString *)key;
@end
@implementation ScreenSelectionController
- (id)initWithConnectionParams:(ConnectionParams*)params
- (id)initWithConnectionParams:(ConnectionParams *)params
{
return [self initWithConnectionParams:params keyPath:nil];
return [self initWithConnectionParams:params keyPath:nil];
}
- (id)initWithConnectionParams:(ConnectionParams*)params keyPath:(NSString*)keyPath
- (id)initWithConnectionParams:(ConnectionParams *)params keyPath:(NSString *)keyPath
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
_params = [params retain];
_keyPath = (keyPath != nil ? [keyPath retain] : nil);
_color_options = (OrderedDictionary*)[SelectionForColorSetting() retain];
_resolution_modes = [ResolutionModes() retain];
// init current selections
NSUInteger idx = [_color_options indexForValue:[NSNumber numberWithInt:[_params intForKeyPath:[self keyPathForKey:@"colors"]]]];
_selection_color = (idx != NSNotFound) ? idx : 0;
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
_params = [params retain];
_keyPath = (keyPath != nil ? [keyPath retain] : nil);
idx = [_resolution_modes indexOfObject:ScreenResolutionDescription([_params intForKeyPath:[self keyPathForKey:@"screen_resolution_type"]],
[_params intForKeyPath:[self keyPathForKey:@"width"]],
[_params intForKeyPath:[self keyPathForKey:@"height"]])];
_selection_resolution = (idx != NSNotFound) ? idx : 0;
}
return self;
_color_options = (OrderedDictionary *)[SelectionForColorSetting() retain];
_resolution_modes = [ResolutionModes() retain];
// init current selections
NSUInteger idx = [_color_options
indexForValue:[NSNumber
numberWithInt:[_params
intForKeyPath:[self keyPathForKey:@"colors"]]]];
_selection_color = (idx != NSNotFound) ? idx : 0;
idx = [_resolution_modes
indexOfObject:ScreenResolutionDescription(
[_params
intForKeyPath:[self keyPathForKey:@"screen_resolution_type"]],
[_params intForKeyPath:[self keyPathForKey:@"width"]],
[_params intForKeyPath:[self keyPathForKey:@"height"]])];
_selection_resolution = (idx != NSNotFound) ? idx : 0;
}
return self;
}
- (void)dealloc
{
[super dealloc];
[_params autorelease];
[_keyPath autorelease];
[_color_options autorelease];
[_resolution_modes autorelease];
[super dealloc];
[_params autorelease];
[_keyPath autorelease];
[_color_options autorelease];
[_resolution_modes autorelease];
}
-(NSString*)keyPathForKey:(NSString*)key
- (NSString *)keyPathForKey:(NSString *)key
{
if (_keyPath)
return [_keyPath stringByAppendingFormat:@".%@", key];
return key;
if (_keyPath)
return [_keyPath stringByAppendingFormat:@".%@", key];
return key;
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
// Return YES for supported orientations
return YES;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0)
return [_color_options count];
return [_resolution_modes count] + 2; // +2 for custom width/height input fields
// Return the number of rows in the section.
if (section == 0)
return [_color_options count];
return [_resolution_modes count] + 2; // +2 for custom width/height input fields
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
switch ([indexPath section])
{
case 0:
cell = [self tableViewCellFromIdentifier:TableCellIdentifierMultiChoice];
[[cell textLabel] setText:[_color_options keyAtIndex:[indexPath row]]];
break;
case 1:
if ([indexPath row] < [_resolution_modes count])
{
cell = [self tableViewCellFromIdentifier:TableCellIdentifierMultiChoice];
[[cell textLabel] setText:[_resolution_modes objectAtIndex:[indexPath row]]];
}
else
cell = [self tableViewCellFromIdentifier:TableCellIdentifierText];
break;
default:
break;
}
if ([indexPath section] == 1)
{
BOOL enabled = ([_params intForKeyPath:[self keyPathForKey:@"screen_resolution_type"]] == TSXScreenOptionCustom);
if ([indexPath row] == [_resolution_modes count])
{
int value = [_params intForKeyPath:[self keyPathForKey:@"width"]];
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
[[textCell label] setText:NSLocalizedString(@"Width", @"Custom Screen Width")];
[[textCell textfield] setText:[NSString stringWithFormat:@"%d", value ? value : 800]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
[[textCell label] setEnabled:enabled];
[[textCell textfield] setEnabled:enabled];
[[textCell textfield] setTag:1];
}
else if ([indexPath row] == ([_resolution_modes count] + 1))
{
int value = [_params intForKeyPath:[self keyPathForKey:@"height"]];
EditTextTableViewCell* textCell = (EditTextTableViewCell*)cell;
[[textCell label] setText:NSLocalizedString(@"Height", @"Custom Screen Height")];
[[textCell textfield] setText:[NSString stringWithFormat:@"%d", value ? value : 600]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
[[textCell label] setEnabled:enabled];
[[textCell textfield] setEnabled:enabled];
[[textCell textfield] setTag:2];
}
}
UITableViewCell *cell = nil;
switch ([indexPath section])
{
case 0:
cell = [self tableViewCellFromIdentifier:TableCellIdentifierMultiChoice];
[[cell textLabel] setText:[_color_options keyAtIndex:[indexPath row]]];
break;
case 1:
if ([indexPath row] < [_resolution_modes count])
{
cell = [self tableViewCellFromIdentifier:TableCellIdentifierMultiChoice];
[[cell textLabel] setText:[_resolution_modes objectAtIndex:[indexPath row]]];
}
else
cell = [self tableViewCellFromIdentifier:TableCellIdentifierText];
break;
default:
break;
}
if ([indexPath section] == 1)
{
BOOL enabled = ([_params intForKeyPath:[self keyPathForKey:@"screen_resolution_type"]] ==
TSXScreenOptionCustom);
if ([indexPath row] == [_resolution_modes count])
{
int value = [_params intForKeyPath:[self keyPathForKey:@"width"]];
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell label] setText:NSLocalizedString(@"Width", @"Custom Screen Width")];
[[textCell textfield] setText:[NSString stringWithFormat:@"%d", value ? value : 800]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
[[textCell label] setEnabled:enabled];
[[textCell textfield] setEnabled:enabled];
[[textCell textfield] setTag:1];
}
else if ([indexPath row] == ([_resolution_modes count] + 1))
{
int value = [_params intForKeyPath:[self keyPathForKey:@"height"]];
EditTextTableViewCell *textCell = (EditTextTableViewCell *)cell;
[[textCell label] setText:NSLocalizedString(@"Height", @"Custom Screen Height")];
[[textCell textfield] setText:[NSString stringWithFormat:@"%d", value ? value : 600]];
[[textCell textfield] setKeyboardType:UIKeyboardTypeNumberPad];
[[textCell label] setEnabled:enabled];
[[textCell textfield] setEnabled:enabled];
[[textCell textfield] setTag:2];
}
}
// set default checkmark
if([indexPath row] == ([indexPath section] == 0 ? _selection_color : _selection_resolution))
if ([indexPath row] == ([indexPath section] == 0 ? _selection_color : _selection_resolution))
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
else
[cell setAccessoryType:UITableViewCellAccessoryNone];
return cell;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// custom widht/height cells are not selectable
if ([indexPath section] == 1 && [indexPath row] >= [_resolution_modes count])
return;
// custom widht/height cells are not selectable
if ([indexPath section] == 1 && [indexPath row] >= [_resolution_modes count])
return;
// has selection change?
int cur_selection = ([indexPath section] == 0 ? _selection_color : _selection_resolution);
if([indexPath row] != cur_selection)
int cur_selection = ([indexPath section] == 0 ? _selection_color : _selection_resolution);
if ([indexPath row] != cur_selection)
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSIndexPath* oldIndexPath = [NSIndexPath indexPathForRow:cur_selection inSection:[indexPath section]];
// clear old checkmark
UITableViewCell* old_sel_cell = [tableView cellForRowAtIndexPath:oldIndexPath];
old_sel_cell.accessoryType = UITableViewCellAccessoryNone;
// set new checkmark
UITableViewCell* new_sel_cell = [tableView cellForRowAtIndexPath:indexPath];
new_sel_cell.accessoryType = UITableViewCellAccessoryCheckmark;
if ([indexPath section] == 0)
{
// get value from color dictionary
int sel_value = [[_color_options valueForKey:[_color_options keyAtIndex:[indexPath row]]] intValue];
// update selection index and params value
[_params setInt:sel_value forKeyPath:[self keyPathForKey:@"colors"]];
_selection_color = [indexPath row];
}
else
{
// update selection index and params value
int width, height;
TSXScreenOptions mode;
ScanScreenResolution([_resolution_modes objectAtIndex:[indexPath row]], &width, &height, &mode);
[_params setInt:mode forKeyPath:[self keyPathForKey:@"screen_resolution_type"]];
if (mode != TSXScreenOptionCustom)
{
[_params setInt:width forKeyPath:[self keyPathForKey:@"width"]];
[_params setInt:height forKeyPath:[self keyPathForKey:@"height"]];
}
_selection_resolution = [indexPath row];
// refresh width/height edit fields if custom selection changed
NSArray* indexPaths = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:[_resolution_modes count] inSection:1],
[NSIndexPath indexPathForRow:([_resolution_modes count] + 1) inSection:1], nil];
[[self tableView] reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
}
}
NSIndexPath *oldIndexPath = [NSIndexPath indexPathForRow:cur_selection
inSection:[indexPath section]];
// clear old checkmark
UITableViewCell *old_sel_cell = [tableView cellForRowAtIndexPath:oldIndexPath];
old_sel_cell.accessoryType = UITableViewCellAccessoryNone;
// set new checkmark
UITableViewCell *new_sel_cell = [tableView cellForRowAtIndexPath:indexPath];
new_sel_cell.accessoryType = UITableViewCellAccessoryCheckmark;
if ([indexPath section] == 0)
{
// get value from color dictionary
int sel_value =
[[_color_options valueForKey:[_color_options keyAtIndex:[indexPath row]]] intValue];
// update selection index and params value
[_params setInt:sel_value forKeyPath:[self keyPathForKey:@"colors"]];
_selection_color = [indexPath row];
}
else
{
// update selection index and params value
int width, height;
TSXScreenOptions mode;
ScanScreenResolution([_resolution_modes objectAtIndex:[indexPath row]], &width, &height,
&mode);
[_params setInt:mode forKeyPath:[self keyPathForKey:@"screen_resolution_type"]];
if (mode != TSXScreenOptionCustom)
{
[_params setInt:width forKeyPath:[self keyPathForKey:@"width"]];
[_params setInt:height forKeyPath:[self keyPathForKey:@"height"]];
}
_selection_resolution = [indexPath row];
// refresh width/height edit fields if custom selection changed
NSArray *indexPaths = [NSArray
arrayWithObjects:[NSIndexPath indexPathForRow:[_resolution_modes count]
inSection:1],
[NSIndexPath indexPathForRow:([_resolution_modes count] + 1)
inSection:1],
nil];
[[self tableView] reloadRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationNone];
}
}
}
#pragma mark -
#pragma mark Text Field delegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
@@ -211,20 +228,22 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
switch([textField tag])
{
// update resolution settings (and check for invalid input)
switch ([textField tag])
{
// update resolution settings (and check for invalid input)
case 1:
if ([[textField text] intValue] < 640) [textField setText:@"640"];
if ([[textField text] intValue] < 640)
[textField setText:@"640"];
[_params setInt:[[textField text] intValue] forKeyPath:[self keyPathForKey:@"width"]];
break;
case 2:
if ([[textField text] intValue] < 480) [textField setText:@"480"];
if ([[textField text] intValue] < 480)
[textField setText:@"480"];
[_params setInt:[[textField text] intValue] forKeyPath:[self keyPathForKey:@"height"]];
break;
default:
break;
}

View File

@@ -1,10 +1,11 @@
/*
Certificate verification controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -13,17 +14,20 @@
@interface VerifyCertificateController : UIViewController
{
@private
IBOutlet UILabel* _label_issuer;
IBOutlet UIButton* _btn_accept;
IBOutlet UIButton* _btn_decline;
IBOutlet UILabel* _label_message;
IBOutlet UILabel* _label_for_issuer;
@private
IBOutlet UILabel *_label_issuer;
IBOutlet UIButton *_btn_accept;
IBOutlet UIButton *_btn_decline;
IBOutlet UILabel *_label_message;
IBOutlet UILabel *_label_for_issuer;
RDPSession* _session;
NSMutableDictionary* _params;
RDPSession *_session;
NSMutableDictionary *_params;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil session:(RDPSession*)session params:(NSMutableDictionary*)params;
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
session:(RDPSession *)session
params:(NSMutableDictionary *)params;
@end

View File

@@ -1,10 +1,11 @@
/*
Certificate verification controller
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "VerifyCertificateController.h"
@@ -12,68 +13,74 @@
@implementation VerifyCertificateController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil session:(RDPSession *)session params:(NSMutableDictionary *)params
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
session:(RDPSession *)session
params:(NSMutableDictionary *)params
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_session = session;
_params = params;
[self setModalPresentationStyle:UIModalPresentationFormSheet];
}
return self;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
_session = session;
_params = params;
[self setModalPresentationStyle:UIModalPresentationFormSheet];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[super viewDidLoad];
NSString* message = NSLocalizedString(@"The identity of the remote computer cannot be verified. Do you want to connect anyway?", @"Verify certificate view message");
// init strings
[_label_message setText:message];
[_label_for_issuer setText:NSLocalizedString(@"Issuer:", @"Verify certificate view issuer label")];
[_btn_accept setTitle:NSLocalizedString(@"Yes", @"Yes Button") forState:UIControlStateNormal];
[_btn_decline setTitle:NSLocalizedString(@"No", @"No Button") forState:UIControlStateNormal];
NSString *message = NSLocalizedString(
@"The identity of the remote computer cannot be verified. Do you want to connect anyway?",
@"Verify certificate view message");
[_label_issuer setText:[_params valueForKey:@"issuer"]];
// init strings
[_label_message setText:message];
[_label_for_issuer
setText:NSLocalizedString(@"Issuer:", @"Verify certificate view issuer label")];
[_btn_accept setTitle:NSLocalizedString(@"Yes", @"Yes Button") forState:UIControlStateNormal];
[_btn_decline setTitle:NSLocalizedString(@"No", @"No Button") forState:UIControlStateNormal];
[_label_issuer setText:[_params valueForKey:@"issuer"]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[super viewDidDisappear:animated];
// set signal
[[_session uiRequestCompleted] signal];
// set signal
[[_session uiRequestCompleted] signal];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
return YES;
}
#pragma mark - Action handlers
- (IBAction)acceptPressed:(id)sender
{
[_params setValue:[NSNumber numberWithBool:YES] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
[_params setValue:[NSNumber numberWithBool:YES] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)declinePressed:(id)sender
{
[_params setValue:[NSNumber numberWithBool:NO] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
[_params setValue:[NSNumber numberWithBool:NO] forKey:@"result"];
// dismiss controller
[self dismissModalViewControllerAnimated:YES];
}
@end

View File

@@ -1,10 +1,11 @@
/*
RDP run-loop
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <CoreGraphics/CoreGraphics.h>
@@ -18,40 +19,37 @@
// FreeRDP extended structs
typedef struct mf_info mfInfo;
typedef struct mf_context
{
rdpContext _p;
mfInfo* mfi;
rdpSettings* settings;
} mfContext;
mfInfo *mfi;
rdpSettings *settings;
} mfContext;
struct mf_info
{
// RDP
freerdp* instance;
mfContext* context;
rdpContext* _context;
freerdp *instance;
mfContext *context;
rdpContext *_context;
// UI
RDPSession* session;
RDPSession *session;
// Graphics
CGContextRef bitmap_context;
// Events
int event_pipe_producer, event_pipe_consumer;
// Tracking connection state
volatile TSXConnectionState connection_state;
volatile BOOL unwanted; // set when controlling Session no longer wants the connection to continue
volatile BOOL
unwanted; // set when controlling Session no longer wants the connection to continue
};
#define MFI_FROM_INSTANCE(inst) (((mfContext*)((inst)->context))->mfi)
#define MFI_FROM_INSTANCE(inst) (((mfContext *)((inst)->context))->mfi)
enum MF_EXIT_CODE
{
@@ -59,17 +57,13 @@ enum MF_EXIT_CODE
MF_EXIT_CONN_FAILED = 128,
MF_EXIT_CONN_CANCELED = 129,
MF_EXIT_LOGON_TIMEOUT = 130,
MF_EXIT_LOGON_TIMEOUT = 130,
MF_EXIT_UNKNOWN = 255
};
void ios_init_freerdp(void);
void ios_uninit_freerdp(void);
freerdp* ios_freerdp_new(void);
int ios_run_freerdp(freerdp* instance);
void ios_freerdp_free(freerdp* instance);
freerdp *ios_freerdp_new(void);
int ios_run_freerdp(freerdp *instance);
void ios_freerdp_free(freerdp *instance);

View File

@@ -4,7 +4,8 @@
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <freerdp/gdi/gdi.h>
@@ -27,94 +28,85 @@
#pragma mark Connection helpers
static void ios_OnChannelConnectedEventHandler(
void* context,
ChannelConnectedEventArgs* e)
static void ios_OnChannelConnectedEventHandler(void *context, ChannelConnectedEventArgs *e)
{
rdpSettings* settings;
mfContext* afc;
rdpSettings *settings;
mfContext *afc;
if (!context || !e)
{
WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p",
__FUNCTION__, context, (void*) e);
WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", __FUNCTION__, context, (void *)e);
return;
}
afc = (mfContext*) context;
afc = (mfContext *)context;
settings = afc->_p.settings;
if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
{
gdi_graphics_pipeline_init(afc->_p.gdi,
(RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_init(afc->_p.gdi, (RdpgfxClientContext *)e->pInterface);
}
else
{
WLog_WARN(TAG, "GFX without software GDI requested. "
" This is not supported, add /gdi:sw");
" This is not supported, add /gdi:sw");
}
}
}
static void ios_OnChannelDisconnectedEventHandler(
void* context, ChannelDisconnectedEventArgs* e)
static void ios_OnChannelDisconnectedEventHandler(void *context, ChannelDisconnectedEventArgs *e)
{
rdpSettings* settings;
mfContext* afc;
rdpSettings *settings;
mfContext *afc;
if (!context || !e)
{
WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p",
__FUNCTION__, context, (void*) e);
WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", __FUNCTION__, context, (void *)e);
return;
}
afc = (mfContext*) context;
afc = (mfContext *)context;
settings = afc->_p.settings;
if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
{
gdi_graphics_pipeline_uninit(afc->_p.gdi,
(RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_uninit(afc->_p.gdi, (RdpgfxClientContext *)e->pInterface);
}
else
{
WLog_WARN(TAG, "GFX without software GDI requested. "
" This is not supported, add /gdi:sw");
" This is not supported, add /gdi:sw");
}
}
}
static BOOL ios_pre_connect(freerdp* instance)
static BOOL ios_pre_connect(freerdp *instance)
{
int rc;
rdpSettings* settings;
rdpSettings *settings;
if (!instance || !instance->settings)
return FALSE;
settings = instance->settings;
settings->AutoLogonEnabled = settings->Password
&& (strlen(settings->Password) > 0);
settings->AutoLogonEnabled = settings->Password && (strlen(settings->Password) > 0);
// Verify screen width/height are sane
if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64)
|| (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096))
if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) ||
(settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096))
{
NSLog(@"%s: invalid dimensions %d %d", __func__, settings->DesktopWidth,
settings->DesktopHeight);
return FALSE;
}
rc = PubSub_SubscribeChannelConnected(
instance->context->pubSub,
ios_OnChannelConnectedEventHandler);
rc = PubSub_SubscribeChannelConnected(instance->context->pubSub,
ios_OnChannelConnectedEventHandler);
if (rc != CHANNEL_RC_OK)
{
@@ -122,9 +114,8 @@ static BOOL ios_pre_connect(freerdp* instance)
return FALSE;
}
rc = PubSub_SubscribeChannelDisconnected(
instance->context->pubSub,
ios_OnChannelDisconnectedEventHandler);
rc = PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
ios_OnChannelDisconnectedEventHandler);
if (rc != CHANNEL_RC_OK)
{
@@ -132,8 +123,7 @@ static BOOL ios_pre_connect(freerdp* instance)
return FALSE;
}
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
{
WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError());
return FALSE;
@@ -142,7 +132,7 @@ static BOOL ios_pre_connect(freerdp* instance)
return TRUE;
}
static BOOL ios_Pointer_New(rdpContext* context, rdpPointer* pointer)
static BOOL ios_Pointer_New(rdpContext *context, rdpPointer *pointer)
{
if (!context || !pointer || !context->gdi)
return FALSE;
@@ -150,14 +140,13 @@ static BOOL ios_Pointer_New(rdpContext* context, rdpPointer* pointer)
return TRUE;
}
static void ios_Pointer_Free(rdpContext* context, rdpPointer* pointer)
static void ios_Pointer_Free(rdpContext *context, rdpPointer *pointer)
{
if (!context || !pointer)
return;
}
static BOOL ios_Pointer_Set(rdpContext* context,
const rdpPointer* pointer)
static BOOL ios_Pointer_Set(rdpContext *context, const rdpPointer *pointer)
{
if (!context)
return FALSE;
@@ -165,8 +154,7 @@ static BOOL ios_Pointer_Set(rdpContext* context,
return TRUE;
}
static BOOL ios_Pointer_SetPosition(rdpContext* context,
UINT32 x, UINT32 y)
static BOOL ios_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y)
{
if (!context)
return FALSE;
@@ -174,7 +162,7 @@ static BOOL ios_Pointer_SetPosition(rdpContext* context,
return TRUE;
}
static BOOL ios_Pointer_SetNull(rdpContext* context)
static BOOL ios_Pointer_SetNull(rdpContext *context)
{
if (!context)
return FALSE;
@@ -182,7 +170,7 @@ static BOOL ios_Pointer_SetNull(rdpContext* context)
return TRUE;
}
static BOOL ios_Pointer_SetDefault(rdpContext* context)
static BOOL ios_Pointer_SetDefault(rdpContext *context)
{
if (!context)
return FALSE;
@@ -190,7 +178,7 @@ static BOOL ios_Pointer_SetDefault(rdpContext* context)
return TRUE;
}
static BOOL ios_register_pointer(rdpGraphics* graphics)
static BOOL ios_register_pointer(rdpGraphics *graphics)
{
rdpPointer pointer;
@@ -208,9 +196,9 @@ static BOOL ios_register_pointer(rdpGraphics* graphics)
return TRUE;
}
static BOOL ios_post_connect(freerdp* instance)
static BOOL ios_post_connect(freerdp *instance)
{
mfInfo* mfi;
mfInfo *mfi;
if (!instance)
return FALSE;
@@ -231,11 +219,12 @@ static BOOL ios_post_connect(freerdp* instance)
instance->update->EndPaint = ios_ui_end_paint;
instance->update->DesktopResize = ios_ui_resize_window;
[mfi->session performSelectorOnMainThread:@selector(sessionDidConnect)
withObject:nil waitUntilDone:YES];
withObject:nil
waitUntilDone:YES];
return TRUE;
}
static void ios_post_disconnect(freerdp* instance)
static void ios_post_disconnect(freerdp *instance)
{
gdi_free(instance);
}
@@ -243,11 +232,11 @@ static void ios_post_disconnect(freerdp* instance)
#pragma mark -
#pragma mark Running the connection
int ios_run_freerdp(freerdp* instance)
int ios_run_freerdp(freerdp *instance)
{
mfContext* context = (mfContext*)instance->context;
mfInfo* mfi = context->mfi;
rdpChannels* channels = instance->context->channels;
mfContext *context = (mfContext *)instance->context;
mfInfo *mfi = context->mfi;
rdpChannels *channels = instance->context->channels;
mfi->connection_state = TSXConnectionConnecting;
if (!freerdp_connect(instance))
@@ -261,14 +250,14 @@ int ios_run_freerdp(freerdp* instance)
mfi->connection_state = TSXConnectionConnected;
// Connection main loop
NSAutoreleasePool* pool;
NSAutoreleasePool *pool;
int i;
int fds;
int max_fds;
int rcount;
int wcount;
void* rfds[32];
void* wfds[32];
void *rfds[32];
void *wfds[32];
fd_set rfds_set;
fd_set wfds_set;
struct timeval timeout;
@@ -287,8 +276,7 @@ int ios_run_freerdp(freerdp* instance)
break;
}
if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds,
&wcount) != TRUE)
if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
NSLog(@"%s: freerdp_chanman_get_fds failed", __func__);
break;
@@ -329,9 +317,7 @@ int ios_run_freerdp(freerdp* instance)
else if (select_status == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
NSLog(@"%s: select failed!", __func__);
@@ -350,7 +336,7 @@ int ios_run_freerdp(freerdp* instance)
if (ios_events_check_fds(mfi, &rfds_set) != TRUE)
{
// This event will fail when the app asks for a disconnect.
//NSLog(@"%s: ios_events_check_fds failed: terminating connection.", __func__);
// NSLog(@"%s: ios_events_check_fds failed: terminating connection.", __func__);
break;
}
@@ -380,9 +366,9 @@ int ios_run_freerdp(freerdp* instance)
#pragma mark -
#pragma mark Context callbacks
static BOOL ios_client_new(freerdp* instance, rdpContext* context)
static BOOL ios_client_new(freerdp *instance, rdpContext *context)
{
mfContext* ctx = (mfContext*)context;
mfContext *ctx = (mfContext *)context;
if (!instance || !context)
return FALSE;
@@ -390,7 +376,7 @@ static BOOL ios_client_new(freerdp* instance, rdpContext* context)
if ((ctx->mfi = calloc(1, sizeof(mfInfo))) == NULL)
return FALSE;
ctx->mfi->context = (mfContext*)context;
ctx->mfi->context = (mfContext *)context;
ctx->mfi->_context = context;
ctx->mfi->context->settings = instance->settings;
ctx->mfi->instance = instance;
@@ -409,19 +395,19 @@ static BOOL ios_client_new(freerdp* instance, rdpContext* context)
return TRUE;
}
static void ios_client_free(freerdp* instance, rdpContext* context)
static void ios_client_free(freerdp *instance, rdpContext *context)
{
mfInfo* mfi;
mfInfo *mfi;
if (!context)
return;
mfi = ((mfContext*) context)->mfi;
mfi = ((mfContext *)context)->mfi;
ios_events_free_pipe(mfi);
free(mfi);
}
static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS *pEntryPoints)
{
ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
@@ -439,9 +425,9 @@ static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
#pragma mark -
#pragma mark Initialization and cleanup
freerdp* ios_freerdp_new()
freerdp *ios_freerdp_new()
{
rdpContext* context;
rdpContext *context;
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
RdpClientEntry(&clientEntryPoints);
context = freerdp_client_context_new(&clientEntryPoints);
@@ -452,7 +438,7 @@ freerdp* ios_freerdp_new()
return context->instance;
}
void ios_freerdp_free(freerdp* instance)
void ios_freerdp_free(freerdp *instance)
{
if (!instance || !instance->context)
return;
@@ -470,7 +456,7 @@ void ios_uninit_freerdp()
}
/* compatibilty functions */
size_t fwrite$UNIX2003(const void* ptr, size_t size, size_t nmemb, FILE* stream)
size_t fwrite$UNIX2003(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fwrite(ptr, size, nmemb, stream);
}

View File

@@ -1,10 +1,11 @@
/*
RDP event queuing
RDP event queuing
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#ifndef IOS_RDP_EVENT_H
@@ -14,12 +15,13 @@
#import "ios_freerdp.h"
// For UI: use to send events
BOOL ios_events_send(mfInfo* mfi, NSDictionary * event_description);
BOOL ios_events_send(mfInfo *mfi, NSDictionary *event_description);
// For connection runloop: use to poll for queued input events
BOOL ios_events_get_fds(mfInfo* mfi, void ** read_fds, int * read_count, void ** write_fds, int * write_count);
BOOL ios_events_check_fds(mfInfo* mfi, fd_set* rfds);
BOOL ios_events_create_pipe(mfInfo* mfi);
void ios_events_free_pipe(mfInfo* mfi);
BOOL ios_events_get_fds(mfInfo *mfi, void **read_fds, int *read_count, void **write_fds,
int *write_count);
BOOL ios_events_check_fds(mfInfo *mfi, fd_set *rfds);
BOOL ios_events_create_pipe(mfInfo *mfi);
void ios_events_free_pipe(mfInfo *mfi);
#endif /* IOS_RDP_EVENT_H */

View File

@@ -1,10 +1,11 @@
/*
RDP event queuing
RDP event queuing
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "ios_freerdp_events.h"
@@ -12,107 +13,114 @@
#pragma mark -
#pragma mark Sending compacted input events (from main thread)
// While this function may be called from any thread that has an autorelease pool allocated, it is not threadsafe: caller is responsible for synchronization
BOOL ios_events_send(mfInfo* mfi, NSDictionary * event_description)
{
NSData * encoded_description = [NSKeyedArchiver archivedDataWithRootObject:event_description];
if ([encoded_description length] > 32000 || (mfi->event_pipe_producer == -1) )
// While this function may be called from any thread that has an autorelease pool allocated, it is
// not threadsafe: caller is responsible for synchronization
BOOL ios_events_send(mfInfo *mfi, NSDictionary *event_description)
{
NSData *encoded_description = [NSKeyedArchiver archivedDataWithRootObject:event_description];
if ([encoded_description length] > 32000 || (mfi->event_pipe_producer == -1))
return FALSE;
uint32_t archived_data_len = (uint32_t)[encoded_description length];
//NSLog(@"writing %d bytes to input event pipe", archived_data_len);
// NSLog(@"writing %d bytes to input event pipe", archived_data_len);
if (write(mfi->event_pipe_producer, &archived_data_len, 4) == -1)
{
NSLog(@"%s: Failed to write length descriptor to pipe.", __func__);
return FALSE;
}
if (write(mfi->event_pipe_producer, [encoded_description bytes], archived_data_len) == -1)
{
NSLog(@"%s: Failed to write %d bytes into the event queue (event type: %@).", __func__, (int)[encoded_description length], [event_description objectForKey:@"type"]);
NSLog(@"%s: Failed to write %d bytes into the event queue (event type: %@).", __func__,
(int)[encoded_description length], [event_description objectForKey:@"type"]);
return FALSE;
}
return TRUE;
}
return TRUE;
}
#pragma mark -
#pragma mark Processing compacted input events (from connection thread runloop)
static BOOL ios_events_handle_event(mfInfo* mfi, NSDictionary * event_description)
static BOOL ios_events_handle_event(mfInfo *mfi, NSDictionary *event_description)
{
NSString * event_type = [event_description objectForKey:@"type"];
NSString *event_type = [event_description objectForKey:@"type"];
BOOL should_continue = TRUE;
freerdp* instance = mfi->instance;
freerdp *instance = mfi->instance;
if ([event_type isEqualToString:@"mouse"])
{
instance->input->MouseEvent(instance->input,
[[event_description objectForKey:@"flags"] unsignedShortValue],
[[event_description objectForKey:@"coord_x"] unsignedShortValue],
[[event_description objectForKey:@"coord_y"] unsignedShortValue]);
{
instance->input->MouseEvent(
instance->input, [[event_description objectForKey:@"flags"] unsignedShortValue],
[[event_description objectForKey:@"coord_x"] unsignedShortValue],
[[event_description objectForKey:@"coord_y"] unsignedShortValue]);
}
else if ([event_type isEqualToString:@"keyboard"])
{
if ([[event_description objectForKey:@"subtype"] isEqualToString:@"scancode"])
instance->input->KeyboardEvent(instance->input,
[[event_description objectForKey:@"flags"] unsignedShortValue],
[[event_description objectForKey:@"scancode"] unsignedShortValue]);
instance->input->KeyboardEvent(
instance->input, [[event_description objectForKey:@"flags"] unsignedShortValue],
[[event_description objectForKey:@"scancode"] unsignedShortValue]);
else if ([[event_description objectForKey:@"subtype"] isEqualToString:@"unicode"])
instance->input->UnicodeKeyboardEvent(instance->input,
[[event_description objectForKey:@"flags"] unsignedShortValue],
[[event_description objectForKey:@"unicode_char"] unsignedShortValue]);
instance->input->UnicodeKeyboardEvent(
instance->input, [[event_description objectForKey:@"flags"] unsignedShortValue],
[[event_description objectForKey:@"unicode_char"] unsignedShortValue]);
else
NSLog(@"%s: doesn't know how to send keyboard input with subtype %@", __func__, [event_description objectForKey:@"subtype"]);
NSLog(@"%s: doesn't know how to send keyboard input with subtype %@", __func__,
[event_description objectForKey:@"subtype"]);
}
else if ([event_type isEqualToString:@"disconnect"])
should_continue = FALSE;
else
NSLog(@"%s: unrecognized event type: %@", __func__, event_type);
return should_continue;
}
BOOL ios_events_check_fds(mfInfo* mfi, fd_set* rfds)
{
if ( (mfi->event_pipe_consumer == -1) || !FD_ISSET(mfi->event_pipe_consumer, rfds))
BOOL ios_events_check_fds(mfInfo *mfi, fd_set *rfds)
{
if ((mfi->event_pipe_consumer == -1) || !FD_ISSET(mfi->event_pipe_consumer, rfds))
return TRUE;
uint32_t archived_data_length = 0;
ssize_t bytes_read;
// First, read the length of the blob
bytes_read = read(mfi->event_pipe_consumer, &archived_data_length, 4);
if (bytes_read == -1 || archived_data_length < 1 || archived_data_length > 32000)
{
NSLog(@"%s: just read length descriptor. bytes_read=%ld, archived_data_length=%u", __func__, bytes_read, archived_data_length);
NSLog(@"%s: just read length descriptor. bytes_read=%ld, archived_data_length=%u", __func__,
bytes_read, archived_data_length);
return FALSE;
}
//NSLog(@"reading %d bytes from input event pipe", archived_data_length);
NSMutableData * archived_object_data = [[NSMutableData alloc] initWithLength:archived_data_length];
bytes_read = read(mfi->event_pipe_consumer, [archived_object_data mutableBytes], archived_data_length);
// NSLog(@"reading %d bytes from input event pipe", archived_data_length);
NSMutableData *archived_object_data =
[[NSMutableData alloc] initWithLength:archived_data_length];
bytes_read =
read(mfi->event_pipe_consumer, [archived_object_data mutableBytes], archived_data_length);
if (bytes_read != archived_data_length)
{
NSLog(@"%s: attempted to read data; read %ld bytes but wanted %d bytes.", __func__, bytes_read, archived_data_length);
NSLog(@"%s: attempted to read data; read %ld bytes but wanted %d bytes.", __func__,
bytes_read, archived_data_length);
[archived_object_data release];
return FALSE;
}
id unarchived_object_data = [NSKeyedUnarchiver unarchiveObjectWithData:archived_object_data];
[archived_object_data release];
return ios_events_handle_event(mfi, unarchived_object_data);
}
BOOL ios_events_get_fds(mfInfo* mfi, void ** read_fds, int * read_count, void ** write_fds, int * write_count)
BOOL ios_events_get_fds(mfInfo *mfi, void **read_fds, int *read_count, void **write_fds,
int *write_count)
{
read_fds[*read_count] = (void *)(long)(mfi->event_pipe_consumer);
(*read_count)++;
@@ -120,26 +128,26 @@ BOOL ios_events_get_fds(mfInfo* mfi, void ** read_fds, int * read_count, void **
}
// Sets up the event pipe
BOOL ios_events_create_pipe(mfInfo* mfi)
BOOL ios_events_create_pipe(mfInfo *mfi)
{
int pipe_fds[2];
if (pipe(pipe_fds) == -1)
{
NSLog(@"%s: pipe failed.", __func__);
return FALSE;
}
mfi->event_pipe_consumer = pipe_fds[0];
mfi->event_pipe_producer = pipe_fds[1];
return TRUE;
}
void ios_events_free_pipe(mfInfo* mfi)
void ios_events_free_pipe(mfInfo *mfi)
{
int consumer_fd = mfi->event_pipe_consumer, producer_fd = mfi->event_pipe_producer;
mfi->event_pipe_consumer = mfi->event_pipe_producer = -1;
close(producer_fd);
close(consumer_fd);
close(consumer_fd);
}

View File

@@ -4,7 +4,8 @@
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "ios_freerdp.h"
@@ -13,23 +14,13 @@ BOOL ios_ui_begin_paint(rdpContext* context);
BOOL ios_ui_end_paint(rdpContext* context);
BOOL ios_ui_resize_window(rdpContext* context);
BOOL ios_ui_authenticate(freerdp* instance, char** username, char** password,
char** domain);
BOOL ios_ui_gw_authenticate(freerdp* instance, char** username, char** password,
char** domain);
DWORD ios_ui_verify_certificate(freerdp* instance,
const char* common_name,
const char* subject,
const char* issuer,
const char* fingerprint,
BOOL host_mismatch);
DWORD ios_ui_verify_changed_certificate(freerdp* instance,
const char* common_name,
const char* subject,
const char* issuer,
const char* new_fingerprint,
const char* old_subject,
const char* old_issuer,
const char* old_fingerprint);
BOOL ios_ui_authenticate(freerdp* instance, char** username, char** password, char** domain);
BOOL ios_ui_gw_authenticate(freerdp* instance, char** username, char** password, char** domain);
DWORD ios_ui_verify_certificate(freerdp* instance, const char* common_name, const char* subject,
const char* issuer, const char* fingerprint, BOOL host_mismatch);
DWORD ios_ui_verify_changed_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* new_fingerprint, const char* old_subject,
const char* old_issuer, const char* old_fingerprint);
void ios_allocate_display_buffer(mfInfo* mfi);

View File

@@ -4,7 +4,8 @@
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@@ -17,22 +18,26 @@
#pragma mark -
#pragma mark Certificate authentication
static void ios_resize_display_buffer(mfInfo* mfi);
static BOOL ios_ui_authenticate_raw(freerdp* instance, char** username,
char** password,
char** domain, const char* title)
static void ios_resize_display_buffer(mfInfo *mfi);
static BOOL ios_ui_authenticate_raw(freerdp *instance, char **username, char **password,
char **domain, const char *title)
{
mfInfo* mfi = MFI_FROM_INSTANCE(instance);
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(*username) ? [NSString stringWithUTF8String:*username] : @"", @"username",
(*password) ? [NSString stringWithUTF8String:*password] : @"", @"password",
(*domain) ? [NSString stringWithUTF8String:*domain] : @"", @"domain",
[NSString stringWithUTF8String:instance->settings->ServerHostname],
@"hostname", // used for the auth prompt message; not changed
nil];
mfInfo *mfi = MFI_FROM_INSTANCE(instance);
NSMutableDictionary *params = [NSMutableDictionary
dictionaryWithObjectsAndKeys:(*username) ? [NSString stringWithUTF8String:*username] : @"",
@"username",
(*password) ? [NSString stringWithUTF8String:*password] : @"",
@"password",
(*domain) ? [NSString stringWithUTF8String:*domain] : @"",
@"domain",
[NSString
stringWithUTF8String:instance->settings->ServerHostname],
@"hostname", // used for the auth prompt message; not changed
nil];
// request auth UI
[mfi->session performSelectorOnMainThread:@selector(
sessionRequestsAuthenticationWithParams:) withObject:params waitUntilDone:YES];
[mfi->session performSelectorOnMainThread:@selector(sessionRequestsAuthenticationWithParams:)
withObject:params
waitUntilDone:YES];
// wait for UI request to be completed
[[mfi->session uiRequestCompleted] lock];
[[mfi->session uiRequestCompleted] wait];
@@ -64,40 +69,35 @@ static BOOL ios_ui_authenticate_raw(freerdp* instance, char** username,
return TRUE;
}
BOOL ios_ui_authenticate(freerdp* instance, char** username, char** password,
char** domain)
BOOL ios_ui_authenticate(freerdp *instance, char **username, char **password, char **domain)
{
return ios_ui_authenticate_raw(instance, username, password, domain, "");
}
BOOL ios_ui_gw_authenticate(freerdp* instance, char** username, char** password,
char** domain)
BOOL ios_ui_gw_authenticate(freerdp *instance, char **username, char **password, char **domain)
{
return ios_ui_authenticate_raw(instance, username, password, domain, "gateway");
}
DWORD ios_ui_verify_certificate(freerdp* instance,
const char* common_name,
const char* subject,
const char* issuer,
const char* fingerprint,
BOOL host_mismatch)
DWORD ios_ui_verify_certificate(freerdp *instance, const char *common_name, const char *subject,
const char *issuer, const char *fingerprint, BOOL host_mismatch)
{
// check whether we accept all certificates
if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"security.accept_certificates"] == YES)
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"] == YES)
return 2;
mfInfo* mfi = MFI_FROM_INSTANCE(instance);
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject",
(issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer",
(fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint",
nil];
mfInfo *mfi = MFI_FROM_INSTANCE(instance);
NSMutableDictionary *params = [NSMutableDictionary
dictionaryWithObjectsAndKeys:(subject) ? [NSString stringWithUTF8String:subject] : @"",
@"subject",
(issuer) ? [NSString stringWithUTF8String:issuer] : @"",
@"issuer",
(fingerprint) ? [NSString stringWithUTF8String:subject] : @"",
@"fingerprint", nil];
// request certificate verification UI
[mfi->session performSelectorOnMainThread:@selector(
sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES];
[mfi->session performSelectorOnMainThread:@selector(sessionVerifyCertificateWithParams:)
withObject:params
waitUntilDone:YES];
// wait for UI request to be completed
[[mfi->session uiRequestCompleted] lock];
[[mfi->session uiRequestCompleted] wait];
@@ -112,51 +112,45 @@ DWORD ios_ui_verify_certificate(freerdp* instance,
return 1;
}
DWORD ios_ui_verify_changed_certificate(freerdp* instance,
const char* common_name,
const char* subject,
const char* issuer,
const char* new_fingerprint,
const char* old_subject,
const char* old_issuer,
const char* old_fingerprint)
DWORD ios_ui_verify_changed_certificate(freerdp *instance, const char *common_name,
const char *subject, const char *issuer,
const char *new_fingerprint, const char *old_subject,
const char *old_issuer, const char *old_fingerprint)
{
return ios_ui_verify_certificate(instance, common_name, subject, issuer,
new_fingerprint, FALSE);
return ios_ui_verify_certificate(instance, common_name, subject, issuer, new_fingerprint,
FALSE);
}
#pragma mark -
#pragma mark Graphics updates
BOOL ios_ui_begin_paint(rdpContext* context)
BOOL ios_ui_begin_paint(rdpContext *context)
{
rdpGdi* gdi = context->gdi;
rdpGdi *gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = TRUE;
return TRUE;
}
BOOL ios_ui_end_paint(rdpContext* context)
BOOL ios_ui_end_paint(rdpContext *context)
{
mfInfo* mfi = MFI_FROM_INSTANCE(context->instance);
rdpGdi* gdi = context->gdi;
CGRect dirty_rect = CGRectMake(gdi->primary->hdc->hwnd->invalid->x,
gdi->primary->hdc->hwnd->invalid->y, gdi->primary->hdc->hwnd->invalid->w,
gdi->primary->hdc->hwnd->invalid->h);
mfInfo *mfi = MFI_FROM_INSTANCE(context->instance);
rdpGdi *gdi = context->gdi;
CGRect dirty_rect =
CGRectMake(gdi->primary->hdc->hwnd->invalid->x, gdi->primary->hdc->hwnd->invalid->y,
gdi->primary->hdc->hwnd->invalid->w, gdi->primary->hdc->hwnd->invalid->h);
if (!gdi->primary->hdc->hwnd->invalid->null)
[mfi->session performSelectorOnMainThread:@selector(
setNeedsDisplayInRectAsValue:) withObject:[NSValue valueWithCGRect:dirty_rect]
waitUntilDone:NO];
[mfi->session performSelectorOnMainThread:@selector(setNeedsDisplayInRectAsValue:)
withObject:[NSValue valueWithCGRect:dirty_rect]
waitUntilDone:NO];
return TRUE;
}
BOOL ios_ui_resize_window(rdpContext* context)
BOOL ios_ui_resize_window(rdpContext *context)
{
rdpSettings* settings;
rdpGdi* gdi;
rdpSettings *settings;
rdpGdi *gdi;
if (!context || !context->settings)
return FALSE;
@@ -171,37 +165,38 @@ BOOL ios_ui_resize_window(rdpContext* context)
return TRUE;
}
#pragma mark -
#pragma mark Exported
static void ios_create_bitmap_context(mfInfo* mfi)
static void ios_create_bitmap_context(mfInfo *mfi)
{
[mfi->session performSelectorOnMainThread:@selector(
sessionBitmapContextWillChange) withObject:nil waitUntilDone:YES];
rdpGdi* gdi = mfi->instance->context->gdi;
[mfi->session performSelectorOnMainThread:@selector(sessionBitmapContextWillChange)
withObject:nil
waitUntilDone:YES];
rdpGdi *gdi = mfi->instance->context->gdi;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
if (GetBytesPerPixel(gdi->dstFormat) == 2)
mfi->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width,
gdi->height, 5, gdi->stride, colorSpace,
kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst);
mfi->bitmap_context = CGBitmapContextCreate(
gdi->primary_buffer, gdi->width, gdi->height, 5, gdi->stride, colorSpace,
kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst);
else
mfi->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width,
gdi->height, 8, gdi->stride, colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
mfi->bitmap_context = CGBitmapContextCreate(
gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->stride, colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
CGColorSpaceRelease(colorSpace);
[mfi->session performSelectorOnMainThread:@selector(
sessionBitmapContextDidChange) withObject:nil waitUntilDone:YES];
[mfi->session performSelectorOnMainThread:@selector(sessionBitmapContextDidChange)
withObject:nil
waitUntilDone:YES];
}
void ios_allocate_display_buffer(mfInfo* mfi)
void ios_allocate_display_buffer(mfInfo *mfi)
{
ios_create_bitmap_context(mfi);
}
void ios_resize_display_buffer(mfInfo* mfi)
void ios_resize_display_buffer(mfInfo *mfi)
{
// Release the old context in a thread-safe manner
CGContextRef old_context = mfi->bitmap_context;
@@ -210,4 +205,3 @@ void ios_resize_display_buffer(mfInfo* mfi)
// Create the new context
ios_create_bitmap_context(mfi);
}

View File

@@ -1,16 +1,16 @@
/*
File: Reachability.h
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
Version: 2.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under
Apple's copyrights in this original Apple software (the "Apple Software"), to
@@ -26,13 +26,13 @@
including but not limited to any patent rights that may be infringed by your
derivative works or by other works in which the Apple Software may be
incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -40,50 +40,48 @@
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2010 Apple Inc. All Rights Reserved.
*/
Copyright (C) 2010 Apple Inc. All Rights Reserved.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
typedef enum {
typedef enum
{
NotReachable = 0,
ReachableViaWiFi = 1,
ReachableViaWWAN = 2
} NetworkStatus;
#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
@interface Reachability: NSObject
@interface Reachability : NSObject
{
BOOL localWiFiRef;
SCNetworkReachabilityRef reachabilityRef;
}
//reachabilityWithHostName- Use to check the reachability of a particular host name.
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
// reachabilityWithHostName- Use to check the reachability of a particular host name.
+ (Reachability *)reachabilityWithHostName:(NSString *)hostName;
//reachabilityWithAddress- Use to check the reachability of a particular IP address.
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
// reachabilityWithAddress- Use to check the reachability of a particular IP address.
+ (Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
//reachabilityForInternetConnection- checks whether the default route is available.
// reachabilityForInternetConnection- checks whether the default route is available.
// Should be used by applications that do not connect to a particular host
+ (Reachability*) reachabilityForInternetConnection;
+ (Reachability *)reachabilityForInternetConnection;
//reachabilityForLocalWiFi- checks whether a local wifi connection is available.
+ (Reachability*) reachabilityForLocalWiFi;
// reachabilityForLocalWiFi- checks whether a local wifi connection is available.
+ (Reachability *)reachabilityForLocalWiFi;
//Start listening for reachability notifications on the current run loop
- (BOOL) startNotifier;
- (void) stopNotifier;
// Start listening for reachability notifications on the current run loop
- (BOOL)startNotifier;
- (void)stopNotifier;
- (NetworkStatus) currentReachabilityStatus;
//WWAN may be available, but not active until a connection has been established.
//WiFi may require a connection for VPN on Demand.
- (BOOL) connectionRequired;
- (NetworkStatus)currentReachabilityStatus;
// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
- (BOOL)connectionRequired;
@end

View File

@@ -1,16 +1,16 @@
/*
File: Reachability.m
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
Version: 2.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under
Apple's copyrights in this original Apple software (the "Apple Software"), to
@@ -26,13 +26,13 @@
including but not limited to any patent rights that may be infringed by your
derivative works or by other works in which the Apple Software may be
incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -40,9 +40,9 @@
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2010 Apple Inc. All Rights Reserved.
*/
#import <sys/socket.h>
@@ -58,52 +58,53 @@
#define kShouldPrintReachabilityFlags 1
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char *comment)
{
#if kShouldPrintReachabilityFlags
NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
comment
);
NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', comment);
#endif
}
@implementation Reachability
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,
void *info)
{
#pragma unused (target, flags)
#pragma unused(target, flags)
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
NSCAssert([(NSObject *)info isKindOfClass:[Reachability class]],
@"info was wrong class in ReachabilityCallback");
//We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
// We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
// in case someon uses the Reachablity object in a different thread.
NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
Reachability* noteObject = (Reachability*) info;
NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
Reachability *noteObject = (Reachability *)info;
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
[[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
object:noteObject];
[myPool release];
}
- (BOOL) startNotifier
- (BOOL)startNotifier
{
BOOL retVal = NO;
SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
SCNetworkReachabilityContext context = { 0, self, NULL, NULL, NULL };
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
{
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
if (SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode))
{
retVal = YES;
}
@@ -111,32 +112,34 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
return retVal;
}
- (void) stopNotifier
- (void)stopNotifier
{
if(reachabilityRef!= NULL)
if (reachabilityRef != NULL)
{
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
}
}
- (void) dealloc
- (void)dealloc
{
[self stopNotifier];
if(reachabilityRef!= NULL)
if (reachabilityRef != NULL)
{
CFRelease(reachabilityRef);
}
[super dealloc];
}
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
+ (Reachability *)reachabilityWithHostName:(NSString *)hostName;
{
Reachability* retVal = NULL;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if(reachability!= NULL)
Reachability *retVal = NULL;
SCNetworkReachabilityRef reachability =
SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if (reachability != NULL)
{
retVal= [[[self alloc] init] autorelease];
if(retVal!= NULL)
retVal = [[[self alloc] init] autorelease];
if (retVal != NULL)
{
retVal->reachabilityRef = reachability;
retVal->localWiFiRef = NO;
@@ -145,14 +148,15 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
return retVal;
}
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
+ (Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
Reachability* retVal = NULL;
if(reachability!= NULL)
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(
kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
Reachability *retVal = NULL;
if (reachability != NULL)
{
retVal= [[[self alloc] init] autorelease];
if(retVal!= NULL)
retVal = [[[self alloc] init] autorelease];
if (retVal != NULL)
{
retVal->reachabilityRef = reachability;
retVal->localWiFiRef = NO;
@@ -161,16 +165,16 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
return retVal;
}
+ (Reachability*) reachabilityForInternetConnection;
+ (Reachability *)reachabilityForInternetConnection;
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress: &zeroAddress];
return [self reachabilityWithAddress:&zeroAddress];
}
+ (Reachability*) reachabilityForLocalWiFi;
+ (Reachability *)reachabilityForLocalWiFi;
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
@@ -178,8 +182,8 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
if(retVal!= NULL)
Reachability *retVal = [self reachabilityWithAddress:&localWifiAddress];
if (retVal != NULL)
{
retVal->localWiFiRef = YES;
}
@@ -188,19 +192,20 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
#pragma mark Network Flag Handling
- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
- (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
BOOL retVal = NotReachable;
if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
if ((flags & kSCNetworkReachabilityFlagsReachable) &&
(flags & kSCNetworkReachabilityFlagsIsDirect))
{
retVal = ReachableViaWiFi;
retVal = ReachableViaWiFi;
}
return retVal;
}
- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "networkStatusForFlags");
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
@@ -210,28 +215,27 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
}
BOOL retVal = NotReachable;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
// if target host is reachable and no connection is required
// then we'll assume (for now) that your on Wi-Fi
retVal = ReachableViaWiFi;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
// ... and the connection is on-demand (or on-traffic) if the
// calling application is using the CFSocketStream or higher APIs
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
// ... and no [user] intervention is needed
retVal = ReachableViaWiFi;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
// ... and the connection is on-demand (or on-traffic) if the
// calling application is using the CFSocketStream or higher APIs
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
// ... and no [user] intervention is needed
retVal = ReachableViaWiFi;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
// ... but WWAN connections are OK if the calling application
@@ -241,7 +245,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
return retVal;
}
- (BOOL) connectionRequired;
- (BOOL)connectionRequired;
{
NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
SCNetworkReachabilityFlags flags;
@@ -252,20 +256,20 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
return NO;
}
- (NetworkStatus) currentReachabilityStatus
- (NetworkStatus)currentReachabilityStatus
{
NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
NetworkStatus retVal = NotReachable;
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
if(localWiFiRef)
if (localWiFiRef)
{
retVal = [self localWiFiStatusForFlags: flags];
retVal = [self localWiFiStatusForFlags:flags];
}
else
{
retVal = [self networkStatusForFlags: flags];
retVal = [self networkStatusForFlags:flags];
}
}
return retVal;

View File

@@ -29,13 +29,20 @@
#import <UIKit/UIKit.h>
@interface SFHFKeychainUtils : NSObject {
@interface SFHFKeychainUtils : NSObject
{
}
+ (NSString *) getPasswordForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error;
+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServerName: (NSString *) serverName updateExisting: (BOOL) updateExisting error: (NSError **) error;
+ (BOOL) deleteItemForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error;
+ (NSString *)getPasswordForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error;
+ (BOOL)storeUsername:(NSString *)username
andPassword:(NSString *)password
forServerName:(NSString *)serverName
updateExisting:(BOOL)updateExisting
error:(NSError **)error;
+ (BOOL)deleteItemForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error;
@end

View File

@@ -34,7 +34,9 @@ static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
@interface SFHFKeychainUtils (PrivateMethods)
+ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error;
+ (SecKeychainItemRef)getKeychainItemReferenceForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error;
@end
#endif
@@ -42,391 +44,456 @@ static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
+ (NSString *) getPasswordForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error {
if (!username || !serviceName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ (NSString *)getPasswordForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error
{
if (!username || !serviceName)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
return nil;
}
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServerName: serverName error: error];
if (*error || !item) {
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername:username
andServerName:serverName
error:error];
if (*error || !item)
{
return nil;
}
// from Advanced Mac OS X Programming, ch. 16
UInt32 length;
char *password;
SecKeychainAttribute attributes[8];
SecKeychainAttributeList list;
attributes[0].tag = kSecAccountItemAttr;
attributes[1].tag = kSecDescriptionItemAttr;
attributes[2].tag = kSecLabelItemAttr;
attributes[3].tag = kSecModDateItemAttr;
list.count = 4;
list.attr = attributes;
OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password);
if (status != noErr) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
UInt32 length;
char *password;
SecKeychainAttribute attributes[8];
SecKeychainAttributeList list;
attributes[0].tag = kSecAccountItemAttr;
attributes[1].tag = kSecDescriptionItemAttr;
attributes[2].tag = kSecLabelItemAttr;
attributes[3].tag = kSecModDateItemAttr;
list.count = 4;
list.attr = attributes;
OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password);
if (status != noErr)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
return nil;
}
}
NSString *passwordString = nil;
if (password != NULL) {
if (password != NULL)
{
char passwordBuffer[1024];
if (length > 1023) {
if (length > 1023)
{
length = 1023;
}
strncpy(passwordBuffer, password, length);
passwordBuffer[length] = '\0';
passwordString = [NSString stringWithCString:passwordBuffer];
}
SecKeychainItemFreeContent(&list, password);
CFRelease(item);
return passwordString;
CFRelease(item);
return passwordString;
}
+ (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServerName: (NSString *) serverName updateExisting: (BOOL) updateExisting error: (NSError **) error {
if (!username || !password || !serverName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ (void)storeUsername:(NSString *)username
andPassword:(NSString *)password
forServerName:(NSString *)serverName
updateExisting:(BOOL)updateExisting
error:(NSError **)error
{
if (!username || !password || !serverName)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
return;
}
OSStatus status = noErr;
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServerName: serverName error: error];
if (*error && [*error code] != noErr) {
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername:username
andServerName:serverName
error:error];
if (*error && [*error code] != noErr)
{
return;
}
*error = nil;
if (item) {
status = SecKeychainItemModifyAttributesAndData(item,
NULL,
strlen([password UTF8String]),
[password UTF8String]);
if (item)
{
status = SecKeychainItemModifyAttributesAndData(item, NULL, strlen([password UTF8String]),
[password UTF8String]);
CFRelease(item);
}
else {
status = SecKeychainAddGenericPassword(NULL,
strlen([serverName UTF8String]),
[serverName UTF8String],
strlen([username UTF8String]),
[username UTF8String],
strlen([password UTF8String]),
[password UTF8String],
NULL);
else
{
status = SecKeychainAddGenericPassword(
NULL, strlen([serverName UTF8String]), [serverName UTF8String],
strlen([username UTF8String]), [username UTF8String], strlen([password UTF8String]),
[password UTF8String], NULL);
}
if (status != noErr) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
if (status != noErr)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
}
}
+ (void) deleteItemForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error {
if (!username || !serverName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil];
+ (void)deleteItemForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error
{
if (!username || !serverName)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:2000 userInfo:nil];
return;
}
*error = nil;
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServerName: serverName error: error];
if (*error && [*error code] != noErr) {
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername:username
andServerName:serverName
error:error];
if (*error && [*error code] != noErr)
{
return;
}
OSStatus status;
if (item) {
if (item)
{
status = SecKeychainItemDelete(item);
CFRelease(item);
}
if (status != noErr) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
if (status != noErr)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
}
}
+ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error {
if (!username || !serverName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ (SecKeychainItemRef)getKeychainItemReferenceForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error
{
if (!username || !serverName)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
return nil;
}
*error = nil;
SecKeychainItemRef item;
OSStatus status = SecKeychainFindGenericPassword(NULL,
strlen([serverName UTF8String]),
[serverName UTF8String],
strlen([username UTF8String]),
[username UTF8String],
NULL,
NULL,
&item);
if (status != noErr) {
if (status != errSecItemNotFound) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
OSStatus status = SecKeychainFindGenericPassword(
NULL, strlen([serverName UTF8String]), [serverName UTF8String],
strlen([username UTF8String]), [username UTF8String], NULL, NULL, &item);
if (status != noErr)
{
if (status != errSecItemNotFound)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
code:status
userInfo:nil];
}
return nil;
return nil;
}
return item;
}
#else
+ (NSString *) getPasswordForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error {
if (!username || !serverName) {
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ (NSString *)getPasswordForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error
{
if (!username || !serverName)
{
if (error != nil)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
}
return nil;
}
if (error != nil) {
if (error != nil)
{
*error = nil;
}
// Set up a query dictionary with the base query attributes: item type (generic), username, and service
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serverName, nil] autorelease];
NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
// First do a query for attributes, in case we already have a Keychain item with no password data set.
// One likely way such an incorrect item could have come about is due to the previous (incorrect)
// version of this code (which set the password as a generic attribute instead of password data).
// Set up a query dictionary with the base query attributes: item type (generic), username, and
// service
NSArray *keys = [[[NSArray alloc]
initWithObjects:(NSString *)kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword,
username, serverName, nil] autorelease];
NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects:objects
forKeys:keys] autorelease];
// First do a query for attributes, in case we already have a Keychain item with no password
// data set. One likely way such an incorrect item could have come about is due to the previous
// (incorrect) version of this code (which set the password as a generic attribute instead of
// password data).
NSDictionary *attributeResult = NULL;
NSMutableDictionary *attributeQuery = [query mutableCopy];
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(id) kSecReturnAttributes];
OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult);
[attributeQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
OSStatus status =
SecItemCopyMatching((CFDictionaryRef)attributeQuery, (CFTypeRef *)&attributeResult);
[attributeResult release];
[attributeQuery release];
if (status != noErr) {
if (status != noErr)
{
// No existing item found--simply return nil for the password
if (error != nil && status != errSecItemNotFound) {
//Only return an error if a real exception happened--not simply for "not found."
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
if (error != nil && status != errSecItemNotFound)
{
// Only return an error if a real exception happened--not simply for "not found."
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
code:status
userInfo:nil];
}
return nil;
}
// We have an existing item, now query for the password data associated with it.
NSData *resultData = nil;
NSMutableDictionary *passwordQuery = [query mutableCopy];
[passwordQuery setObject: (id) kCFBooleanTrue forKey: (id) kSecReturnData];
status = SecItemCopyMatching((CFDictionaryRef) passwordQuery, (CFTypeRef *) &resultData);
[passwordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
status = SecItemCopyMatching((CFDictionaryRef)passwordQuery, (CFTypeRef *)&resultData);
[resultData autorelease];
[passwordQuery release];
if (status != noErr) {
if (status == errSecItemNotFound) {
// We found attributes for the item previously, but no password now, so return a special error.
// Users of this API will probably want to detect this error and prompt the user to
// re-enter their credentials. When you attempt to store the re-entered credentials
if (status != noErr)
{
if (status == errSecItemNotFound)
{
// We found attributes for the item previously, but no password now, so return a special
// error. Users of this API will probably want to detect this error and prompt the user
// to re-enter their credentials. When you attempt to store the re-entered credentials
// using storeUsername:andPassword:forServiceName:updateExisting:error
// the old, incorrect entry will be deleted and a new one with a properly encrypted
// password will be added.
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
if (error != nil)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
code:-1999
userInfo:nil];
}
}
else {
else
{
// Something else went wrong. Simply return the normal Keychain API error code.
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
if (error != nil)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
code:status
userInfo:nil];
}
}
return nil;
}
NSString *password = nil;
if (resultData) {
password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding];
NSString *password = nil;
if (resultData)
{
password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
}
else {
// There is an existing item, but we weren't able to get password data for it for some reason,
// Possibly as a result of an item being incorrectly entered by the previous code.
else
{
// There is an existing item, but we weren't able to get password data for it for some
// reason, Possibly as a result of an item being incorrectly entered by the previous code.
// Set the -1999 error so the code above us can prompt the user again.
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
if (error != nil)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-1999 userInfo:nil];
}
}
return [password autorelease];
}
+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServerName: (NSString *) serverName updateExisting: (BOOL) updateExisting error: (NSError **) error
{
if (!username || !password || !serverName)
{
if (error != nil)
{
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ (BOOL)storeUsername:(NSString *)username
andPassword:(NSString *)password
forServerName:(NSString *)serverName
updateExisting:(BOOL)updateExisting
error:(NSError **)error
{
if (!username || !password || !serverName)
{
if (error != nil)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
}
return NO;
}
// See if we already have a password entered for these credentials.
NSError *getError = nil;
NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServerName: serverName error:&getError];
if ([getError code] == -1999)
{
// There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code.
// Delete the existing item before moving on entering a correct one.
NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername:username
andServerName:serverName
error:&getError];
if ([getError code] == -1999)
{
// There is an existing entry without a password properly stored (possibly as a result of
// the previous incorrect version of this code. Delete the existing item before moving on
// entering a correct one.
getError = nil;
[self deleteItemForUsername: username andServerName: serverName error: &getError];
if ([getError code] != noErr)
{
if (error != nil)
{
[self deleteItemForUsername:username andServerName:serverName error:&getError];
if ([getError code] != noErr)
{
if (error != nil)
{
*error = getError;
}
return NO;
}
}
else if ([getError code] != noErr)
{
if (error != nil)
{
else if ([getError code] != noErr)
{
if (error != nil)
{
*error = getError;
}
return NO;
}
if (error != nil)
{
if (error != nil)
{
*error = nil;
}
OSStatus status = noErr;
if (existingPassword)
{
if (existingPassword)
{
// We have an existing, properly entered item with a password.
// Update the existing item.
if (![existingPassword isEqualToString:password] && updateExisting)
{
//Only update if we're allowed to update existing. If not, simply do nothing.
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass,
kSecAttrService,
kSecAttrLabel,
kSecAttrAccount,
nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword,
serverName,
serverName,
username,
nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (NSString *) kSecValueData]);
if (![existingPassword isEqualToString:password] && updateExisting)
{
// Only update if we're allowed to update existing. If not, simply do nothing.
NSArray *keys =
[[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrService,
kSecAttrLabel, kSecAttrAccount, nil] autorelease];
NSArray *objects =
[[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword, serverName,
serverName, username, nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects
forKeys:keys] autorelease];
status = SecItemUpdate(
(CFDictionaryRef)query,
(CFDictionaryRef)[NSDictionary
dictionaryWithObject:[password dataUsingEncoding:NSUTF8StringEncoding]
forKey:(NSString *)kSecValueData]);
}
}
else
{
else
{
// No existing entry (or an existing, improperly entered, and therefore now
// deleted, entry). Create a new entry.
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass,
kSecAttrService,
kSecAttrLabel,
kSecAttrAccount,
kSecValueData,
nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword,
serverName,
serverName,
username,
[password dataUsingEncoding: NSUTF8StringEncoding],
nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
status = SecItemAdd((CFDictionaryRef) query, NULL);
NSArray *keys =
[[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrService, kSecAttrLabel,
kSecAttrAccount, kSecValueData, nil] autorelease];
NSArray *objects = [[[NSArray alloc]
initWithObjects:(NSString *)kSecClassGenericPassword, serverName, serverName, username,
[password dataUsingEncoding:NSUTF8StringEncoding], nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects
forKeys:keys] autorelease];
status = SecItemAdd((CFDictionaryRef)query, NULL);
}
if (error != nil && status != noErr)
{
if (error != nil && status != noErr)
{
// Something went wrong with adding the new item. Return the Keychain error code.
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
return NO;
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
return NO;
}
return YES;
return YES;
}
+ (BOOL) deleteItemForUsername: (NSString *) username andServerName: (NSString *) serverName error: (NSError **) error
+ (BOOL)deleteItemForUsername:(NSString *)username
andServerName:(NSString *)serverName
error:(NSError **)error
{
if (!username || !serverName)
{
if (error != nil)
{
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
if (!username || !serverName)
{
if (error != nil)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
}
return NO;
}
if (error != nil)
{
if (error != nil)
{
*error = nil;
}
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serverName, kCFBooleanTrue, nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
OSStatus status = SecItemDelete((CFDictionaryRef) query);
if (error != nil && status != noErr)
{
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
return NO;
NSArray *keys =
[[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrAccount, kSecAttrService,
kSecReturnAttributes, nil] autorelease];
NSArray *objects =
[[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword, username,
serverName, kCFBooleanTrue, nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects forKeys:keys] autorelease];
OSStatus status = SecItemDelete((CFDictionaryRef)query);
if (error != nil && status != noErr)
{
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
return NO;
}
return YES;
return YES;
}
#endif

View File

@@ -1,10 +1,11 @@
/*
Basic type defines for TSX RDC
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#ifndef TSXRemoteDesktop_TSXTypes_h
@@ -15,33 +16,40 @@
// Represents the underlying state of a TWSession RDP connection.
typedef enum _TSXConnectionState
{
TSXConnectionClosed = 0, // Session either hasn't begun connecting, or its connection has finished disconnecting.
TSXConnectionConnecting = 1, // Session is in the process of establishing an RDP connection. A TCP or SSL connection might be established, but the RDP initialization sequence isn't finished.
TSXConnectionConnected = 2, // Session has a full RDP connection established; though if the windows computer doesn't support NLA, a login screen might be shown in the session.
TSXConnectionDisconnected = 3 // Session is disconnected at the RDP layer. TSX RDC might still be disposing of resources, however.
TSXConnectionClosed =
0, // Session either hasn't begun connecting, or its connection has finished disconnecting.
TSXConnectionConnecting =
1, // Session is in the process of establishing an RDP connection. A TCP or SSL connection
// might be established, but the RDP initialization sequence isn't finished.
TSXConnectionConnected =
2, // Session has a full RDP connection established; though if the windows computer doesn't
// support NLA, a login screen might be shown in the session.
TSXConnectionDisconnected = 3 // Session is disconnected at the RDP layer. TSX RDC might still
// be disposing of resources, however.
} TSXConnectionState;
#pragma mark Session settings
// Represents the type of screen resolution the user has selected. Most are dynamic sizes, meaning that the actual session dimensions are calculated when connecting.
// Represents the type of screen resolution the user has selected. Most are dynamic sizes, meaning
// that the actual session dimensions are calculated when connecting.
typedef enum _TSXScreenOptions
{
TSXScreenOptionFixed = 0, // A static resolution, like 1024x768
TSXScreenOptionFitScreen = 1, // Upon connection, fit the session to the entire screen size
TSXScreenOptionCustom = 2, // Like fixed just specified by the user
TSXScreenOptionFixed = 0, // A static resolution, like 1024x768
TSXScreenOptionFitScreen = 1, // Upon connection, fit the session to the entire screen size
TSXScreenOptionCustom = 2, // Like fixed just specified by the user
} TSXScreenOptions;
typedef enum _TSXAudioPlaybackOptions
{
TSXAudioPlaybackLocal = 0,
TSXAudioPlaybackLocal = 0,
TSXAudioPlaybackServer = 1,
TSXAudioPlaybackSilent = 2
} TSXAudioPlaybackOptions;
typedef enum _TSXProtocolSecurityOptions
{
TSXProtocolSecurityAutomatic = 0,
TSXProtocolSecurityRDP = 1,
TSXProtocolSecurityAutomatic = 0,
TSXProtocolSecurityRDP = 1,
TSXProtocolSecurityTLS = 2,
TSXProtocolSecurityNLA = 3
} TSXProtocolSecurityOptions;

View File

@@ -1,42 +1,43 @@
/*
Utility functions
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TSXTypes.h"
// helper macro to encode a table path into a tag value (used to identify controls in their delegate handlers)
// helper macro to encode a table path into a tag value (used to identify controls in their delegate
// handlers)
#define GET_TAG(section, row) ((((int)section) << 16) | ((int)(row)))
#define GET_TAG_FROM_PATH(path) ((((int)path.section) << 16) | ((int)(path.row)))
BOOL ScanHostNameAndPort(NSString* address, NSString** host, unsigned short* port);
BOOL ScanHostNameAndPort(NSString *address, NSString **host, unsigned short *port);
#pragma mark -
#pragma mark Screen Resolutions
NSString* ScreenResolutionDescription(TSXScreenOptions type, int width, int height);
BOOL ScanScreenResolution(NSString* description, int* width, int* height, TSXScreenOptions* type);
NSString *ScreenResolutionDescription(TSXScreenOptions type, int width, int height);
BOOL ScanScreenResolution(NSString *description, int *width, int *height, TSXScreenOptions *type);
NSDictionary* SelectionForColorSetting(void);
NSArray* ResolutionModes(void);
NSDictionary *SelectionForColorSetting(void);
NSArray *ResolutionModes(void);
#pragma mark Security Protocol
NSString* ProtocolSecurityDescription(TSXProtocolSecurityOptions type);
BOOL ScanProtocolSecurity(NSString* description, TSXProtocolSecurityOptions* type);
NSDictionary* SelectionForSecuritySetting(void);
NSString *ProtocolSecurityDescription(TSXProtocolSecurityOptions type);
BOOL ScanProtocolSecurity(NSString *description, TSXProtocolSecurityOptions *type);
NSDictionary *SelectionForSecuritySetting(void);
#pragma mark Bookmarks
@class BookmarkBase;
NSMutableArray* FilterBookmarks(NSArray* bookmarks, NSArray* filter_words);
NSMutableArray* FilterHistory(NSArray* history, NSString* filterStr);
NSMutableArray *FilterBookmarks(NSArray *bookmarks, NSArray *filter_words);
NSMutableArray *FilterHistory(NSArray *history, NSString *filterStr);
#pragma mark iPad/iPhone detection
@@ -44,7 +45,7 @@ BOOL IsPad(void);
BOOL IsPhone(void);
#pragma mark Version Info
NSString* TSXAppFullVersion(void);
NSString *TSXAppFullVersion(void);
#pragma mark Touch/Mouse handling
@@ -54,10 +55,10 @@ void SetSwapMouseButtonsFlag(BOOL swapped);
// set invert scrolling flag
void SetInvertScrollingFlag(BOOL invert);
// return event value for left mouse button
// return event value for left mouse button
int GetLeftMouseButtonClickEvent(BOOL down);
// return event value for right mouse button
// return event value for right mouse button
int GetRightMouseButtonClickEvent(BOOL down);
// return event value for mouse move event
@@ -74,7 +75,6 @@ CGFloat GetScrollGestureDelta(void);
void WakeUpWWAN(void);
#pragma mark System Info functions
NSString* TSXGetPlatform(void);
NSString *TSXGetPlatform(void);
BOOL TSXDeviceHasJailBreak(void);
NSString* TSXGetPrimaryMACAddress(NSString *sep);
NSString *TSXGetPrimaryMACAddress(NSString *sep);

View File

@@ -4,7 +4,8 @@
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "Utils.h"
@@ -21,8 +22,7 @@
#include <ifaddrs.h>
#include <net/if_dl.h>
BOOL ScanHostNameAndPort(NSString* address, NSString** host,
unsigned short* port)
BOOL ScanHostNameAndPort(NSString *address, NSString **host, unsigned short *port)
{
*host = @"";
*port = 0;
@@ -30,8 +30,7 @@ BOOL ScanHostNameAndPort(NSString* address, NSString** host,
if (![address length])
return NO;
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"rdp://%@",
address]];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"rdp://%@", address]];
if (!url || ![[url host] length])
return NO;
@@ -44,19 +43,18 @@ BOOL ScanHostNameAndPort(NSString* address, NSString** host,
#pragma mark -
#pragma mark Working with Screen Resolutions
NSString* LocalizedFitScreen()
NSString *LocalizedFitScreen()
{
return NSLocalizedString(@"Automatic",
@"Screen resolution selector: Automatic resolution (Full Screen on iPad, reasonable size on iPhone)");
return NSLocalizedString(@"Automatic", @"Screen resolution selector: Automatic resolution "
@"(Full Screen on iPad, reasonable size on iPhone)");
}
NSString* LocalizedCustom()
NSString *LocalizedCustom()
{
return NSLocalizedString(@"Custom", @"Screen resolution selector: Custom");
}
BOOL ScanScreenResolution(NSString* description, int* width, int* height,
TSXScreenOptions* type)
BOOL ScanScreenResolution(NSString *description, int *width, int *height, TSXScreenOptions *type)
{
*height = 0;
*width = 0;
@@ -73,9 +71,9 @@ BOOL ScanScreenResolution(NSString* description, int* width, int* height,
return YES;
}
NSArray* resolution_components = [description
componentsSeparatedByCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:@"x*×"]];
NSArray *resolution_components = [description
componentsSeparatedByCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:@"x*×"]];
if ([resolution_components count] != 2)
return NO;
@@ -85,8 +83,7 @@ BOOL ScanScreenResolution(NSString* description, int* width, int* height,
return YES;
}
NSString* ScreenResolutionDescription(TSXScreenOptions type, int width,
int height)
NSString *ScreenResolutionDescription(TSXScreenOptions type, int width, int height)
{
if (type == TSXScreenOptionFitScreen)
return LocalizedFitScreen();
@@ -96,48 +93,47 @@ NSString* ScreenResolutionDescription(TSXScreenOptions type, int width,
return [NSString stringWithFormat:@"%dx%d", width, height];
}
NSDictionary* SelectionForColorSetting()
NSDictionary *SelectionForColorSetting()
{
OrderedDictionary* dict = [OrderedDictionary dictionaryWithCapacity:3];
[dict setValue:[NSNumber numberWithInt:8] forKey:NSLocalizedString(
@"Palette Color (8 Bit)", @"8 bit color selection")];
[dict setValue:[NSNumber numberWithInt:15] forKey:NSLocalizedString(
@"High Color (15 Bit)", @"15 bit color selection")];
[dict setValue:[NSNumber numberWithInt:16] forKey:NSLocalizedString(
@"High Color (16 Bit)", @"16 bit color selection")];
[dict setValue:[NSNumber numberWithInt:24] forKey:NSLocalizedString(
@"True Color (24 Bit)", @"24 bit color selection")];
[dict setValue:[NSNumber numberWithInt:32] forKey:NSLocalizedString(
@"Highest Quality (32 Bit)", @"32 bit color selection")];
OrderedDictionary *dict = [OrderedDictionary dictionaryWithCapacity:3];
[dict setValue:[NSNumber numberWithInt:8]
forKey:NSLocalizedString(@"Palette Color (8 Bit)", @"8 bit color selection")];
[dict setValue:[NSNumber numberWithInt:15]
forKey:NSLocalizedString(@"High Color (15 Bit)", @"15 bit color selection")];
[dict setValue:[NSNumber numberWithInt:16]
forKey:NSLocalizedString(@"High Color (16 Bit)", @"16 bit color selection")];
[dict setValue:[NSNumber numberWithInt:24]
forKey:NSLocalizedString(@"True Color (24 Bit)", @"24 bit color selection")];
[dict setValue:[NSNumber numberWithInt:32]
forKey:NSLocalizedString(@"Highest Quality (32 Bit)", @"32 bit color selection")];
return dict;
}
NSArray* ResolutionModes()
NSArray *ResolutionModes()
{
NSArray* array = [NSArray arrayWithObjects:ScreenResolutionDescription(
TSXScreenOptionFitScreen, 0, 0),
ScreenResolutionDescription(TSXScreenOptionFixed, 640, 480),
ScreenResolutionDescription(TSXScreenOptionFixed, 800, 600),
ScreenResolutionDescription(TSXScreenOptionFixed, 1024, 768),
ScreenResolutionDescription(TSXScreenOptionFixed, 1280, 1024),
ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 900),
ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 1050),
ScreenResolutionDescription(TSXScreenOptionFixed, 1600, 1200),
ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1080),
ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1200),
ScreenResolutionDescription(TSXScreenOptionCustom, 0, 0), nil];
NSArray *array =
[NSArray arrayWithObjects:ScreenResolutionDescription(TSXScreenOptionFitScreen, 0, 0),
ScreenResolutionDescription(TSXScreenOptionFixed, 640, 480),
ScreenResolutionDescription(TSXScreenOptionFixed, 800, 600),
ScreenResolutionDescription(TSXScreenOptionFixed, 1024, 768),
ScreenResolutionDescription(TSXScreenOptionFixed, 1280, 1024),
ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 900),
ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 1050),
ScreenResolutionDescription(TSXScreenOptionFixed, 1600, 1200),
ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1080),
ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1200),
ScreenResolutionDescription(TSXScreenOptionCustom, 0, 0), nil];
return array;
}
#pragma mark Working with Security Protocols
NSString* LocalizedAutomaticSecurity()
NSString *LocalizedAutomaticSecurity()
{
return NSLocalizedString(@"Automatic", @"Automatic protocl security selection");
}
NSString* ProtocolSecurityDescription(TSXProtocolSecurityOptions type)
NSString *ProtocolSecurityDescription(TSXProtocolSecurityOptions type)
{
if (type == TSXProtocolSecurityNLA)
return @"NLA";
@@ -149,8 +145,7 @@ NSString* ProtocolSecurityDescription(TSXProtocolSecurityOptions type)
return LocalizedAutomaticSecurity();
}
BOOL ScanProtocolSecurity(NSString* description,
TSXProtocolSecurityOptions* type)
BOOL ScanProtocolSecurity(NSString *description, TSXProtocolSecurityOptions *type)
{
*type = TSXProtocolSecurityRDP;
@@ -178,69 +173,69 @@ BOOL ScanProtocolSecurity(NSString* description,
return NO;
}
NSDictionary* SelectionForSecuritySetting()
NSDictionary *SelectionForSecuritySetting()
{
OrderedDictionary* dict = [OrderedDictionary dictionaryWithCapacity:4];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityAutomatic] forKey:
ProtocolSecurityDescription(TSXProtocolSecurityAutomatic)];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityRDP] forKey:
ProtocolSecurityDescription(TSXProtocolSecurityRDP)];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityTLS] forKey:
ProtocolSecurityDescription(TSXProtocolSecurityTLS)];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityNLA] forKey:
ProtocolSecurityDescription(TSXProtocolSecurityNLA)];
OrderedDictionary *dict = [OrderedDictionary dictionaryWithCapacity:4];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityAutomatic]
forKey:ProtocolSecurityDescription(TSXProtocolSecurityAutomatic)];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityRDP]
forKey:ProtocolSecurityDescription(TSXProtocolSecurityRDP)];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityTLS]
forKey:ProtocolSecurityDescription(TSXProtocolSecurityTLS)];
[dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityNLA]
forKey:ProtocolSecurityDescription(TSXProtocolSecurityNLA)];
return dict;
}
#pragma mark -
#pragma mark Bookmarks
#import "Bookmark.h"
NSMutableArray* FilterBookmarks(NSArray* bookmarks, NSArray* filter_words)
NSMutableArray *FilterBookmarks(NSArray *bookmarks, NSArray *filter_words)
{
NSMutableArray* matching_items = [NSMutableArray array];
NSArray* searched_keys = [NSArray arrayWithObjects:@"label", @"params.hostname",
@"params.username", @"params.domain", nil];
NSMutableArray *matching_items = [NSMutableArray array];
NSArray *searched_keys = [NSArray
arrayWithObjects:@"label", @"params.hostname", @"params.username", @"params.domain", nil];
for (ComputerBookmark * cur_bookmark in bookmarks)
for (ComputerBookmark *cur_bookmark in bookmarks)
{
double match_score = 0.0;
for (int i = 0; i < [searched_keys count]; i++)
{
NSString* val = [cur_bookmark valueForKeyPath:[searched_keys objectAtIndex:i]];
NSString *val = [cur_bookmark valueForKeyPath:[searched_keys objectAtIndex:i]];
if (![val isKindOfClass:[NSString class]] || ![val length])
continue;
for (NSString * word in filter_words)
if ([val rangeOfString:word options:(NSCaseInsensitiveSearch |
NSWidthInsensitiveSearch)].location != NSNotFound)
for (NSString *word in filter_words)
if ([val rangeOfString:word
options:(NSCaseInsensitiveSearch | NSWidthInsensitiveSearch)]
.location != NSNotFound)
match_score += (1.0 / [filter_words count]) * pow(2, [searched_keys count] - i);
}
if (match_score > 0.001)
[matching_items addObject:[NSDictionary dictionaryWithObjectsAndKeys:
cur_bookmark, @"bookmark",
[NSNumber numberWithFloat:match_score], @"score",
nil]];
[matching_items
addObject:[NSDictionary
dictionaryWithObjectsAndKeys:cur_bookmark, @"bookmark",
[NSNumber numberWithFloat:match_score],
@"score", nil]];
}
[matching_items sortUsingComparator:^NSComparisonResult(NSDictionary * obj1,
NSDictionary * obj2)
{
return [[obj2 objectForKey:@"score"] compare:[obj1 objectForKey:@"score"]];
}];
[matching_items
sortUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
return [[obj2 objectForKey:@"score"] compare:[obj1 objectForKey:@"score"]];
}];
return matching_items;
}
NSMutableArray* FilterHistory(NSArray* history, NSString* filterStr)
NSMutableArray *FilterHistory(NSArray *history, NSString *filterStr)
{
NSMutableArray* result = [NSMutableArray array];
NSMutableArray *result = [NSMutableArray array];
for (NSString * item in history)
for (NSString *item in history)
{
if ([item rangeOfString:filterStr].location != NSNotFound)
[result addObject:item];
@@ -250,7 +245,7 @@ NSMutableArray* FilterHistory(NSArray* history, NSString* filterStr)
}
#pragma mark Version Info
NSString* TSXAppFullVersion()
NSString *TSXAppFullVersion()
{
return [NSString stringWithUTF8String:GIT_REVISION];
}
@@ -334,20 +329,18 @@ CGFloat GetScrollGestureDelta()
// this hack activates the iphone's WWAN interface in case it is offline
void WakeUpWWAN()
{
NSURL* url = [[[NSURL alloc] initWithString:
@"http://www.nonexistingdummyurl.com"] autorelease];
//NSData * data =
[NSData dataWithContentsOfURL:
url]; // we don't need data but assigning one causes a "data not used" compiler warning
NSURL *url = [[[NSURL alloc] initWithString:@"http://www.nonexistingdummyurl.com"] autorelease];
// NSData * data =
[NSData dataWithContentsOfURL:url]; // we don't need data but assigning one causes a "data not
// used" compiler warning
}
#pragma mark System Info functions
NSString* TSXGetPrimaryMACAddress(NSString* sep)
NSString *TSXGetPrimaryMACAddress(NSString *sep)
{
NSString* macaddress = @"";
struct ifaddrs* addrs;
NSString *macaddress = @"";
struct ifaddrs *addrs;
if (getifaddrs(&addrs) < 0)
{
@@ -355,22 +348,24 @@ NSString* TSXGetPrimaryMACAddress(NSString* sep)
return macaddress;
}
for (struct ifaddrs* cursor = addrs; cursor != NULL; cursor = cursor->ifa_next)
for (struct ifaddrs *cursor = addrs; cursor != NULL; cursor = cursor->ifa_next)
{
if (strcmp(cursor->ifa_name, "en0"))
continue;
if ((cursor->ifa_addr->sa_family == AF_LINK)
&& (((struct sockaddr_dl*) cursor->ifa_addr)->sdl_type == 0x6 /*IFT_ETHER*/))
if ((cursor->ifa_addr->sa_family == AF_LINK) &&
(((struct sockaddr_dl *)cursor->ifa_addr)->sdl_type == 0x6 /*IFT_ETHER*/))
{
struct sockaddr_dl* dlAddr = (struct sockaddr_dl*) cursor->ifa_addr;
struct sockaddr_dl *dlAddr = (struct sockaddr_dl *)cursor->ifa_addr;
if (dlAddr->sdl_alen != 6)
continue;
unsigned char* base = (unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
macaddress = [NSString hexStringFromData:base ofSize:6 withSeparator:sep
afterNthChar:1];
unsigned char *base = (unsigned char *)&dlAddr->sdl_data[dlAddr->sdl_nlen];
macaddress = [NSString hexStringFromData:base
ofSize:6
withSeparator:sep
afterNthChar:1];
break;
}
}
@@ -381,8 +376,7 @@ NSString* TSXGetPrimaryMACAddress(NSString* sep)
BOOL TSXDeviceHasJailBreak()
{
if ([[NSFileManager defaultManager] fileExistsAtPath:
@"/Applications/Cydia.app/"])
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app/"])
return YES;
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/etc/apt/"])
@@ -391,15 +385,13 @@ BOOL TSXDeviceHasJailBreak()
return NO;
}
NSString* TSXGetPlatform()
NSString *TSXGetPlatform()
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char* machine = malloc(size);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString* platform = [NSString stringWithCString:machine encoding:
NSASCIIStringEncoding];
NSString *platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];
free(machine);
return platform;
}

View File

@@ -1,32 +1,33 @@
/*
Bookmark model abstraction
Copyright 2013 Thincast Technologies GmbH, Authors: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Authors: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "ConnectionParams.h"
@interface ComputerBookmark : NSObject <NSCoding> {
@protected
ComputerBookmark* _parent;
NSString* _uuid, * _label;
UIImage* _image;
ConnectionParams* _connection_params;
BOOL _connected_via_wlan;
@interface ComputerBookmark : NSObject <NSCoding>
{
@protected
ComputerBookmark *_parent;
NSString *_uuid, *_label;
UIImage *_image;
ConnectionParams *_connection_params;
BOOL _connected_via_wlan;
}
@property (nonatomic,assign) ComputerBookmark* parent;
@property (nonatomic,readonly) NSString* uuid;
@property (nonatomic,copy) NSString* label;
@property (nonatomic,retain) UIImage* image;
@property (readonly, nonatomic) ConnectionParams* params;
@property (nonatomic, assign) BOOL conntectedViaWLAN;
@property(nonatomic, assign) ComputerBookmark *parent;
@property(nonatomic, readonly) NSString *uuid;
@property(nonatomic, copy) NSString *label;
@property(nonatomic, retain) UIImage *image;
@property(readonly, nonatomic) ConnectionParams *params;
@property(nonatomic, assign) BOOL conntectedViaWLAN;
// Creates a copy of this object, with a new UUID
- (id)copy;
@@ -38,11 +39,10 @@
- (BOOL)isRenamable;
- (BOOL)hasImmutableHost;
- (id)initWithConnectionParameters:(ConnectionParams*)params;
- (id)initWithConnectionParameters:(ConnectionParams *)params;
- (id)initWithBaseDefaultParameters;
// A copy of @params, with _bookmark_uuid set.
- (ConnectionParams*)copyMarkedParams;
- (ConnectionParams *)copyMarkedParams;
@end

View File

@@ -1,12 +1,12 @@
/*
Bookmark model abstraction
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "Bookmark.h"
#import "TSXAdditions.h"
@@ -21,67 +21,66 @@
@implementation ComputerBookmark
@synthesize parent=_parent, uuid=_uuid, label=_label, image=_image;
@synthesize params=_connection_params, conntectedViaWLAN = _connected_via_wlan;
@synthesize parent = _parent, uuid = _uuid, label = _label, image = _image;
@synthesize params = _connection_params, conntectedViaWLAN = _connected_via_wlan;
- (id)init
{
if (!(self = [super init]))
if (!(self = [super init]))
return nil;
_uuid = [[NSString stringWithUUID] retain];
_label = @"";
_connected_via_wlan = NO;
return self;
}
// Designated initializer.
- (id)initWithConnectionParameters:(ConnectionParams*)params
{
if (!(self = [self init]))
return nil;
_connection_params = [params copy];
_connected_via_wlan = NO;
_connected_via_wlan = NO;
return self;
}
// Designated initializer.
- (id)initWithConnectionParameters:(ConnectionParams *)params
{
if (!(self = [self init]))
return nil;
_connection_params = [params copy];
_connected_via_wlan = NO;
return self;
}
- (id)initWithCoder:(NSCoder *)decoder
{
if (!(self = [self init]))
return nil;
if (![decoder allowsKeyedCoding])
[NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
if ([decoder containsValueForKey:@"uuid"])
{
[_uuid release];
_uuid = [[decoder decodeObjectForKey:@"uuid"] retain];
_uuid = [[decoder decodeObjectForKey:@"uuid"] retain];
}
if ([decoder containsValueForKey:@"label"])
[self setLabel:[decoder decodeObjectForKey:@"label"]];
if ([decoder containsValueForKey:@"connectionParams"])
{
[_connection_params release];
_connection_params = [[decoder decodeObjectForKey:@"connectionParams"] retain];
}
return self;
}
- (id)initWithBaseDefaultParameters
{
return [self initWithConnectionParameters:[[[ConnectionParams alloc] initWithBaseDefaultParameters] autorelease]];
return [self initWithConnectionParameters:[[[ConnectionParams alloc]
initWithBaseDefaultParameters] autorelease]];
}
- (id)copy
{
ComputerBookmark* copy = [[[self class] alloc] init];
ComputerBookmark *copy = [[[self class] alloc] init];
[copy setLabel:[self label]];
copy->_connection_params = [_connection_params copy];
return copy;
@@ -89,33 +88,36 @@
- (id)copyWithUUID
{
ComputerBookmark* copy = [self copy];
copy->_uuid = [[self uuid] copy];
return copy;
ComputerBookmark *copy = [self copy];
copy->_uuid = [[self uuid] copy];
return copy;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
if (![coder allowsKeyedCoding])
[NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
[coder encodeObject:_uuid forKey:@"uuid"];
[coder encodeObject:_label forKey:@"label"];
[coder encodeObject:_connection_params forKey:@"connectionParams"];
}
- (void)dealloc
{
{
_parent = nil;
[_label release]; _label = nil;
[_uuid release]; _uuid = nil;
[_connection_params release]; _connection_params = nil;
[_label release];
_label = nil;
[_uuid release];
_uuid = nil;
[_connection_params release];
_connection_params = nil;
[super dealloc];
}
- (UIImage*)image
- (UIImage *)image
{
return nil;
return nil;
}
- (BOOL)isEqual:(id)object
@@ -123,29 +125,40 @@
return [object respondsToSelector:@selector(uuid)] && [[object uuid] isEqual:_uuid];
}
- (NSString*)description
- (NSString *)description
{
return ([self label] != nil) ? [self label] : _uuid;
return ([self label] != nil) ? [self label] : _uuid;
}
- (BOOL)validateValue:(id *)val forKey:(NSString *)key error:(NSError **)error
{
NSString* string_value = *val;
NSString *string_value = *val;
if ([key isEqualToString:@"label"])
{
if (![[string_value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length])
if (![[string_value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
length])
{
if (error)
*error = [NSError errorWithDomain:@"" code:NSKeyValueValidationError userInfo:
[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(@"Connection labels cannot be blank", @"Bookmark data validation: label blank title."), NSLocalizedDescriptionKey,
NSLocalizedString(@"Please enter the short description of this Connection that will appear in the Connection list.", @"Bookmark data validation: label blank message."), NSLocalizedRecoverySuggestionErrorKey,
nil]];
*error = [NSError
errorWithDomain:@""
code:NSKeyValueValidationError
userInfo:
[NSDictionary
dictionaryWithObjectsAndKeys:
NSLocalizedString(
@"Connection labels cannot be blank",
@"Bookmark data validation: label blank title."),
NSLocalizedDescriptionKey,
NSLocalizedString(
@"Please enter the short description of this Connection "
@"that will appear in the Connection list.",
@"Bookmark data validation: label blank message."),
NSLocalizedRecoverySuggestionErrorKey, nil]];
return NO;
}
}
return YES;
}
@@ -155,11 +168,22 @@
return [super validateValue:val forKeyPath:keyPath error:error];
}
- (BOOL)isDeletable { return YES; }
- (BOOL)isMovable { return YES; }
- (BOOL)isRenamable { return YES; }
- (BOOL)hasImmutableHost { return NO; }
- (BOOL)isDeletable
{
return YES;
}
- (BOOL)isMovable
{
return YES;
}
- (BOOL)isRenamable
{
return YES;
}
- (BOOL)hasImmutableHost
{
return NO;
}
#pragma mark Custom KVC
@@ -173,7 +197,7 @@
{
[_connection_params willChangeValueForKey:@"resolution"];
[[self params] setInt:type forKey:@"screen_resolution_type"];
if (type == TSXScreenOptionFixed)
{
[[self params] setInt:width forKey:@"width"];
@@ -182,12 +206,13 @@
[_connection_params didChangeValueForKey:@"resolution"];
}
else
[NSException raise:NSInvalidArgumentException format:@"%s got invalid screen resolution '%@'", __func__, value];
[NSException raise:NSInvalidArgumentException
format:@"%s got invalid screen resolution '%@'", __func__, value];
}
else
{
[self willChangeValueForKeyPath:keyPath];
[super setValue:value forKeyPath:keyPath];
[super setValue:value forKeyPath:keyPath];
[self didChangeValueForKeyPath:keyPath];
}
}
@@ -195,63 +220,93 @@
- (id)valueForKeyPath:(NSString *)keyPath
{
if ([keyPath isEqualToString:@"params.resolution"])
return ScreenResolutionDescription([[self params] intForKey:@"screen_resolution_type"], [[self params] intForKey:@"width"], [[self params] intForKey:@"height"]);
return ScreenResolutionDescription([[self params] intForKey:@"screen_resolution_type"],
[[self params] intForKey:@"width"],
[[self params] intForKey:@"height"]);
return [super valueForKeyPath:keyPath];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
[self willChangeValueForKeyPath:keyPath];
else
[self didChangeValueForKeyPath:keyPath];
[self didChangeValueForKeyPath:keyPath];
}
- (NSDictionary*)targetForChangeNotificationForKeyPath:(NSString*)keyPath
- (NSDictionary *)targetForChangeNotificationForKeyPath:(NSString *)keyPath
{
NSString* changed_key = keyPath;
NSObject* changed_object = self;
NSString *changed_key = keyPath;
NSObject *changed_object = self;
if ([keyPath rangeOfString:@"params."].location == 0)
{
changed_key = [keyPath substringFromIndex:[@"params." length]];
changed_object = _connection_params;
}
return [NSDictionary dictionaryWithObjectsAndKeys:changed_key, @"key", changed_object, @"object", nil];
return [NSDictionary
dictionaryWithObjectsAndKeys:changed_key, @"key", changed_object, @"object", nil];
}
- (void)willChangeValueForKeyPath:(NSString *)keyPath
{
NSDictionary* target = [self targetForChangeNotificationForKeyPath:keyPath];
NSDictionary *target = [self targetForChangeNotificationForKeyPath:keyPath];
[[target objectForKey:@"object"] willChangeValueForKey:[target objectForKey:@"key"]];
}
- (void)didChangeValueForKeyPath:(NSString *)keyPath
{
NSDictionary* target = [self targetForChangeNotificationForKeyPath:keyPath];
NSDictionary *target = [self targetForChangeNotificationForKeyPath:keyPath];
[[target objectForKey:@"object"] didChangeValueForKey:[target objectForKey:@"key"]];
}
- (ConnectionParams*)copyMarkedParams
- (ConnectionParams *)copyMarkedParams
{
ConnectionParams* param_copy = [[self params] copy];
ConnectionParams *param_copy = [[self params] copy];
[param_copy setValue:[self uuid] forKey:@"_bookmark_uuid"];
return param_copy;
}
#pragma mark No children
- (NSUInteger)numberOfChildren { return 0; }
- (NSUInteger)numberOfDescendants { return 1; }
- (BookmarkBase *)childAtIndex:(NSUInteger)index { return nil; }
- (NSUInteger)indexOfChild:(BookmarkBase *)child { return 0; }
- (void)removeChild:(BookmarkBase *)child { }
- (void)addChild:(BookmarkBase *)child { }
- (void)addChild:(BookmarkBase *)child afterExistingChild:(BookmarkBase *)existingChild { }
- (void)addChild:(BookmarkBase *)child atIndex:(NSInteger)index { }
- (BOOL)hasDescendant:(BookmarkBase *)needle { return NO; }
- (BOOL)canContainChildren { return NO; }
- (NSUInteger)numberOfChildren
{
return 0;
}
- (NSUInteger)numberOfDescendants
{
return 1;
}
- (BookmarkBase *)childAtIndex:(NSUInteger)index
{
return nil;
}
- (NSUInteger)indexOfChild:(BookmarkBase *)child
{
return 0;
}
- (void)removeChild:(BookmarkBase *)child
{
}
- (void)addChild:(BookmarkBase *)child
{
}
- (void)addChild:(BookmarkBase *)child afterExistingChild:(BookmarkBase *)existingChild
{
}
- (void)addChild:(BookmarkBase *)child atIndex:(NSInteger)index
{
}
- (BOOL)hasDescendant:(BookmarkBase *)needle
{
return NO;
}
- (BOOL)canContainChildren
{
return NO;
}
@end

View File

@@ -1,47 +1,46 @@
/*
Connection Parameters abstraction
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@interface ConnectionParams : NSObject
{
@private
NSMutableDictionary* _connection_params;
@private
NSMutableDictionary *_connection_params;
}
// Designated initializer.
- (id)initWithDictionary:(NSDictionary*)dict;
- (id)initWithDictionary:(NSDictionary *)dict;
- (id)initWithBaseDefaultParameters;
// Getting/setting values
- (NSArray*)allKeys;
- (NSArray *)allKeys;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKey:(NSString*)key;
- (BOOL)hasValueForKey:(NSString*)key;
- (void)setInt:(int)integer forKey:(NSString*)key;
- (int)intForKey:(NSString*)key;
- (void)setBool:(BOOL)v forKey:(NSString*)key;
- (BOOL)boolForKey:(NSString*)key;
- (const char*)UTF8StringForKey:(NSString*)key;
- (NSString*)StringForKey:(NSString*)key;
- (id)valueForKey:(NSString *)key;
- (BOOL)hasValueForKey:(NSString *)key;
- (void)setInt:(int)integer forKey:(NSString *)key;
- (int)intForKey:(NSString *)key;
- (void)setBool:(BOOL)v forKey:(NSString *)key;
- (BOOL)boolForKey:(NSString *)key;
- (const char *)UTF8StringForKey:(NSString *)key;
- (NSString *)StringForKey:(NSString *)key;
- (BOOL)hasValueForKeyPath:(NSString*)key;
- (void)setInt:(int)integer forKeyPath:(NSString*)key;
- (int)intForKeyPath:(NSString*)key;
- (void)setBool:(BOOL)v forKeyPath:(NSString*)key;
- (BOOL)boolForKeyPath:(NSString*)key;
- (const char*)UTF8StringForKeyPath:(NSString*)key;
- (NSString*)StringForKeyPath:(NSString*)key;
- (BOOL)hasValueForKeyPath:(NSString *)key;
- (void)setInt:(int)integer forKeyPath:(NSString *)key;
- (int)intForKeyPath:(NSString *)key;
- (void)setBool:(BOOL)v forKeyPath:(NSString *)key;
- (BOOL)boolForKeyPath:(NSString *)key;
- (const char *)UTF8StringForKeyPath:(NSString *)key;
- (NSString *)StringForKeyPath:(NSString *)key;
- (int)intForKey:(NSString*)key with3GEnabled:(BOOL)enabled;
- (BOOL)boolForKey:(NSString*)key with3GEnabled:(BOOL)enabled;
- (int)intForKey:(NSString *)key with3GEnabled:(BOOL)enabled;
- (BOOL)boolForKey:(NSString *)key with3GEnabled:(BOOL)enabled;
@end

View File

@@ -1,12 +1,12 @@
/*
Connection Parameters abstraction
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "ConnectionParams.h"
#import "GlobalDefaults.h"
@@ -15,37 +15,39 @@
#import "TSXAdditions.h"
@interface ConnectionParams (Private)
- (id)initWithConnectionParams:(ConnectionParams*)params;
- (id)initWithConnectionParams:(ConnectionParams *)params;
@end
@implementation ConnectionParams
// Designated initializer.
- (id)initWithDictionary:(NSDictionary*)dict
- (id)initWithDictionary:(NSDictionary *)dict
{
if (!(self = [super init]))
return nil;
_connection_params = [dict mutableDeepCopy];
[self decryptPasswordForKey:@"password"];
[self decryptPasswordForKey:@"tsg_password"];
[self decryptPasswordForKey:@"password"];
[self decryptPasswordForKey:@"tsg_password"];
return self;
}
- (void)decryptPasswordForKey:(NSString*)key
- (void)decryptPasswordForKey:(NSString *)key
{
if ([[_connection_params objectForKey:key] isKindOfClass:[NSData class]])
{
NSString* plaintext_password = [[[EncryptionController sharedEncryptionController] decryptor] decryptString:[_connection_params objectForKey:key]];
NSString *plaintext_password = [[[EncryptionController sharedEncryptionController]
decryptor] decryptString:[_connection_params objectForKey:key]];
[self setValue:plaintext_password forKey:key];
}
}
- (id)initWithBaseDefaultParameters
{
return [self initWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"TSXDefaultComputerBookmarkSettings"]];
return [self initWithDictionary:[[NSUserDefaults standardUserDefaults]
dictionaryForKey:@"TSXDefaultComputerBookmarkSettings"]];
}
- (id)init
@@ -53,13 +55,14 @@
return [self initWithDictionary:[NSDictionary dictionary]];
}
- (id)initWithConnectionParams:(ConnectionParams*)params
- (id)initWithConnectionParams:(ConnectionParams *)params
{
return [self initWithDictionary:params->_connection_params];
}
- (void)dealloc
{
[_connection_params release]; _connection_params = nil;
[_connection_params release];
_connection_params = nil;
[super dealloc];
}
@@ -68,7 +71,7 @@
return [[ConnectionParams alloc] initWithDictionary:_connection_params];
}
- (NSString*)description
- (NSString *)description
{
return [NSString stringWithFormat:@"ConnectionParams: %@", [_connection_params description]];
}
@@ -80,36 +83,38 @@
{
if ([decoder containsValueForKey:@"connectionParams"])
return [self initWithDictionary:[decoder decodeObjectForKey:@"connectionParams"]];
return [self init];
}
- (void)encodeWithCoder:(NSCoder *)coder
{
NSSet* unserializable_keys = [NSSet setWithObjects:@"view", nil];
NSMutableDictionary* serializable_params = [[NSMutableDictionary alloc] initWithCapacity:[_connection_params count]];
for (NSString* k in _connection_params)
if ( ([k characterAtIndex:0] != '_') && ![unserializable_keys containsObject:k])
{
NSSet *unserializable_keys = [NSSet setWithObjects:@"view", nil];
NSMutableDictionary *serializable_params =
[[NSMutableDictionary alloc] initWithCapacity:[_connection_params count]];
for (NSString *k in _connection_params)
if (([k characterAtIndex:0] != '_') && ![unserializable_keys containsObject:k])
[serializable_params setObject:[_connection_params objectForKey:k] forKey:k];
if ([serializable_params objectForKey:@"password"] != nil)
[self serializeDecryptedForKey:@"password" forParams:serializable_params];
[self serializeDecryptedForKey:@"password" forParams:serializable_params];
if ([serializable_params objectForKey:@"tsg_password"] != nil)
[self serializeDecryptedForKey:@"tsg_password" forParams:serializable_params];
[self serializeDecryptedForKey:@"tsg_password" forParams:serializable_params];
[coder encodeObject:serializable_params forKey:@"connectionParams"];
[serializable_params release];
}
- (void)serializeDecryptedForKey:(NSString*)key forParams:(NSMutableDictionary*)params
- (void)serializeDecryptedForKey:(NSString *)key forParams:(NSMutableDictionary *)params
{
NSData* encrypted_password = [[[EncryptionController sharedEncryptionController] encryptor] encryptString:[params objectForKey:key]];
if (encrypted_password)
[params setObject:encrypted_password forKey:key];
else
[params removeObjectForKey:key];
NSData *encrypted_password = [[[EncryptionController sharedEncryptionController] encryptor]
encryptString:[params objectForKey:key]];
if (encrypted_password)
[params setObject:encrypted_password forKey:key];
else
[params removeObjectForKey:key];
}
#pragma mark -
@@ -118,24 +123,24 @@
- (void)setValue:(id)value forKey:(NSString *)key
{
[self willChangeValueForKey:key];
if (value == nil)
[self setNilValueForKey:key];
else
[_connection_params setValue:value forKey:key];
[self didChangeValueForKey:key];
}
- (void)setValue:(id)value forKeyPath:(NSString *)key
{
[self willChangeValueForKey:key];
if (value == nil)
[self setNilValueForKey:key];
else
[_connection_params setValue:value forKeyPath:key];
[self didChangeValueForKey:key];
}
@@ -144,12 +149,12 @@
[_connection_params removeObjectForKey:key];
}
- (id)valueForKey:(NSString*)key
- (id)valueForKey:(NSString *)key
{
return [_connection_params valueForKey:key];
}
- (NSArray*)allKeys
- (NSArray *)allKeys
{
return [_connection_params allKeys];
}
@@ -157,100 +162,97 @@
#pragma mark -
#pragma mark KV convenience
- (BOOL)hasValueForKey:(NSString*)key
- (BOOL)hasValueForKey:(NSString *)key
{
return [_connection_params objectForKey:key] != nil;
}
- (void)setInt:(int)integer forKey:(NSString*)key
- (void)setInt:(int)integer forKey:(NSString *)key
{
[self setValue:[NSNumber numberWithInteger:integer] forKey:key];
}
- (int)intForKey:(NSString*)key
- (int)intForKey:(NSString *)key
{
return [[self valueForKey:key] intValue];
}
- (void)setBool:(BOOL)v forKey:(NSString*)key
- (void)setBool:(BOOL)v forKey:(NSString *)key
{
[self setValue:[NSNumber numberWithBool:v] forKey:key];
}
- (BOOL)boolForKey:(NSString*)key
- (BOOL)boolForKey:(NSString *)key
{
return [[_connection_params objectForKey:key] boolValue];
}
- (const char*)UTF8StringForKey:(NSString*)key
- (const char *)UTF8StringForKey:(NSString *)key
{
id val = [self valueForKey:key];
const char* str;
const char *str;
if ([val respondsToSelector:@selector(UTF8String)] && (str = [val UTF8String]))
return str;
return "";
}
- (NSString*)StringForKey:(NSString*)key
- (NSString *)StringForKey:(NSString *)key
{
return [self valueForKey:key];
}
- (BOOL)hasValueForKeyPath:(NSString*)key
- (BOOL)hasValueForKeyPath:(NSString *)key
{
return [_connection_params valueForKeyPath:key] != nil;
return [_connection_params valueForKeyPath:key] != nil;
}
- (void)setInt:(int)integer forKeyPath:(NSString*)key
- (void)setInt:(int)integer forKeyPath:(NSString *)key
{
[self setValue:[NSNumber numberWithInteger:integer] forKeyPath:key];
}
- (int)intForKeyPath:(NSString*)key
- (int)intForKeyPath:(NSString *)key
{
return [[self valueForKeyPath:key] intValue];
}
- (void)setBool:(BOOL)v forKeyPath:(NSString*)key
- (void)setBool:(BOOL)v forKeyPath:(NSString *)key
{
[self setValue:[NSNumber numberWithBool:v] forKeyPath:key];
}
- (BOOL)boolForKeyPath:(NSString*)key
- (BOOL)boolForKeyPath:(NSString *)key
{
return [[self valueForKeyPath:key] boolValue];
}
- (const char*)UTF8StringForKeyPath:(NSString*)key
- (const char *)UTF8StringForKeyPath:(NSString *)key
{
id val = [self valueForKeyPath:key];
const char* str;
const char *str;
if ([val respondsToSelector:@selector(UTF8String)] && (str = [val UTF8String]))
return str;
return "";
}
- (NSString*)StringForKeyPath:(NSString*)key
- (NSString *)StringForKeyPath:(NSString *)key
{
return [self valueForKeyPath:key];
}
- (int)intForKey:(NSString*)key with3GEnabled:(BOOL)enabled
- (int)intForKey:(NSString *)key with3GEnabled:(BOOL)enabled
{
if (enabled && [self boolForKey:@"enable_3g_settings"])
return [self intForKeyPath:[NSString stringWithFormat:@"settings_3g.%@", key]];
return [self intForKeyPath:key];
if (enabled && [self boolForKey:@"enable_3g_settings"])
return [self intForKeyPath:[NSString stringWithFormat:@"settings_3g.%@", key]];
return [self intForKeyPath:key];
}
- (BOOL)boolForKey:(NSString*)key with3GEnabled:(BOOL)enabled
- (BOOL)boolForKey:(NSString *)key with3GEnabled:(BOOL)enabled
{
if (enabled && [self boolForKey:@"enable_3g_settings"])
return [self boolForKeyPath:[NSString stringWithFormat:@"settings_3g.%@", key]];
return [self boolForKeyPath:key];
if (enabled && [self boolForKey:@"enable_3g_settings"])
return [self boolForKeyPath:[NSString stringWithFormat:@"settings_3g.%@", key]];
return [self boolForKeyPath:key];
}
@end

View File

@@ -1,10 +1,11 @@
/*
Password Encryptor
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
/* Encrypts data using AES 128 with a 256 bit key derived using PBKDF2-HMAC-SHA1 */
@@ -23,20 +24,20 @@
#define TSXEncryptorPBKDF2SaltLen TSXEncryptorBlockCipherOptions
#define TSXEncryptorPBKDF2KeySize TSXEncryptorBlockCipherKeySize
@interface Encryptor : NSObject {
@private
NSData* _encryption_key;
NSString* _plaintext_password;
@interface Encryptor : NSObject
{
@private
NSData *_encryption_key;
NSString *_plaintext_password;
}
@property(readonly) NSString* plaintextPassword;
@property(readonly) NSString *plaintextPassword;
- (id)initWithPassword:(NSString*)plaintext_password;
- (id)initWithPassword:(NSString *)plaintext_password;
- (NSData*)encryptData:(NSData*)plaintext_data;
- (NSData*)decryptData:(NSData*)encrypted_data;
- (NSData*)encryptString:(NSString*)plaintext_string;
- (NSString*)decryptString:(NSData*)encrypted_string;
- (NSData *)encryptData:(NSData *)plaintext_data;
- (NSData *)decryptData:(NSData *)encrypted_data;
- (NSData *)encryptString:(NSString *)plaintext_string;
- (NSString *)decryptString:(NSData *)encrypted_string;
@end

View File

@@ -1,56 +1,64 @@
/*
Password Encryptor
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
/* We try to use CommonCrypto as much as possible. PBKDF2 was added to CommonCrypto in iOS 5, so use OpenSSL only as a fallback to do PBKDF2 on pre iOS 5 systems. */
/* We try to use CommonCrypto as much as possible. PBKDF2 was added to CommonCrypto in iOS 5, so use
* OpenSSL only as a fallback to do PBKDF2 on pre iOS 5 systems. */
#import "Encryptor.h"
#import <CommonCrypto/CommonKeyDerivation.h>
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonKeyDerivation.h>
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>
#import <openssl/evp.h> // For PBKDF2 on < 5.0
#include <fcntl.h>
#pragma mark -
@interface Encryptor (Private)
- (NSData*)randomInitializationVector;
- (NSData *)randomInitializationVector;
@end
@implementation Encryptor
@synthesize plaintextPassword=_plaintext_password;
@synthesize plaintextPassword = _plaintext_password;
- (id)initWithPassword:(NSString*)plaintext_password
- (id)initWithPassword:(NSString *)plaintext_password
{
if (plaintext_password == nil)
return nil;
if ( !(self = [super init]) )
return nil;
if (!(self = [super init]))
return nil;
_plaintext_password = [plaintext_password retain];
const char* plaintext_password_data = [plaintext_password length] ? [plaintext_password UTF8String] : " ";
const char *plaintext_password_data =
[plaintext_password length] ? [plaintext_password UTF8String] : " ";
if (!plaintext_password_data || !strlen(plaintext_password_data))
[NSException raise:NSInternalInconsistencyException format:@"%s: plaintext password data is zero length!", __func__];
uint8_t* derived_key = calloc(1, TSXEncryptorPBKDF2KeySize);
[NSException raise:NSInternalInconsistencyException
format:@"%s: plaintext password data is zero length!", __func__];
uint8_t *derived_key = calloc(1, TSXEncryptorPBKDF2KeySize);
if (CCKeyDerivationPBKDF != NULL)
{
int ret = CCKeyDerivationPBKDF(kCCPBKDF2, plaintext_password_data, strlen(plaintext_password_data)-1, (const uint8_t*)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen, kCCPRFHmacAlgSHA1, TSXEncryptorPBKDF2Rounds, derived_key, TSXEncryptorPBKDF2KeySize);
//NSLog(@"CCKeyDerivationPBKDF ret = %d; key: %@", ret, [NSData dataWithBytesNoCopy:derived_key length:TWEncryptorPBKDF2KeySize freeWhenDone:NO]);
int ret = CCKeyDerivationPBKDF(
kCCPBKDF2, plaintext_password_data, strlen(plaintext_password_data) - 1,
(const uint8_t *)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen, kCCPRFHmacAlgSHA1,
TSXEncryptorPBKDF2Rounds, derived_key, TSXEncryptorPBKDF2KeySize);
// NSLog(@"CCKeyDerivationPBKDF ret = %d; key: %@", ret, [NSData
// dataWithBytesNoCopy:derived_key length:TWEncryptorPBKDF2KeySize freeWhenDone:NO]);
if (ret)
{
NSLog(@"%s: CCKeyDerivationPBKDF ret == %d, indicating some sort of failure.", __func__, ret);
free(derived_key);
NSLog(@"%s: CCKeyDerivationPBKDF ret == %d, indicating some sort of failure.", __func__,
ret);
free(derived_key);
[self autorelease];
return nil;
}
@@ -58,115 +66,139 @@
else
{
// iOS 4.x or earlier -- use OpenSSL
unsigned long ret = PKCS5_PBKDF2_HMAC_SHA1(plaintext_password_data, (int)strlen(plaintext_password_data)-1, (const unsigned char*)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen, TSXEncryptorPBKDF2Rounds, TSXEncryptorPBKDF2KeySize, derived_key);
//NSLog(@"PKCS5_PBKDF2_HMAC_SHA1 ret = %lu; key: %@", ret, [NSData dataWithBytesNoCopy:derived_key length:TWEncryptorPBKDF2KeySize freeWhenDone:NO]);
unsigned long ret = PKCS5_PBKDF2_HMAC_SHA1(
plaintext_password_data, (int)strlen(plaintext_password_data) - 1,
(const unsigned char *)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen,
TSXEncryptorPBKDF2Rounds, TSXEncryptorPBKDF2KeySize, derived_key);
// NSLog(@"PKCS5_PBKDF2_HMAC_SHA1 ret = %lu; key: %@", ret, [NSData
// dataWithBytesNoCopy:derived_key length:TWEncryptorPBKDF2KeySize freeWhenDone:NO]);
if (ret != 1)
{
NSLog(@"%s: PKCS5_PBKDF2_HMAC_SHA1 ret == %lu, indicating some sort of failure.", __func__, ret);
free(derived_key);
NSLog(@"%s: PKCS5_PBKDF2_HMAC_SHA1 ret == %lu, indicating some sort of failure.",
__func__, ret);
free(derived_key);
[self release];
return nil;
}
}
_encryption_key = [[NSData alloc] initWithBytesNoCopy:derived_key length:TSXEncryptorPBKDF2KeySize freeWhenDone:YES];
}
_encryption_key = [[NSData alloc] initWithBytesNoCopy:derived_key
length:TSXEncryptorPBKDF2KeySize
freeWhenDone:YES];
return self;
}
#pragma mark -
#pragma mark Encrypting/Decrypting data
- (NSData*)encryptData:(NSData*)plaintext_data
- (NSData *)encryptData:(NSData *)plaintext_data
{
if (![plaintext_data length])
return nil;
NSData* iv = [self randomInitializationVector];
NSMutableData* encrypted_data = [NSMutableData dataWithLength:[iv length] + [plaintext_data length] + TSXEncryptorBlockCipherBlockSize];
NSData *iv = [self randomInitializationVector];
NSMutableData *encrypted_data = [NSMutableData
dataWithLength:[iv length] + [plaintext_data length] + TSXEncryptorBlockCipherBlockSize];
[encrypted_data replaceBytesInRange:NSMakeRange(0, [iv length]) withBytes:[iv bytes]];
size_t data_out_moved = 0;
int ret = CCCrypt(kCCEncrypt, TSXEncryptorBlockCipherAlgo, TSXEncryptorBlockCipherOptions, [_encryption_key bytes], TSXEncryptorBlockCipherKeySize, [iv bytes], [plaintext_data bytes], [plaintext_data length], [encrypted_data mutableBytes]+[iv length], [encrypted_data length]-[iv length], &data_out_moved);
int ret = CCCrypt(kCCEncrypt, TSXEncryptorBlockCipherAlgo, TSXEncryptorBlockCipherOptions,
[_encryption_key bytes], TSXEncryptorBlockCipherKeySize, [iv bytes],
[plaintext_data bytes], [plaintext_data length],
[encrypted_data mutableBytes] + [iv length],
[encrypted_data length] - [iv length], &data_out_moved);
switch (ret)
{
case kCCSuccess:
[encrypted_data setLength:[iv length] + data_out_moved];
return encrypted_data;
default:
NSLog(@"%s: uncaught error, ret CCCryptorStatus = %d (plaintext len = %lu; buffer size = %lu)", __func__, ret, (unsigned long)[plaintext_data length], (unsigned long)([encrypted_data length]-[iv length]));
NSLog(
@"%s: uncaught error, ret CCCryptorStatus = %d (plaintext len = %lu; buffer size = "
@"%lu)",
__func__, ret, (unsigned long)[plaintext_data length],
(unsigned long)([encrypted_data length] - [iv length]));
return nil;
}
return nil;
}
- (NSData*)decryptData:(NSData*)encrypted_data
- (NSData *)decryptData:(NSData *)encrypted_data
{
if ([encrypted_data length] <= TSXEncryptorBlockCipherBlockSize)
return nil;
NSMutableData* plaintext_data = [NSMutableData dataWithLength:[encrypted_data length] + TSXEncryptorBlockCipherBlockSize];
NSMutableData *plaintext_data =
[NSMutableData dataWithLength:[encrypted_data length] + TSXEncryptorBlockCipherBlockSize];
size_t data_out_moved = 0;
int ret = CCCrypt(kCCDecrypt, TSXEncryptorBlockCipherAlgo, TSXEncryptorBlockCipherOptions, [_encryption_key bytes], TSXEncryptorBlockCipherKeySize, [encrypted_data bytes], [encrypted_data bytes] + TSXEncryptorBlockCipherBlockSize, [encrypted_data length] - TSXEncryptorBlockCipherBlockSize, [plaintext_data mutableBytes], [plaintext_data length], &data_out_moved);
int ret =
CCCrypt(kCCDecrypt, TSXEncryptorBlockCipherAlgo, TSXEncryptorBlockCipherOptions,
[_encryption_key bytes], TSXEncryptorBlockCipherKeySize, [encrypted_data bytes],
[encrypted_data bytes] + TSXEncryptorBlockCipherBlockSize,
[encrypted_data length] - TSXEncryptorBlockCipherBlockSize,
[plaintext_data mutableBytes], [plaintext_data length], &data_out_moved);
switch (ret)
{
case kCCSuccess:
[plaintext_data setLength:data_out_moved];
return plaintext_data;
case kCCBufferTooSmall: // Our output buffer is big enough to decrypt valid data. This return code indicates malformed data.
case kCCBufferTooSmall: // Our output buffer is big enough to decrypt valid data. This
// return code indicates malformed data.
case kCCAlignmentError: // Shouldn't get this, since we're using padding.
case kCCDecodeError: // Wrong key.
case kCCDecodeError: // Wrong key.
return nil;
default:
NSLog(@"%s: uncaught error, ret CCCryptorStatus = %d (encrypted data len = %lu; buffer size = %lu; dom = %lu)", __func__, ret, (unsigned long)[encrypted_data length], (unsigned long)[plaintext_data length], data_out_moved);
NSLog(@"%s: uncaught error, ret CCCryptorStatus = %d (encrypted data len = %lu; buffer "
@"size = %lu; dom = %lu)",
__func__, ret, (unsigned long)[encrypted_data length],
(unsigned long)[plaintext_data length], data_out_moved);
return nil;
}
return nil;
}
- (NSData*)encryptString:(NSString*)plaintext_string
- (NSData *)encryptString:(NSString *)plaintext_string
{
return [self encryptData:[plaintext_string dataUsingEncoding:NSUTF8StringEncoding]];
}
- (NSString*)decryptString:(NSData*)encrypted_string
- (NSString *)decryptString:(NSData *)encrypted_string
{
return [[[NSString alloc] initWithData:[self decryptData:encrypted_string] encoding:NSUTF8StringEncoding] autorelease];
return [[[NSString alloc] initWithData:[self decryptData:encrypted_string]
encoding:NSUTF8StringEncoding] autorelease];
}
- (NSData*)randomInitializationVector
- (NSData *)randomInitializationVector
{
NSMutableData* iv = [NSMutableData dataWithLength:TSXEncryptorBlockCipherBlockSize];
NSMutableData *iv = [NSMutableData dataWithLength:TSXEncryptorBlockCipherBlockSize];
int fd;
if ( (fd = open("/dev/urandom", O_RDONLY)) < 0)
if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
return nil;
NSInteger bytes_needed = [iv length];
char* p = [iv mutableBytes];
char *p = [iv mutableBytes];
while (bytes_needed)
{
long bytes_read = read(fd, p, bytes_needed);
if (bytes_read < 0)
continue;
p += bytes_read;
bytes_needed -= bytes_read;
}
close(fd);
return iv;
}

View File

@@ -1,29 +1,30 @@
/*
Global default bookmark settings
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@class ConnectionParams, ComputerBookmark;
@interface GlobalDefaults : NSObject{
@private
ComputerBookmark* _default_bookmark;
@interface GlobalDefaults : NSObject
{
@private
ComputerBookmark *_default_bookmark;
}
+ (GlobalDefaults*)sharedGlobalDefaults;
+ (GlobalDefaults *)sharedGlobalDefaults;
// The same object is always returned from this method.
@property (readonly,nonatomic) ComputerBookmark* bookmark;
@property(readonly, nonatomic) ComputerBookmark *bookmark;
- (ConnectionParams*)newParams;
- (ComputerBookmark*)newBookmark;
- (ComputerBookmark*)newTestServerBookmark;
- (ConnectionParams *)newParams;
- (ComputerBookmark *)newBookmark;
- (ComputerBookmark *)newTestServerBookmark;
@end

View File

@@ -4,7 +4,8 @@
Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "GlobalDefaults.h"
@@ -13,9 +14,9 @@
@implementation GlobalDefaults
+ (GlobalDefaults*)sharedGlobalDefaults
+ (GlobalDefaults *)sharedGlobalDefaults
{
static GlobalDefaults* _shared_global_defaults = nil;
static GlobalDefaults *_shared_global_defaults = nil;
if (_shared_global_defaults == nil)
{
@@ -34,16 +35,15 @@
if (!(self = [super init]))
return nil;
ComputerBookmark* bookmark = nil;
NSData* bookmark_data = [[NSUserDefaults standardUserDefaults] objectForKey:
@"TSXSharedGlobalDefaultBookmark"];
ComputerBookmark *bookmark = nil;
NSData *bookmark_data =
[[NSUserDefaults standardUserDefaults] objectForKey:@"TSXSharedGlobalDefaultBookmark"];
if (bookmark_data && [bookmark_data length])
bookmark = [NSKeyedUnarchiver unarchiveObjectWithData:bookmark_data];
if (!bookmark)
bookmark = [[[ComputerBookmark alloc] initWithBaseDefaultParameters]
autorelease];
bookmark = [[[ComputerBookmark alloc] initWithBaseDefaultParameters] autorelease];
_default_bookmark = [bookmark retain];
return self;
@@ -59,21 +59,20 @@
@synthesize bookmark = _default_bookmark;
- (ComputerBookmark*)newBookmark
- (ComputerBookmark *)newBookmark
{
return [[ComputerBookmark alloc] initWithConnectionParameters:[[self newParams]
autorelease]];
return [[ComputerBookmark alloc] initWithConnectionParameters:[[self newParams] autorelease]];
}
- (ConnectionParams*)newParams
- (ConnectionParams *)newParams
{
ConnectionParams* param_copy = [[[self bookmark] params] copy];
ConnectionParams *param_copy = [[[self bookmark] params] copy];
return param_copy;
}
- (ComputerBookmark*)newTestServerBookmark
- (ComputerBookmark *)newTestServerBookmark
{
ComputerBookmark* bm = [self newBookmark];
ComputerBookmark *bm = [self newBookmark];
[bm setLabel:@"Test Server"];
[[bm params] setValue:@"testservice.ifreerdp.com" forKey:@"hostname"];
[[bm params] setInt:0 forKey:@"screen_resolution_type"];

View File

@@ -1,10 +1,11 @@
/*
RDP Keyboard helper
RDP Keyboard helper
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@@ -12,40 +13,39 @@
@class RDPKeyboard;
@protocol RDPKeyboardDelegate <NSObject>
@optional
- (void)modifiersChangedForKeyboard:(RDPKeyboard*)keyboard;
- (void)modifiersChangedForKeyboard:(RDPKeyboard *)keyboard;
@end
@interface RDPKeyboard : NSObject
{
@interface RDPKeyboard : NSObject {
RDPSession *_session;
RDPSession* _session;
int _virtual_key_map[256];
int _unicode_map[256];
NSDictionary* _special_keys;
int _unicode_map[256];
NSDictionary *_special_keys;
NSObject<RDPKeyboardDelegate> *_delegate;
NSObject<RDPKeyboardDelegate>* _delegate;
BOOL _ctrl_pressed;
BOOL _alt_pressed;
BOOL _shift_pressed;
BOOL _win_pressed;
BOOL _alt_pressed;
BOOL _shift_pressed;
BOOL _win_pressed;
}
@property (assign) id <RDPKeyboardDelegate> delegate;
@property (readonly) BOOL ctrlPressed;
@property (readonly) BOOL altPressed;
@property (readonly) BOOL shiftPressed;
@property (readonly) BOOL winPressed;
@property(assign) id<RDPKeyboardDelegate> delegate;
@property(readonly) BOOL ctrlPressed;
@property(readonly) BOOL altPressed;
@property(readonly) BOOL shiftPressed;
@property(readonly) BOOL winPressed;
// returns a keyboard instance
+ (RDPKeyboard*)getSharedRDPKeyboard;
+ (RDPKeyboard *)getSharedRDPKeyboard;
// init the keyboard and assign the given rdp session and delegate
- (void)initWithSession:(RDPSession*)session delegate:(NSObject<RDPKeyboardDelegate>*)delegate;
- (void)initWithSession:(RDPSession *)session delegate:(NSObject<RDPKeyboardDelegate> *)delegate;
// called to reset any pending key states (i.e. pressed modifier keys)
- (void)reset;

View File

@@ -1,10 +1,11 @@
/*
RDP Keyboard helper
RDP Keyboard helper
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "RDPKeyboard.h"
@@ -19,17 +20,18 @@
@implementation RDPKeyboard
@synthesize delegate = _delegate, ctrlPressed = _ctrl_pressed, altPressed = _alt_pressed, shiftPressed = _shift_pressed, winPressed = _win_pressed;
@synthesize delegate = _delegate, ctrlPressed = _ctrl_pressed, altPressed = _alt_pressed,
shiftPressed = _shift_pressed, winPressed = _win_pressed;
- (id)init
{
if((self = [super init]) != nil)
if ((self = [super init]) != nil)
{
[self initWithSession:nil delegate:nil];
[self initWithSession:nil delegate:nil];
memset(_virtual_key_map, 0, sizeof(_virtual_key_map));
memset(_unicode_map, 0, sizeof(_unicode_map));
memset(_unicode_map, 0, sizeof(_unicode_map));
// init vkey map - used for alpha-num characters
_virtual_key_map['0'] = VK_KEY_0;
_virtual_key_map['1'] = VK_KEY_1;
@@ -41,7 +43,7 @@
_virtual_key_map['7'] = VK_KEY_7;
_virtual_key_map['8'] = VK_KEY_8;
_virtual_key_map['9'] = VK_KEY_9;
_virtual_key_map['a'] = VK_KEY_A;
_virtual_key_map['b'] = VK_KEY_B;
_virtual_key_map['c'] = VK_KEY_C;
@@ -68,42 +70,42 @@
_virtual_key_map['x'] = VK_KEY_X;
_virtual_key_map['y'] = VK_KEY_Y;
_virtual_key_map['z'] = VK_KEY_Z;
// init scancode map - used for special characters
_unicode_map['-'] = 45;
_unicode_map['/'] = 47;
_unicode_map[':'] = 58;
_unicode_map[';'] = 59;
_unicode_map['('] = 40;
_unicode_map[')'] = 41;
_unicode_map['&'] = 38;
_unicode_map['@'] = 64;
_unicode_map['.'] = 46;
_unicode_map[','] = 44;
_unicode_map['?'] = 63;
_unicode_map['!'] = 33;
_unicode_map['\''] = 39;
_unicode_map['\"'] = 34;
_unicode_map['['] = 91;
_unicode_map[']'] = 93;
_unicode_map['{'] = 123;
_unicode_map['}'] = 125;
_unicode_map['#'] = 35;
_unicode_map['%'] = 37;
_unicode_map['^'] = 94;
_unicode_map['*'] = 42;
_unicode_map['+'] = 43;
_unicode_map['='] = 61;
_unicode_map['_'] = 95;
_unicode_map['\\'] = 92;
_unicode_map['|'] = 124;
_unicode_map['~'] = 126;
_unicode_map['<'] = 60;
_unicode_map['>'] = 62;
_unicode_map['$'] = 36;
}
// init scancode map - used for special characters
_unicode_map['-'] = 45;
_unicode_map['/'] = 47;
_unicode_map[':'] = 58;
_unicode_map[';'] = 59;
_unicode_map['('] = 40;
_unicode_map[')'] = 41;
_unicode_map['&'] = 38;
_unicode_map['@'] = 64;
_unicode_map['.'] = 46;
_unicode_map[','] = 44;
_unicode_map['?'] = 63;
_unicode_map['!'] = 33;
_unicode_map['\''] = 39;
_unicode_map['\"'] = 34;
_unicode_map['['] = 91;
_unicode_map[']'] = 93;
_unicode_map['{'] = 123;
_unicode_map['}'] = 125;
_unicode_map['#'] = 35;
_unicode_map['%'] = 37;
_unicode_map['^'] = 94;
_unicode_map['*'] = 42;
_unicode_map['+'] = 43;
_unicode_map['='] = 61;
_unicode_map['_'] = 95;
_unicode_map['\\'] = 92;
_unicode_map['|'] = 124;
_unicode_map['~'] = 126;
_unicode_map['<'] = 60;
_unicode_map['>'] = 62;
_unicode_map['$'] = 36;
}
return self;
}
@@ -116,114 +118,114 @@
#pragma mark class methods
// return a keyboard instance
+ (RDPKeyboard*)getSharedRDPKeyboard
+ (RDPKeyboard *)getSharedRDPKeyboard
{
static RDPKeyboard* _shared_keyboard = nil;
static RDPKeyboard *_shared_keyboard = nil;
if (_shared_keyboard == nil)
{
@synchronized(self)
{
if (_shared_keyboard == nil)
_shared_keyboard = [[RDPKeyboard alloc] init];
_shared_keyboard = [[RDPKeyboard alloc] init];
}
}
return _shared_keyboard;
return _shared_keyboard;
}
// reset the keyboard instance and assign the given rdp instance
- (void)initWithSession:(RDPSession *)session delegate:(NSObject<RDPKeyboardDelegate> *)delegate
{
_alt_pressed = NO;
_ctrl_pressed = NO;
_shift_pressed = NO;
_win_pressed = NO;
_session = session;
_delegate = delegate;
_alt_pressed = NO;
_ctrl_pressed = NO;
_shift_pressed = NO;
_win_pressed = NO;
_session = session;
_delegate = delegate;
}
- (void)reset
{
// reset pressed ctrl, alt, shift or win key
if(_shift_pressed)
[self toggleShiftKey];
if(_alt_pressed)
[self toggleAltKey];
if(_ctrl_pressed)
[self toggleCtrlKey];
if(_win_pressed)
[self toggleWinKey];
// reset pressed ctrl, alt, shift or win key
if (_shift_pressed)
[self toggleShiftKey];
if (_alt_pressed)
[self toggleAltKey];
if (_ctrl_pressed)
[self toggleCtrlKey];
if (_win_pressed)
[self toggleWinKey];
}
// handles button pressed input event from the iOS keyboard
// performs all conversions etc.
- (void)sendUnicode:(int)character
{
if(isalnum(character))
[self handleAlphaNumChar:character];
else
[self handleSpecialKey:character];
{
if (isalnum(character))
[self handleAlphaNumChar:character];
else
[self handleSpecialKey:character];
[self reset];
[self reset];
}
// send a backspace key press
- (void)sendVirtualKeyCode:(int)keyCode
{
[self sendVirtualKey:keyCode up:NO];
[self sendVirtualKey:keyCode up:YES];
[self sendVirtualKey:keyCode up:NO];
[self sendVirtualKey:keyCode up:YES];
}
#pragma mark modifier key handling
// toggle ctrl key, returns true if pressed, otherwise false
- (void)toggleCtrlKey
{
[self sendVirtualKey:VK_LCONTROL up:_ctrl_pressed];
_ctrl_pressed = !_ctrl_pressed;
[self notifyDelegateModifiersChanged];
{
[self sendVirtualKey:VK_LCONTROL up:_ctrl_pressed];
_ctrl_pressed = !_ctrl_pressed;
[self notifyDelegateModifiersChanged];
}
// toggle alt key, returns true if pressed, otherwise false
- (void)toggleAltKey
{
[self sendVirtualKey:VK_LMENU up:_alt_pressed];
_alt_pressed = !_alt_pressed;
[self notifyDelegateModifiersChanged];
[self sendVirtualKey:VK_LMENU up:_alt_pressed];
_alt_pressed = !_alt_pressed;
[self notifyDelegateModifiersChanged];
}
// toggle shift key, returns true if pressed, otherwise false
- (void)toggleShiftKey
{
[self sendVirtualKey:VK_LSHIFT up:_shift_pressed];
_shift_pressed = !_shift_pressed;
[self notifyDelegateModifiersChanged];
[self sendVirtualKey:VK_LSHIFT up:_shift_pressed];
_shift_pressed = !_shift_pressed;
[self notifyDelegateModifiersChanged];
}
// toggle windows key, returns true if pressed, otherwise false
- (void)toggleWinKey
{
[self sendVirtualKey:(VK_LWIN | KBDEXT) up:_win_pressed];
_win_pressed = !_win_pressed;
[self notifyDelegateModifiersChanged];
[self sendVirtualKey:(VK_LWIN | KBDEXT) up:_win_pressed];
_win_pressed = !_win_pressed;
[self notifyDelegateModifiersChanged];
}
#pragma mark Sending special key strokes
- (void)sendEnterKeyStroke
{
[self sendVirtualKeyCode:(VK_RETURN | KBDEXT)];
[self sendVirtualKeyCode:(VK_RETURN | KBDEXT)];
}
- (void)sendEscapeKeyStroke
{
[self sendVirtualKeyCode:VK_ESCAPE];
[self sendVirtualKeyCode:VK_ESCAPE];
}
- (void)sendBackspaceKeyStroke
{
[self sendVirtualKeyCode:VK_BACK];
[self sendVirtualKeyCode:VK_BACK];
}
@end
@@ -233,74 +235,76 @@
- (void)handleAlphaNumChar:(int)character
{
// if we recive an uppercase letter - make it lower and send an shift down event to server
BOOL shift_was_sent = NO;
if(isupper(character) && _shift_pressed == NO)
{
character = tolower(character);
[self sendVirtualKey:VK_LSHIFT up:NO];
shift_was_sent = YES;
}
// convert the character to a VK
int vk = _virtual_key_map[character];
if(vk != 0)
{
// send key pressed
[self sendVirtualKey:vk up:NO];
[self sendVirtualKey:vk up:YES];
}
// send the missing shift up if we had a shift down
if(shift_was_sent)
[self sendVirtualKey:VK_LSHIFT up:YES];
// if we recive an uppercase letter - make it lower and send an shift down event to server
BOOL shift_was_sent = NO;
if (isupper(character) && _shift_pressed == NO)
{
character = tolower(character);
[self sendVirtualKey:VK_LSHIFT up:NO];
shift_was_sent = YES;
}
// convert the character to a VK
int vk = _virtual_key_map[character];
if (vk != 0)
{
// send key pressed
[self sendVirtualKey:vk up:NO];
[self sendVirtualKey:vk up:YES];
}
// send the missing shift up if we had a shift down
if (shift_was_sent)
[self sendVirtualKey:VK_LSHIFT up:YES];
}
- (void)handleSpecialKey:(int)character
{
NSDictionary* eventDescriptor = nil;
if(character < 256)
{
// convert the character to a unicode character
int code = _unicode_map[character];
if(code != 0)
eventDescriptor = [NSDictionary dictionaryWithObjectsAndKeys:
@"keyboard", @"type",
@"unicode", @"subtype",
[NSNumber numberWithUnsignedShort:0], @"flags",
[NSNumber numberWithUnsignedShort:code], @"unicode_char",
nil];
}
NSDictionary *eventDescriptor = nil;
if (character < 256)
{
// convert the character to a unicode character
int code = _unicode_map[character];
if (code != 0)
eventDescriptor = [NSDictionary
dictionaryWithObjectsAndKeys:@"keyboard", @"type", @"unicode", @"subtype",
[NSNumber numberWithUnsignedShort:0], @"flags",
[NSNumber numberWithUnsignedShort:code],
@"unicode_char", nil];
}
if (eventDescriptor == nil)
eventDescriptor = [NSDictionary dictionaryWithObjectsAndKeys:
@"keyboard", @"type",
@"unicode", @"subtype",
[NSNumber numberWithUnsignedShort:0], @"flags",
[NSNumber numberWithUnsignedShort:character], @"unicode_char",
nil];
if (eventDescriptor == nil)
eventDescriptor = [NSDictionary
dictionaryWithObjectsAndKeys:@"keyboard", @"type", @"unicode", @"subtype",
[NSNumber numberWithUnsignedShort:0], @"flags",
[NSNumber numberWithUnsignedShort:character],
@"unicode_char", nil];
[_session sendInputEvent:eventDescriptor];
[_session sendInputEvent:eventDescriptor];
}
// sends the vk code to the session
- (void)sendVirtualKey:(int)vKey up:(BOOL)up
{
DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(vKey, 4);
int flags = (up ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN);
flags |= ((scancode & KBDEXT) ? KBD_FLAGS_EXTENDED : 0);
[_session sendInputEvent:[NSDictionary dictionaryWithObjectsAndKeys:
@"keyboard", @"type",
@"scancode", @"subtype",
[NSNumber numberWithUnsignedShort:flags], @"flags",
[NSNumber numberWithUnsignedShort:(scancode & 0xFF)], @"scancode",
nil]];
DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(vKey, 4);
int flags = (up ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN);
flags |= ((scancode & KBDEXT) ? KBD_FLAGS_EXTENDED : 0);
[_session
sendInputEvent:[NSDictionary
dictionaryWithObjectsAndKeys:@"keyboard", @"type", @"scancode",
@"subtype",
[NSNumber numberWithUnsignedShort:flags],
@"flags",
[NSNumber
numberWithUnsignedShort:(scancode &
0xFF)],
@"scancode", nil]];
}
- (void)notifyDelegateModifiersChanged
{
if ([[self delegate] respondsToSelector:@selector(modifiersChangedForKeyboard:)])
[[self delegate] modifiersChangedForKeyboard:self];
if ([[self delegate] respondsToSelector:@selector(modifiersChangedForKeyboard:)])
[[self delegate] modifiersChangedForKeyboard:self];
}
@end

View File

@@ -1,10 +1,11 @@
/*
RDP Session object
RDP Session object
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <Foundation/Foundation.h>
@@ -18,91 +19,91 @@
@class ConnectionParams;
// notification handler for session disconnect
extern NSString* TSXSessionDidDisconnectNotification;
extern NSString* TSXSessionDidFailToConnectNotification;
extern NSString *TSXSessionDidDisconnectNotification;
extern NSString *TSXSessionDidFailToConnectNotification;
// protocol for session notifications
@protocol RDPSessionDelegate <NSObject>
@optional
- (void)session:(RDPSession*)session didFailToConnect:(int)reason;
- (void)sessionWillConnect:(RDPSession*)session;
- (void)sessionDidConnect:(RDPSession*)session;
- (void)sessionWillDisconnect:(RDPSession*)session;
- (void)sessionDidDisconnect:(RDPSession*)session;
- (void)sessionBitmapContextWillChange:(RDPSession*)session;
- (void)sessionBitmapContextDidChange:(RDPSession*)session;
- (void)session:(RDPSession*)session needsRedrawInRect:(CGRect)rect;
- (CGSize)sizeForFitScreenForSession:(RDPSession*)session;
- (void)session:(RDPSession *)session didFailToConnect:(int)reason;
- (void)sessionWillConnect:(RDPSession *)session;
- (void)sessionDidConnect:(RDPSession *)session;
- (void)sessionWillDisconnect:(RDPSession *)session;
- (void)sessionDidDisconnect:(RDPSession *)session;
- (void)sessionBitmapContextWillChange:(RDPSession *)session;
- (void)sessionBitmapContextDidChange:(RDPSession *)session;
- (void)session:(RDPSession *)session needsRedrawInRect:(CGRect)rect;
- (CGSize)sizeForFitScreenForSession:(RDPSession *)session;
- (void)session:(RDPSession*)session requestsAuthenticationWithParams:(NSMutableDictionary*)params;
- (void)session:(RDPSession*)session verifyCertificateWithParams:(NSMutableDictionary*)params;
- (void)session:(RDPSession *)session
requestsAuthenticationWithParams:(NSMutableDictionary *)params;
- (void)session:(RDPSession *)session verifyCertificateWithParams:(NSMutableDictionary *)params;
@end
// rdp session
@interface RDPSession : NSObject
@interface RDPSession : NSObject
{
@private
freerdp* _freerdp;
@private
freerdp *_freerdp;
ComputerBookmark *_bookmark;
ConnectionParams *_params;
NSObject<RDPSessionDelegate> *_delegate;
NSCondition *_ui_request_completed;
NSString *_name;
// flag if the session is suspended
BOOL _suspended;
ComputerBookmark* _bookmark;
ConnectionParams* _params;
NSObject<RDPSessionDelegate>* _delegate;
NSCondition* _ui_request_completed;
NSString* _name;
// flag if the session is suspended
BOOL _suspended;
// flag that specifies whether the RDP toolbar is visible
BOOL _toolbar_visible;
BOOL _toolbar_visible;
}
@property (readonly) ConnectionParams* params;
@property (readonly) ComputerBookmark* bookmark;
@property (assign) id <RDPSessionDelegate> delegate;
@property (assign) BOOL toolbarVisible;
@property (readonly) CGContextRef bitmapContext;
@property (readonly) NSCondition* uiRequestCompleted;
@property(readonly) ConnectionParams *params;
@property(readonly) ComputerBookmark *bookmark;
@property(assign) id<RDPSessionDelegate> delegate;
@property(assign) BOOL toolbarVisible;
@property(readonly) CGContextRef bitmapContext;
@property(readonly) NSCondition *uiRequestCompleted;
// initialize a new session with the given bookmark
- (id)initWithBookmark:(ComputerBookmark*)bookmark;
- (id)initWithBookmark:(ComputerBookmark *)bookmark;
#pragma mark - session control functions
// connect the session
-(void)connect;
- (void)connect;
// disconnect session
-(void)disconnect;
- (void)disconnect;
// suspends the session
-(void)suspend;
- (void)suspend;
// resumes a previously suspended session
-(void)resume;
- (void)resume;
// returns YES if the session is started
-(BOOL)isSuspended;
- (BOOL)isSuspended;
// send input event to the server
-(void)sendInputEvent:(NSDictionary*)event;
- (void)sendInputEvent:(NSDictionary *)event;
// session needs a refresh of its view
- (void)setNeedsDisplayInRectAsValue:(NSValue*)rect_value;
- (void)setNeedsDisplayInRectAsValue:(NSValue *)rect_value;
// get a small session screenshot
- (UIImage*)getScreenshotWithSize:(CGSize)size;
- (UIImage *)getScreenshotWithSize:(CGSize)size;
// returns the session's current paramters
- (rdpSettings*)getSessionParams;
- (rdpSettings *)getSessionParams;
// returns the session's name (usually the label of the bookmark the session was created with)
- (NSString*)sessionName;
- (NSString *)sessionName;
@end

View File

@@ -4,7 +4,8 @@
Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "ios_freerdp.h"
@@ -16,14 +17,13 @@
#import "Bookmark.h"
#import "ConnectionParams.h"
NSString* TSXSessionDidDisconnectNotification = @"TSXSessionDidDisconnect";
NSString* TSXSessionDidFailToConnectNotification =
@"TSXSessionDidFailToConnect";
NSString *TSXSessionDidDisconnectNotification = @"TSXSessionDidDisconnect";
NSString *TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect";
@interface RDPSession(Private)
@interface RDPSession (Private)
- (void)runSession;
- (void)runSessionFinished:(NSNumber*)result;
- (mfInfo*)mfi;
- (void)runSessionFinished:(NSNumber *)result;
- (mfInfo *)mfi;
// The connection thread calls these on the main thread.
- (void)sessionWillConnect;
@@ -36,20 +36,19 @@ NSString* TSXSessionDidFailToConnectNotification =
@implementation RDPSession
@synthesize delegate = _delegate, params = _params,
toolbarVisible = _toolbar_visible, uiRequestCompleted = _ui_request_completed,
bookmark = _bookmark;
@synthesize delegate = _delegate, params = _params, toolbarVisible = _toolbar_visible,
uiRequestCompleted = _ui_request_completed, bookmark = _bookmark;
+ (void)initialize
{
ios_init_freerdp();
}
static BOOL addArgument(int* argc, char** *argv, const char* fmt, ...)
static BOOL addArgument(int *argc, char ***argv, const char *fmt, ...)
{
va_list ap;
char* arg = NULL;
char** tmp = realloc(*argv, (*argc + 1) * sizeof(char*));
char *arg = NULL;
char **tmp = realloc(*argv, (*argc + 1) * sizeof(char *));
if (!tmp)
return FALSE;
@@ -63,12 +62,12 @@ static BOOL addArgument(int* argc, char** *argv, const char* fmt, ...)
return TRUE;
}
static BOOL addFlag(int* argc, char** *argv, const char* str, BOOL flag)
static BOOL addFlag(int *argc, char ***argv, const char *str, BOOL flag)
{
return addArgument(argc, argv, "%s%s", flag ? "+" : "-", str);
}
static void freeArguments(int argc, char** argv)
static void freeArguments(int argc, char **argv)
{
int i;
@@ -79,18 +78,18 @@ static void freeArguments(int argc, char** argv)
}
// Designated initializer.
- (id)initWithBookmark:(ComputerBookmark*)bookmark
- (id)initWithBookmark:(ComputerBookmark *)bookmark
{
int status;
char** argv = NULL;
char **argv = NULL;
int argc = 0;
if (!(self = [super init]))
return nil;
if (!bookmark)
[NSException raise:NSInvalidArgumentException format:
@"%s: params may not be nil.", __func__];
[NSException raise:NSInvalidArgumentException
format:@"%s: params may not be nil.", __func__];
_bookmark = [bookmark retain];
_params = [[bookmark params] copy];
@@ -107,13 +106,13 @@ static void freeArguments(int argc, char** argv)
if (!addArgument(&argc, &argv, "/gdi:sw"))
goto out_free;
// Screen Size is set on connect (we need a valid delegate in case the user choose an automatic screen size)
// Screen Size is set on connect (we need a valid delegate in case the user choose an automatic
// screen size)
// Other simple numeric settings
if ([_params hasValueForKey:@"colors"])
if (!addArgument(&argc, &argv,
"/bpp:%d", [_params intForKey:@"colors" with3GEnabled:
connected_via_3g]))
if (!addArgument(&argc, &argv, "/bpp:%d",
[_params intForKey:@"colors" with3GEnabled:connected_via_3g]))
goto out_free;
if ([_params hasValueForKey:@"port"])
@@ -124,43 +123,38 @@ static void freeArguments(int argc, char** argv)
if (!addArgument(&argc, &argv, "/admin"))
goto out_free;
if (!addArgument(&argc, &argv, "/v:%s", [_params UTF8StringForKey:
@"hostname"]))
if (!addArgument(&argc, &argv, "/v:%s", [_params UTF8StringForKey:@"hostname"]))
goto out_free;
// String settings
if ([[_params StringForKey:@"username"] length])
{
if (!addArgument(&argc, &argv, "/u:%s", [_params UTF8StringForKey:
@"username"]))
if (!addArgument(&argc, &argv, "/u:%s", [_params UTF8StringForKey:@"username"]))
goto out_free;
}
if ([[_params StringForKey:@"password"] length])
{
if (!addArgument(&argc, &argv, "/p:%s", [_params UTF8StringForKey:
@"password"]))
if (!addArgument(&argc, &argv, "/p:%s", [_params UTF8StringForKey:@"password"]))
goto out_free;
}
if ([[_params StringForKey:@"domain"] length])
{
if (!addArgument(&argc, &argv, "/d:%s", [_params UTF8StringForKey:
@"domain"]))
if (!addArgument(&argc, &argv, "/d:%s", [_params UTF8StringForKey:@"domain"]))
goto out_free;
}
if ([[_params StringForKey:@"working_directory"] length])
{
if (!addArgument(&argc, &argv, "/shell-dir:%s", [_params UTF8StringForKey:
@"working_directory"]))
if (!addArgument(&argc, &argv, "/shell-dir:%s",
[_params UTF8StringForKey:@"working_directory"]))
goto out_free;
}
if ([[_params StringForKey:@"remote_program"] length])
{
if (!addArgument(&argc, &argv, "/shell:%s", [_params UTF8StringForKey:
@"remote_program"]))
if (!addArgument(&argc, &argv, "/shell:%s", [_params UTF8StringForKey:@"remote_program"]))
goto out_free;
}
@@ -186,30 +180,28 @@ static void freeArguments(int argc, char** argv)
if (!addFlag(&argc, &argv, "bitmap-cache", TRUE))
goto out_free;
if (!addFlag(&argc, &argv, "wallpaper", [_params boolForKey:@"perf_show_desktop"
with3GEnabled:connected_via_3g]))
if (!addFlag(&argc, &argv, "wallpaper",
[_params boolForKey:@"perf_show_desktop" with3GEnabled:connected_via_3g]))
goto out_free;
if (!addFlag(&argc, &argv,
"window-drag", [_params boolForKey:@"perf_window_dragging"
with3GEnabled:connected_via_3g]))
if (!addFlag(&argc, &argv, "window-drag",
[_params boolForKey:@"perf_window_dragging" with3GEnabled:connected_via_3g]))
goto out_free;
if (!addFlag(&argc, &argv,
"menu-anims", [_params boolForKey:@"perf_menu_animation"
with3GEnabled:connected_via_3g]))
if (!addFlag(&argc, &argv, "menu-anims",
[_params boolForKey:@"perf_menu_animation" with3GEnabled:connected_via_3g]))
goto out_free;
if (!addFlag(&argc, &argv, "themes", [_params boolForKey:@"perf_windows_themes"
with3GEnabled:connected_via_3g]))
if (!addFlag(&argc, &argv, "themes",
[_params boolForKey:@"perf_windows_themes" with3GEnabled:connected_via_3g]))
goto out_free;
if (!addFlag(&argc, &argv, "fonts", [_params boolForKey:@"perf_font_smoothing"
with3GEnabled:connected_via_3g]))
if (!addFlag(&argc, &argv, "fonts",
[_params boolForKey:@"perf_font_smoothing" with3GEnabled:connected_via_3g]))
goto out_free;
if (!addFlag(&argc, &argv, "aero", [_params boolForKey:
@"perf_desktop_composition" with3GEnabled:connected_via_3g]))
if (!addFlag(&argc, &argv, "aero",
[_params boolForKey:@"perf_desktop_composition" with3GEnabled:connected_via_3g]))
goto out_free;
if ([_params hasValueForKey:@"width"])
@@ -248,8 +240,7 @@ static void freeArguments(int argc, char** argv)
// ts gateway settings
if ([_params boolForKey:@"enable_tsg_settings"])
{
if (!addArgument(&argc, &argv,
"/g:%s", [_params UTF8StringForKey:@"tsg_hostname"]))
if (!addArgument(&argc, &argv, "/g:%s", [_params UTF8StringForKey:@"tsg_hostname"]))
goto out_free;
if (!addArgument(&argc, &argv, "/gp:%d", [_params intForKey:@"tsg_port"]))
@@ -269,9 +260,7 @@ static void freeArguments(int argc, char** argv)
if (!addArgument(&argc, &argv, "/kbd:%d", 0x409))
goto out_free;
status = freerdp_client_settings_parse_command_line(_freerdp->settings, argc,
argv,
FALSE);
status = freerdp_client_settings_parse_command_line(_freerdp->settings, argc, argv, FALSE);
if (0 != status)
goto out_free;
@@ -307,7 +296,7 @@ out_free:
- (void)connect
{
// Set Screen Size to automatic if widht or height are still 0
rdpSettings* settings = _freerdp->settings;
rdpSettings *settings = _freerdp->settings;
if (settings->DesktopWidth == 0 || settings->DesktopHeight == 0)
{
@@ -325,7 +314,8 @@ out_free:
}
}
// TODO: This is a hack to ensure connections to RDVH with 16bpp don't have an odd screen resolution width
// TODO: This is a hack to ensure connections to RDVH with 16bpp don't have an odd screen
// resolution width
// Otherwise this could result in screen corruption ..
if (settings->ColorDepth <= 16)
settings->DesktopWidth &= (~1);
@@ -335,9 +325,8 @@ out_free:
- (void)disconnect
{
mfInfo* mfi = [self mfi];
ios_events_send(mfi, [NSDictionary dictionaryWithObject:@"disconnect" forKey:
@"type"]);
mfInfo *mfi = [self mfi];
ios_events_send(mfi, [NSDictionary dictionaryWithObject:@"disconnect" forKey:@"type"]);
if (mfi->connection_state == TSXConnectionConnecting)
{
@@ -353,7 +342,7 @@ out_free:
}
// suspends the session
-(void)suspend
- (void)suspend
{
if (!_suspended)
{
@@ -363,7 +352,7 @@ out_free:
}
// resumes a previously suspended session
-(void)resume
- (void)resume
{
if (_suspended)
{
@@ -380,7 +369,7 @@ out_free:
}
// returns YES if the session is started
-(BOOL)isSuspended
- (BOOL)isSuspended
{
return _suspended;
}
@@ -388,7 +377,7 @@ out_free:
#pragma mark -
#pragma mark Input events
- (void)sendInputEvent:(NSDictionary*)eventDescriptor
- (void)sendInputEvent:(NSDictionary *)eventDescriptor
{
if ([self mfi]->connection_state == TSXConnectionConnected)
ios_events_send([self mfi], eventDescriptor);
@@ -397,17 +386,16 @@ out_free:
#pragma mark -
#pragma mark Server events (main thread)
- (void)setNeedsDisplayInRectAsValue:(NSValue*)rect_value
- (void)setNeedsDisplayInRectAsValue:(NSValue *)rect_value
{
if ([[self delegate] respondsToSelector:@selector(session:needsRedrawInRect:)])
[[self delegate] session:self needsRedrawInRect:[rect_value CGRectValue]];
}
#pragma mark -
#pragma mark interface functions
- (UIImage*)getScreenshotWithSize:(CGSize)size
- (UIImage *)getScreenshotWithSize:(CGSize)size
{
NSAssert([self mfi]->bitmap_context != nil,
@"Screenshot requested while having no valid RDP drawing context");
@@ -415,20 +403,20 @@ out_free:
UIGraphicsBeginImageContext(size);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, size.height);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width,
size.height), cgImage);
UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext();
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, size.height),
cgImage);
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(cgImage);
return viewImage;
}
- (rdpSettings*)getSessionParams
- (rdpSettings *)getSessionParams
{
return _freerdp->settings;
}
- (NSString*)sessionName
- (NSString *)sessionName
{
return _name;
}
@@ -436,9 +424,9 @@ out_free:
@end
#pragma mark -
@implementation RDPSession(Private)
@implementation RDPSession (Private)
- (mfInfo*)mfi
- (mfInfo *)mfi
{
return MFI_FROM_INSTANCE(_freerdp);
}
@@ -446,19 +434,21 @@ out_free:
// Blocks until rdp session finishes.
- (void)runSession
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Run the session
[self performSelectorOnMainThread:@selector(sessionWillConnect) withObject:nil
waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(sessionWillConnect)
withObject:nil
waitUntilDone:YES];
int result_code = ios_run_freerdp(_freerdp);
[self mfi]->connection_state = TSXConnectionDisconnected;
[self performSelectorOnMainThread:@selector(runSessionFinished:) withObject:
[NSNumber numberWithInt:result_code] waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(runSessionFinished:)
withObject:[NSNumber numberWithInt:result_code]
waitUntilDone:YES];
[pool release];
}
// Main thread.
- (void)runSessionFinished:(NSNumber*)result
- (void)runSessionFinished:(NSNumber *)result
{
int result_code = [result intValue];
@@ -497,8 +487,9 @@ out_free:
- (void)sessionDidFailToConnect:(int)reason
{
[[NSNotificationCenter defaultCenter] postNotificationName:
TSXSessionDidFailToConnectNotification object:self];
[[NSNotificationCenter defaultCenter]
postNotificationName:TSXSessionDidFailToConnectNotification
object:self];
if ([[self delegate] respondsToSelector:@selector(session:didFailToConnect:)])
[[self delegate] session:self didFailToConnect:reason];
@@ -506,8 +497,8 @@ out_free:
- (void)sessionDidDisconnect
{
[[NSNotificationCenter defaultCenter] postNotificationName:
TSXSessionDidDisconnectNotification object:self];
[[NSNotificationCenter defaultCenter] postNotificationName:TSXSessionDidDisconnectNotification
object:self];
if ([[self delegate] respondsToSelector:@selector(sessionDidDisconnect:)])
[[self delegate] sessionDidDisconnect:self];
@@ -515,29 +506,25 @@ out_free:
- (void)sessionBitmapContextWillChange
{
if ([[self delegate] respondsToSelector:@selector(
sessionBitmapContextWillChange:)])
if ([[self delegate] respondsToSelector:@selector(sessionBitmapContextWillChange:)])
[[self delegate] sessionBitmapContextWillChange:self];
}
- (void)sessionBitmapContextDidChange
{
if ([[self delegate] respondsToSelector:@selector(sessionBitmapContextDidChange
:)])
if ([[self delegate] respondsToSelector:@selector(sessionBitmapContextDidChange:)])
[[self delegate] sessionBitmapContextDidChange:self];
}
- (void)sessionRequestsAuthenticationWithParams:(NSMutableDictionary*)params
- (void)sessionRequestsAuthenticationWithParams:(NSMutableDictionary *)params
{
if ([[self delegate] respondsToSelector:@selector(session:
requestsAuthenticationWithParams:)])
if ([[self delegate] respondsToSelector:@selector(session:requestsAuthenticationWithParams:)])
[[self delegate] session:self requestsAuthenticationWithParams:params];
}
- (void)sessionVerifyCertificateWithParams:(NSMutableDictionary*)params
- (void)sessionVerifyCertificateWithParams:(NSMutableDictionary *)params
{
if ([[self delegate] respondsToSelector:@selector(session:
verifyCertificateWithParams:)])
if ([[self delegate] respondsToSelector:@selector(session:verifyCertificateWithParams:)])
[[self delegate] session:self verifyCertificateWithParams:params];
}

View File

@@ -1,12 +1,12 @@
/*
Advanced keyboard view interface
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -15,36 +15,34 @@
@optional
// called when a function key was pressed and a virtual keycode is provided
// @key: virtual key code
-(void)advancedKeyPressedVKey:(int)key;
- (void)advancedKeyPressedVKey:(int)key;
// called when a function key was pressed and the keys unicode is provided
// @key: unicode character
-(void)advancedKeyPressedUnicode:(int)key;
- (void)advancedKeyPressedUnicode:(int)key;
@end
@interface AdvancedKeyboardView : UIView
@interface AdvancedKeyboardView : UIView
{
@private
// view containing function keys (F-keys) and function block (ins, del, home, end, ...)
UIView* _function_keys_view;
@private
// view containing function keys (F-keys) and function block (ins, del, home, end, ...)
UIView *_function_keys_view;
// view containing numpad keys (0-9, +-/*)
UIView* _numpad_keys_view;
// view containing cursor keys (up, down, left, right)
UIView* _cursor_keys_view;
// currently visible view
UIView* _cur_view;
// view containing numpad keys (0-9, +-/*)
UIView *_numpad_keys_view;
// delegate
NSObject<AdvancedKeyboardDelegate>* _delegate;
// view containing cursor keys (up, down, left, right)
UIView *_cursor_keys_view;
// currently visible view
UIView *_cur_view;
// delegate
NSObject<AdvancedKeyboardDelegate> *_delegate;
}
@property (assign) NSObject<AdvancedKeyboardDelegate>* delegate;
@property(assign) NSObject<AdvancedKeyboardDelegate> *delegate;
// init keyboard view with frame and delegate
- (id)initWithFrame:(CGRect)frame delegate:(NSObject<AdvancedKeyboardDelegate>*)delegate;
- (id)initWithFrame:(CGRect)frame delegate:(NSObject<AdvancedKeyboardDelegate> *)delegate;
@end

View File

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

View File

@@ -5,15 +5,16 @@
#import <UIKit/UIKit.h>
@interface BlockAlertView : NSObject {
@protected
UIView *_view;
NSMutableArray *_blocks;
CGFloat _height;
NSString *_title;
NSString *_message;
BOOL _shown;
BOOL _cancelBounce;
@interface BlockAlertView : NSObject
{
@protected
UIView *_view;
NSMutableArray *_blocks;
CGFloat _height;
NSString *_title;
NSString *_message;
BOOL _shown;
BOOL _cancelBounce;
}
+ (BlockAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message;
@@ -34,8 +35,8 @@
- (void)setupDisplay;
@property (nonatomic, retain) UIImage *backgroundImage;
@property (nonatomic, readonly) UIView *view;
@property (nonatomic, readwrite) BOOL vignetteBackground;
@property(nonatomic, retain) UIImage *backgroundImage;
@property(nonatomic, readonly) UIView *view;
@property(nonatomic, readwrite) BOOL vignetteBackground;
@end

View File

@@ -19,429 +19,457 @@ static UIFont *titleFont = nil;
static UIFont *messageFont = nil;
static UIFont *buttonFont = nil;
#pragma mark - init
+ (void)initialize
{
if (self == [BlockAlertView class])
{
background = [UIImage imageNamed:kAlertViewBackground];
background = [[background stretchableImageWithLeftCapWidth:0 topCapHeight:kAlertViewBackgroundCapHeight] retain];
backgroundlandscape = [UIImage imageNamed:kAlertViewBackgroundLandscape];
backgroundlandscape = [[backgroundlandscape stretchableImageWithLeftCapWidth:0 topCapHeight:kAlertViewBackgroundCapHeight] retain];
titleFont = [kAlertViewTitleFont retain];
messageFont = [kAlertViewMessageFont retain];
buttonFont = [kAlertViewButtonFont retain];
}
if (self == [BlockAlertView class])
{
background = [UIImage imageNamed:kAlertViewBackground];
background =
[[background stretchableImageWithLeftCapWidth:0
topCapHeight:kAlertViewBackgroundCapHeight] retain];
backgroundlandscape = [UIImage imageNamed:kAlertViewBackgroundLandscape];
backgroundlandscape = [[backgroundlandscape
stretchableImageWithLeftCapWidth:0
topCapHeight:kAlertViewBackgroundCapHeight] retain];
titleFont = [kAlertViewTitleFont retain];
messageFont = [kAlertViewMessageFont retain];
buttonFont = [kAlertViewButtonFont retain];
}
}
+ (BlockAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message
{
return [[[BlockAlertView alloc] initWithTitle:title message:message] autorelease];
return [[[BlockAlertView alloc] initWithTitle:title message:message] autorelease];
}
+ (void)showInfoAlertWithTitle:(NSString *)title message:(NSString *)message
{
BlockAlertView *alert = [[BlockAlertView alloc] initWithTitle:title message:message];
[alert setCancelButtonWithTitle:NSLocalizedString(@"Dismiss", nil) block:nil];
[alert show];
[alert release];
BlockAlertView *alert = [[BlockAlertView alloc] initWithTitle:title message:message];
[alert setCancelButtonWithTitle:NSLocalizedString(@"Dismiss", nil) block:nil];
[alert show];
[alert release];
}
+ (void)showErrorAlert:(NSError *)error
{
BlockAlertView *alert = [[BlockAlertView alloc] initWithTitle:NSLocalizedString(@"Operation Failed", nil) message:[NSString stringWithFormat:NSLocalizedString(@"The operation did not complete successfully: %@", nil), error]];
[alert setCancelButtonWithTitle:@"Dismiss" block:nil];
[alert show];
[alert release];
BlockAlertView *alert = [[BlockAlertView alloc]
initWithTitle:NSLocalizedString(@"Operation Failed", nil)
message:[NSString
stringWithFormat:NSLocalizedString(
@"The operation did not complete successfully: %@",
nil),
error]];
[alert setCancelButtonWithTitle:@"Dismiss" block:nil];
[alert show];
[alert release];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - NSObject
- (void)addComponents:(CGRect)frame {
if (_title)
{
CGSize size = [_title sizeWithFont:titleFont
constrainedToSize:CGSizeMake(frame.size.width-kAlertViewBorder*2, 1000)
lineBreakMode:NSLineBreakByWordWrapping];
UILabel *labelView = [[UILabel alloc] initWithFrame:CGRectMake(kAlertViewBorder, _height, frame.size.width-kAlertViewBorder*2, size.height)];
labelView.font = titleFont;
labelView.numberOfLines = 0;
labelView.lineBreakMode = NSLineBreakByWordWrapping;
labelView.textColor = kAlertViewTitleTextColor;
labelView.backgroundColor = [UIColor clearColor];
labelView.textAlignment = NSTextAlignmentCenter;
labelView.shadowColor = kAlertViewTitleShadowColor;
labelView.shadowOffset = kAlertViewTitleShadowOffset;
labelView.text = _title;
[_view addSubview:labelView];
[labelView release];
_height += size.height + kAlertViewBorder;
}
if (_message)
{
CGSize size = [_message sizeWithFont:messageFont
constrainedToSize:CGSizeMake(frame.size.width-kAlertViewBorder*2, 1000)
lineBreakMode:NSLineBreakByWordWrapping];
UILabel *labelView = [[UILabel alloc] initWithFrame:CGRectMake(kAlertViewBorder, _height, frame.size.width-kAlertViewBorder*2, size.height)];
labelView.font = messageFont;
labelView.numberOfLines = 0;
labelView.lineBreakMode = NSLineBreakByWordWrapping;
labelView.textColor = kAlertViewMessageTextColor;
labelView.backgroundColor = [UIColor clearColor];
labelView.textAlignment = NSTextAlignmentCenter;
labelView.shadowColor = kAlertViewMessageShadowColor;
labelView.shadowOffset = kAlertViewMessageShadowOffset;
labelView.text = _message;
[_view addSubview:labelView];
[labelView release];
_height += size.height + kAlertViewBorder;
}
- (void)addComponents:(CGRect)frame
{
if (_title)
{
CGSize size = [_title sizeWithFont:titleFont
constrainedToSize:CGSizeMake(frame.size.width - kAlertViewBorder * 2, 1000)
lineBreakMode:NSLineBreakByWordWrapping];
UILabel *labelView = [[UILabel alloc]
initWithFrame:CGRectMake(kAlertViewBorder, _height,
frame.size.width - kAlertViewBorder * 2, size.height)];
labelView.font = titleFont;
labelView.numberOfLines = 0;
labelView.lineBreakMode = NSLineBreakByWordWrapping;
labelView.textColor = kAlertViewTitleTextColor;
labelView.backgroundColor = [UIColor clearColor];
labelView.textAlignment = NSTextAlignmentCenter;
labelView.shadowColor = kAlertViewTitleShadowColor;
labelView.shadowOffset = kAlertViewTitleShadowOffset;
labelView.text = _title;
[_view addSubview:labelView];
[labelView release];
_height += size.height + kAlertViewBorder;
}
if (_message)
{
CGSize size =
[_message sizeWithFont:messageFont
constrainedToSize:CGSizeMake(frame.size.width - kAlertViewBorder * 2, 1000)
lineBreakMode:NSLineBreakByWordWrapping];
UILabel *labelView = [[UILabel alloc]
initWithFrame:CGRectMake(kAlertViewBorder, _height,
frame.size.width - kAlertViewBorder * 2, size.height)];
labelView.font = messageFont;
labelView.numberOfLines = 0;
labelView.lineBreakMode = NSLineBreakByWordWrapping;
labelView.textColor = kAlertViewMessageTextColor;
labelView.backgroundColor = [UIColor clearColor];
labelView.textAlignment = NSTextAlignmentCenter;
labelView.shadowColor = kAlertViewMessageShadowColor;
labelView.shadowOffset = kAlertViewMessageShadowOffset;
labelView.text = _message;
[_view addSubview:labelView];
[labelView release];
_height += size.height + kAlertViewBorder;
}
}
- (void)setupDisplay
{
[[_view subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[obj removeFromSuperview];
}];
UIWindow *parentView = [BlockBackground sharedInstance];
CGRect frame = parentView.bounds;
frame.origin.x = floorf((frame.size.width - background.size.width) * 0.5);
frame.size.width = background.size.width;
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(orientation)) {
frame.size.width += 150;
frame.origin.x -= 75;
}
_view.frame = frame;
_height = kAlertViewBorder + 15;
if (NeedsLandscapePhoneTweaks) {
_height -= 15; // landscape phones need to trimmed a bit
}
[[_view subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[obj removeFromSuperview];
}];
[self addComponents:frame];
UIWindow *parentView = [BlockBackground sharedInstance];
CGRect frame = parentView.bounds;
frame.origin.x = floorf((frame.size.width - background.size.width) * 0.5);
frame.size.width = background.size.width;
if (_shown)
[self show];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(orientation))
{
frame.size.width += 150;
frame.origin.x -= 75;
}
_view.frame = frame;
_height = kAlertViewBorder + 15;
if (NeedsLandscapePhoneTweaks)
{
_height -= 15; // landscape phones need to trimmed a bit
}
[self addComponents:frame];
if (_shown)
[self show];
}
- (id)initWithTitle:(NSString *)title message:(NSString *)message
- (id)initWithTitle:(NSString *)title message:(NSString *)message
{
self = [super init];
if (self)
{
_title = [title copy];
_message = [message copy];
_view = [[UIView alloc] init];
_view.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
_blocks = [[NSMutableArray alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(setupDisplay)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
if ([self class] == [BlockAlertView class])
[self setupDisplay];
_vignetteBackground = NO;
}
return self;
self = [super init];
if (self)
{
_title = [title copy];
_message = [message copy];
_view = [[UIView alloc] init];
_view.autoresizingMask =
UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
_blocks = [[NSMutableArray alloc] init];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(setupDisplay)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
if ([self class] == [BlockAlertView class])
[self setupDisplay];
_vignetteBackground = NO;
}
return self;
}
- (void)dealloc
- (void)dealloc
{
[_title release];
[_message release];
[_backgroundImage release];
[_view release];
[_blocks release];
[super dealloc];
[_title release];
[_message release];
[_backgroundImage release];
[_view release];
[_blocks release];
[super dealloc];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Public
- (void)addButtonWithTitle:(NSString *)title color:(NSString*)color block:(void (^)())block
- (void)addButtonWithTitle:(NSString *)title color:(NSString *)color block:(void (^)())block
{
[_blocks addObject:[NSArray arrayWithObjects:
block ? [[block copy] autorelease] : [NSNull null],
title,
color,
nil]];
[_blocks addObject:[NSArray arrayWithObjects:block ? [[block copy] autorelease] : [NSNull null],
title, color, nil]];
}
- (void)addButtonWithTitle:(NSString *)title block:(void (^)())block
- (void)addButtonWithTitle:(NSString *)title block:(void (^)())block
{
[self addButtonWithTitle:title color:@"gray" block:block];
[self addButtonWithTitle:title color:@"gray" block:block];
}
- (void)setCancelButtonWithTitle:(NSString *)title block:(void (^)())block
- (void)setCancelButtonWithTitle:(NSString *)title block:(void (^)())block
{
[self addButtonWithTitle:title color:@"black" block:block];
[self addButtonWithTitle:title color:@"black" block:block];
}
- (void)setDestructiveButtonWithTitle:(NSString *)title block:(void (^)())block
{
[self addButtonWithTitle:title color:@"red" block:block];
[self addButtonWithTitle:title color:@"red" block:block];
}
- (void)show
{
_shown = YES;
BOOL isSecondButton = NO;
NSUInteger index = 0;
for (NSUInteger i = 0; i < _blocks.count; i++)
{
NSArray *block = [_blocks objectAtIndex:i];
NSString *title = [block objectAtIndex:1];
NSString *color = [block objectAtIndex:2];
_shown = YES;
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"alert-%@-button.png", color]];
image = [image stretchableImageWithLeftCapWidth:(int)(image.size.width+1)>>1 topCapHeight:0];
CGFloat maxHalfWidth = floorf((_view.bounds.size.width-kAlertViewBorder*3)*0.5);
CGFloat width = _view.bounds.size.width-kAlertViewBorder*2;
CGFloat xOffset = kAlertViewBorder;
if (isSecondButton)
{
width = maxHalfWidth;
xOffset = width + kAlertViewBorder * 2;
isSecondButton = NO;
}
else if (i + 1 < _blocks.count)
{
// In this case there's another button.
// Let's check if they fit on the same line.
CGSize size = [title sizeWithFont:buttonFont
minFontSize:10
actualFontSize:nil
forWidth:_view.bounds.size.width-kAlertViewBorder*2
lineBreakMode:NSLineBreakByClipping];
if (size.width < maxHalfWidth - kAlertViewBorder)
{
// It might fit. Check the next Button
NSArray *block2 = [_blocks objectAtIndex:i+1];
NSString *title2 = [block2 objectAtIndex:1];
size = [title2 sizeWithFont:buttonFont
minFontSize:10
actualFontSize:nil
forWidth:_view.bounds.size.width-kAlertViewBorder*2
lineBreakMode:NSLineBreakByClipping];
if (size.width < maxHalfWidth - kAlertViewBorder)
{
// They'll fit!
isSecondButton = YES; // For the next iteration
width = maxHalfWidth;
}
}
}
else if (_blocks.count == 1)
{
// In this case this is the ony button. We'll size according to the text
CGSize size = [title sizeWithFont:buttonFont
minFontSize:10
actualFontSize:nil
forWidth:_view.bounds.size.width-kAlertViewBorder*2
lineBreakMode:UILineBreakModeClip];
size.width = MAX(size.width, 80);
if (size.width + 2 * kAlertViewBorder < width)
{
width = size.width + 2 * kAlertViewBorder;
xOffset = floorf((_view.bounds.size.width - width) * 0.5);
}
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(xOffset, _height, width, kAlertButtonHeight);
button.titleLabel.font = buttonFont;
if (IOS_LESS_THAN_6) {
BOOL isSecondButton = NO;
NSUInteger index = 0;
for (NSUInteger i = 0; i < _blocks.count; i++)
{
NSArray *block = [_blocks objectAtIndex:i];
NSString *title = [block objectAtIndex:1];
NSString *color = [block objectAtIndex:2];
UIImage *image =
[UIImage imageNamed:[NSString stringWithFormat:@"alert-%@-button.png", color]];
image = [image stretchableImageWithLeftCapWidth:(int)(image.size.width + 1) >> 1
topCapHeight:0];
CGFloat maxHalfWidth = floorf((_view.bounds.size.width - kAlertViewBorder * 3) * 0.5);
CGFloat width = _view.bounds.size.width - kAlertViewBorder * 2;
CGFloat xOffset = kAlertViewBorder;
if (isSecondButton)
{
width = maxHalfWidth;
xOffset = width + kAlertViewBorder * 2;
isSecondButton = NO;
}
else if (i + 1 < _blocks.count)
{
// In this case there's another button.
// Let's check if they fit on the same line.
CGSize size = [title sizeWithFont:buttonFont
minFontSize:10
actualFontSize:nil
forWidth:_view.bounds.size.width - kAlertViewBorder * 2
lineBreakMode:NSLineBreakByClipping];
if (size.width < maxHalfWidth - kAlertViewBorder)
{
// It might fit. Check the next Button
NSArray *block2 = [_blocks objectAtIndex:i + 1];
NSString *title2 = [block2 objectAtIndex:1];
size = [title2 sizeWithFont:buttonFont
minFontSize:10
actualFontSize:nil
forWidth:_view.bounds.size.width - kAlertViewBorder * 2
lineBreakMode:NSLineBreakByClipping];
if (size.width < maxHalfWidth - kAlertViewBorder)
{
// They'll fit!
isSecondButton = YES; // For the next iteration
width = maxHalfWidth;
}
}
}
else if (_blocks.count == 1)
{
// In this case this is the ony button. We'll size according to the text
CGSize size = [title sizeWithFont:buttonFont
minFontSize:10
actualFontSize:nil
forWidth:_view.bounds.size.width - kAlertViewBorder * 2
lineBreakMode:UILineBreakModeClip];
size.width = MAX(size.width, 80);
if (size.width + 2 * kAlertViewBorder < width)
{
width = size.width + 2 * kAlertViewBorder;
xOffset = floorf((_view.bounds.size.width - width) * 0.5);
}
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(xOffset, _height, width, kAlertButtonHeight);
button.titleLabel.font = buttonFont;
if (IOS_LESS_THAN_6)
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
button.titleLabel.minimumFontSize = 10;
button.titleLabel.minimumFontSize = 10;
#pragma clang diagnostic pop
}
else {
button.titleLabel.adjustsFontSizeToFitWidth = YES;
button.titleLabel.adjustsLetterSpacingToFitWidth = YES;
button.titleLabel.minimumScaleFactor = 0.1;
}
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.shadowOffset = kAlertViewButtonShadowOffset;
button.backgroundColor = [UIColor clearColor];
button.tag = i+1;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitleColor:kAlertViewButtonTextColor forState:UIControlStateNormal];
[button setTitleShadowColor:kAlertViewButtonShadowColor forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
button.accessibilityLabel = title;
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_view addSubview:button];
if (!isSecondButton)
_height += kAlertButtonHeight + kAlertViewBorder;
index++;
}
}
else
{
button.titleLabel.adjustsFontSizeToFitWidth = YES;
button.titleLabel.adjustsLetterSpacingToFitWidth = YES;
button.titleLabel.minimumScaleFactor = 0.1;
}
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.shadowOffset = kAlertViewButtonShadowOffset;
button.backgroundColor = [UIColor clearColor];
button.tag = i + 1;
_height += 10; // Margin for the shadow
if (_height < background.size.height)
{
CGFloat offset = background.size.height - _height;
_height = background.size.height;
CGRect frame;
for (NSUInteger i = 0; i < _blocks.count; i++)
{
UIButton *btn = (UIButton *)[_view viewWithTag:i+1];
frame = btn.frame;
frame.origin.y += offset;
btn.frame = frame;
}
}
CGRect frame = _view.frame;
frame.origin.y = - _height;
frame.size.height = _height;
_view.frame = frame;
UIImageView *modalBackground = [[UIImageView alloc] initWithFrame:_view.bounds];
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
modalBackground.image = backgroundlandscape;
else
modalBackground.image = background;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitleColor:kAlertViewButtonTextColor forState:UIControlStateNormal];
[button setTitleShadowColor:kAlertViewButtonShadowColor forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
button.accessibilityLabel = title;
modalBackground.contentMode = UIViewContentModeScaleToFill;
modalBackground.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[_view insertSubview:modalBackground atIndex:0];
[modalBackground release];
if (_backgroundImage)
{
[BlockBackground sharedInstance].backgroundImage = _backgroundImage;
[_backgroundImage release];
_backgroundImage = nil;
}
[BlockBackground sharedInstance].vignetteBackground = _vignetteBackground;
[[BlockBackground sharedInstance] addToMainWindow:_view];
[button addTarget:self
action:@selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
__block CGPoint center = _view.center;
center.y = floorf([BlockBackground sharedInstance].bounds.size.height * 0.5) + kAlertViewBounce;
_cancelBounce = NO;
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
[BlockBackground sharedInstance].alpha = 1.0f;
_view.center = center;
}
completion:^(BOOL finished) {
if (_cancelBounce) return;
[UIView animateWithDuration:0.1
delay:0.0
options:0
animations:^{
center.y -= kAlertViewBounce;
_view.center = center;
}
completion:^(BOOL finished) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"AlertViewFinishedAnimations" object:nil];
}];
}];
[self retain];
[_view addSubview:button];
if (!isSecondButton)
_height += kAlertButtonHeight + kAlertViewBorder;
index++;
}
_height += 10; // Margin for the shadow
if (_height < background.size.height)
{
CGFloat offset = background.size.height - _height;
_height = background.size.height;
CGRect frame;
for (NSUInteger i = 0; i < _blocks.count; i++)
{
UIButton *btn = (UIButton *)[_view viewWithTag:i + 1];
frame = btn.frame;
frame.origin.y += offset;
btn.frame = frame;
}
}
CGRect frame = _view.frame;
frame.origin.y = -_height;
frame.size.height = _height;
_view.frame = frame;
UIImageView *modalBackground = [[UIImageView alloc] initWithFrame:_view.bounds];
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
modalBackground.image = backgroundlandscape;
else
modalBackground.image = background;
modalBackground.contentMode = UIViewContentModeScaleToFill;
modalBackground.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[_view insertSubview:modalBackground atIndex:0];
[modalBackground release];
if (_backgroundImage)
{
[BlockBackground sharedInstance].backgroundImage = _backgroundImage;
[_backgroundImage release];
_backgroundImage = nil;
}
[BlockBackground sharedInstance].vignetteBackground = _vignetteBackground;
[[BlockBackground sharedInstance] addToMainWindow:_view];
__block CGPoint center = _view.center;
center.y = floorf([BlockBackground sharedInstance].bounds.size.height * 0.5) + kAlertViewBounce;
_cancelBounce = NO;
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
[BlockBackground sharedInstance].alpha = 1.0f;
_view.center = center;
}
completion:^(BOOL finished) {
if (_cancelBounce)
return;
[UIView animateWithDuration:0.1
delay:0.0
options:0
animations:^{
center.y -= kAlertViewBounce;
_view.center = center;
}
completion:^(BOOL finished) {
[[NSNotificationCenter defaultCenter]
postNotificationName:@"AlertViewFinishedAnimations"
object:nil];
}];
}];
[self retain];
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
_shown = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (buttonIndex >= 0 && buttonIndex < [_blocks count])
{
id obj = [[_blocks objectAtIndex: buttonIndex] objectAtIndex:0];
if (![obj isEqual:[NSNull null]])
{
((void (^)())obj)();
}
}
if (animated)
{
[UIView animateWithDuration:0.1
delay:0.0
options:0
animations:^{
CGPoint center = _view.center;
center.y += 20;
_view.center = center;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationCurveEaseIn
animations:^{
CGRect frame = _view.frame;
frame.origin.y = -frame.size.height;
_view.frame = frame;
[[BlockBackground sharedInstance] reduceAlphaIfEmpty];
}
completion:^(BOOL finished) {
[[BlockBackground sharedInstance] removeView:_view];
[_view release]; _view = nil;
[self autorelease];
}];
}];
}
else
{
[[BlockBackground sharedInstance] removeView:_view];
[_view release]; _view = nil;
[self autorelease];
}
_shown = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (buttonIndex >= 0 && buttonIndex < [_blocks count])
{
id obj = [[_blocks objectAtIndex:buttonIndex] objectAtIndex:0];
if (![obj isEqual:[NSNull null]])
{
((void (^)())obj)();
}
}
if (animated)
{
[UIView animateWithDuration:0.1
delay:0.0
options:0
animations:^{
CGPoint center = _view.center;
center.y += 20;
_view.center = center;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationCurveEaseIn
animations:^{
CGRect frame = _view.frame;
frame.origin.y = -frame.size.height;
_view.frame = frame;
[[BlockBackground sharedInstance] reduceAlphaIfEmpty];
}
completion:^(BOOL finished) {
[[BlockBackground sharedInstance] removeView:_view];
[_view release];
_view = nil;
[self autorelease];
}];
}];
}
else
{
[[BlockBackground sharedInstance] removeView:_view];
[_view release];
_view = nil;
[self autorelease];
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Action
- (void)buttonClicked:(id)sender
- (void)buttonClicked:(id)sender
{
/* Run the button's block */
int buttonIndex = [sender tag] - 1;
[self dismissWithClickedButtonIndex:buttonIndex animated:YES];
/* Run the button's block */
int buttonIndex = [sender tag] - 1;
[self dismissWithClickedButtonIndex:buttonIndex animated:YES];
}
@end

View File

@@ -8,18 +8,19 @@
#import <UIKit/UIKit.h>
@interface BlockBackground : UIWindow {
@private
UIWindow *_previousKeyWindow;
@interface BlockBackground : UIWindow
{
@private
UIWindow *_previousKeyWindow;
}
+ (BlockBackground *) sharedInstance;
+ (BlockBackground *)sharedInstance;
- (void)addToMainWindow:(UIView *)view;
- (void)reduceAlphaIfEmpty;
- (void)removeView:(UIView *)view;
@property (nonatomic, retain) UIImage *backgroundImage;
@property (nonatomic, readwrite) BOOL vignetteBackground;
@property(nonatomic, retain) UIImage *backgroundImage;
@property(nonatomic, readwrite) BOOL vignetteBackground;
@end

View File

@@ -15,46 +15,51 @@
static BlockBackground *_sharedInstance = nil;
+ (BlockBackground*)sharedInstance
+ (BlockBackground *)sharedInstance
{
if (_sharedInstance != nil) {
return _sharedInstance;
}
if (_sharedInstance != nil)
{
return _sharedInstance;
}
@synchronized(self) {
if (_sharedInstance == nil) {
[[[self alloc] init] autorelease];
}
}
@synchronized(self)
{
if (_sharedInstance == nil)
{
[[[self alloc] init] autorelease];
}
}
return _sharedInstance;
return _sharedInstance;
}
+ (id)allocWithZone:(NSZone*)zone
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (_sharedInstance == nil) {
_sharedInstance = [super allocWithZone:zone];
return _sharedInstance;
}
}
NSAssert(NO, @ "[BlockBackground alloc] explicitly called on singleton class.");
return nil;
@synchronized(self)
{
if (_sharedInstance == nil)
{
_sharedInstance = [super allocWithZone:zone];
return _sharedInstance;
}
}
NSAssert(NO, @ "[BlockBackground alloc] explicitly called on singleton class.");
return nil;
}
- (id)copyWithZone:(NSZone*)zone
- (id)copyWithZone:(NSZone *)zone
{
return self;
return self;
}
- (id)retain
{
return self;
return self;
}
- (unsigned)retainCount
{
return UINT_MAX;
return UINT_MAX;
}
- (oneway void)release
@@ -63,165 +68,171 @@ static BlockBackground *_sharedInstance = nil;
- (id)autorelease
{
return self;
return self;
}
- (void)setRotation:(NSNotification*)notification
- (void)setRotation:(NSNotification *)notification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect orientationFrame = [UIScreen mainScreen].bounds;
if(
(UIInterfaceOrientationIsLandscape(orientation) && orientationFrame.size.height > orientationFrame.size.width) ||
(UIInterfaceOrientationIsPortrait(orientation) && orientationFrame.size.width > orientationFrame.size.height)
) {
float temp = orientationFrame.size.width;
orientationFrame.size.width = orientationFrame.size.height;
orientationFrame.size.height = temp;
}
self.transform = CGAffineTransformIdentity;
self.frame = orientationFrame;
CGFloat posY = orientationFrame.size.height/2;
CGFloat posX = orientationFrame.size.width/2;
CGPoint newCenter;
CGFloat rotateAngle;
switch (orientation) {
case UIInterfaceOrientationPortraitUpsideDown:
rotateAngle = M_PI;
newCenter = CGPointMake(posX, orientationFrame.size.height-posY);
break;
case UIInterfaceOrientationLandscapeLeft:
rotateAngle = -M_PI/2.0f;
newCenter = CGPointMake(posY, posX);
break;
case UIInterfaceOrientationLandscapeRight:
rotateAngle = M_PI/2.0f;
newCenter = CGPointMake(orientationFrame.size.height-posY, posX);
break;
default: // UIInterfaceOrientationPortrait
rotateAngle = 0.0;
newCenter = CGPointMake(posX, posY);
break;
}
self.transform = CGAffineTransformMakeRotation(rotateAngle);
self.center = newCenter;
[self setNeedsLayout];
[self layoutSubviews];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect orientationFrame = [UIScreen mainScreen].bounds;
if ((UIInterfaceOrientationIsLandscape(orientation) &&
orientationFrame.size.height > orientationFrame.size.width) ||
(UIInterfaceOrientationIsPortrait(orientation) &&
orientationFrame.size.width > orientationFrame.size.height))
{
float temp = orientationFrame.size.width;
orientationFrame.size.width = orientationFrame.size.height;
orientationFrame.size.height = temp;
}
self.transform = CGAffineTransformIdentity;
self.frame = orientationFrame;
CGFloat posY = orientationFrame.size.height / 2;
CGFloat posX = orientationFrame.size.width / 2;
CGPoint newCenter;
CGFloat rotateAngle;
switch (orientation)
{
case UIInterfaceOrientationPortraitUpsideDown:
rotateAngle = M_PI;
newCenter = CGPointMake(posX, orientationFrame.size.height - posY);
break;
case UIInterfaceOrientationLandscapeLeft:
rotateAngle = -M_PI / 2.0f;
newCenter = CGPointMake(posY, posX);
break;
case UIInterfaceOrientationLandscapeRight:
rotateAngle = M_PI / 2.0f;
newCenter = CGPointMake(orientationFrame.size.height - posY, posX);
break;
default: // UIInterfaceOrientationPortrait
rotateAngle = 0.0;
newCenter = CGPointMake(posX, posY);
break;
}
self.transform = CGAffineTransformMakeRotation(rotateAngle);
self.center = newCenter;
[self setNeedsLayout];
[self layoutSubviews];
}
- (id)init
{
self = [super initWithFrame:[[UIScreen mainScreen] bounds]];
if (self) {
self.windowLevel = UIWindowLevelStatusBar;
self.hidden = YES;
self.userInteractionEnabled = NO;
self.backgroundColor = [UIColor colorWithWhite:0.4 alpha:0.5f];
self.vignetteBackground = NO;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(setRotation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
[self setRotation:nil];
self = [super initWithFrame:[[UIScreen mainScreen] bounds]];
if (self)
{
self.windowLevel = UIWindowLevelStatusBar;
self.hidden = YES;
self.userInteractionEnabled = NO;
self.backgroundColor = [UIColor colorWithWhite:0.4 alpha:0.5f];
self.vignetteBackground = NO;
}
return self;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(setRotation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
[self setRotation:nil];
}
return self;
}
- (void)addToMainWindow:(UIView *)view
{
[self setRotation:nil];
if ([self.subviews containsObject:view]) return;
[self setRotation:nil];
if (self.hidden)
{
_previousKeyWindow = [[[UIApplication sharedApplication] keyWindow] retain];
self.alpha = 0.0f;
self.hidden = NO;
self.userInteractionEnabled = YES;
[self makeKeyWindow];
}
if (self.subviews.count > 0)
{
((UIView*)[self.subviews lastObject]).userInteractionEnabled = NO;
}
if (_backgroundImage)
{
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:_backgroundImage];
backgroundView.frame = self.bounds;
backgroundView.contentMode = UIViewContentModeScaleToFill;
[self addSubview:backgroundView];
[backgroundView release];
[_backgroundImage release];
_backgroundImage = nil;
}
[self addSubview:view];
if ([self.subviews containsObject:view])
return;
if (self.hidden)
{
_previousKeyWindow = [[[UIApplication sharedApplication] keyWindow] retain];
self.alpha = 0.0f;
self.hidden = NO;
self.userInteractionEnabled = YES;
[self makeKeyWindow];
}
if (self.subviews.count > 0)
{
((UIView *)[self.subviews lastObject]).userInteractionEnabled = NO;
}
if (_backgroundImage)
{
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:_backgroundImage];
backgroundView.frame = self.bounds;
backgroundView.contentMode = UIViewContentModeScaleToFill;
[self addSubview:backgroundView];
[backgroundView release];
[_backgroundImage release];
_backgroundImage = nil;
}
[self addSubview:view];
}
- (void)reduceAlphaIfEmpty
{
if (self.subviews.count == 1 || (self.subviews.count == 2 && [[self.subviews objectAtIndex:0] isKindOfClass:[UIImageView class]]))
{
self.alpha = 0.0f;
self.userInteractionEnabled = NO;
}
if (self.subviews.count == 1 ||
(self.subviews.count == 2 &&
[[self.subviews objectAtIndex:0] isKindOfClass:[UIImageView class]]))
{
self.alpha = 0.0f;
self.userInteractionEnabled = NO;
}
}
- (void)removeView:(UIView *)view
{
[view removeFromSuperview];
[view removeFromSuperview];
UIView *topView = [self.subviews lastObject];
if ([topView isKindOfClass:[UIImageView class]])
{
// It's a background. Remove it too
[topView removeFromSuperview];
}
if (self.subviews.count == 0)
{
self.hidden = YES;
[_previousKeyWindow makeKeyWindow];
[_previousKeyWindow release];
_previousKeyWindow = nil;
}
else
{
((UIView*)[self.subviews lastObject]).userInteractionEnabled = YES;
}
UIView *topView = [self.subviews lastObject];
if ([topView isKindOfClass:[UIImageView class]])
{
// It's a background. Remove it too
[topView removeFromSuperview];
}
if (self.subviews.count == 0)
{
self.hidden = YES;
[_previousKeyWindow makeKeyWindow];
[_previousKeyWindow release];
_previousKeyWindow = nil;
}
else
{
((UIView *)[self.subviews lastObject]).userInteractionEnabled = YES;
}
}
- (void)drawRect:(CGRect)rect
{
if (_backgroundImage || !_vignetteBackground) return;
CGContextRef context = UIGraphicsGetCurrentContext();
- (void)drawRect:(CGRect)rect
{
if (_backgroundImage || !_vignetteBackground)
return;
CGContextRef context = UIGraphicsGetCurrentContext();
size_t locationsCount = 2;
CGFloat locations[2] = {0.0f, 1.0f};
CGFloat colors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f};
CGFloat locations[2] = { 0.0f, 1.0f };
CGFloat colors[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f };
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount);
CGGradientRef gradient =
CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount);
CGColorSpaceRelease(colorSpace);
CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
float radius = MIN(self.bounds.size.width , self.bounds.size.height) ;
CGContextDrawRadialGradient (context, gradient, center, 0, center, radius, kCGGradientDrawsAfterEndLocation);
CGPoint center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
float radius = MIN(self.bounds.size.width, self.bounds.size.height);
CGContextDrawRadialGradient(context, gradient, center, 0, center, radius,
kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
}
@end

View File

@@ -8,65 +8,67 @@
#define BlockUI_h
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
#define NSTextAlignmentCenter UITextAlignmentCenter
#define NSLineBreakByWordWrapping UILineBreakModeWordWrap
#define NSLineBreakByClipping UILineBreakModeClip
#define NSTextAlignmentCenter UITextAlignmentCenter
#define NSLineBreakByWordWrapping UILineBreakModeWordWrap
#define NSLineBreakByClipping UILineBreakModeClip
#endif
#ifndef IOS_LESS_THAN_6
#define IOS_LESS_THAN_6 !([[[UIDevice currentDevice] systemVersion] compare:@"6.0" options:NSNumericSearch] != NSOrderedAscending)
#define IOS_LESS_THAN_6 \
!([[[UIDevice currentDevice] systemVersion] compare:@"6.0" \
options:NSNumericSearch] != NSOrderedAscending)
#endif
#define NeedsLandscapePhoneTweaks (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)
#define NeedsLandscapePhoneTweaks \
(UIInterfaceOrientationIsLandscape( \
[[UIApplication sharedApplication] statusBarOrientation]) && \
UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)
// Action Sheet constants
#define kActionSheetBounce 10
#define kActionSheetBorder 10
#define kActionSheetButtonHeight 45
#define kActionSheetTopMargin 15
#define kActionSheetBounce 10
#define kActionSheetBorder 10
#define kActionSheetButtonHeight 45
#define kActionSheetTopMargin 15
#define kActionSheetTitleFont [UIFont systemFontOfSize:18]
#define kActionSheetTitleTextColor [UIColor whiteColor]
#define kActionSheetTitleShadowColor [UIColor blackColor]
#define kActionSheetTitleShadowOffset CGSizeMake(0, -1)
#define kActionSheetTitleFont [UIFont systemFontOfSize:18]
#define kActionSheetTitleTextColor [UIColor whiteColor]
#define kActionSheetTitleShadowColor [UIColor blackColor]
#define kActionSheetTitleShadowOffset CGSizeMake(0, -1)
#define kActionSheetButtonFont [UIFont boldSystemFontOfSize:20]
#define kActionSheetButtonTextColor [UIColor whiteColor]
#define kActionSheetButtonShadowColor [UIColor blackColor]
#define kActionSheetButtonShadowOffset CGSizeMake(0, -1)
#define kActionSheetBackground @"action-sheet-panel.png"
#define kActionSheetBackgroundCapHeight 30
#define kActionSheetButtonFont [UIFont boldSystemFontOfSize:20]
#define kActionSheetButtonTextColor [UIColor whiteColor]
#define kActionSheetButtonShadowColor [UIColor blackColor]
#define kActionSheetButtonShadowOffset CGSizeMake(0, -1)
#define kActionSheetBackground @"action-sheet-panel.png"
#define kActionSheetBackgroundCapHeight 30
// Alert View constants
#define kAlertViewBounce 20
#define kAlertViewBorder (NeedsLandscapePhoneTweaks ? 5 : 10)
#define kAlertButtonHeight (NeedsLandscapePhoneTweaks ? 35 : 44)
#define kAlertViewBounce 20
#define kAlertViewBorder (NeedsLandscapePhoneTweaks ? 5 : 10)
#define kAlertButtonHeight (NeedsLandscapePhoneTweaks ? 35 : 44)
#define kAlertViewTitleFont [UIFont boldSystemFontOfSize:20]
#define kAlertViewTitleTextColor [UIColor colorWithWhite:244.0 / 255.0 alpha:1.0]
#define kAlertViewTitleShadowColor [UIColor blackColor]
#define kAlertViewTitleShadowOffset CGSizeMake(0, -1)
#define kAlertViewTitleFont [UIFont boldSystemFontOfSize:20]
#define kAlertViewTitleTextColor [UIColor colorWithWhite:244.0/255.0 alpha:1.0]
#define kAlertViewTitleShadowColor [UIColor blackColor]
#define kAlertViewTitleShadowOffset CGSizeMake(0, -1)
#define kAlertViewMessageFont [UIFont systemFontOfSize:18]
#define kAlertViewMessageTextColor [UIColor colorWithWhite:244.0 / 255.0 alpha:1.0]
#define kAlertViewMessageShadowColor [UIColor blackColor]
#define kAlertViewMessageShadowOffset CGSizeMake(0, -1)
#define kAlertViewMessageFont [UIFont systemFontOfSize:18]
#define kAlertViewMessageTextColor [UIColor colorWithWhite:244.0/255.0 alpha:1.0]
#define kAlertViewMessageShadowColor [UIColor blackColor]
#define kAlertViewMessageShadowOffset CGSizeMake(0, -1)
#define kAlertViewButtonFont [UIFont boldSystemFontOfSize:18]
#define kAlertViewButtonTextColor [UIColor whiteColor]
#define kAlertViewButtonShadowColor [UIColor blackColor]
#define kAlertViewButtonShadowOffset CGSizeMake(0, -1)
#define kAlertViewButtonFont [UIFont boldSystemFontOfSize:18]
#define kAlertViewButtonTextColor [UIColor whiteColor]
#define kAlertViewButtonShadowColor [UIColor blackColor]
#define kAlertViewButtonShadowOffset CGSizeMake(0, -1)
#define kAlertViewBackground @"alert-window.png"
#define kAlertViewBackgroundLandscape @"alert-window-landscape.png"
#define kAlertViewBackgroundCapHeight 38
#define kAlertViewBackground @"alert-window.png"
#define kAlertViewBackgroundLandscape @"alert-window-landscape.png"
#define kAlertViewBackgroundCapHeight 38
#endif

View File

@@ -1,25 +1,24 @@
/*
Custom bookmark table cell
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface BookmarkTableCell : UITableViewCell
@interface BookmarkTableCell : UITableViewCell
{
IBOutlet UILabel* _title;
IBOutlet UILabel* _sub_title;
IBOutlet UIImageView* _connection_state_icon;
IBOutlet UILabel *_title;
IBOutlet UILabel *_sub_title;
IBOutlet UIImageView *_connection_state_icon;
}
@property (retain, nonatomic) UILabel* title;
@property (retain, nonatomic) UILabel* subTitle;
@property (retain, nonatomic) UIImageView* connectionStateIcon;
@property(retain, nonatomic) UILabel *title;
@property(retain, nonatomic) UILabel *subTitle;
@property(retain, nonatomic) UIImageView *connectionStateIcon;
@end

View File

@@ -1,38 +1,39 @@
/*
Custom bookmark table cell
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "BookmarkTableCell.h"
@implementation BookmarkTableCell
@synthesize title = _title, subTitle = _sub_title, connectionStateIcon = _connection_state_icon;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
// Initialization code
}
return self;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]))
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
[super setSelected:selected animated:animated];
// Configure the view for the selected state
// Configure the view for the selected state
}
- (void)dealloc {
[super dealloc];
- (void)dealloc
{
[super dealloc];
}
@end

View File

@@ -1,21 +1,22 @@
/*
Custom table cell with a button
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface EditButtonTableViewCell : UITableViewCell
{
IBOutlet UILabel* _label;
IBOutlet UIButton* _button;
IBOutlet UILabel *_label;
IBOutlet UIButton *_button;
}
@property (retain, nonatomic) UILabel* label;
@property (retain, nonatomic) UIButton* button;
@property(retain, nonatomic) UILabel *label;
@property(retain, nonatomic) UIButton *button;
@end

View File

@@ -1,10 +1,11 @@
/*
Custom table cell with a button
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditButtonTableViewCell.h"
@@ -15,18 +16,19 @@
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
[super setSelected:selected animated:animated];
// Configure the view for the selected state
// Configure the view for the selected state
}
@end

View File

@@ -1,21 +1,22 @@
/*
Custom table cell with toggle switch
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface EditFlagTableViewCell : UITableViewCell
{
IBOutlet UILabel* _label;
IBOutlet UISwitch* _toggle;
IBOutlet UILabel *_label;
IBOutlet UISwitch *_toggle;
}
@property (retain, nonatomic) UILabel* label;
@property (retain, nonatomic) UISwitch* toggle;
@property(retain, nonatomic) UILabel *label;
@property(retain, nonatomic) UISwitch *toggle;
@end

View File

@@ -1,10 +1,11 @@
/*
Custom table cell with toggle switch
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditFlagTableViewCell.h"
@@ -15,18 +16,19 @@
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
[super setSelected:selected animated:animated];
// Configure the view for the selected state
// Configure the view for the selected state
}
@end

View File

@@ -1,23 +1,24 @@
/*
Custom table cell with secret edit text field
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface EditSecretTextTableViewCell : UITableViewCell
{
IBOutlet UILabel* _label;
IBOutlet UITextField* _textfield;
IBOutlet UIButton* _unhide_button;
IBOutlet UILabel *_label;
IBOutlet UITextField *_textfield;
IBOutlet UIButton *_unhide_button;
}
@property (retain, nonatomic) UILabel* label;
@property (retain, nonatomic) UITextField* textfield;
@property(retain, nonatomic) UILabel *label;
@property(retain, nonatomic) UITextField *textfield;
- (void)setEnabled:(BOOL)enabled;

View File

@@ -1,10 +1,11 @@
/*
Custom table cell with secret edit text field
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditSecretTextTableViewCell.h"
@@ -15,40 +16,46 @@
- (void)awakeFromNib
{
[super awakeFromNib];
[_unhide_button setTitle:NSLocalizedString(@"Unhide", @"Button title 'Unhide'") forState:UIControlStateNormal];
[_unhide_button addTarget:self action:@selector(togglePasswordMode:) forControlEvents:UIControlEventTouchUpInside];
[super awakeFromNib];
[_unhide_button setTitle:NSLocalizedString(@"Unhide", @"Button title 'Unhide'")
forState:UIControlStateNormal];
[_unhide_button addTarget:self
action:@selector(togglePasswordMode:)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)setEnabled:(BOOL)enabled
{
[_label setEnabled:enabled];
[_textfield setEnabled:enabled];
[_unhide_button setEnabled:enabled];
[_label setEnabled:enabled];
[_textfield setEnabled:enabled];
[_unhide_button setEnabled:enabled];
}
#pragma mark - action handlers
- (void)togglePasswordMode:(id)sender
{
BOOL isSecure = [_textfield isSecureTextEntry];
BOOL isSecure = [_textfield isSecureTextEntry];
if (isSecure)
{
[_unhide_button setTitle:NSLocalizedString(@"Hide", @"Button title 'Hide'") forState:UIControlStateNormal];
[_textfield setSecureTextEntry:NO];
}
else
{
BOOL first_responder = [_textfield isFirstResponder];
// little trick to make non-secure to secure transition working - this seems to be an ios bug:
// http://stackoverflow.com/questions/6710019/uitextfield-securetextentry-works-going-from-yes-to-no-but-changing-back-to-y
[_textfield setEnabled:NO];
[_unhide_button setTitle:NSLocalizedString(@"Unhide", @"Button title 'Unhide'") forState:UIControlStateNormal];
[_textfield setSecureTextEntry:YES];
[_textfield setEnabled:YES];
if (first_responder)
[_textfield becomeFirstResponder];
}
if (isSecure)
{
[_unhide_button setTitle:NSLocalizedString(@"Hide", @"Button title 'Hide'")
forState:UIControlStateNormal];
[_textfield setSecureTextEntry:NO];
}
else
{
BOOL first_responder = [_textfield isFirstResponder];
// little trick to make non-secure to secure transition working - this seems to be an ios
// bug:
// http://stackoverflow.com/questions/6710019/uitextfield-securetextentry-works-going-from-yes-to-no-but-changing-back-to-y
[_textfield setEnabled:NO];
[_unhide_button setTitle:NSLocalizedString(@"Unhide", @"Button title 'Unhide'")
forState:UIControlStateNormal];
[_textfield setSecureTextEntry:YES];
[_textfield setEnabled:YES];
if (first_responder)
[_textfield becomeFirstResponder];
}
}
@end

View File

@@ -1,21 +1,22 @@
/*
Custom table cell with a label on the right, showing the current selection
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface EditSelectionTableViewCell : UITableViewCell
{
IBOutlet UILabel* _label;
IBOutlet UILabel* _selection;
IBOutlet UILabel *_label;
IBOutlet UILabel *_selection;
}
@property (retain, nonatomic) UILabel* label;
@property (retain, nonatomic) UILabel* selection;
@property(retain, nonatomic) UILabel *label;
@property(retain, nonatomic) UILabel *selection;
@end

View File

@@ -1,10 +1,11 @@
/*
Custom table cell with a label on the right, showing the current selection
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditSelectionTableViewCell.h"
@@ -15,18 +16,19 @@
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
[super setSelected:selected animated:animated];
// Configure the view for the selected state
// Configure the view for the selected state
}
@end

View File

@@ -1,19 +1,20 @@
/*
Custom table cell indicating a switch to a sub-view
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface EditSubEditTableViewCell : UITableViewCell
{
IBOutlet UILabel* _label;
IBOutlet UILabel *_label;
}
@property (retain, nonatomic) UILabel* label;
@property(retain, nonatomic) UILabel *label;
@end

View File

@@ -1,10 +1,11 @@
/*
Custom table cell indicating a switch to a sub-view
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditSubEditTableViewCell.h"
@@ -15,18 +16,19 @@
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
[super setSelected:selected animated:animated];
// Configure the view for the selected state
// Configure the view for the selected state
}
@end

View File

@@ -1,21 +1,22 @@
/*
Custom table cell with edit text field
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface EditTextTableViewCell : UITableViewCell
{
IBOutlet UILabel* _label;
IBOutlet UITextField* _textfield;
IBOutlet UILabel *_label;
IBOutlet UITextField *_textfield;
}
@property (retain, nonatomic) UILabel* label;
@property (retain, nonatomic) UITextField* textfield;
@property(retain, nonatomic) UILabel *label;
@property(retain, nonatomic) UITextField *textfield;
@end

View File

@@ -1,10 +1,11 @@
/*
Custom table cell with edit text field
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "EditTextTableViewCell.h"
@@ -15,18 +16,19 @@
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
[super setSelected:selected animated:animated];
// Configure the view for the selected state
// Configure the view for the selected state
}
@end

View File

@@ -1,10 +1,11 @@
/*
RDP Session View
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -12,9 +13,9 @@
@interface RDPSessionView : UIView
{
RDPSession* _session;
RDPSession *_session;
}
- (void)setSession:(RDPSession*)session;
- (void)setSession:(RDPSession *)session;
@end

View File

@@ -1,51 +1,58 @@
/*
RDP Session View
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "RDPSessionView.h"
@implementation RDPSessionView
- (void)setSession:(RDPSession*)session
- (void)setSession:(RDPSession *)session
{
_session = session;
_session = session;
}
- (void)awakeFromNib
{
[super awakeFromNib];
_session = nil;
[super awakeFromNib];
_session = nil;
}
- (void)drawRect:(CGRect)rect
- (void)drawRect:(CGRect)rect
{
if(_session != nil && [_session bitmapContext])
if (_session != nil && [_session bitmapContext])
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef cgImage = CGBitmapContextCreateImage([_session bitmapContext]);
CGContextTranslateCTM(context, 0, [self bounds].size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToRect(context, CGRectMake(rect.origin.x, [self bounds].size.height - rect.origin.y - rect.size.height, rect.size.width, rect.size.height));
CGContextDrawImage(context, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), cgImage);
CGImageRelease(cgImage);
CGContextTranslateCTM(context, 0, [self bounds].size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToRect(context,
CGRectMake(rect.origin.x,
[self bounds].size.height - rect.origin.y - rect.size.height,
rect.size.width, rect.size.height));
CGContextDrawImage(context,
CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height),
cgImage);
CGImageRelease(cgImage);
}
else
{
// just clear the screen with black
[[UIColor blackColor] set];
UIRectFill([self bounds]);
}
else
{
// just clear the screen with black
[[UIColor blackColor] set];
UIRectFill([self bounds]);
}
}
- (void)dealloc {
[super dealloc];
- (void)dealloc
{
[super dealloc];
}
@end

View File

@@ -1,28 +1,28 @@
/*
Custom session table cell
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@interface SessionTableCell : UITableViewCell
@interface SessionTableCell : UITableViewCell
{
IBOutlet UILabel* _title;
IBOutlet UILabel* _server;
IBOutlet UILabel* _username;
IBOutlet UIImageView* _screenshot;
IBOutlet UIButton* _disconnect_button;
IBOutlet UILabel *_title;
IBOutlet UILabel *_server;
IBOutlet UILabel *_username;
IBOutlet UIImageView *_screenshot;
IBOutlet UIButton *_disconnect_button;
}
@property (retain, nonatomic) UILabel* title;
@property (retain, nonatomic) UILabel* server;
@property (retain, nonatomic) UILabel* username;
@property (retain, nonatomic) UIImageView* screenshot;
@property (retain, nonatomic) UIButton* disconnectButton;
@property(retain, nonatomic) UILabel *title;
@property(retain, nonatomic) UILabel *server;
@property(retain, nonatomic) UILabel *username;
@property(retain, nonatomic) UIImageView *screenshot;
@property(retain, nonatomic) UIButton *disconnectButton;
@end

View File

@@ -1,40 +1,42 @@
/*
Custom session table cell
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "SessionTableCell.h"
@implementation SessionTableCell
@synthesize title = _title, server = _server, username = _username, screenshot = _screenshot, disconnectButton = _disconnect_button;
@synthesize title = _title, server = _server, username = _username, screenshot = _screenshot,
disconnectButton = _disconnect_button;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
}
return self;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code.
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state.
[super setSelected:selected animated:animated];
// Configure the view for the selected state.
}
- (void)dealloc {
[super dealloc];
- (void)dealloc
{
[super dealloc];
}
@end

View File

@@ -1,10 +1,11 @@
/*
RDP Touch Pointer View
RDP Touch Pointer View
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
@@ -12,58 +13,59 @@
// protocol for touch pointer callbacks
@protocol TouchPointerDelegate
// callback if touch pointer should be closed
-(void)touchPointerClose;
- (void)touchPointerClose;
// callback for a left click action
-(void)touchPointerLeftClick:(CGPoint)pos down:(BOOL)down;
- (void)touchPointerLeftClick:(CGPoint)pos down:(BOOL)down;
// callback for a right click action
-(void)touchPointerRightClick:(CGPoint)pos down:(BOOL)down;
- (void)touchPointerRightClick:(CGPoint)pos down:(BOOL)down;
// callback for pointer move action
-(void)touchPointerMove:(CGPoint)pos;
- (void)touchPointerMove:(CGPoint)pos;
// callback if scrolling is performed
-(void)touchPointerScrollDown:(BOOL)down;
- (void)touchPointerScrollDown:(BOOL)down;
// callback for toggling the standard keyboard
-(void)touchPointerToggleKeyboard;
- (void)touchPointerToggleKeyboard;
// callback for toggling the extended keyboard
-(void)touchPointerToggleExtendedKeyboard;
- (void)touchPointerToggleExtendedKeyboard;
// callback for reset session view
-(void)touchPointerResetSessionView;
- (void)touchPointerResetSessionView;
@end
@interface TouchPointerView : UIView
{
// transformation and image currently drawn
CGAffineTransform _pointer_transformation;
UIImage* _cur_pointer_img;
// transformation and image currently drawn
CGAffineTransform _pointer_transformation;
UIImage *_cur_pointer_img;
// action images
UIImage* _default_pointer_img;
UIImage* _active_pointer_img;
UIImage* _lclick_pointer_img;
UIImage* _rclick_pointer_img;
UIImage* _scroll_pointer_img;
UIImage* _extkeyboard_pointer_img;
UIImage* _keyboard_pointer_img;
UIImage* _reset_pointer_img;
// action images
UIImage *_default_pointer_img;
UIImage *_active_pointer_img;
UIImage *_lclick_pointer_img;
UIImage *_rclick_pointer_img;
UIImage *_scroll_pointer_img;
UIImage *_extkeyboard_pointer_img;
UIImage *_keyboard_pointer_img;
UIImage *_reset_pointer_img;
// predefined areas for all actions
CGRect _pointer_areas[9];
// scroll/drag n drop handling
CGPoint _prev_touch_location;
BOOL _pointer_moving;
BOOL _pointer_scrolling;
NSObject<TouchPointerDelegate>* _delegate;
// predefined areas for all actions
CGRect _pointer_areas[9];
// scroll/drag n drop handling
CGPoint _prev_touch_location;
BOOL _pointer_moving;
BOOL _pointer_scrolling;
NSObject<TouchPointerDelegate> *_delegate;
}
@property (assign) IBOutlet NSObject<TouchPointerDelegate>* delegate;
@property(assign) IBOutlet NSObject<TouchPointerDelegate> *delegate;
// positions the pointer on screen if it got offscreen after an orentation change or after displaying the keyboard
-(void)ensurePointerIsVisible;
// positions the pointer on screen if it got offscreen after an orentation change or after
// displaying the keyboard
- (void)ensurePointerIsVisible;
// returns the extent required for the scrollview to use the touch pointer near the edges of the session view
-(UIEdgeInsets)getEdgeInsets;
// returns the extent required for the scrollview to use the touch pointer near the edges of the
// session view
- (UIEdgeInsets)getEdgeInsets;
// return pointer dimension and position information
- (CGPoint)getPointerPosition;

View File

@@ -1,37 +1,37 @@
/*
RDP Touch Pointer View
RDP Touch Pointer View
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import "TouchPointerView.h"
#import "Utils.h"
#define RESET_DEFAULT_POINTER_IMAGE_DELAY 0.15
#define POINTER_ACTION_CURSOR 0
#define POINTER_ACTION_CLOSE 3
#define POINTER_ACTION_RCLICK 2
#define POINTER_ACTION_LCLICK 4
#define POINTER_ACTION_MOVE 4
#define POINTER_ACTION_SCROLL 5
#define POINTER_ACTION_CURSOR 0
#define POINTER_ACTION_CLOSE 3
#define POINTER_ACTION_RCLICK 2
#define POINTER_ACTION_LCLICK 4
#define POINTER_ACTION_MOVE 4
#define POINTER_ACTION_SCROLL 5
#define POINTER_ACTION_KEYBOARD 7
#define POINTER_ACTION_EXTKEYBOARD 8
#define POINTER_ACTION_RESET 6
@interface TouchPointerView (Private)
- (void)setCurrentPointerImage:(UIImage*)image;
- (void)displayPointerActionImage:(UIImage*)image;
- (void)setCurrentPointerImage:(UIImage *)image;
- (void)displayPointerActionImage:(UIImage *)image;
- (BOOL)pointInsidePointer:(CGPoint)point;
- (BOOL)pointInsidePointerArea:(int)area point:(CGPoint)point;
- (CGPoint)getCursorPosition;
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
- (void)handleSingleTap:(UITapGestureRecognizer*)gesture;
- (void)handlerForGesture:(UIGestureRecognizer*)gesture sendClick:(BOOL)sendClick;
- (void)handleSingleTap:(UITapGestureRecognizer *)gesture;
- (void)handlerForGesture:(UIGestureRecognizer *)gesture sendClick:(BOOL)sendClick;
@end
@implementation TouchPointerView
@@ -40,289 +40,320 @@
- (void)awakeFromNib
{
[super awakeFromNib];
// set content mode when rotating (keep aspect ratio)
[self setContentMode:UIViewContentModeTopLeft];
// load touchPointerImage
_default_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_default" ofType:@"png"]] retain];
_active_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_active" ofType:@"png"]] retain];
_lclick_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_lclick" ofType:@"png"]] retain];
_rclick_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_rclick" ofType:@"png"]] retain];
_scroll_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_scroll" ofType:@"png"]] retain];
_extkeyboard_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_ext_keyboard" ofType:@"png"]] retain];
_keyboard_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_keyboard" ofType:@"png"]] retain];
_reset_pointer_img = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_reset" ofType:@"png"]] retain];
_cur_pointer_img = _default_pointer_img;
_pointer_transformation = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
// init flags
_pointer_moving = NO;
_pointer_scrolling = NO;
// create areas array
int i, j;
CGFloat area_width = [_cur_pointer_img size].width / 3.0f;
CGFloat area_height = [_cur_pointer_img size].height / 3.0f;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
_pointer_areas[j + i * 3] = CGRectMake(j * area_width, i * area_height, area_width, area_height);
}
}
// init gesture recognizers
UITapGestureRecognizer* singleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)] autorelease];
[singleTapRecognizer setNumberOfTouchesRequired:1];
[singleTapRecognizer setNumberOfTapsRequired:1];
UILongPressGestureRecognizer* dragDropRecognizer = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleDragDrop:)] autorelease];
dragDropRecognizer.minimumPressDuration = 0.4;
// dragDropRecognizer.allowableMovement = 1000.0;
UILongPressGestureRecognizer* pointerMoveScrollRecognizer = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePointerMoveScroll:)] autorelease];
pointerMoveScrollRecognizer.minimumPressDuration = 0.15;
pointerMoveScrollRecognizer.allowableMovement = 1000.0;
[pointerMoveScrollRecognizer requireGestureRecognizerToFail:dragDropRecognizer];
[self addGestureRecognizer:singleTapRecognizer];
[self addGestureRecognizer:dragDropRecognizer];
[self addGestureRecognizer:pointerMoveScrollRecognizer];
[super awakeFromNib];
// set content mode when rotating (keep aspect ratio)
[self setContentMode:UIViewContentModeTopLeft];
// load touchPointerImage
_default_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_default"
ofType:@"png"]] retain];
_active_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_active"
ofType:@"png"]] retain];
_lclick_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_lclick"
ofType:@"png"]] retain];
_rclick_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_rclick"
ofType:@"png"]] retain];
_scroll_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_scroll"
ofType:@"png"]] retain];
_extkeyboard_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_ext_keyboard"
ofType:@"png"]] retain];
_keyboard_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_keyboard"
ofType:@"png"]] retain];
_reset_pointer_img = [[UIImage
imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_reset"
ofType:@"png"]] retain];
_cur_pointer_img = _default_pointer_img;
_pointer_transformation = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
// init flags
_pointer_moving = NO;
_pointer_scrolling = NO;
// create areas array
int i, j;
CGFloat area_width = [_cur_pointer_img size].width / 3.0f;
CGFloat area_height = [_cur_pointer_img size].height / 3.0f;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
_pointer_areas[j + i * 3] =
CGRectMake(j * area_width, i * area_height, area_width, area_height);
}
}
// init gesture recognizers
UITapGestureRecognizer *singleTapRecognizer =
[[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleSingleTap:)] autorelease];
[singleTapRecognizer setNumberOfTouchesRequired:1];
[singleTapRecognizer setNumberOfTapsRequired:1];
UILongPressGestureRecognizer *dragDropRecognizer = [[[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:@selector(handleDragDrop:)] autorelease];
dragDropRecognizer.minimumPressDuration = 0.4;
// dragDropRecognizer.allowableMovement = 1000.0;
UILongPressGestureRecognizer *pointerMoveScrollRecognizer =
[[[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(handlePointerMoveScroll:)]
autorelease];
pointerMoveScrollRecognizer.minimumPressDuration = 0.15;
pointerMoveScrollRecognizer.allowableMovement = 1000.0;
[pointerMoveScrollRecognizer requireGestureRecognizerToFail:dragDropRecognizer];
[self addGestureRecognizer:singleTapRecognizer];
[self addGestureRecognizer:dragDropRecognizer];
[self addGestureRecognizer:pointerMoveScrollRecognizer];
}
- (void)dealloc
{
[super dealloc];
[_default_pointer_img autorelease];
[_active_pointer_img autorelease];
[_lclick_pointer_img autorelease];
[_rclick_pointer_img autorelease];
[_scroll_pointer_img autorelease];
[_extkeyboard_pointer_img autorelease];
[_keyboard_pointer_img autorelease];
[_reset_pointer_img autorelease];
[super dealloc];
[_default_pointer_img autorelease];
[_active_pointer_img autorelease];
[_lclick_pointer_img autorelease];
[_rclick_pointer_img autorelease];
[_scroll_pointer_img autorelease];
[_extkeyboard_pointer_img autorelease];
[_keyboard_pointer_img autorelease];
[_reset_pointer_img autorelease];
}
#pragma mark - Public interface
// positions the pointer on screen if it got offscreen after an orentation change
-(void)ensurePointerIsVisible
- (void)ensurePointerIsVisible
{
CGRect bounds = [self bounds];
if(_pointer_transformation.tx > (bounds.size.width - _cur_pointer_img.size.width))
_pointer_transformation.tx = bounds.size.width - _cur_pointer_img.size.width;
if(_pointer_transformation.ty > (bounds.size.height - _cur_pointer_img.size.height))
_pointer_transformation.ty = bounds.size.height - _cur_pointer_img.size.height;
[self setNeedsDisplay];
CGRect bounds = [self bounds];
if (_pointer_transformation.tx > (bounds.size.width - _cur_pointer_img.size.width))
_pointer_transformation.tx = bounds.size.width - _cur_pointer_img.size.width;
if (_pointer_transformation.ty > (bounds.size.height - _cur_pointer_img.size.height))
_pointer_transformation.ty = bounds.size.height - _cur_pointer_img.size.height;
[self setNeedsDisplay];
}
// show/hides the touch pointer
-(void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
- (void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
// if shown center pointer in view
if(!hidden)
{
_pointer_transformation = CGAffineTransformMakeTranslation(([self bounds].size.width - [_cur_pointer_img size].width) / 2,
([self bounds].size.height - [_cur_pointer_img size].height) / 2);
[self setNeedsDisplay];
}
// if shown center pointer in view
if (!hidden)
{
_pointer_transformation = CGAffineTransformMakeTranslation(
([self bounds].size.width - [_cur_pointer_img size].width) / 2,
([self bounds].size.height - [_cur_pointer_img size].height) / 2);
[self setNeedsDisplay];
}
}
-(UIEdgeInsets)getEdgeInsets
- (UIEdgeInsets)getEdgeInsets
{
return UIEdgeInsetsMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height);
return UIEdgeInsetsMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height);
}
- (CGPoint)getPointerPosition
{
return CGPointMake(_pointer_transformation.tx, _pointer_transformation.ty);
return CGPointMake(_pointer_transformation.tx, _pointer_transformation.ty);
}
- (int)getPointerWidth
{
return [_cur_pointer_img size].width;
return [_cur_pointer_img size].width;
}
- (int)getPointerHeight
{
return [_cur_pointer_img size].height;
return [_cur_pointer_img size].height;
}
@end
@implementation TouchPointerView (Private)
- (void)setCurrentPointerImage:(UIImage*)image
- (void)setCurrentPointerImage:(UIImage *)image
{
_cur_pointer_img = image;
[self setNeedsDisplay];
_cur_pointer_img = image;
[self setNeedsDisplay];
}
- (void)displayPointerActionImage:(UIImage*)image
- (void)displayPointerActionImage:(UIImage *)image
{
[self setCurrentPointerImage:image];
[self performSelector:@selector(setCurrentPointerImage:) withObject:_default_pointer_img afterDelay:RESET_DEFAULT_POINTER_IMAGE_DELAY];
[self setCurrentPointerImage:image];
[self performSelector:@selector(setCurrentPointerImage:)
withObject:_default_pointer_img
afterDelay:RESET_DEFAULT_POINTER_IMAGE_DELAY];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextConcatCTM(context, _pointer_transformation);
CGContextDrawImage(context, CGRectMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height), [_cur_pointer_img CGImage]);
CGContextRestoreGState(context);
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextConcatCTM(context, _pointer_transformation);
CGContextDrawImage(
context, CGRectMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height),
[_cur_pointer_img CGImage]);
CGContextRestoreGState(context);
}
// helper that returns YES if the given point is within the pointer
-(BOOL) pointInsidePointer:(CGPoint)point
- (BOOL)pointInsidePointer:(CGPoint)point
{
CGRect rec = CGRectMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height);
return CGRectContainsPoint(CGRectApplyAffineTransform(rec, _pointer_transformation), point);
CGRect rec = CGRectMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height);
return CGRectContainsPoint(CGRectApplyAffineTransform(rec, _pointer_transformation), point);
}
// helper that returns YES if the given point is within the given pointer area
-(BOOL) pointInsidePointerArea:(int)area point:(CGPoint)point
- (BOOL)pointInsidePointerArea:(int)area point:(CGPoint)point
{
CGRect rec = _pointer_areas[area];
return CGRectContainsPoint(CGRectApplyAffineTransform(rec, _pointer_transformation), point);
CGRect rec = _pointer_areas[area];
return CGRectContainsPoint(CGRectApplyAffineTransform(rec, _pointer_transformation), point);
}
// returns the position of the cursor
-(CGPoint) getCursorPosition
- (CGPoint)getCursorPosition
{
CGRect transPointerArea = CGRectApplyAffineTransform(_pointer_areas[POINTER_ACTION_CURSOR], _pointer_transformation);
return CGPointMake(CGRectGetMidX(transPointerArea), CGRectGetMidY(transPointerArea));
CGRect transPointerArea =
CGRectApplyAffineTransform(_pointer_areas[POINTER_ACTION_CURSOR], _pointer_transformation);
return CGPointMake(CGRectGetMidX(transPointerArea), CGRectGetMidY(transPointerArea));
}
// this filters events - if the pointer was clicked the scrollview won't get any events
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return [self pointInsidePointer:point];
return [self pointInsidePointer:point];
}
#pragma mark - Action handlers
// handles single tap gestures, returns YES if the event was handled by the pointer, NO otherwise
-(void) handleSingleTap:(UITapGestureRecognizer*)gesture
- (void)handleSingleTap:(UITapGestureRecognizer *)gesture
{
// get touch position within our view
CGPoint touchPos = [gesture locationInView:self];
// look if pointer was in one of our action areas
if([self pointInsidePointerArea:POINTER_ACTION_CLOSE point:touchPos])
[[self delegate] touchPointerClose];
else if([self pointInsidePointerArea:POINTER_ACTION_LCLICK point:touchPos])
{
[self displayPointerActionImage:_lclick_pointer_img];
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:YES];
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:NO];
}
else if([self pointInsidePointerArea:POINTER_ACTION_RCLICK point:touchPos])
{
[self displayPointerActionImage:_rclick_pointer_img];
[[self delegate] touchPointerRightClick:[self getCursorPosition] down:YES];
[[self delegate] touchPointerRightClick:[self getCursorPosition] down:NO];
}
else if([self pointInsidePointerArea:POINTER_ACTION_KEYBOARD point:touchPos])
{
[self displayPointerActionImage:_keyboard_pointer_img];
[[self delegate] touchPointerToggleKeyboard];
}
else if([self pointInsidePointerArea:POINTER_ACTION_EXTKEYBOARD point:touchPos])
{
[self displayPointerActionImage:_extkeyboard_pointer_img];
[[self delegate] touchPointerToggleExtendedKeyboard];
}
else if([self pointInsidePointerArea:POINTER_ACTION_RESET point:touchPos])
{
[self displayPointerActionImage:_reset_pointer_img];
[[self delegate] touchPointerResetSessionView];
}
// get touch position within our view
CGPoint touchPos = [gesture locationInView:self];
// look if pointer was in one of our action areas
if ([self pointInsidePointerArea:POINTER_ACTION_CLOSE point:touchPos])
[[self delegate] touchPointerClose];
else if ([self pointInsidePointerArea:POINTER_ACTION_LCLICK point:touchPos])
{
[self displayPointerActionImage:_lclick_pointer_img];
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:YES];
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:NO];
}
else if ([self pointInsidePointerArea:POINTER_ACTION_RCLICK point:touchPos])
{
[self displayPointerActionImage:_rclick_pointer_img];
[[self delegate] touchPointerRightClick:[self getCursorPosition] down:YES];
[[self delegate] touchPointerRightClick:[self getCursorPosition] down:NO];
}
else if ([self pointInsidePointerArea:POINTER_ACTION_KEYBOARD point:touchPos])
{
[self displayPointerActionImage:_keyboard_pointer_img];
[[self delegate] touchPointerToggleKeyboard];
}
else if ([self pointInsidePointerArea:POINTER_ACTION_EXTKEYBOARD point:touchPos])
{
[self displayPointerActionImage:_extkeyboard_pointer_img];
[[self delegate] touchPointerToggleExtendedKeyboard];
}
else if ([self pointInsidePointerArea:POINTER_ACTION_RESET point:touchPos])
{
[self displayPointerActionImage:_reset_pointer_img];
[[self delegate] touchPointerResetSessionView];
}
}
-(void) handlerForGesture:(UIGestureRecognizer*)gesture sendClick:(BOOL)sendClick
- (void)handlerForGesture:(UIGestureRecognizer *)gesture sendClick:(BOOL)sendClick
{
if([gesture state] == UIGestureRecognizerStateBegan)
{
CGPoint touchPos = [gesture locationInView:self];
if([self pointInsidePointerArea:POINTER_ACTION_LCLICK point:touchPos])
{
_prev_touch_location = touchPos;
_pointer_moving = YES;
if(sendClick == YES)
{
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:YES];
[self setCurrentPointerImage:_active_pointer_img];
}
}
else if([self pointInsidePointerArea:POINTER_ACTION_SCROLL point:touchPos])
{
[self setCurrentPointerImage:_scroll_pointer_img];
_prev_touch_location = touchPos;
_pointer_scrolling = YES;
}
}
else if([gesture state] == UIGestureRecognizerStateChanged)
{
if(_pointer_moving)
{
CGPoint touchPos = [gesture locationInView:self];
_pointer_transformation = CGAffineTransformTranslate(_pointer_transformation, touchPos.x - _prev_touch_location.x, touchPos.y - _prev_touch_location.y);
[[self delegate] touchPointerMove:[self getCursorPosition]];
_prev_touch_location = touchPos;
[self setNeedsDisplay];
}
else if(_pointer_scrolling)
{
CGPoint touchPos = [gesture locationInView:self];
float delta = touchPos.y - _prev_touch_location.y;
if(delta > GetScrollGestureDelta())
{
[[self delegate] touchPointerScrollDown:YES];
_prev_touch_location = touchPos;
}
else if(delta < -GetScrollGestureDelta())
{
[[self delegate] touchPointerScrollDown:NO];
_prev_touch_location = touchPos;
}
}
}
else if([gesture state] == UIGestureRecognizerStateEnded)
{
if(_pointer_moving)
{
if(sendClick == YES)
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:NO];
_pointer_moving = NO;
[self setCurrentPointerImage:_default_pointer_img];
}
if ([gesture state] == UIGestureRecognizerStateBegan)
{
CGPoint touchPos = [gesture locationInView:self];
if ([self pointInsidePointerArea:POINTER_ACTION_LCLICK point:touchPos])
{
_prev_touch_location = touchPos;
_pointer_moving = YES;
if (sendClick == YES)
{
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:YES];
[self setCurrentPointerImage:_active_pointer_img];
}
}
else if ([self pointInsidePointerArea:POINTER_ACTION_SCROLL point:touchPos])
{
[self setCurrentPointerImage:_scroll_pointer_img];
_prev_touch_location = touchPos;
_pointer_scrolling = YES;
}
}
else if ([gesture state] == UIGestureRecognizerStateChanged)
{
if (_pointer_moving)
{
CGPoint touchPos = [gesture locationInView:self];
_pointer_transformation = CGAffineTransformTranslate(
_pointer_transformation, touchPos.x - _prev_touch_location.x,
touchPos.y - _prev_touch_location.y);
[[self delegate] touchPointerMove:[self getCursorPosition]];
_prev_touch_location = touchPos;
[self setNeedsDisplay];
}
else if (_pointer_scrolling)
{
CGPoint touchPos = [gesture locationInView:self];
float delta = touchPos.y - _prev_touch_location.y;
if (delta > GetScrollGestureDelta())
{
[[self delegate] touchPointerScrollDown:YES];
_prev_touch_location = touchPos;
}
else if (delta < -GetScrollGestureDelta())
{
[[self delegate] touchPointerScrollDown:NO];
_prev_touch_location = touchPos;
}
}
}
else if ([gesture state] == UIGestureRecognizerStateEnded)
{
if (_pointer_moving)
{
if (sendClick == YES)
[[self delegate] touchPointerLeftClick:[self getCursorPosition] down:NO];
_pointer_moving = NO;
[self setCurrentPointerImage:_default_pointer_img];
}
if(_pointer_scrolling)
{
[self setCurrentPointerImage:_default_pointer_img];
_pointer_scrolling = NO;
}
}
if (_pointer_scrolling)
{
[self setCurrentPointerImage:_default_pointer_img];
_pointer_scrolling = NO;
}
}
}
// handles long press gestures
-(void) handleDragDrop:(UILongPressGestureRecognizer*)gesture
- (void)handleDragDrop:(UILongPressGestureRecognizer *)gesture
{
[self handlerForGesture:gesture sendClick:YES];
[self handlerForGesture:gesture sendClick:YES];
}
-(void) handlePointerMoveScroll:(UILongPressGestureRecognizer*)gesture
- (void)handlePointerMoveScroll:(UILongPressGestureRecognizer *)gesture
{
[self handlerForGesture:gesture sendClick:NO];
[self handlerForGesture:gesture sendClick:NO];
}
@end

View File

@@ -1,18 +1,19 @@
/*
Main App Entry
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*/
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}