| Index: sky/examples/terminal/terminal.sky
|
| diff --git a/sky/examples/terminal/terminal.sky b/sky/examples/terminal/terminal.sky
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..03d784c25de99624fc7890787a11a88fe18478c0
|
| --- /dev/null
|
| +++ b/sky/examples/terminal/terminal.sky
|
| @@ -0,0 +1,115 @@
|
| +<!--
|
| +// 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/sky-element.sky" />
|
| +<import src="/sky/framework/sky-scrollable.sky" />
|
| +<sky-element>
|
| +<template>
|
| + <style>
|
| + #control {
|
| + height: -webkit-fill-available;
|
| + background-color: black;
|
| + color: rgb(255, 191, 0);
|
| + font-family: 'Courier', 'monospace';
|
| + }
|
| + span {
|
| + white-space: nowrap;
|
| + }
|
| + </style>
|
| + <sky-scrollable id="control" contenteditable />
|
| +</template>
|
| +<script>
|
| +import 'dart:async';
|
| +import 'dart:core';
|
| +import 'dart:sky';
|
| +import 'package:examples/echo_terminal/terminal_client.mojom.dart' as terminal;
|
| +import '/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 _control;
|
| +
|
| + // 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() {
|
| + _control = shadowRoot.getElementById('control');
|
| + _control.addEventListener('keypress', _handleKeyPress);
|
| +
|
| + // Initialize with the first line.
|
| + _newLine();
|
| +
|
| + _connect(getAttribute('url'));
|
| + }
|
| +
|
| + void _handleKeyPress(KeyboardEvent event) {
|
| + // TODO(vtl): Add "echo" mode; do |putChar(event.charCode);| if echo is on.
|
| +
|
| + if (_readerQueue.isEmpty) {
|
| + _inputQueue.add(event.charCode);
|
| + } else {
|
| + _readerQueue.removeAt(0).complete(event.charCode);
|
| + }
|
| +
|
| + event.preventDefault();
|
| + }
|
| +
|
| + void _newLine() {
|
| + _control.appendChild(document.createElement('span'));
|
| + }
|
| +
|
| + // TODO(vtl): Should we always auto-connect? Should there be facilities for
|
| + // programmatically connecting? (What if the |url| attribute isn't set?)
|
| + void _connect(String url) {
|
| + var terminalClient = new terminal.TerminalClientProxy.unbound();
|
| + embedder.connectToService(url, terminalClient);
|
| + terminalClient.ptr.connectToTerminal(new TerminalFileImpl(this).stub);
|
| + terminalClient.close();
|
| + }
|
| +
|
| + // |TerminalDisplay| implementation:
|
| +
|
| + @override
|
| + void putChar(int byte) {
|
| + if (byte == 10 || byte == 13) {
|
| + _newLine();
|
| + return;
|
| + }
|
| + _control.lastChild.textContent += new String.fromCharCode(byte);
|
| + }
|
| +
|
| + @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>
|
|
|