Imported Upstream version 878.70.2
[platform/upstream/mdnsresponder.git] / mDNSMacOSX / SettingsBundle / CNBrowseDomainsController.m
1 /*
2  *
3  * Copyright (c) 2016 Apple Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #import "CNBrowseDomainsController.h"
19 #import "CNDomainBrowserViewController.h"
20 #import "CNDomainBrowserPathUtils.h"
21 #import "BonjourSCStore.h"
22 #import <AssertMacros.h>
23
24 #define kTag_AddBrowse                      100
25 #define kTag_AddManual                      101
26
27 const NSString *    _CNBrowseDomainKey_fullname     = (NSString *)SC_DYNDNS_DOMAIN_KEY;
28 const NSString *    _CNBrowseDomainKey_enabled      = (NSString *)SC_DYNDNS_ENABLED_KEY;
29
30 #define LocalizedStringFromMyBundle(key, comment )     \
31         NSLocalizedStringFromTableInBundle(key, @"Localizable", [NSBundle bundleForClass: [self class]], comment )
32
33 @interface CNPathPopoverViewController : UIViewController
34
35 @property (strong) UILabel *    label;
36 @property (copy)   NSArray *    pathArray;
37 @property (assign) CGPoint      offset;
38
39 @end
40
41 @implementation CNPathPopoverViewController
42
43 - (instancetype)initWithPathArray:(NSArray *)pathArray
44 {
45     if (self = [self initWithNibName: nil bundle: nil] )
46     {
47         _pathArray = pathArray;
48         NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
49         [paragraphStyle setLineSpacing: [UIFont labelFontSize] * 0.3];
50         
51         NSMutableAttributedString * itemStr = [[NSMutableAttributedString alloc] init];
52         NSUInteger  count = 0;
53         for (NSString * next in _pathArray )
54         {
55             NSString * nextLine = [NSString stringWithFormat: @"%@%@", itemStr.length ? @"\n" : @"", next];
56             UIColor *  nextColor = ((count++ == 0) || (count == _pathArray.count)) ? [UIColor grayColor] : [UIColor blackColor];
57             [itemStr appendAttributedString:
58              [[NSMutableAttributedString alloc] initWithString: nextLine
59                                                     attributes: @{ NSForegroundColorAttributeName: nextColor,
60                                                                    NSParagraphStyleAttributeName: paragraphStyle
61                                                                 }]];
62         }
63
64         _label = [[UILabel alloc] initWithFrame: CGRectZero];
65         _label.numberOfLines = 0;
66         _label.attributedText = itemStr;
67         [_label sizeToFit];
68         
69         _offset = CGPointMake(25, 15 );
70         CGRect rect = _label.frame;
71         rect.origin.x += _offset.x;
72         rect.origin.y += _offset.y;
73         [_label setFrame: rect];
74     }
75     return(self );
76 }
77
78 - (void)viewDidLoad
79 {
80     [super viewDidLoad];
81     [self.view addSubview: _label];
82 }
83
84 - (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
85 {
86     [super willTransitionToTraitCollection: newCollection withTransitionCoordinator: coordinator];
87     [self.presentingViewController dismissViewControllerAnimated: NO completion: nil];
88 }
89
90 @end
91
92 @interface CNPathAccessoryView : UIView
93
94 @property (strong, readonly) UIButton *         elipsisButton;
95 @property (strong, readonly) UIButton *         pathLabel;
96 @property (weak)             UITableView *      tableView;
97 @property (weak)             UITableViewCell *  cell;
98 @property (strong, readonly) NSArray *          pathArray;
99
100 @end
101
102 @implementation CNPathAccessoryView
103
104 - (instancetype) initWithFrame:(CGRect)frame pathArray:(NSArray *)pathArray
105 {
106     self = [super initWithFrame:frame];
107     if (self) {
108         _pathArray = pathArray;
109         if (_pathArray )
110         {
111             _pathLabel = [UIButton buttonWithType: UIButtonTypeCustom];
112             [_pathLabel setTitle: _pathArray[_pathArray.count-1] forState: UIControlStateNormal];
113             [_pathLabel setTitleColor: [UIColor blackColor] forState: UIControlStateNormal];
114             _pathLabel.titleLabel.font = [UIFont systemFontOfSize: [UIFont labelFontSize]];
115             [self addSubview: _pathLabel];
116             
117             _pathLabel.translatesAutoresizingMaskIntoConstraints = NO;
118             [_pathLabel sizeToFit];
119             [_pathLabel.widthAnchor      constraintEqualToConstant: _pathLabel.frame.size.width].active = YES;
120             [_pathLabel.trailingAnchor   constraintEqualToAnchor: self.trailingAnchor].active = YES;
121             [_pathLabel.topAnchor        constraintEqualToAnchor: self.topAnchor].active = YES;
122             [_pathLabel.bottomAnchor     constraintEqualToAnchor: self.bottomAnchor].active = YES;
123         }
124         if (_pathArray.count > 2 )
125         {
126             _elipsisButton = [UIButton buttonWithType: UIButtonTypeCustom];
127             [_elipsisButton setTitle: @"…" forState: UIControlStateNormal];
128             [_elipsisButton setTitleColor: _elipsisButton.tintColor forState: UIControlStateNormal];
129             [_elipsisButton setTitleColor: [UIColor grayColor] forState: UIControlStateHighlighted];
130             _elipsisButton.titleLabel.font = [UIFont boldSystemFontOfSize: [UIFont labelFontSize]];
131             [_elipsisButton addTarget: self action: @selector(pathButtonPressed:withEvent:) forControlEvents: UIControlEventTouchUpInside];
132             _elipsisButton.userInteractionEnabled = YES;
133             [self addSubview: _elipsisButton];
134
135             _elipsisButton.translatesAutoresizingMaskIntoConstraints = NO;
136             [_elipsisButton sizeToFit];
137             [_elipsisButton.widthAnchor      constraintEqualToConstant: _elipsisButton.frame.size.width].active = YES;
138             [_elipsisButton.trailingAnchor   constraintEqualToAnchor: _pathLabel.leadingAnchor].active = YES;
139             [_elipsisButton.topAnchor        constraintGreaterThanOrEqualToAnchor: self.topAnchor].active = YES;
140             [_elipsisButton.bottomAnchor     constraintLessThanOrEqualToAnchor: self.bottomAnchor].active = YES;
141         }
142      }
143     return self;
144 }
145
146 - (BOOL) canBecomeFirstResponder
147 {
148     return YES;
149 }
150
151 - (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection
152 {
153     (void)controller;       // Unused
154     (void)traitCollection;  // Unused
155     return UIModalPresentationNone;
156 }
157
158 - (void) pathButtonPressed:(UIControl *)button withEvent:(UIEvent *)event
159 {
160     (void)button;           // Unused
161     
162     if (!self.cell.showingDeleteConfirmation )
163     {
164         [self becomeFirstResponder];
165         
166         UIView *buttonView = [[event.allTouches anyObject] view];
167         CGRect buttonFrame = [buttonView convertRect: buttonView.frame toView: self];
168         
169         CNPathPopoverViewController * controller = [[CNPathPopoverViewController alloc] initWithPathArray: self.pathArray];
170         controller.modalPresentationStyle = UIModalPresentationPopover;
171         controller.preferredContentSize = CGSizeMake(controller.label.frame.size.width + controller.offset.x * 2, controller.label.frame.size.height + controller.offset.y * 2 );
172         
173         UIPopoverPresentationController *popover =  controller.popoverPresentationController;
174         popover.delegate = (id<UIPopoverPresentationControllerDelegate>)self;
175         popover.sourceView = buttonView;
176         popover.sourceRect = buttonFrame;
177         popover.permittedArrowDirections = UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionRight;
178         
179         [(UIViewController *)self.tableView.delegate presentViewController: controller
180                                                                   animated: YES
181                                                                 completion: nil];
182     }
183 }
184
185 - (CGSize) sizeThatFits:(CGSize)size
186 {
187     (void)size;         // Unused
188     CGSize ret = CGSizeZero;
189     CGFloat maxX = 0.0;
190     CGFloat maxHeight = 0.0;
191     for (UIView *view in [self subviews] )
192     {
193         CGRect frame = view.frame;
194         CGFloat frameMaxX = CGRectGetMaxX(frame);
195         CGFloat frameHeight = CGRectGetHeight(frame);
196         maxX += frameMaxX;
197         if (frameHeight > maxHeight )
198         {
199             maxHeight = frameHeight;
200         }
201     }
202     ret.width = maxX;
203     ret.height = maxHeight;
204     return ret;
205 }
206
207 @end
208
209 @interface CNManualDomainViewController : UITableViewController
210
211 @property (weak)        CNBrowseDomainsController * delegate;
212 @property (weak)        UITextField *               textField;
213
214 @end
215
216 #define kTag_EditTextField          103
217
218 @implementation CNManualDomainViewController
219
220 - (void)viewDidLoad
221 {
222     [super viewDidLoad];
223     
224     self.tableView.dataSource = (id<UITableViewDataSource>)self;
225     self.tableView.delegate = (id<UITableViewDelegate>)self;
226     
227     self.title = LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.title", nil );
228     self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.cancel", nil )
229                                                                              style: UIBarButtonItemStylePlain
230                                                                             target: self
231                                                                             action: @selector(cancelAction:)];
232     
233     self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.add", nil )
234                                                                              style: UIBarButtonItemStylePlain
235                                                                             target: self
236                                                                             action: @selector(addAction:)];
237     self.navigationItem.rightBarButtonItem.enabled = NO;
238 }
239
240 - (void)viewWillDisappear:(BOOL)animated
241 {
242     [super viewWillDisappear: animated];
243     if (self.isMovingFromParentViewController )
244     {
245         [[NSNotificationCenter defaultCenter] removeObserver: self];
246     }
247 }
248
249 - (void)viewDidAppear:(BOOL)animated
250 {
251     [super viewDidAppear: animated];
252     if (self.isMovingToParentViewController )
253     {
254         [self.textField becomeFirstResponder];
255     }
256 }
257
258 - (IBAction)addAction:(id)sender
259 {
260     (void)sender;   // Unused
261     [self.navigationController dismissViewControllerAnimated: YES completion: ^{
262         [self.delegate addBrowseDomain: self.textField.text];
263     }];
264 }
265
266 - (IBAction)cancelAction:(id)sender
267 {
268     (void)sender;   // Unused
269     [self.navigationController dismissViewControllerAnimated: YES completion: nil];
270 }
271
272 #pragma mark - Notifications
273
274 - (void)textFieldDidChange:(NSNotification *)notification
275 {
276     UITextField * textField = (UITextField *)notification.object;
277     self.navigationItem.rightBarButtonItem.enabled = (textField.text.length > 0);
278 }
279
280 #pragma mark - TableView Delegates
281
282 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
283 {
284     (void)tableView;        // Unused
285     (void)indexPath;        // Unused
286     return UITableViewAutomaticDimension;
287 }
288
289 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
290 {
291     (void)tableView;        // Unused
292     NSInteger result = 0;
293     
294     if (tableView == self.tableView )   result = 1;
295     
296     return(result );
297 }
298
299 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
300 {
301     (void)section;        // Unused
302     NSInteger result = 0;
303     
304     if (tableView == self.tableView && section == 0 ) result = 1;
305     
306     return(result );
307 }
308
309 - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
310 {
311     NSString * result = nil;
312     
313     if (tableView == self.tableView && section == 0 )
314     {
315         result = LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.footer", nil );
316     }
317     
318     return(result );
319 }
320
321 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
322 {
323     UITableViewCell *cell = nil;
324     
325     if (tableView == self.tableView )
326     {
327         if (indexPath.section == 0 && indexPath.row == 0 )
328         {
329             static NSString *MyIdentifier = @"manual_domain_cell_id";
330             cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
331             if (!cell )
332             {
333                 cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleValue1  reuseIdentifier: MyIdentifier];
334             }
335             
336             cell.textLabel.hidden = YES;
337             cell.detailTextLabel.hidden = YES;
338             
339             [[cell viewWithTag: kTag_EditTextField] removeFromSuperview];
340             UITextField * textField = [[UITextField alloc] initWithFrame:CGRectZero];
341             textField.tag = kTag_EditTextField;
342             textField.adjustsFontSizeToFitWidth = YES;
343             textField.placeholder = LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.defaultValue", nil );
344             textField.keyboardType = UIKeyboardTypeURL;
345             textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
346             textField.autocorrectionType = UITextAutocorrectionTypeNo;
347             textField.enablesReturnKeyAutomatically = YES;
348             textField.clearButtonMode = UITextFieldViewModeAlways;
349             [cell.contentView addSubview: textField];
350             
351             textField.translatesAutoresizingMaskIntoConstraints = NO;
352             [textField.leadingAnchor    constraintEqualToAnchor: cell.layoutMarginsGuide.leadingAnchor].active = YES;
353             [textField.trailingAnchor   constraintEqualToAnchor: cell.layoutMarginsGuide.trailingAnchor].active = YES;
354             [textField.topAnchor        constraintEqualToAnchor: cell.layoutMarginsGuide.topAnchor].active = YES;
355             [textField.bottomAnchor     constraintEqualToAnchor: cell.layoutMarginsGuide.bottomAnchor].active = YES;
356
357             [[NSNotificationCenter defaultCenter] addObserver: self
358                                                      selector: @selector(textFieldDidChange:)
359                                                          name: UITextFieldTextDidChangeNotification
360                                                        object: textField];
361             self.textField = textField;
362         }
363     }
364     
365     return(cell );
366 }
367
368 - (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
369 {
370     (void)tableView;    // Unused
371     (void)indexPath;    // Unused
372     return(nil );
373 }
374
375 @end
376
377 @interface CNBrowseDomainsController ()
378
379 @property (strong) NSDictionary *                   selectedInstance;
380 @property (strong) NSMutableDictionary *            instanceInfoStrings;
381 @property (strong) NSMutableDictionary *            instanceStatusViews;
382
383 @property (strong) CNDomainBrowserViewController *  browseController;
384
385 @end
386
387 @implementation CNBrowseDomainsController
388
389 - (instancetype)initWithStyle:(UITableViewStyle)style
390 {
391     if (self = [super initWithStyle: style] )
392     {
393         [self commonInit];
394     }
395     return(self );
396 }
397
398 - (void)contentViewsInit
399 {
400     self.tableView.allowsMultipleSelectionDuringEditing = NO;
401 }
402
403 - (void)commonInit
404 {
405     self.instanceInfoStrings = [NSMutableDictionary dictionary];
406     self.instanceStatusViews = [NSMutableDictionary dictionary];
407     self.browseController = [[CNDomainBrowserViewController alloc] initWithStyle: UITableViewStylePlain];
408     _browseController.delegate = (id<CNDomainBrowserViewControllerDelegate>)self;
409     _browseController.ignoreLocal = YES;
410 }
411
412 - (void)viewDidLoad
413 {
414     [super viewDidLoad];
415     [self contentViewsInit];
416     
417     self.tableView.dataSource = (id<UITableViewDataSource>)self;
418     self.tableView.delegate = (id<UITableViewDelegate>)self;
419 }
420
421 - (void)viewWillAppear:(BOOL)animated
422 {
423     [super viewWillAppear: animated];
424     if (self.isMovingToParentViewController)
425     {
426         [_browseController startBrowse];
427     }
428 }
429
430 - (void)viewWillDisappear:(BOOL)animated
431 {
432     [super viewWillDisappear: animated];
433     if (self.isMovingFromParentViewController )
434     {
435         [self savePreferences];
436         [_browseController stopBrowse];
437     }
438 }
439
440 -(void)savePreferences
441 {
442     [BonjourSCStore setObject: _browseDomainsA.count ? _browseDomainsA : nil forKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY];
443 }
444
445 - (NSDictionary *)browseDomainForRow:(NSInteger)row
446 {
447     NSDictionary *      result = nil;
448     NSInteger           curRow = 0;
449     
450     for (NSDictionary * nextDomain in self.browseDomainsA )
451     {
452         if (curRow == row )
453         {
454             result = nextDomain;
455             break;
456         }
457         curRow++;
458     }
459     
460     return(result );
461 }
462
463 - (NSInteger)indexOfDomainInList:(NSString *)domainString
464 {
465     NSInteger  index = 0;
466     if (_browseDomainsA ) {
467         NSDictionary *domainDict;
468         NSString     *domainName;
469         NSEnumerator *arrayEnumerator = [_browseDomainsA objectEnumerator];
470         while ((domainDict = [arrayEnumerator nextObject]) != NULL)
471         {
472             domainName = [domainDict objectForKey:_CNBrowseDomainKey_fullname];
473             if ([domainString caseInsensitiveCompare:domainName] == NSOrderedSame) return index;
474             index++;
475         }
476     }
477     return NSNotFound;
478 }
479
480 - (void)addBrowseDomain:(NSString *)fullPath
481 {
482     NSString * trimmedPath = TrimCharactersFromDNSDomain(fullPath );
483     NSInteger index = [self indexOfDomainInList: trimmedPath];
484     NSMutableArray * domains = [NSMutableArray arrayWithArray: self.browseDomainsA];
485
486     if (index == NSNotFound )
487     {
488         [domains addObject: @{
489                               _CNBrowseDomainKey_fullname: trimmedPath,
490                               _CNBrowseDomainKey_enabled: @YES
491                               }];
492         
493         self.browseDomainsA = [NSArray arrayWithArray: domains];
494         [self.tableView insertRowsAtIndexPaths: @[[NSIndexPath indexPathForRow: domains.count-1 inSection: 0]] withRowAnimation: UITableViewRowAnimationAutomatic];
495     }
496     else
497     {
498         NSDictionary * domain = domains[index];
499         domains[index] = @{
500                            _CNBrowseDomainKey_fullname: domain[_CNBrowseDomainKey_fullname],
501                            _CNBrowseDomainKey_enabled: @YES
502                            };
503         self.browseDomainsA = [NSArray arrayWithArray: domains];
504         NSIndexPath * indexPath = [NSIndexPath indexPathForRow: index inSection: 0];
505         [CATransaction begin];
506         [CATransaction setCompletionBlock:^{
507             [self.tableView deselectRowAtIndexPath: indexPath animated: YES];
508         }];
509         [self.tableView reloadRowsAtIndexPaths: @[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
510         [self.tableView selectRowAtIndexPath: indexPath animated: YES scrollPosition: UITableViewScrollPositionMiddle];
511         [CATransaction commit];
512
513     }
514 }
515
516 #pragma mark - CNDomainBrowserViewControllerDelegate
517
518 - (void)domainBrowserDomainSelected:(NSString *)domain
519 {
520     [self newPathSelected: domain];
521 }
522
523 - (void)bonjourBrowserDomainUpdate:(NSString *)defaultDomain
524 {
525     (void)defaultDomain;    // Unused
526     [self.tableView reloadData];
527 }
528
529 #pragma mark - TableView Delegates
530
531 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
532 {
533     (void)tableView;        // Unused
534     (void)indexPath;        // Unused
535     return UITableViewAutomaticDimension;
536 }
537
538 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
539 {
540     (void)tableView;        // Unused
541     NSInteger result = 0;
542     
543     if (tableView == self.tableView )   result = (self.browseController.flattenedDNSDomains.count > 0) ? 3 : 2;
544     else                                result = 1;
545     
546     return(result );
547 }
548
549 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
550 {
551     (void)section;        // Unused
552     NSInteger result = 0;
553
554     if (tableView == self.tableView )
555     {
556         if (section == 0 )
557         {
558             result = self.browseDomainsA.count;
559         }
560         else
561         {
562             result = 1;
563         }
564     }
565     
566     return(result );
567 }
568
569 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
570 {
571     UITableViewCell *cell = nil;
572     
573     if (tableView == self.tableView )
574     {
575         if (indexPath.section == 0 )
576         {
577             NSDictionary * record = [self browseDomainForRow: indexPath.row];
578             if (record )
579             {
580                 static NSString *MyIdentifier = @"browse_cell_id";
581                 cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
582                 if (!cell )
583                 {
584                     cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle  reuseIdentifier: MyIdentifier];
585                 }
586                 NSArray *  pathArray = DNSDomainToDomainPath(record[_CNBrowseDomainKey_fullname] );
587                 cell.textLabel.text = pathArray[pathArray.count-1];
588                 cell.textLabel.textColor = nil;
589                 cell.textLabel.numberOfLines = 0;
590                 cell.accessoryType = UITableViewCellAccessoryNone;
591                 cell.accessoryView = nil;
592                 cell.imageView.image = [[UIImage imageNamed: @"UIPreferencesBlueCheck.png"
593                                                    inBundle: [NSBundle bundleForClass: [self class]]
594                               compatibleWithTraitCollection: nil] imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate];
595                 cell.imageView.hidden = ![record[_CNBrowseDomainKey_enabled] boolValue];
596                 
597                 NSArray *   accPathArray = (pathArray.count > 2) ?
598                                             [[pathArray reverseObjectEnumerator] allObjects] :
599                                             ((pathArray.count > 1) ? @[pathArray[0]] : nil);
600                 if (accPathArray )
601                 {
602                     CNPathAccessoryView * accView = [[CNPathAccessoryView alloc] initWithFrame: CGRectZero
603                                                                                      pathArray: accPathArray];
604                     accView.tableView = tableView;
605                     accView.cell = cell;
606                     [accView sizeToFit];
607                     cell.accessoryView = accView;
608                 }
609             }
610         }
611         else
612         {
613             static NSString *MyIdentifier = @"button_cell_id";
614             cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
615             if (!cell )
616             {
617                 cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault  reuseIdentifier: MyIdentifier];
618             }
619             
620            if (self.browseController.flattenedDNSDomains.count > 0 && indexPath.section == 1 )
621            {
622                 cell.textLabel.textColor = self.view.tintColor;
623                 cell.textLabel.text = LocalizedStringFromMyBundle(@"_dnsBrowser.domains.selectdomain", nil );
624                 cell.accessoryType = UITableViewCellAccessoryNone;
625                 cell.tag = kTag_AddBrowse;
626            }
627            else
628            {
629                cell.textLabel.textColor = self.view.tintColor;
630                cell.textLabel.text = LocalizedStringFromMyBundle(@"_dnsBrowser.domains.selectmanual", nil );
631                cell.accessoryType = UITableViewCellAccessoryNone;
632                cell.tag = kTag_AddManual;
633            }
634         }
635     }
636     
637     return(cell );
638 }
639
640 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
641 {
642     BOOL result = NO;
643     
644     if (tableView == self.tableView && indexPath.section == 0 ) result = YES;
645     
646     return(result );
647 }
648
649 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
650 {
651     if (editingStyle == UITableViewCellEditingStyleDelete )
652     {
653         NSMutableArray * domains = [NSMutableArray arrayWithArray: self.browseDomainsA];
654         [domains removeObjectAtIndex: indexPath.row];
655         self.browseDomainsA = [NSArray arrayWithArray: domains];
656         [tableView deleteRowsAtIndexPaths: @[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
657     }
658 }
659
660 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
661 {
662     UITableViewCell * cell = [tableView cellForRowAtIndexPath: indexPath];
663     if (tableView == self.tableView )
664     {
665         if (indexPath.section == 0 )
666         {   //  Toggle check and enable bit
667             NSMutableArray * domains = [NSMutableArray arrayWithArray: self.browseDomainsA];
668             NSMutableDictionary *  selection = [NSMutableDictionary dictionaryWithDictionary: domains[indexPath.row]];
669             selection[_CNBrowseDomainKey_enabled] = [NSNumber numberWithBool: ![selection[_CNBrowseDomainKey_enabled] boolValue]];
670             domains[indexPath.row] = selection;
671             self.browseDomainsA = [NSArray arrayWithArray: domains];
672             [tableView reloadRowsAtIndexPaths: @[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
673         }
674         else
675         {
676             if (cell.tag == kTag_AddBrowse )
677             {
678                 CNDomainBrowserViewController *c = _browseController;
679                 c.title = LocalizedStringFromMyBundle(@"_bonjour.browse.name", nil);
680                 c.clearsSelectionOnViewWillAppear = NO;
681                 c.modalPresentationStyle = UIModalPresentationFormSheet;
682                 UINavigationController * nv = [[UINavigationController alloc] initWithRootViewController: c];
683                 [self presentViewController: nv animated: YES completion: nil];
684             }
685             else if (cell.tag == kTag_AddManual )
686             {
687                 CNManualDomainViewController * c = [[CNManualDomainViewController alloc] initWithStyle: UITableViewStyleGrouped];
688                 c.delegate = self;
689                 c.modalPresentationStyle = UIModalPresentationFormSheet;
690                 UINavigationController * nv = [[UINavigationController alloc] initWithRootViewController: c];
691                 [self presentViewController: nv animated: YES completion: nil];
692             }
693         }
694     }
695     [tableView deselectRowAtIndexPath: indexPath animated: YES];
696 }
697
698 #pragma mark - Commands
699
700 - (void)newPathSelected:(NSString *)fullPath
701 {
702     [CATransaction begin];
703     [CATransaction setCompletionBlock:^{
704         [self addBrowseDomain: fullPath];
705     }];
706     [self.navigationController popToViewController: self animated: YES];
707     [CATransaction commit];
708  }
709
710 @end