Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
fe77808d
Commit
fe77808d
authored
Sep 25, 2015
by
Adam Barth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Copy Input and EditableText into fn3
parent
b5893f9e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
367 additions
and
0 deletions
+367
-0
editable_text.dart
packages/flutter/lib/src/fn3/editable_text.dart
+236
-0
input.dart
packages/flutter/lib/src/fn3/input.dart
+131
-0
No files found.
packages/flutter/lib/src/fn3/editable_text.dart
0 → 100644
View file @
fe77808d
// 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
'dart:async'
;
import
'dart:sky'
as
sky
;
import
'package:mojo_services/keyboard/keyboard.mojom.dart'
;
import
'package:sky/painting.dart'
;
import
'package:sky/src/widgets/basic.dart'
;
import
'package:sky/src/widgets/framework.dart'
;
const
_kCursorBlinkPeriod
=
500
;
// milliseconds
const
_kCursorGap
=
1.0
;
const
_kCursorHeightOffset
=
2.0
;
const
_kCursorWidth
=
1.0
;
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
();
}
}
class
EditableText
extends
StatefulComponent
{
EditableText
({
Key
key
,
this
.
value
,
this
.
focused
:
false
,
this
.
style
,
this
.
cursorColor
})
:
super
(
key:
key
);
EditableString
value
;
bool
focused
;
TextStyle
style
;
Color
cursorColor
;
void
syncConstructorArguments
(
EditableText
source
)
{
value
=
source
.
value
;
focused
=
source
.
focused
;
style
=
source
.
style
;
cursorColor
=
source
.
cursorColor
;
}
Timer
_cursorTimer
;
bool
_showCursor
=
false
;
/// Whether the blinking cursor is visible (exposed for testing).
bool
get
test_showCursor
=>
_showCursor
;
/// The cursor blink interval (exposed for testing).
Duration
get
test_cursorBlinkPeriod
=>
new
Duration
(
milliseconds:
_kCursorBlinkPeriod
);
void
_cursorTick
(
Timer
timer
)
{
setState
(()
{
_showCursor
=
!
_showCursor
;
});
}
void
_startCursorTimer
()
{
_showCursor
=
true
;
_cursorTimer
=
new
Timer
.
periodic
(
new
Duration
(
milliseconds:
_kCursorBlinkPeriod
),
_cursorTick
);
}
void
didUnmount
()
{
if
(
_cursorTimer
!=
null
)
_stopCursorTimer
();
super
.
didUnmount
();
}
void
_stopCursorTimer
()
{
_cursorTimer
.
cancel
();
_cursorTimer
=
null
;
_showCursor
=
false
;
}
void
_paintCursor
(
sky
.
Canvas
canvas
,
Size
size
)
{
if
(!
_showCursor
)
return
;
double
cursorHeight
=
style
.
fontSize
+
2.0
*
_kCursorHeightOffset
;
Rect
cursorRect
=
new
Rect
.
fromLTWH
(
_kCursorGap
,
(
size
.
height
-
cursorHeight
)
/
2.0
,
_kCursorWidth
,
cursorHeight
);
canvas
.
drawRect
(
cursorRect
,
new
Paint
()..
color
=
cursorColor
);
}
Widget
build
()
{
assert
(
style
!=
null
);
assert
(
focused
!=
null
);
assert
(
cursorColor
!=
null
);
if
(
focused
&&
_cursorTimer
==
null
)
_startCursorTimer
();
else
if
(!
focused
&&
_cursorTimer
!=
null
)
_stopCursorTimer
();
Widget
text
;
if
(
value
.
composing
.
isValid
)
{
TextStyle
composingStyle
=
style
.
merge
(
const
TextStyle
(
decoration:
underline
));
text
=
new
StyledText
(
elements:
[
style
,
value
.
textBefore
(
value
.
composing
),
[
composingStyle
,
value
.
textInside
(
value
.
composing
)],
value
.
textAfter
(
value
.
composing
)
]);
}
else
{
// TODO(eseidel): This is the wrong height if empty!
text
=
new
Text
(
value
.
text
,
style:
style
);
}
Widget
cursor
=
new
Container
(
height:
style
.
fontSize
*
style
.
height
,
width:
_kCursorGap
+
_kCursorWidth
,
child:
new
CustomPaint
(
callback:
_paintCursor
,
token:
_showCursor
)
);
return
new
Row
([
text
,
cursor
]);
}
}
packages/flutter/lib/src/fn3/input.dart
0 → 100644
View file @
fe77808d
// 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:sky/services.dart'
;
import
'package:sky/painting.dart'
;
import
'package:sky/src/widgets/basic.dart'
;
import
'package:sky/src/widgets/editable_text.dart'
;
import
'package:sky/src/widgets/focus.dart'
;
import
'package:sky/src/widgets/framework.dart'
;
import
'package:sky/src/widgets/theme.dart'
;
export
'package:sky/services.dart'
show
KeyboardType
;
typedef
void
StringValueChanged
(
String
value
);
// TODO(eseidel): This isn't right, it's 16px on the bottom:
// http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field
const
EdgeDims
_kTextfieldPadding
=
const
EdgeDims
.
symmetric
(
vertical:
8.0
);
class
Input
extends
StatefulComponent
{
Input
({
GlobalKey
key
,
String
initialValue:
''
,
this
.
placeholder
,
this
.
onChanged
,
this
.
keyboardType
:
KeyboardType
.
TEXT
}):
_value
=
initialValue
,
super
(
key:
key
);
KeyboardType
keyboardType
;
String
placeholder
;
StringValueChanged
onChanged
;
String
_value
;
EditableString
_editableValue
;
KeyboardHandle
_keyboardHandle
=
KeyboardHandle
.
unattached
;
void
initState
()
{
_editableValue
=
new
EditableString
(
text:
_value
,
onUpdated:
_handleTextUpdated
);
super
.
initState
();
}
void
syncConstructorArguments
(
Input
source
)
{
placeholder
=
source
.
placeholder
;
onChanged
=
source
.
onChanged
;
keyboardType
=
source
.
keyboardType
;
}
void
_handleTextUpdated
()
{
if
(
_value
!=
_editableValue
.
text
)
{
setState
(()
{
_value
=
_editableValue
.
text
;
});
if
(
onChanged
!=
null
)
onChanged
(
_value
);
}
}
Widget
build
()
{
ThemeData
themeData
=
Theme
.
of
(
this
);
bool
focused
=
Focus
.
at
(
this
);
if
(
focused
&&
!
_keyboardHandle
.
attached
)
{
_keyboardHandle
=
keyboard
.
show
(
_editableValue
.
stub
,
keyboardType
);
}
else
if
(!
focused
&&
_keyboardHandle
.
attached
)
{
_keyboardHandle
.
release
();
}
TextStyle
textStyle
=
themeData
.
text
.
subhead
;
List
<
Widget
>
textChildren
=
<
Widget
>[];
if
(
placeholder
!=
null
&&
_value
.
isEmpty
)
{
Widget
child
=
new
Opacity
(
key:
const
ValueKey
<
String
>(
'placeholder'
),
child:
new
Text
(
placeholder
,
style:
textStyle
),
opacity:
themeData
.
hintOpacity
);
textChildren
.
add
(
child
);
}
Color
focusHighlightColor
=
themeData
.
accentColor
;
Color
cursorColor
=
themeData
.
accentColor
;
if
(
themeData
.
primarySwatch
!=
null
)
{
cursorColor
=
themeData
.
primarySwatch
[
200
];
focusHighlightColor
=
focused
?
themeData
.
primarySwatch
[
400
]
:
themeData
.
hintColor
;
}
textChildren
.
add
(
new
EditableText
(
value:
_editableValue
,
focused:
focused
,
style:
textStyle
,
cursorColor:
cursorColor
));
Border
focusHighlight
=
new
Border
(
bottom:
new
BorderSide
(
color:
focusHighlightColor
,
width:
focused
?
2.0
:
1.0
));
Container
input
=
new
Container
(
child:
new
Stack
(
textChildren
),
padding:
_kTextfieldPadding
,
decoration:
new
BoxDecoration
(
border:
focusHighlight
)
);
return
new
Listener
(
child:
input
,
onPointerDown:
focus
);
}
void
focus
(
_
)
{
if
(
Focus
.
at
(
this
))
{
assert
(
_keyboardHandle
.
attached
);
_keyboardHandle
.
showByRequest
();
}
else
{
Focus
.
moveTo
(
this
);
// we'll get told to rebuild and we'll take care of the keyboard then
}
}
void
didUnmount
()
{
if
(
_keyboardHandle
.
attached
)
_keyboardHandle
.
release
();
super
.
didUnmount
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment