| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.ui; | 5 library trydart.ui; |
| 6 | 6 |
| 7 import 'dart:html'; | 7 import 'dart:html'; |
| 8 | 8 |
| 9 import 'dart:async' show | 9 import 'dart:async' show |
| 10 Future, | 10 Future, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 import 'settings.dart'; | 36 import 'settings.dart'; |
| 37 | 37 |
| 38 import 'user_option.dart'; | 38 import 'user_option.dart'; |
| 39 | 39 |
| 40 import 'messages.dart' show messages; | 40 import 'messages.dart' show messages; |
| 41 | 41 |
| 42 // TODO(ahe): Make internal to buildUI once all interactions have been moved to | 42 // TODO(ahe): Make internal to buildUI once all interactions have been moved to |
| 43 // the manager. | 43 // the manager. |
| 44 InteractionManager interaction; | 44 InteractionManager interaction; |
| 45 | 45 |
| 46 DivElement inputPre; | 46 DivElement mainEditorPane; |
| 47 PreElement outputDiv; | 47 PreElement outputDiv; |
| 48 DivElement hackDiv; | 48 DivElement hackDiv; |
| 49 IFrameElement outputFrame; | 49 IFrameElement outputFrame; |
| 50 MutationObserver observer; | 50 MutationObserver observer; |
| 51 SpanElement cacheStatusElement; | 51 SpanElement cacheStatusElement; |
| 52 Theme currentTheme = Theme.named(theme); | 52 Theme currentTheme = Theme.named(theme); |
| 53 | 53 |
| 54 buildButton(message, action) { | 54 buildButton(message, action) { |
| 55 if (message is String) { | 55 if (message is String) { |
| 56 message = new Text(message); | 56 message = new Text(message); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 outputFrame.style.display = 'none'; | 89 outputFrame.style.display = 'none'; |
| 90 } | 90 } |
| 91 | 91 |
| 92 buildUI() { | 92 buildUI() { |
| 93 interaction = new InteractionManager(); | 93 interaction = new InteractionManager(); |
| 94 | 94 |
| 95 window.localStorage['currentSample'] = '$currentSample'; | 95 window.localStorage['currentSample'] = '$currentSample'; |
| 96 | 96 |
| 97 buildCode(interaction); | 97 buildCode(interaction); |
| 98 | 98 |
| 99 (inputPre = new DivElement()) | 99 (mainEditorPane = new DivElement()) |
| 100 ..classes.add('well') | 100 ..classes.add('well') |
| 101 ..style.backgroundColor = currentTheme.background.color | 101 ..style.backgroundColor = currentTheme.background.color |
| 102 ..style.color = currentTheme.foreground.color | 102 ..style.color = currentTheme.foreground.color |
| 103 ..style.overflow = 'visible' | 103 ..style.overflow = 'visible' |
| 104 ..style.whiteSpace = 'pre' | 104 ..style.whiteSpace = 'pre' |
| 105 ..style.font = codeFont | 105 ..style.font = codeFont |
| 106 ..spellcheck = false; | 106 ..spellcheck = false; |
| 107 | 107 |
| 108 inputPre | 108 mainEditorPane |
| 109 ..contentEditable = 'true' | 109 ..contentEditable = 'true' |
| 110 ..onKeyDown.listen(interaction.onKeyUp) | 110 ..onKeyDown.listen(interaction.onKeyUp) |
| 111 ..onInput.listen(interaction.onInput); | 111 ..onInput.listen(interaction.onInput); |
| 112 | 112 |
| 113 document.onSelectionChange.listen(interaction.onSelectionChange); | 113 document.onSelectionChange.listen(interaction.onSelectionChange); |
| 114 | 114 |
| 115 var inputWrapper = new DivElement() | 115 var inputWrapper = new DivElement() |
| 116 ..append(inputPre) | 116 ..append(mainEditorPane) |
| 117 ..style.position = 'relative'; | 117 ..style.position = 'relative'; |
| 118 | 118 |
| 119 var inputHeader = new DivElement()..appendText('Code'); | 119 var inputHeader = new DivElement()..appendText('Code'); |
| 120 | 120 |
| 121 inputHeader.style | 121 inputHeader.style |
| 122 ..right = '3px' | 122 ..right = '3px' |
| 123 ..top = '0px' | 123 ..top = '0px' |
| 124 ..position = 'absolute'; | 124 ..position = 'absolute'; |
| 125 inputWrapper.append(inputHeader); | 125 inputWrapper.append(inputHeader); |
| 126 | 126 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 147 ..right = '3px' | 147 ..right = '3px' |
| 148 ..top = '0px' | 148 ..top = '0px' |
| 149 ..position = 'absolute'; | 149 ..position = 'absolute'; |
| 150 outputWrapper.append(consoleHeader); | 150 outputWrapper.append(consoleHeader); |
| 151 | 151 |
| 152 hackDiv = new DivElement(); | 152 hackDiv = new DivElement(); |
| 153 | 153 |
| 154 var saveButton = new ButtonElement() | 154 var saveButton = new ButtonElement() |
| 155 ..onClick.listen((_) { | 155 ..onClick.listen((_) { |
| 156 var blobUrl = | 156 var blobUrl = |
| 157 Url.createObjectUrl(new Blob([inputPre.text], 'text/plain')); | 157 Url.createObjectUrl(new Blob([mainEditorPane.text], 'text/plain')); |
| 158 var save = new AnchorElement(href: blobUrl); | 158 var save = new AnchorElement(href: blobUrl); |
| 159 save.target = '_blank'; | 159 save.target = '_blank'; |
| 160 save.download = 'untitled.dart'; | 160 save.download = 'untitled.dart'; |
| 161 save.dispatchEvent(new Event.eventType('Event', 'click')); | 161 save.dispatchEvent(new Event.eventType('Event', 'click')); |
| 162 }) | 162 }) |
| 163 ..style.position = 'absolute' | 163 ..style.position = 'absolute' |
| 164 ..style.right = '0px' | 164 ..style.right = '0px' |
| 165 ..appendText('Save'); | 165 ..appendText('Save'); |
| 166 | 166 |
| 167 cacheStatusElement = document.getElementById('appcache-status'); | 167 cacheStatusElement = document.getElementById('appcache-status'); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 197 outputFrame.style.height = '${scrollHeight}px'; | 197 outputFrame.style.height = '${scrollHeight}px'; |
| 198 } | 198 } |
| 199 return; | 199 return; |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 outputDiv.appendText('${event.data}\n'); | 203 outputDiv.appendText('${event.data}\n'); |
| 204 }); | 204 }); |
| 205 | 205 |
| 206 observer = new MutationObserver(interaction.onMutation) | 206 observer = new MutationObserver(interaction.onMutation) |
| 207 ..observe(inputPre, childList: true, characterData: true, subtree: true); | 207 ..observe( |
| 208 mainEditorPane, childList: true, characterData: true, subtree: true); |
| 208 | 209 |
| 209 scheduleMicrotask(() { | 210 scheduleMicrotask(() { |
| 210 inputPre.appendText(window.localStorage['currentSource']); | 211 mainEditorPane.appendText(window.localStorage['currentSource']); |
| 211 }); | 212 }); |
| 212 | 213 |
| 213 // You cannot install event handlers on window.applicationCache | 214 // You cannot install event handlers on window.applicationCache |
| 214 // until the window has loaded. In dartium, that's later than this | 215 // until the window has loaded. In dartium, that's later than this |
| 215 // method is called. | 216 // method is called. |
| 216 window.onLoad.listen(onLoad); | 217 window.onLoad.listen(onLoad); |
| 217 | 218 |
| 218 // However, in dart2js, the window has already loaded, and onLoad is | 219 // However, in dart2js, the window has already loaded, and onLoad is |
| 219 // never called. | 220 // never called. |
| 220 onLoad(null); | 221 onLoad(null); |
| 221 } | 222 } |
| 222 | 223 |
| 223 buildCode(InteractionManager interaction) { | 224 buildCode(InteractionManager interaction) { |
| 224 var codePicker = | 225 var codePicker = |
| 225 document.getElementById('code-picker') | 226 document.getElementById('code-picker') |
| 226 ..style.visibility = 'hidden' | 227 ..style.visibility = 'hidden' |
| 227 ..onChange.listen(onCodeChange); | 228 ..onChange.listen(onCodeChange); |
| 228 var htmlGroup = new OptGroupElement()..label = 'HTML'; | 229 var htmlGroup = new OptGroupElement()..label = 'HTML'; |
| 229 var benchmarkGroup = new OptGroupElement()..label = 'Benchmarks'; | 230 var benchmarkGroup = new OptGroupElement()..label = 'Benchmarks'; |
| 230 | 231 |
| 231 new Future(() => HttpRequest.getString('project?list').then( | 232 new Future(() => HttpRequest.getString('project?list').then( |
| 232 (String response) { | 233 (String response) { |
| 233 OptionElement none = new OptionElement() | 234 OptionElement none = new OptionElement() |
| 234 ..appendText('--') | 235 ..appendText('--') |
| 235 ..disabled = true; | 236 ..disabled = true; |
| 236 codePicker.append(none); | 237 codePicker.append(none); |
| 237 for (String projectFile in JSON.decode(response)) { | 238 for (String projectFile in JSON.decode(response)) { |
| 238 codePicker.append(buildTab(projectFile, projectFile, (_) { | 239 codePicker.append(buildTab(projectFile, projectFile, (_) { |
| 239 inputPre.contentEditable = 'false'; | 240 mainEditorPane.contentEditable = 'false'; |
| 240 HttpRequest.getString('project/$projectFile').then((String text) { | 241 HttpRequest.getString('project/$projectFile').then((String text) { |
| 241 inputPre | 242 mainEditorPane |
| 242 ..contentEditable = 'true' | 243 ..contentEditable = 'true' |
| 243 ..nodes.clear(); | 244 ..nodes.clear(); |
| 244 observer.takeRecords(); | 245 observer.takeRecords(); |
| 245 inputPre.appendText(text); | 246 mainEditorPane.appendText(text); |
| 246 }); | 247 }); |
| 247 })); | 248 })); |
| 248 } | 249 } |
| 249 codePicker.style.visibility = 'visible'; | 250 codePicker.style.visibility = 'visible'; |
| 250 codePicker.selectedIndex = 0; | 251 codePicker.selectedIndex = 0; |
| 251 })).catchError((error) { | 252 })).catchError((error) { |
| 252 codePicker.style.visibility = 'visible'; | 253 codePicker.style.visibility = 'visible'; |
| 253 print(error); | 254 print(error); |
| 254 OptionElement none = new OptionElement() | 255 OptionElement none = new OptionElement() |
| 255 ..appendText('Pick an example') | 256 ..appendText('Pick an example') |
| 256 ..disabled = true; | 257 ..disabled = true; |
| 257 codePicker.append(none); | 258 codePicker.append(none); |
| 258 | 259 |
| 259 // codePicker.classes.addAll(['nav', 'nav-tabs']); | 260 // codePicker.classes.addAll(['nav', 'nav-tabs']); |
| 260 codePicker.append(buildTab('Hello, World!', 'EXAMPLE_HELLO', (_) { | 261 codePicker.append(buildTab('Hello, World!', 'EXAMPLE_HELLO', (_) { |
| 261 inputPre | 262 mainEditorPane |
| 262 ..nodes.clear() | 263 ..nodes.clear() |
| 263 ..appendText(EXAMPLE_HELLO); | 264 ..appendText(EXAMPLE_HELLO); |
| 264 })); | 265 })); |
| 265 codePicker.append(buildTab('Fibonacci', 'EXAMPLE_FIBONACCI', (_) { | 266 codePicker.append(buildTab('Fibonacci', 'EXAMPLE_FIBONACCI', (_) { |
| 266 inputPre | 267 mainEditorPane |
| 267 ..nodes.clear() | 268 ..nodes.clear() |
| 268 ..appendText(EXAMPLE_FIBONACCI); | 269 ..appendText(EXAMPLE_FIBONACCI); |
| 269 })); | 270 })); |
| 270 codePicker.append(htmlGroup); | 271 codePicker.append(htmlGroup); |
| 271 // TODO(ahe): Restore benchmarks. | 272 // TODO(ahe): Restore benchmarks. |
| 272 // codePicker.append(benchmarkGroup); | 273 // codePicker.append(benchmarkGroup); |
| 273 | 274 |
| 274 htmlGroup.append( | 275 htmlGroup.append( |
| 275 buildTab('Hello, World!', 'EXAMPLE_HELLO_HTML', (_) { | 276 buildTab('Hello, World!', 'EXAMPLE_HELLO_HTML', (_) { |
| 276 inputPre | 277 mainEditorPane |
| 277 ..nodes.clear() | 278 ..nodes.clear() |
| 278 ..appendText(EXAMPLE_HELLO_HTML); | 279 ..appendText(EXAMPLE_HELLO_HTML); |
| 279 })); | 280 })); |
| 280 htmlGroup.append( | 281 htmlGroup.append( |
| 281 buildTab('Fibonacci', 'EXAMPLE_FIBONACCI_HTML', (_) { | 282 buildTab('Fibonacci', 'EXAMPLE_FIBONACCI_HTML', (_) { |
| 282 inputPre | 283 mainEditorPane |
| 283 ..nodes.clear() | 284 ..nodes.clear() |
| 284 ..appendText(EXAMPLE_FIBONACCI_HTML); | 285 ..appendText(EXAMPLE_FIBONACCI_HTML); |
| 285 })); | 286 })); |
| 286 htmlGroup.append(buildTab('Sunflower', 'EXAMPLE_SUNFLOWER', (_) { | 287 htmlGroup.append(buildTab('Sunflower', 'EXAMPLE_SUNFLOWER', (_) { |
| 287 inputPre | 288 mainEditorPane |
| 288 ..nodes.clear() | 289 ..nodes.clear() |
| 289 ..appendText(EXAMPLE_SUNFLOWER); | 290 ..appendText(EXAMPLE_SUNFLOWER); |
| 290 })); | 291 })); |
| 291 | 292 |
| 292 benchmarkGroup.append(buildTab('DeltaBlue', 'BENCHMARK_DELTA_BLUE', (_) { | 293 benchmarkGroup.append(buildTab('DeltaBlue', 'BENCHMARK_DELTA_BLUE', (_) { |
| 293 inputPre.contentEditable = 'false'; | 294 mainEditorPane.contentEditable = 'false'; |
| 294 LinkElement link = querySelector('link[rel="benchmark-DeltaBlue"]'); | 295 LinkElement link = querySelector('link[rel="benchmark-DeltaBlue"]'); |
| 295 String deltaBlueUri = link.href; | 296 String deltaBlueUri = link.href; |
| 296 link = querySelector('link[rel="benchmark-base"]'); | 297 link = querySelector('link[rel="benchmark-base"]'); |
| 297 String benchmarkBaseUri = link.href; | 298 String benchmarkBaseUri = link.href; |
| 298 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { | 299 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { |
| 299 HttpRequest.getString(deltaBlueUri).then((String deltaBlue) { | 300 HttpRequest.getString(deltaBlueUri).then((String deltaBlue) { |
| 300 benchmarkBase = benchmarkBase.replaceFirst( | 301 benchmarkBase = benchmarkBase.replaceFirst( |
| 301 'part of benchmark_harness;', '// part of benchmark_harness;'); | 302 'part of benchmark_harness;', '// part of benchmark_harness;'); |
| 302 deltaBlue = deltaBlue.replaceFirst( | 303 deltaBlue = deltaBlue.replaceFirst( |
| 303 "import 'package:benchmark_harness/benchmark_harness.dart';", | 304 "import 'package:benchmark_harness/benchmark_harness.dart';", |
| 304 benchmarkBase); | 305 benchmarkBase); |
| 305 inputPre | 306 mainEditorPane |
| 306 ..nodes.clear() | 307 ..nodes.clear() |
| 307 ..appendText(deltaBlue) | 308 ..appendText(deltaBlue) |
| 308 ..contentEditable = 'true'; | 309 ..contentEditable = 'true'; |
| 309 }); | 310 }); |
| 310 }); | 311 }); |
| 311 })); | 312 })); |
| 312 | 313 |
| 313 benchmarkGroup.append(buildTab('Richards', 'BENCHMARK_RICHARDS', (_) { | 314 benchmarkGroup.append(buildTab('Richards', 'BENCHMARK_RICHARDS', (_) { |
| 314 inputPre.contentEditable = 'false'; | 315 mainEditorPane.contentEditable = 'false'; |
| 315 LinkElement link = querySelector('link[rel="benchmark-Richards"]'); | 316 LinkElement link = querySelector('link[rel="benchmark-Richards"]'); |
| 316 String richardsUri = link.href; | 317 String richardsUri = link.href; |
| 317 link = querySelector('link[rel="benchmark-base"]'); | 318 link = querySelector('link[rel="benchmark-base"]'); |
| 318 String benchmarkBaseUri = link.href; | 319 String benchmarkBaseUri = link.href; |
| 319 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { | 320 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { |
| 320 HttpRequest.getString(richardsUri).then((String richards) { | 321 HttpRequest.getString(richardsUri).then((String richards) { |
| 321 benchmarkBase = benchmarkBase.replaceFirst( | 322 benchmarkBase = benchmarkBase.replaceFirst( |
| 322 'part of benchmark_harness;', '// part of benchmark_harness;'); | 323 'part of benchmark_harness;', '// part of benchmark_harness;'); |
| 323 richards = richards.replaceFirst( | 324 richards = richards.replaceFirst( |
| 324 "import 'package:benchmark_harness/benchmark_harness.dart';", | 325 "import 'package:benchmark_harness/benchmark_harness.dart';", |
| 325 benchmarkBase); | 326 benchmarkBase); |
| 326 inputPre | 327 mainEditorPane |
| 327 ..nodes.clear() | 328 ..nodes.clear() |
| 328 ..appendText(richards) | 329 ..appendText(richards) |
| 329 ..contentEditable = 'true'; | 330 ..contentEditable = 'true'; |
| 330 }); | 331 }); |
| 331 }); | 332 }); |
| 332 })); | 333 })); |
| 333 | 334 |
| 334 codePicker.selectedIndex = 0; | 335 codePicker.selectedIndex = 0; |
| 335 }); | 336 }); |
| 336 } | 337 } |
| 337 | 338 |
| 338 num settingsHeight = 0; | 339 num settingsHeight = 0; |
| 339 | 340 |
| 340 void openSettings(MouseEvent event) { | 341 void openSettings(MouseEvent event) { |
| 341 event.preventDefault(); | 342 event.preventDefault(); |
| 342 | 343 |
| 343 if (settingsHeight != 0) { | 344 if (settingsHeight != 0) { |
| 344 var dialog = document.getElementById('settings-dialog'); | 345 var dialog = document.getElementById('settings-dialog'); |
| 345 if (dialog.getBoundingClientRect().height > 0) { | 346 if (dialog.getBoundingClientRect().height > 0) { |
| 346 dialog.style.height = '0px'; | 347 dialog.style.height = '0px'; |
| 347 } else { | 348 } else { |
| 348 dialog.style.height = '${settingsHeight}px'; | 349 dialog.style.height = '${settingsHeight}px'; |
| 349 } | 350 } |
| 350 return; | 351 return; |
| 351 } | 352 } |
| 352 | 353 |
| 353 void updateCodeFont(Event e) { | 354 void updateCodeFont(Event e) { |
| 354 TextInputElement target = e.target; | 355 TextInputElement target = e.target; |
| 355 codeFont = target.value; | 356 codeFont = target.value; |
| 356 inputPre.style.font = codeFont; | 357 mainEditorPane.style.font = codeFont; |
| 357 } | 358 } |
| 358 | 359 |
| 359 void updateTheme(Event e) { | 360 void updateTheme(Event e) { |
| 360 var select = e.target; | 361 var select = e.target; |
| 361 String theme = select.queryAll('option')[select.selectedIndex].text; | 362 String theme = select.queryAll('option')[select.selectedIndex].text; |
| 362 window.localStorage['theme'] = theme; | 363 window.localStorage['theme'] = theme; |
| 363 currentTheme = Theme.named(theme); | 364 currentTheme = Theme.named(theme); |
| 364 | 365 |
| 365 inputPre.style | 366 mainEditorPane.style |
| 366 ..backgroundColor = currentTheme.background.color | 367 ..backgroundColor = currentTheme.background.color |
| 367 ..color = currentTheme.foreground.color; | 368 ..color = currentTheme.foreground.color; |
| 368 | 369 |
| 369 outputDiv.style | 370 outputDiv.style |
| 370 ..backgroundColor = currentTheme.background.color | 371 ..backgroundColor = currentTheme.background.color |
| 371 ..color = currentTheme.foreground.color; | 372 ..color = currentTheme.foreground.color; |
| 372 | 373 |
| 373 bool oldCompilationPaused = compilationPaused; | 374 bool oldCompilationPaused = compilationPaused; |
| 374 compilationPaused = true; | 375 compilationPaused = true; |
| 375 interaction.onMutation([], observer); | 376 interaction.onMutation([], observer); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 window.localStorage['compilationPaused'] = '$compilationPaused'; | 476 window.localStorage['compilationPaused'] = '$compilationPaused'; |
| 476 window.localStorage['codeFont'] = '$codeFont'; | 477 window.localStorage['codeFont'] = '$codeFont'; |
| 477 | 478 |
| 478 dialog.style.height = '0px'; | 479 dialog.style.height = '0px'; |
| 479 } | 480 } |
| 480 form.onSubmit.listen(onSubmit); | 481 form.onSubmit.listen(onSubmit); |
| 481 | 482 |
| 482 var doneButton = document.getElementById('settings-done'); | 483 var doneButton = document.getElementById('settings-done'); |
| 483 doneButton.onClick.listen(onSubmit); | 484 doneButton.onClick.listen(onSubmit); |
| 484 } | 485 } |
| OLD | NEW |