Start making input work

Does not work yet.

R=ianh@google.com

Review URL: https://codereview.chromium.org/1163973005
This commit is contained in:
Eric Seidel 2015-06-04 15:18:09 -07:00
parent 4674ab6ff8
commit ca3b643ca9
6 changed files with 284 additions and 42 deletions

View File

@ -8,9 +8,9 @@ import 'package:sky/framework/components2/drawer.dart';
// import 'package:sky/framework/components2/floating_action_button.dart';
// import 'package:sky/framework/components2/icon.dart';
import 'package:sky/framework/components2/icon_button.dart';
// import 'package:sky/framework/components2/input.dart';
import 'package:sky/framework/components2/menu_divider.dart';
import 'package:sky/framework/components2/menu_item.dart';
import 'package:sky/framework/components2/input.dart';
// import 'package:sky/framework/components2/modal_overlay.dart';
// import 'package:sky/framework/components2/popup_menu.dart';
// import 'package:sky/framework/components2/radio.dart';
@ -30,9 +30,6 @@ enum StockMode { optimistic, pessimistic }
class StocksApp extends App {
// static final Style _searchBarStyle = new Style('''
// background-color: ${Grey[50]};''');
// static final Style _titleStyle = new Style('''
// ${typography.white.title};''');
@ -179,16 +176,16 @@ class StocksApp extends App {
// TODO(abarth): Should we factor this into a SearchBar in the framework?
UINode buildSearchBar() {
// return new StyleNode(
// new ToolBar(
// left: new IconButton(
// icon: 'navigation/arrow_back_grey600',
// onGestureTap: _handleSearchEnd),
// center: new Input(
// focused: true,
// placeholder: 'Search stocks',
// onChanged: _handleSearchQueryChanged)),
// _searchBarStyle);
return new ToolBar(
left: new IconButton(
icon: 'navigation/arrow_back_grey600',
onGestureTap: _handleSearchEnd),
center: new Input(
focused: true,
placeholder: 'Search stocks',
onChanged: _handleSearchQueryChanged),
backgroundColor: colors.Grey[50]
);
}
void addMenuToOverlays(List<UINode> overlays) {

View File

@ -70,6 +70,9 @@ dart_pkg("sdk") {
"lib/framework/editing/editable_string.dart",
"lib/framework/editing/editable_text.dart",
"lib/framework/editing/keyboard.dart",
"lib/framework/editing2/editable_string.dart",
"lib/framework/editing2/editable_text.dart",
"lib/framework/editing2/keyboard.dart",
"lib/framework/elements/animation/controller.dart",
"lib/framework/elements/animation/timer.dart",
"lib/framework/elements/material-element.sky",

View File

@ -2,38 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../editing/editable_string.dart';
import '../editing/editable_text.dart';
import '../editing/keyboard.dart';
import '../editing2/editable_string.dart';
import '../editing2/editable_text.dart';
import '../editing2/keyboard.dart';
import '../fn2.dart';
import '../theme/colors.dart';
import '../theme/typography.dart' as typography;
import '../theme2/colors.dart';
import '../theme2/typography.dart' as typography;
import '../rendering/flex.dart';
import 'dart:sky' as sky;
typedef void ValueChanged(value);
class Input extends Component {
static final Style _style = new Style('''
transform: translateX(0);
margin: 8px;
padding: 8px;
border-bottom: 1px solid ${Grey[200]};
align-self: center;
height: 1.2em;
white-space: pre;
overflow: hidden;'''
);
// static final Style _style = new Style('''
// transform: translateX(0);
// margin: 8px;
// padding: 8px;
// border-bottom: 1px solid ${Grey[200]};
// align-self: center;
// height: 1.2em;
// white-space: pre;
// overflow: hidden;'''
// );
static final Style _placeholderStyle = new Style('''
top: 8px;
left: 8px;
position: absolute;
${typography.black.caption};'''
);
// static final Style _placeholderStyle = new Style('''
// top: 8px;
// left: 8px;
// position: absolute;
// ${typography.black.caption};'''
// );
static final String _focusedInlineStyle = '''
padding: 7px;
border-bottom: 2px solid ${Blue[500]};''';
// static final String _focusedInlineStyle = '''
// padding: 7px;
// border-bottom: 2px solid ${Blue[500]};''';
ValueChanged onChanged;
String placeholder;
@ -75,8 +76,8 @@ class Input extends Component {
if (placeholder != null && _value.isEmpty) {
children.add(new Container(
style: _placeholderStyle,
children: [new Text(placeholder)]
// style: _placeholderStyle,
child: new Text(placeholder)
));
}
@ -85,8 +86,8 @@ class Input extends Component {
return new EventListenerNode(
new FlexContainer(
direction: FlexDirection.vertical,
style: _style,
inlineStyle: focused ? _focusedInlineStyle : null,
// style: _style,
// inlineStyle: focused ? _focusedInlineStyle : null,
children: children
),
onPointerDown: (sky.Event e) => keyboard.showByRequest()

View File

@ -0,0 +1,122 @@
// 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 'package:mojom/keyboard/keyboard.mojom.dart';
typedef void StringUpdated();
class TextRange {
final int start;
final int end;
TextRange({this.start, this.end});
TextRange.collapsed(int position)
: start = position,
end = position;
const TextRange.empty()
: start = -1,
end = -1;
bool get isValid => start >= 0 && end >= 0;
bool get isCollapsed => start == end;
}
class EditableString implements KeyboardClient {
String text;
TextRange composing = const TextRange.empty();
TextRange selection = const TextRange.empty();
final StringUpdated onUpdated;
KeyboardClientStub stub;
EditableString({this.text: '', this.onUpdated}) {
stub = new KeyboardClientStub.unbound()..impl = this;
}
String textBefore(TextRange range) {
return text.substring(0, range.start);
}
String textAfter(TextRange range) {
return text.substring(range.end);
}
String textInside(TextRange range) {
return text.substring(range.start, range.end);
}
void _delete(TextRange range) {
if (range.isCollapsed || !range.isValid) return;
text = textBefore(range) + textAfter(range);
}
TextRange _append(String newText) {
int start = text.length;
text += newText;
return new TextRange(start: start, end: start + newText.length);
}
TextRange _replace(TextRange range, String newText) {
assert(range.isValid);
String before = textBefore(range);
String after = textAfter(range);
text = before + newText + after;
return new TextRange(
start: before.length, end: before.length + newText.length);
}
TextRange _replaceOrAppend(TextRange range, String newText) {
if (!range.isValid) return _append(newText);
return _replace(range, newText);
}
void commitCompletion(CompletionData completion) {
// TODO(abarth): Not implemented.
}
void commitCorrection(CorrectionData correction) {
// TODO(abarth): Not implemented.
}
void commitText(String text, int newCursorPosition) {
// TODO(abarth): Why is |newCursorPosition| always 1?
TextRange committedRange = _replaceOrAppend(composing, text);
selection = new TextRange.collapsed(committedRange.end);
composing = const TextRange.empty();
onUpdated();
}
void deleteSurroundingText(int beforeLength, int afterLength) {
TextRange beforeRange = new TextRange(
start: selection.start - beforeLength, end: selection.start);
TextRange afterRange =
new TextRange(start: selection.end, end: selection.end + afterLength);
_delete(afterRange);
_delete(beforeRange);
selection = new TextRange(
start: selection.start - beforeLength,
end: selection.end - beforeLength);
onUpdated();
}
void setComposingRegion(int start, int end) {
composing = new TextRange(start: start, end: end);
onUpdated();
}
void setComposingText(String text, int newCursorPosition) {
// TODO(abarth): Why is |newCursorPosition| always 1?
composing = _replaceOrAppend(composing, text);
selection = new TextRange.collapsed(composing.end);
onUpdated();
}
void setSelection(int start, int end) {
selection = new TextRange(start: start, end: end);
onUpdated();
}
}

View File

@ -0,0 +1,99 @@
// 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 '../fn2.dart';
import '../theme/colors.dart';
import 'dart:async';
import 'editable_string.dart';
class EditableText extends Component {
// static final Style _cursorStyle = new Style('''
// width: 2px;
// height: 1.2em;
// vertical-align: top;
// background-color: ${Blue[500]};'''
// );
// static final Style _composingStyle = new Style('''
// text-decoration: underline;'''
// );
EditableString value;
bool focused;
Timer _cursorTimer;
bool _showCursor = false;
EditableText({Object key, this.value, this.focused})
: super(key: key, stateful: true) {
onDidUnmount(() {
if (_cursorTimer != null)
_stopCursorTimer();
});
}
void _cursorTick(Timer timer) {
setState(() {
_showCursor = !_showCursor;
});
}
void _startCursorTimer() {
_showCursor = true;
_cursorTimer = new Timer.periodic(
new Duration(milliseconds: 500), _cursorTick);
}
void _stopCursorTimer() {
_cursorTimer.cancel();
_cursorTimer = null;
_showCursor = false;
}
UINode build() {
if (focused && _cursorTimer == null)
_startCursorTimer();
else if (!focused && _cursorTimer != null)
_stopCursorTimer();
//List<UINode> children = new List<UINode>();
String hack = "";
if (!value.composing.isValid) {
// children.add(new TextFragment(value.text));
hack += value.text;
} else {
String beforeComposing = value.textBefore(value.composing);
if (!beforeComposing.isEmpty) {
// children.add(new TextFragment(beforeComposing));
hack += value.beforeComposing;
}
String composing = value.textInside(value.composing);
hack += value.composing;
hack += value.afterComposing;
// if (!composing.isEmpty) {
// children.add(new TextFragment(
// composing,
// key: 'composing',
// style: _composingStyle
// ));
// }
// String afterComposing = value.textAfter(value.composing);
// if (!afterComposing.isEmpty)
// children.add(new TextFragment(afterComposing));
}
// if (_showCursor)
// children.add(new Container(
// key: 'cursor',
// // style: _cursorStyle
// ));
return new Paragraph(
text: hack
);
}
}

View File

@ -0,0 +1,20 @@
// 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 '../shell.dart' as shell;
import 'package:mojom/keyboard/keyboard.mojom.dart';
class _KeyboardConnection {
KeyboardServiceProxy proxy;
_KeyboardConnection() {
proxy = new KeyboardServiceProxy.unbound();
shell.requestService("mojo:keyboard", proxy);
}
KeyboardService get keyboard => proxy.ptr;
}
final _KeyboardConnection _connection = new _KeyboardConnection();
final KeyboardService keyboard = _connection.keyboard;