1/* 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#import "ARDMainView.h" 12 13#import "UIImage+ARDUtilities.h" 14 15// TODO(tkchin): retrieve status bar height dynamically. 16static CGFloat const kStatusBarHeight = 20; 17 18static CGFloat const kRoomTextButtonSize = 40; 19static CGFloat const kRoomTextFieldHeight = 40; 20static CGFloat const kRoomTextFieldMargin = 8; 21static CGFloat const kCallControlMargin = 8; 22static CGFloat const kAppLabelHeight = 20; 23 24// Helper view that contains a text field and a clear button. 25@interface ARDRoomTextField : UIView <UITextFieldDelegate> 26@property(nonatomic, readonly) NSString *roomText; 27@end 28 29@implementation ARDRoomTextField { 30 UITextField *_roomText; 31 UIButton *_clearButton; 32} 33 34- (instancetype)initWithFrame:(CGRect)frame { 35 if (self = [super initWithFrame:frame]) { 36 _roomText = [[UITextField alloc] initWithFrame:CGRectZero]; 37 _roomText.borderStyle = UITextBorderStyleNone; 38 _roomText.font = [UIFont fontWithName:@"Roboto" size:12]; 39 _roomText.placeholder = @"Room name"; 40 _roomText.autocorrectionType = UITextAutocorrectionTypeNo; 41 _roomText.autocapitalizationType = UITextAutocapitalizationTypeNone; 42 _roomText.delegate = self; 43 [_roomText addTarget:self 44 action:@selector(textFieldDidChange:) 45 forControlEvents:UIControlEventEditingChanged]; 46 [self addSubview:_roomText]; 47 48 _clearButton = [UIButton buttonWithType:UIButtonTypeCustom]; 49 UIImage *image = [UIImage imageForName:@"ic_clear_black_24dp.png" 50 color:[UIColor colorWithWhite:0 alpha:.4]]; 51 52 [_clearButton setImage:image forState:UIControlStateNormal]; 53 [_clearButton addTarget:self 54 action:@selector(onClear:) 55 forControlEvents:UIControlEventTouchUpInside]; 56 _clearButton.hidden = YES; 57 [self addSubview:_clearButton]; 58 59 // Give rounded corners and a light gray border. 60 self.layer.borderWidth = 1; 61 self.layer.borderColor = [[UIColor lightGrayColor] CGColor]; 62 self.layer.cornerRadius = 2; 63 } 64 return self; 65} 66 67- (void)layoutSubviews { 68 CGRect bounds = self.bounds; 69 _clearButton.frame = CGRectMake(CGRectGetMaxX(bounds) - kRoomTextButtonSize, 70 CGRectGetMinY(bounds), 71 kRoomTextButtonSize, 72 kRoomTextButtonSize); 73 _roomText.frame = CGRectMake( 74 CGRectGetMinX(bounds) + kRoomTextFieldMargin, 75 CGRectGetMinY(bounds), 76 CGRectGetMinX(_clearButton.frame) - CGRectGetMinX(bounds) - 77 kRoomTextFieldMargin, 78 kRoomTextFieldHeight); 79} 80 81- (CGSize)sizeThatFits:(CGSize)size { 82 size.height = kRoomTextFieldHeight; 83 return size; 84} 85 86- (NSString *)roomText { 87 return _roomText.text; 88} 89 90#pragma mark - UITextFieldDelegate 91 92- (BOOL)textFieldShouldReturn:(UITextField *)textField { 93 // There is no other control that can take focus, so manually resign focus 94 // when return (Join) is pressed to trigger |textFieldDidEndEditing|. 95 [textField resignFirstResponder]; 96 return YES; 97} 98 99#pragma mark - Private 100 101- (void)textFieldDidChange:(id)sender { 102 [self updateClearButton]; 103} 104 105- (void)onClear:(id)sender { 106 _roomText.text = @""; 107 [self updateClearButton]; 108 [_roomText resignFirstResponder]; 109} 110 111- (void)updateClearButton { 112 _clearButton.hidden = _roomText.text.length == 0; 113} 114 115@end 116 117@implementation ARDMainView { 118 UILabel *_appLabel; 119 ARDRoomTextField *_roomText; 120 UILabel *_callOptionsLabel; 121 UISwitch *_audioOnlySwitch; 122 UILabel *_audioOnlyLabel; 123 UISwitch *_loopbackSwitch; 124 UILabel *_loopbackLabel; 125 UIButton *_startCallButton; 126} 127 128@synthesize delegate = _delegate; 129 130- (instancetype)initWithFrame:(CGRect)frame { 131 if (self = [super initWithFrame:frame]) { 132 _appLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 133 _appLabel.text = @"AppRTCDemo"; 134 _appLabel.font = [UIFont fontWithName:@"Roboto" size:34]; 135 _appLabel.textColor = [UIColor colorWithWhite:0 alpha:.2]; 136 [_appLabel sizeToFit]; 137 [self addSubview:_appLabel]; 138 139 _roomText = [[ARDRoomTextField alloc] initWithFrame:CGRectZero]; 140 [self addSubview:_roomText]; 141 142 UIFont *controlFont = [UIFont fontWithName:@"Roboto" size:20]; 143 UIColor *controlFontColor = [UIColor colorWithWhite:0 alpha:.6]; 144 145 _callOptionsLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 146 _callOptionsLabel.text = @"Call Options"; 147 _callOptionsLabel.font = controlFont; 148 _callOptionsLabel.textColor = controlFontColor; 149 [_callOptionsLabel sizeToFit]; 150 [self addSubview:_callOptionsLabel]; 151 152 _audioOnlySwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; 153 [_audioOnlySwitch sizeToFit]; 154 [self addSubview:_audioOnlySwitch]; 155 156 _audioOnlyLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 157 _audioOnlyLabel.text = @"Audio only"; 158 _audioOnlyLabel.font = controlFont; 159 _audioOnlyLabel.textColor = controlFontColor; 160 [_audioOnlyLabel sizeToFit]; 161 [self addSubview:_audioOnlyLabel]; 162 163 _loopbackSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; 164 [_loopbackSwitch sizeToFit]; 165 [self addSubview:_loopbackSwitch]; 166 167 _loopbackLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 168 _loopbackLabel.text = @"Loopback mode"; 169 _loopbackLabel.font = controlFont; 170 _loopbackLabel.textColor = controlFontColor; 171 [_loopbackLabel sizeToFit]; 172 [self addSubview:_loopbackLabel]; 173 174 _startCallButton = [[UIButton alloc] initWithFrame:CGRectZero]; 175 176 _startCallButton = [UIButton buttonWithType:UIButtonTypeSystem]; 177 _startCallButton.backgroundColor = [UIColor blueColor]; 178 _startCallButton.layer.cornerRadius = 10; 179 _startCallButton.clipsToBounds = YES; 180 _startCallButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10); 181 [_startCallButton setTitle:@"Start call" 182 forState:UIControlStateNormal]; 183 _startCallButton.titleLabel.font = controlFont; 184 [_startCallButton setTitleColor:[UIColor whiteColor] 185 forState:UIControlStateNormal]; 186 [_startCallButton setTitleColor:[UIColor lightGrayColor] 187 forState:UIControlStateSelected]; 188 [_startCallButton sizeToFit]; 189 [_startCallButton addTarget:self 190 action:@selector(onStartCall:) 191 forControlEvents:UIControlEventTouchUpInside]; 192 [self addSubview:_startCallButton]; 193 194 self.backgroundColor = [UIColor whiteColor]; 195 } 196 return self; 197} 198 199- (void)layoutSubviews { 200 CGRect bounds = self.bounds; 201 CGFloat roomTextWidth = bounds.size.width - 2 * kRoomTextFieldMargin; 202 CGFloat roomTextHeight = [_roomText sizeThatFits:bounds.size].height; 203 _roomText.frame = CGRectMake(kRoomTextFieldMargin, 204 kStatusBarHeight + kRoomTextFieldMargin, 205 roomTextWidth, 206 roomTextHeight); 207 _appLabel.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds)); 208 209 CGFloat callOptionsLabelTop = 210 CGRectGetMaxY(_roomText.frame) + kCallControlMargin * 4; 211 _callOptionsLabel.frame = CGRectMake(kCallControlMargin, 212 callOptionsLabelTop, 213 _callOptionsLabel.frame.size.width, 214 _callOptionsLabel.frame.size.height); 215 216 CGFloat audioOnlyTop = 217 CGRectGetMaxY(_callOptionsLabel.frame) + kCallControlMargin * 2; 218 CGRect audioOnlyRect = CGRectMake(kCallControlMargin * 3, 219 audioOnlyTop, 220 _audioOnlySwitch.frame.size.width, 221 _audioOnlySwitch.frame.size.height); 222 _audioOnlySwitch.frame = audioOnlyRect; 223 CGFloat audioOnlyLabelCenterX = CGRectGetMaxX(audioOnlyRect) + 224 kCallControlMargin + _audioOnlyLabel.frame.size.width / 2; 225 _audioOnlyLabel.center = CGPointMake(audioOnlyLabelCenterX, 226 CGRectGetMidY(audioOnlyRect)); 227 228 CGFloat loopbackModeTop = 229 CGRectGetMaxY(_audioOnlySwitch.frame) + kCallControlMargin; 230 CGRect loopbackModeRect = CGRectMake(kCallControlMargin * 3, 231 loopbackModeTop, 232 _loopbackSwitch.frame.size.width, 233 _loopbackSwitch.frame.size.height); 234 _loopbackSwitch.frame = loopbackModeRect; 235 CGFloat loopbackModeLabelCenterX = CGRectGetMaxX(loopbackModeRect) + 236 kCallControlMargin + _loopbackLabel.frame.size.width / 2; 237 _loopbackLabel.center = CGPointMake(loopbackModeLabelCenterX, 238 CGRectGetMidY(loopbackModeRect)); 239 240 CGFloat startCallTop = 241 CGRectGetMaxY(loopbackModeRect) + kCallControlMargin * 3; 242 _startCallButton.frame = CGRectMake(kCallControlMargin, 243 startCallTop, 244 _startCallButton.frame.size.width, 245 _startCallButton.frame.size.height); 246} 247 248#pragma mark - Private 249 250- (void)onStartCall:(id)sender { 251 NSString *room = _roomText.roomText; 252 // If this is a loopback call, allow a generated room name. 253 if (!room.length && _loopbackSwitch.isOn) { 254 room = [[NSUUID UUID] UUIDString]; 255 } 256 room = [room stringByReplacingOccurrencesOfString:@"-" withString:@""]; 257 [_delegate mainView:self 258 didInputRoom:room 259 isLoopback:_loopbackSwitch.isOn 260 isAudioOnly:_audioOnlySwitch.isOn]; 261} 262 263@end 264