Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: dart/site/try/src/interaction_manager.dart

Issue 224373003: Detect concurrent edits. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dart/site/try/project_server.dart ('k') | dart/site/try/src/ui.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « dart/site/try/project_server.dart ('k') | dart/site/try/src/ui.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698