Index: sky/examples/terminal/terminal.sky |
diff --git a/sky/examples/terminal/terminal.sky b/sky/examples/terminal/terminal.sky |
deleted file mode 100644 |
index 246bdfccf682fda7ea82dc69f6b9f64be64521de..0000000000000000000000000000000000000000 |
--- a/sky/examples/terminal/terminal.sky |
+++ /dev/null |
@@ -1,218 +0,0 @@ |
-<!-- |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
---> |
-<import src="/sky/framework/elements/sky-element.sky" /> |
-<sky-element> |
-<template> |
- <style> |
- #container { |
- height: -webkit-fill-available; |
- } |
- #input-box { |
- position: absolute; |
- left: 0; |
- top: 0; |
- z-index: 10; |
- width: 100%; |
- height: 100%; |
- opacity: 0; |
- } |
- #output-box { |
- position: absolute; |
- left: 0; |
- top: 0; |
- z-index: 0; |
- width: 100%; |
- height: 100%; |
- background-color: black; |
- color: rgb(255, 191, 0); |
- font-family: 'Courier', 'monospace'; |
- font-size: small; |
- } |
- .line { |
- height: 1em; |
- white-space: nowrap; |
- } |
- </style> |
- <div id="container"> |
- <div id="input-box" contenteditable /> |
- <div id="output-box" /> |
- </div> |
- </div> |
-</template> |
-<script> |
-import 'dart:async'; |
-import 'dart:core'; |
-import 'dart:sky'; |
-import 'package:mojo/services/terminal/public/interfaces/terminal_client.mojom.dart' as terminal; |
-import 'package:sky/framework/embedder.dart'; |
-import 'terminal_display.dart'; |
-import 'terminal_file_impl.dart'; |
- |
-// Implements the <terminal> element, which implements a "terminal display". Has |
-// an |url| attribute, whose value should be a Mojo app that provides the |
-// |terminal.TerminalClient| service. |
-@Tagname('terminal') |
-class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { |
- Element _inputBox; |
- Element _outputBox; |
- int _maxLines; |
- |
- // Queue of unconsumed input (keystrokes), with the head at index 0. |
- // Keystrokes end up here if there's no reader (i.e., |getChar()|) pending, |
- // i.e., if |_readerQueue| is empty. Invariant: At most one of |_inputQueue| |
- // and |_readerQueue| may be nonempty at any given time. |
- List<int> _inputQueue; |
- |
- // Queue of things waiting for input, with the head at index 0. If a keystroke |
- // is received and this is nonempty, the head is given that keystroke (and |
- // dequeued). |
- List<Completer<int>> _readerQueue; |
- |
- TerminalDisplayImpl() |
- : _inputQueue = new List<int>(), |
- _readerQueue = new List<Completer<int>>() { |
- } |
- |
- void shadowRootReady() { |
- _inputBox = shadowRoot.getElementById('input-box'); |
- _inputBox.addEventListener('keydown', _handleKeyDown); |
- _inputBox.addEventListener('keypress', _handleKeyPress); |
- _inputBox.addEventListener('wheel', _handleWheel); |
- _outputBox = shadowRoot.getElementById('output-box'); |
- |
- // Hack to allow |_newLine()| to work. |
- _maxLines = 100; |
- |
- // Initialize with the first line. |
- _newLine(); |
- |
- // Actually compute the maximum number of lines. |
- // TODO(vtl): Recompute on resize. |
- _maxLines = _outputBox.clientHeight ~/ _outputBox.firstChild.offsetHeight; |
- |
- var url = getAttribute('url'); |
- if (url != null) { |
- connect(url); |
- } |
- } |
- |
- void _handleKeyDown(KeyboardEvent event) { |
- // TODO(vtl): In general, our key handling is a total hack (due in part to |
- // sky's keyboard support being incomplete) -- e.g., we shouldn't have to |
- // make our div contenteditable. We have to intercept backspace (^H) here, |
- // since we won't actually get a keypress event for it. (Possibly, we should |
- // only handle keydown instead of keypress, but then we'd have to handle |
- // shift, etc. ourselves.) |
- if (event.key == 8) { |
- _enqueueChar(8); |
- event.preventDefault(); |
- } |
- } |
- |
- void _handleKeyPress(KeyboardEvent event) { |
- if (event.charCode != 0) { |
- _enqueueChar(event.charCode); |
- } |
- event.preventDefault(); |
- } |
- |
- void _handleWheel(WheelEvent event) { |
- _outputBox.dispatchEvent(event); |
- } |
- |
- void _enqueueChar(int charCode) { |
- // TODO(vtl): Add "echo" mode; do |putChar(event.charCode);| if echo is on. |
- |
- if (_readerQueue.isEmpty) { |
- _inputQueue.add(charCode); |
- } else { |
- _readerQueue.removeAt(0).complete(charCode); |
- } |
- } |
- |
- void _backspace() { |
- var oldText = _outputBox.lastChild.textContent; |
- if (oldText.length > 0) { |
- _outputBox.lastChild.textContent = oldText.substring(0, |
- oldText.length - 1); |
- } |
- } |
- |
- void _newLine() { |
- var line = document.createElement('div'); |
- line.setAttribute('class', 'line'); |
- _outputBox.appendChild(line); |
- |
- // Scroll if necessary. |
- var children = _outputBox.getChildNodes(); |
- if (children.length > _maxLines) { |
- children = new List.from(children.skip(children.length - _maxLines)); |
- _outputBox.setChildren(children); |
- } |
- } |
- |
- void _clear() { |
- _outputBox.setChildren([]); |
- _newLine(); |
- } |
- |
- void connect(String url) { |
- var terminalClient = new terminal.TerminalClientProxy.unbound(); |
- embedder.connectToService(url, terminalClient); |
- terminalClient.ptr.connectToTerminal(new TerminalFileImpl(this).stub); |
- terminalClient.close(); |
- } |
- |
- void putString(String s) { |
- for (var i = 0; i < s.length; i++) { |
- putChar(s.codeUnitAt(i)); |
- } |
- } |
- |
- // |TerminalDisplay| implementation: |
- |
- @override |
- void putChar(int byte) { |
- // Fast-path for printable chars. |
- if (byte >= 32) { |
- _outputBox.lastChild.textContent += new String.fromCharCode(byte); |
- return; |
- } |
- |
- switch (byte) { |
- case 8: // BS (^H). |
- _backspace(); |
- break; |
- case 10: // LF ('\n'). |
- _newLine(); // TODO(vtl): LF and CR should be separated. |
- break; |
- case 12: // FF (^L). |
- _clear(); |
- break; |
- case 13: // CR ('\r'). |
- _newLine(); // TODO(vtl): LF and CR should be separated. |
- break; |
- default: |
- // Should beep or something. |
- break; |
- } |
- } |
- |
- @override |
- Future<int> getChar() async { |
- if (_inputQueue.isNotEmpty) { |
- return new Future.value(_inputQueue.removeAt(0)); |
- } |
- |
- var completer = new Completer<int>(); |
- _readerQueue.add(completer); |
- return completer.future; |
- } |
-} |
- |
-_init(script) => register(script, TerminalDisplayImpl); |
-</script> |
-</sky-element> |