OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library trydart.interaction_manager; | 5 library trydart.interaction_manager; |
6 | 6 |
7 import 'dart:html'; | 7 import 'dart:html'; |
8 | 8 |
9 import 'dart:convert' show | 9 import 'dart:convert' show |
10 JSON; | 10 JSON; |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 import 'compilation.dart' show | 28 import 'compilation.dart' show |
29 currentSource, | 29 currentSource, |
30 scheduleCompilation; | 30 scheduleCompilation; |
31 | 31 |
32 import 'ui.dart' show | 32 import 'ui.dart' show |
33 currentTheme, | 33 currentTheme, |
34 hackDiv, | 34 hackDiv, |
35 mainEditorPane, | 35 mainEditorPane, |
36 observer, | 36 observer, |
37 outputDiv; | 37 outputDiv, |
| 38 statusDiv; |
38 | 39 |
39 import 'decoration.dart' show | 40 import 'decoration.dart' show |
40 CodeCompletionDecoration, | 41 CodeCompletionDecoration, |
41 Decoration, | 42 Decoration, |
42 DiagnosticDecoration, | 43 DiagnosticDecoration, |
43 error, | 44 error, |
44 info, | 45 info, |
45 warning; | 46 warning; |
46 | 47 |
47 import 'html_to_text.dart' show | 48 import 'html_to_text.dart' show |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 | 90 |
90 void onSelectionChange(Event event); | 91 void onSelectionChange(Event event); |
91 | 92 |
92 /// Called when the content of a CompilationUnit changed. | 93 /// Called when the content of a CompilationUnit changed. |
93 void onCompilationUnitChanged(CompilationUnit unit); | 94 void onCompilationUnitChanged(CompilationUnit unit); |
94 | 95 |
95 Future<List<String>> projectFileNames(); | 96 Future<List<String>> projectFileNames(); |
96 | 97 |
97 /// Called when the user selected a new project file. | 98 /// Called when the user selected a new project file. |
98 void onProjectFileSelected(String projectFile); | 99 void onProjectFileSelected(String projectFile); |
| 100 |
| 101 /// Called when notified about a project file changed (on the server). |
| 102 void onProjectFileFsEvent(MessageEvent e); |
99 } | 103 } |
100 | 104 |
101 /** | 105 /** |
102 * State machine for UI interactions. | 106 * State machine for UI interactions. |
103 */ | 107 */ |
104 class InteractionContext extends InteractionManager { | 108 class InteractionContext extends InteractionManager { |
105 InteractionState state; | 109 InteractionState state; |
106 | 110 |
107 final Map<String, CompilationUnit> projectFiles = <String, CompilationUnit>{}; | 111 final Map<String, CompilationUnit> projectFiles = <String, CompilationUnit>{}; |
108 | 112 |
109 CompilationUnit currentCompilationUnit = | 113 CompilationUnit currentCompilationUnit = |
110 // TODO(ahe): Don't use a fake unit. | 114 // TODO(ahe): Don't use a fake unit. |
111 new CompilationUnit('fake', ''); | 115 new CompilationUnit('fake', ''); |
112 | 116 |
| 117 CompilationUnit lastSaved; |
| 118 |
113 InteractionContext() | 119 InteractionContext() |
114 : super.internal() { | 120 : super.internal() { |
115 state = new InitialState(this); | 121 state = new InitialState(this); |
116 } | 122 } |
117 | 123 |
118 void onInput(Event event) => state.onInput(event); | 124 void onInput(Event event) => state.onInput(event); |
119 | 125 |
120 void onKeyUp(KeyboardEvent event) => state.onKeyUp(event); | 126 void onKeyUp(KeyboardEvent event) => state.onKeyUp(event); |
121 | 127 |
122 void onMutation(List<MutationRecord> mutations, MutationObserver observer) { | 128 void onMutation(List<MutationRecord> mutations, MutationObserver observer) { |
123 return state.onMutation(mutations, observer); | 129 return state.onMutation(mutations, observer); |
124 } | 130 } |
125 | 131 |
126 void onSelectionChange(Event event) => state.onSelectionChange(event); | 132 void onSelectionChange(Event event) => state.onSelectionChange(event); |
127 | 133 |
128 void onCompilationUnitChanged(CompilationUnit unit) { | 134 void onCompilationUnitChanged(CompilationUnit unit) { |
129 return state.onCompilationUnitChanged(unit); | 135 return state.onCompilationUnitChanged(unit); |
130 } | 136 } |
131 | 137 |
132 Future<List<String>> projectFileNames() => state.projectFileNames(); | 138 Future<List<String>> projectFileNames() => state.projectFileNames(); |
133 | 139 |
134 void onProjectFileSelected(String projectFile) { | 140 void onProjectFileSelected(String projectFile) { |
135 return state.onProjectFileSelected(projectFile); | 141 return state.onProjectFileSelected(projectFile); |
136 } | 142 } |
| 143 |
| 144 void onProjectFileFsEvent(MessageEvent e) { |
| 145 return state.onProjectFileFsEvent(e); |
| 146 } |
137 } | 147 } |
138 | 148 |
139 abstract class InteractionState implements InteractionManager { | 149 abstract class InteractionState implements InteractionManager { |
140 InteractionContext get context; | 150 InteractionContext get context; |
141 | 151 |
142 void set state(InteractionState newState); | 152 void set state(InteractionState newState); |
143 | 153 |
144 void onStateChanged(InteractionState previous) { | 154 void onStateChanged(InteractionState previous) { |
145 print('State change ${previous.runtimeType} -> ${runtimeType}.'); | 155 print('State change ${previous.runtimeType} -> ${runtimeType}.'); |
146 } | 156 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 if (context.projectFiles.containsKey(unit.name)) { | 312 if (context.projectFiles.containsKey(unit.name)) { |
303 postProjectFileUpdate(unit); | 313 postProjectFileUpdate(unit); |
304 } | 314 } |
305 scheduleCompilation(); | 315 scheduleCompilation(); |
306 } else { | 316 } else { |
307 print("Unexpected change to compilation unit '${unit.name}'."); | 317 print("Unexpected change to compilation unit '${unit.name}'."); |
308 } | 318 } |
309 } | 319 } |
310 | 320 |
311 void postProjectFileUpdate(CompilationUnit unit) { | 321 void postProjectFileUpdate(CompilationUnit unit) { |
| 322 context.lastSaved = unit; |
312 onError(ProgressEvent event) { | 323 onError(ProgressEvent event) { |
313 HttpRequest request = event.target; | 324 HttpRequest request = event.target; |
314 window.alert("Couldn't save '${unit.name}': ${request.responseText}"); | 325 statusDiv.text = "Couldn't save '${unit.name}': ${request.responseText}"; |
| 326 context.lastSaved = null; |
315 } | 327 } |
316 new HttpRequest() | 328 new HttpRequest() |
317 ..open("POST", "/project/${unit.name}") | 329 ..open("POST", "/project/${unit.name}") |
318 ..onError.listen(onError) | 330 ..onError.listen(onError) |
319 ..send(unit.content); | 331 ..send(unit.content); |
320 } | 332 } |
321 | 333 |
322 Future<List<String>> projectFileNames() { | 334 Future<List<String>> projectFileNames() { |
323 return getString('project?list').then((String response) { | 335 return getString('project?list').then((String response) { |
324 WebSocket socket = new WebSocket('ws://127.0.0.1:9090/ws/watch'); | 336 WebSocket socket = new WebSocket('ws://127.0.0.1:9090/ws/watch'); |
325 socket.onMessage.listen((MessageEvent e) { | 337 socket.onMessage.listen(context.onProjectFileFsEvent); |
326 print(e.data); | |
327 }); | |
328 return new List<String>.from(JSON.decode(response)); | 338 return new List<String>.from(JSON.decode(response)); |
329 }); | 339 }); |
330 } | 340 } |
331 | 341 |
332 void onProjectFileSelected(String projectFile) { | 342 void onProjectFileSelected(String projectFile) { |
333 // Disable editing whilst fetching data. | 343 // Disable editing whilst fetching data. |
334 mainEditorPane.contentEditable = 'false'; | 344 mainEditorPane.contentEditable = 'false'; |
335 | 345 |
336 CompilationUnit unit = context.projectFiles[projectFile]; | 346 CompilationUnit unit = context.projectFiles[projectFile]; |
337 Future<CompilationUnit> future; | 347 Future<CompilationUnit> future; |
(...skipping 26 matching lines...) Expand all Loading... |
364 | 374 |
365 transitionToInitialState(); | 375 transitionToInitialState(); |
366 context.currentCompilationUnit = unit; | 376 context.currentCompilationUnit = unit; |
367 | 377 |
368 // Install the code, which will trigger a call to onMutation. | 378 // Install the code, which will trigger a call to onMutation. |
369 mainEditorPane.appendText(unit.content); | 379 mainEditorPane.appendText(unit.content); |
370 }); | 380 }); |
371 } | 381 } |
372 | 382 |
373 void transitionToInitialState() {} | 383 void transitionToInitialState() {} |
| 384 |
| 385 void onProjectFileFsEvent(MessageEvent e) { |
| 386 Map map = JSON.decode(e.data); |
| 387 List modified = map['modify']; |
| 388 if (modified == null) return; |
| 389 for (String name in modified) { |
| 390 if (context.lastSaved != null && context.lastSaved.name == name) { |
| 391 context.lastSaved = null; |
| 392 continue; |
| 393 } |
| 394 if (context.currentCompilationUnit.name == name) { |
| 395 mainEditorPane.contentEditable = false; |
| 396 statusDiv.text = 'Modified on disk'; |
| 397 } |
| 398 } |
| 399 } |
374 } | 400 } |
375 | 401 |
376 Future<String> getString(uri) { | 402 Future<String> getString(uri) { |
377 return new Future<String>.sync(() => HttpRequest.getString('$uri')); | 403 return new Future<String>.sync(() => HttpRequest.getString('$uri')); |
378 } | 404 } |
379 | 405 |
380 class PendingInputState extends InitialState { | 406 class PendingInputState extends InitialState { |
381 PendingInputState(InteractionContext context) | 407 PendingInputState(InteractionContext context) |
382 : super(context); | 408 : super(context); |
383 | 409 |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 event.getModifierState("Fn") || | 704 event.getModifierState("Fn") || |
679 event.getModifierState("Meta") || | 705 event.getModifierState("Meta") || |
680 event.getModifierState("NumLock") || | 706 event.getModifierState("NumLock") || |
681 event.getModifierState("ScrollLock") || | 707 event.getModifierState("ScrollLock") || |
682 event.getModifierState("Scroll") || | 708 event.getModifierState("Scroll") || |
683 event.getModifierState("Win") || | 709 event.getModifierState("Win") || |
684 event.getModifierState("Shift") || | 710 event.getModifierState("Shift") || |
685 event.getModifierState("SymbolLock") || | 711 event.getModifierState("SymbolLock") || |
686 event.getModifierState("OS"); | 712 event.getModifierState("OS"); |
687 } | 713 } |
OLD | NEW |