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