| 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 |