blob: b46a07d056dbf6df013bbc368a807dc9dad8fd00 [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 Afanasyev88f0b3a2013-09-24 23:52:08 -070044}
45
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070046-(void)awakeFromNib
47{
48 statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070049 [statusItem setMenu:statusMenu];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070050 [statusItem setToolTip:@"NDN Control Center"];
51 [statusItem setEnabled:YES];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070052 [statusItem setHighlightMode:YES];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070053 //[statusItem setTarget:self];
54
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070055 [statusItem setTitle:@""];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070056 [statusItem setImage:m_disconnectedIcon];
Ilya Moiseenko01264322013-09-26 15:34:21 -070057
Ilya Moiseenko01264322013-09-26 15:34:21 -070058 [connectionStatus setView: connectionStatusView];
59 [connectionStatus setTarget:self];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070060
Ilya Moiseenko01264322013-09-26 15:34:21 -070061 [daemonStatus setView: daemonStatusView];
62 [daemonStatus setTarget:self];
Ilya Moiseenkoa10ef8d2013-09-25 17:23:05 -070063}
64
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070065-(IBAction)openDaemonStatus:(id)sender
66{
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070067}
68
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -070069-(IBAction)showExitConfirmationWindow:(id)sender
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070070{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070071 NSAlert *alert = [[NSAlert alloc] init];
72 [alert addButtonWithTitle:@"Yes"];
73 [alert addButtonWithTitle:@"No"];
74 [alert addButtonWithTitle:@"Cancel"];
75 [alert setMessageText:@"Shutdown NDN daemon as well?"];
76 [alert setInformativeText:@"All NDN operations will be become unavailable."];
77 [alert setAlertStyle:NSCriticalAlertStyle];
78 [alert setShowsSuppressionButton: YES];
79
80 NSInteger res = [alert runModal];
81 if (res == NSAlertFirstButtonReturn) {
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020082 // "YES" stop ndnd
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070083 [m_operationQueue cancelAllOperations];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020084
85 [m_operationQueue addOperationWithBlock:^{
86 NSTask *task = [[NSTask alloc] init];
87 [task setLaunchPath: @NDND_STOP_COMMAND];
88 [task launch];
89 [task waitUntilExit];
90 }];
91
92 [m_operationQueue waitUntilAllOperationsAreFinished];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070093 [NSApp terminate:self];
94 } else if (res == NSAlertSecondButtonReturn) {
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020095 // "NO" terminate app but keep ndnd running
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070096 [m_operationQueue cancelAllOperations];
97 [NSApp terminate:self];
98 }
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070099}
100
Ilya Moiseenko01264322013-09-26 15:34:21 -0700101-(void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
102{
Ilya Moiseenko01264322013-09-26 15:34:21 -0700103 if( ([item view]!=nil) && (item == daemonStatus) )
104 {
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700105 NSView *view = [item view];
106
107 [statusPopover showRelativeToRect:[view bounds]
108 ofView:view
109 preferredEdge:NSMinXEdge];
Ilya Moiseenko01264322013-09-26 15:34:21 -0700110 }
111 else
112 {
113 [statusPopover performClose:nil];
114 }
115}
116
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700117-(void)onTick:(NSTimer *)timer
118{
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +0200119 [self updateStatus];
120}
121
122-(void)updateStatus
123{
124 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
125 [m_operationQueue addOperation:operation];
126}
127
128-(void)updateStatusWithDependency:(NSOperation*)dependency
129{
130 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
131 [operation addDependency:dependency];
132
133 [m_operationQueue addOperation:dependency];
134 [m_operationQueue addOperation:operation];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700135}
136
137- (void)statusUpdated:(NSXMLDocument*)document
138{
139 if (!m_daemonStarted) {
140 m_daemonStarted = true;
141 [connectionStatusText setStringValue:@"Active"];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700142
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700143 [statusItem setImage:m_connectedIcon];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700144 }
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700145
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700146 NSXMLDocument *statusXml = [document objectByApplyingXSLT:m_statusXslt
147 arguments:nil
148 error:nil];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700149
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700150 NSXMLDocument *statusFibXml = [document objectByApplyingXSLT:m_statusToFibXslt
151 arguments:nil
152 error:nil];
153
154 m_statusString = [[NSAttributedString alloc]initWithHTML:[statusXml XMLData] documentAttributes:NULL];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700155 [daemonStatusHtml setAttributedStringValue:m_statusString];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700156
157 [preferencesDelegate updateFibStatus:statusFibXml];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300158
159 NSArray *autoconf = [[statusFibXml rootElement] nodesForXPath:@"//fib/prefix[text()='ndn:/autoconf-route']" error:nil];
160 if ([autoconf count] == 0)
161 {
162 NSLog (@"No automatically detected route configured, trying to get one");
163 [self restartDaemon:nil];
164 }
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700165}
166
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700167- (void)statusUnavailable:(id)none
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700168{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700169 // try start ndnd if it is not started yet
170 if (m_daemonStarted) {
171 m_daemonStarted = false;
172
173 [connectionStatusText setStringValue:@"Starting..."];
174
175 [statusItem setImage:m_disconnectedIcon];
176 }
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700177
178 [daemonStatusHtml setStringValue:@""];
179 [preferencesDelegate updateFibStatus:nil];
180
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300181 m_autoconfInProgress = true;
182
183 NSOperation *startOp = [NSBlockOperation blockOperationWithBlock:^{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700184 NSTask *task = [[NSTask alloc] init];
185 [task setLaunchPath: @NDND_START_COMMAND];
186 [task launch];
187 }];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300188
189 NSOperation *autoconfOp = [NSBlockOperation blockOperationWithBlock:^{
190 NSTask *task = [[NSTask alloc] init];
191 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
192 [task launch];
193 [task waitUntilExit];
194
195 m_autoconfInProgress = false;
196 }];
197
198 [autoconfOp addDependency:startOp];
199
200 [m_operationQueue addOperation:startOp];
201 [m_operationQueue addOperation:autoconfOp];
202}
203
204-(void)restartDaemon:(id)none
205{
206 if (m_autoconfInProgress)
207 return;
208
209 m_autoconfInProgress = true;
210 [m_operationQueue addOperationWithBlock:^{
211 NSTask *task = [[NSTask alloc] init];
212 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
213 [task launch];
214 [task waitUntilExit];
215
216 m_autoconfInProgress = false;
217 }];
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700218}
219
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700220@end