mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
Reformatted to new style
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user