mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Start making input work
Does not work yet. R=ianh@google.com Review URL: https://codereview.chromium.org/1163973005
This commit is contained in:
parent
4674ab6ff8
commit
ca3b643ca9
@ -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) {
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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()
|
||||
|
||||
122
sdk/lib/framework/editing2/editable_string.dart
Normal file
122
sdk/lib/framework/editing2/editable_string.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
99
sdk/lib/framework/editing2/editable_text.dart
Normal file
99
sdk/lib/framework/editing2/editable_text.dart
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
20
sdk/lib/framework/editing2/keyboard.dart
Normal file
20
sdk/lib/framework/editing2/keyboard.dart
Normal 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;
|
||||
Loading…
x
Reference in New Issue
Block a user