blob: e92c82b3fa67a5bf65b0d45f4fa5725071a99031 [file] [log] [blame]
Alexander Afanasyev14b09482013-10-11 18:24:45 +02001/* -*- Mode: obj; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -07002/*
3 * @copyright See LICENCE for copyright and license information.
4 *
5 * @author Alexander Afanasyev <alexander.afanasyev@ucla.edu>
6 * @author Ilya Moiseenko <iliamo@ucla.edu>
7 */
8
Alexander Afanasyev2beff7f2013-09-27 17:50:36 -07009#include "config.h"
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070010#import "menu-delegate.h"
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070011#import "ndnd-status-operation.h"
Ilya Moiseenko2dffcf52013-09-27 15:08:04 -070012
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070013@implementation MenuDelegate
14
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070015-(id)init
16{
17 if (![super init]) {
18 return nil;
19 }
20
Alexander Afanasyevb9024d12013-10-14 18:10:18 +030021 m_autoconfInProgress = false;
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070022 m_operationQueue = [[NSOperationQueue alloc] init];
23 return self;
24}
25
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070026- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
27{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070028 m_daemonStarted = false;
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -070029 allowSoftwareUpdates = true;
30 enableHubDiscovery = true;
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070031
32 NSBundle *bundle = [NSBundle bundleForClass:[self class]];
33 m_connectedIcon = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"FlatConnected" ofType:@"png"]];
34 m_disconnectedIcon = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"FlatDisconnected" ofType:@"png"]];
35 m_statusXslt = [NSData dataWithContentsOfFile:[bundle pathForResource:@"status" ofType:@"xslt"]];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -070036 m_statusToFibXslt = [NSData dataWithContentsOfFile:[bundle pathForResource:@"status-to-fib" ofType:@"xslt"]];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -070037
Alexander Afanasyevb9024d12013-10-14 18:10:18 +030038 [NSTimer scheduledTimerWithTimeInterval: 1.0
39 target: self
40 selector:@selector(onTick:)
41 userInfo: nil
42 repeats:YES];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020043 [self updateStatus];
Alexander Afanasyev17922872013-10-15 11:45:58 +030044
45 m_systemEvents = [[SystemEvents alloc] init];
46}
47
48- (void)applicationWillTerminate:(NSNotification *)aNotification
49{
50 [m_systemEvents disable];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070051}
52
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070053-(void)awakeFromNib
54{
55 statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070056 [statusItem setMenu:statusMenu];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070057 [statusItem setToolTip:@"NDN Control Center"];
58 [statusItem setEnabled:YES];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070059 [statusItem setHighlightMode:YES];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070060 //[statusItem setTarget:self];
61
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070062 [statusItem setTitle:@""];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070063 [statusItem setImage:m_disconnectedIcon];
Ilya Moiseenko01264322013-09-26 15:34:21 -070064
Ilya Moiseenko01264322013-09-26 15:34:21 -070065 [connectionStatus setView: connectionStatusView];
66 [connectionStatus setTarget:self];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070067
Ilya Moiseenko01264322013-09-26 15:34:21 -070068 [daemonStatus setView: daemonStatusView];
69 [daemonStatus setTarget:self];
Ilya Moiseenkoa10ef8d2013-09-25 17:23:05 -070070}
71
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070072-(IBAction)openDaemonStatus:(id)sender
73{
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070074}
75
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -070076-(IBAction)showExitConfirmationWindow:(id)sender
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070077{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070078 NSAlert *alert = [[NSAlert alloc] init];
79 [alert addButtonWithTitle:@"Yes"];
80 [alert addButtonWithTitle:@"No"];
81 [alert addButtonWithTitle:@"Cancel"];
82 [alert setMessageText:@"Shutdown NDN daemon as well?"];
83 [alert setInformativeText:@"All NDN operations will be become unavailable."];
84 [alert setAlertStyle:NSCriticalAlertStyle];
85 [alert setShowsSuppressionButton: YES];
86
87 NSInteger res = [alert runModal];
88 if (res == NSAlertFirstButtonReturn) {
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020089 // "YES" stop ndnd
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070090 [m_operationQueue cancelAllOperations];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020091
92 [m_operationQueue addOperationWithBlock:^{
93 NSTask *task = [[NSTask alloc] init];
94 [task setLaunchPath: @NDND_STOP_COMMAND];
95 [task launch];
96 [task waitUntilExit];
97 }];
98
99 [m_operationQueue waitUntilAllOperationsAreFinished];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700100 [NSApp terminate:self];
101 } else if (res == NSAlertSecondButtonReturn) {
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +0200102 // "NO" terminate app but keep ndnd running
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700103 [m_operationQueue cancelAllOperations];
104 [NSApp terminate:self];
105 }
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700106}
107
Ilya Moiseenko01264322013-09-26 15:34:21 -0700108-(void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
109{
Ilya Moiseenko01264322013-09-26 15:34:21 -0700110 if( ([item view]!=nil) && (item == daemonStatus) )
111 {
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700112 NSView *view = [item view];
113
114 [statusPopover showRelativeToRect:[view bounds]
115 ofView:view
116 preferredEdge:NSMinXEdge];
Ilya Moiseenko01264322013-09-26 15:34:21 -0700117 }
118 else
119 {
120 [statusPopover performClose:nil];
121 }
122}
123
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700124-(void)onTick:(NSTimer *)timer
125{
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +0200126 [self updateStatus];
127}
128
129-(void)updateStatus
130{
131 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
132 [m_operationQueue addOperation:operation];
133}
134
135-(void)updateStatusWithDependency:(NSOperation*)dependency
136{
137 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
138 [operation addDependency:dependency];
139
140 [m_operationQueue addOperation:dependency];
141 [m_operationQueue addOperation:operation];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700142}
143
144- (void)statusUpdated:(NSXMLDocument*)document
145{
146 if (!m_daemonStarted) {
147 m_daemonStarted = true;
148 [connectionStatusText setStringValue:@"Active"];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700149
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700150 [statusItem setImage:m_connectedIcon];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700151 }
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700152
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700153 NSXMLDocument *statusXml = [document objectByApplyingXSLT:m_statusXslt
154 arguments:nil
155 error:nil];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700156
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700157 NSXMLDocument *statusFibXml = [document objectByApplyingXSLT:m_statusToFibXslt
158 arguments:nil
159 error:nil];
160
161 m_statusString = [[NSAttributedString alloc]initWithHTML:[statusXml XMLData] documentAttributes:NULL];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700162 [daemonStatusHtml setAttributedStringValue:m_statusString];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700163
164 [preferencesDelegate updateFibStatus:statusFibXml];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300165
166 NSArray *autoconf = [[statusFibXml rootElement] nodesForXPath:@"//fib/prefix[text()='ndn:/autoconf-route']" error:nil];
167 if ([autoconf count] == 0)
168 {
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300169 [self restartDaemon:nil];
170 }
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700171}
172
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700173- (void)statusUnavailable:(id)none
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700174{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700175 // try start ndnd if it is not started yet
176 if (m_daemonStarted) {
177 m_daemonStarted = false;
178
179 [connectionStatusText setStringValue:@"Starting..."];
180
181 [statusItem setImage:m_disconnectedIcon];
182 }
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700183
184 [daemonStatusHtml setStringValue:@""];
185 [preferencesDelegate updateFibStatus:nil];
186
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300187 m_autoconfInProgress = true;
188
189 NSOperation *startOp = [NSBlockOperation blockOperationWithBlock:^{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700190 NSTask *task = [[NSTask alloc] init];
191 [task setLaunchPath: @NDND_START_COMMAND];
192 [task launch];
193 }];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300194
195 NSOperation *autoconfOp = [NSBlockOperation blockOperationWithBlock:^{
196 NSTask *task = [[NSTask alloc] init];
197 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
198 [task launch];
199 [task waitUntilExit];
200
201 m_autoconfInProgress = false;
202 }];
203
204 [autoconfOp addDependency:startOp];
205
206 [m_operationQueue addOperation:startOp];
207 [m_operationQueue addOperation:autoconfOp];
208}
209
210-(void)restartDaemon:(id)none
211{
212 if (m_autoconfInProgress)
213 return;
214
Alexander Afanasyev17922872013-10-15 11:45:58 +0300215 NSLog (@"No automatically detected route configured, trying to get one");
216
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300217 m_autoconfInProgress = true;
218 [m_operationQueue addOperationWithBlock:^{
219 NSTask *task = [[NSTask alloc] init];
220 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
221 [task launch];
222 [task waitUntilExit];
223
224 m_autoconfInProgress = false;
225 }];
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700226}
227
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700228@end