Commit 94d55d40 authored by Viet-Trung Luu's avatar Viet-Trung Luu

A crappy "netcat"-type example (in Dart).

It's especially crappy since it doesn't actually do much/any error
handling.

Use:
$ sky/tools/skydb start out/Debug \
  'sky/examples/terminal/index.sky?url=mojo:netcat?host=localhost%26port=80'

(Note: We don't have a resolver yet, so the host either has to be
"localhost" or an IPv4 address in the form N1.N2.N3.N4.)

R=erg@chromium.org

Review URL: https://codereview.chromium.org/1032743002
parent 0593b9f8
...@@ -4,22 +4,43 @@ ...@@ -4,22 +4,43 @@
// found in the LICENSE file. // found in the LICENSE file.
--> -->
<import src="/sky/framework/elements/sky-element.sky" /> <import src="/sky/framework/elements/sky-element.sky" />
<import src="/sky/framework/elements/sky-scrollable.sky" />
<sky-element> <sky-element>
<template> <template>
<style> <style>
#control { #container {
height: -webkit-fill-available; 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; background-color: black;
color: rgb(255, 191, 0); color: rgb(255, 191, 0);
font-family: 'Courier', 'monospace'; font-family: 'Courier', 'monospace';
font-size: small; font-size: small;
} }
.line { .line {
height: 1em;
white-space: nowrap; white-space: nowrap;
} }
</style> </style>
<sky-scrollable id="control" contenteditable /> <div id="container">
<div id="input-box" contenteditable />
<div id="output-box" />
</div>
</div>
</template> </template>
<script> <script>
import 'dart:async'; import 'dart:async';
...@@ -35,7 +56,9 @@ import 'terminal_file_impl.dart'; ...@@ -35,7 +56,9 @@ import 'terminal_file_impl.dart';
// |terminal.TerminalClient| service. // |terminal.TerminalClient| service.
@Tagname('terminal') @Tagname('terminal')
class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { class TerminalDisplayImpl extends SkyElement implements TerminalDisplay {
Element _control; Element _inputBox;
Element _outputBox;
int _maxLines;
// Queue of unconsumed input (keystrokes), with the head at index 0. // Queue of unconsumed input (keystrokes), with the head at index 0.
// Keystrokes end up here if there's no reader (i.e., |getChar()|) pending, // Keystrokes end up here if there's no reader (i.e., |getChar()|) pending,
...@@ -54,13 +77,22 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { ...@@ -54,13 +77,22 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay {
} }
void shadowRootReady() { void shadowRootReady() {
_control = shadowRoot.getElementById('control'); _inputBox = shadowRoot.getElementById('input-box');
_control.addEventListener('keydown', _handleKeyDown); _inputBox.addEventListener('keydown', _handleKeyDown);
_control.addEventListener('keypress', _handleKeyPress); _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. // Initialize with the first line.
_newLine(); _newLine();
// Actually compute the maximum number of lines.
// TODO(vtl): Recompute on resize.
_maxLines = _outputBox.clientHeight ~/ _outputBox.firstChild.offsetHeight;
var url = getAttribute('url'); var url = getAttribute('url');
if (url != null) { if (url != null) {
connect(url); connect(url);
...@@ -81,10 +113,16 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { ...@@ -81,10 +113,16 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay {
} }
void _handleKeyPress(KeyboardEvent event) { void _handleKeyPress(KeyboardEvent event) {
if (event.charCode != 0) {
_enqueueChar(event.charCode); _enqueueChar(event.charCode);
}
event.preventDefault(); event.preventDefault();
} }
void _handleWheel(WheelEvent event) {
_outputBox.dispatchEvent(event);
}
void _enqueueChar(int charCode) { void _enqueueChar(int charCode) {
// TODO(vtl): Add "echo" mode; do |putChar(event.charCode);| if echo is on. // TODO(vtl): Add "echo" mode; do |putChar(event.charCode);| if echo is on.
...@@ -96,22 +134,28 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { ...@@ -96,22 +134,28 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay {
} }
void _backspace() { void _backspace() {
var oldText = _control.lastChild.textContent; var oldText = _outputBox.lastChild.textContent;
if (oldText.length > 0) { if (oldText.length > 0) {
_control.lastChild.textContent = oldText.substring(0, oldText.length - 1); _outputBox.lastChild.textContent = oldText.substring(0,
oldText.length - 1);
} }
} }
void _newLine() { void _newLine() {
var line = document.createElement('div'); var line = document.createElement('div');
line.setAttribute('class', 'line'); line.setAttribute('class', 'line');
_control.appendChild(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() { void _clear() {
while (_control.firstChild != null) { _outputBox.setChildren([]);
_control.firstChild.remove();
}
_newLine(); _newLine();
} }
...@@ -134,7 +178,7 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { ...@@ -134,7 +178,7 @@ class TerminalDisplayImpl extends SkyElement implements TerminalDisplay {
void putChar(int byte) { void putChar(int byte) {
// Fast-path for printable chars. // Fast-path for printable chars.
if (byte >= 32) { if (byte >= 32) {
_control.lastChild.textContent += new String.fromCharCode(byte); _outputBox.lastChild.textContent += new String.fromCharCode(byte);
return; return;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment