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
90363ee9
Commit
90363ee9
authored
Jul 21, 2015
by
Viktor Lidholt
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:domokit/sky_engine into HEAD
parents
1b4923a2
df88d38b
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
893 additions
and
201 deletions
+893
-201
BUILD.gn
packages/flutter/BUILD.gn
+1
-1
README.md
packages/flutter/README.md
+2
-2
main.dart
packages/flutter/example/demo_launcher/lib/main.dart
+11
-8
home.dart
packages/flutter/example/fitness/lib/home.dart
+95
-9
main.dart
packages/flutter/example/fitness/lib/main.dart
+28
-2
measurement.dart
packages/flutter/example/fitness/lib/measurement.dart
+103
-1
mutating-dom.dart
packages/flutter/example/raw/mutating-dom.dart
+217
-0
align_items.dart
packages/flutter/example/rendering/align_items.dart
+2
-2
stock_row.dart
packages/flutter/example/stocks/lib/stock_row.dart
+6
-1
block_viewport.dart
packages/flutter/example/widgets/block_viewport.dart
+3
-1
card_collection.dart
packages/flutter/example/widgets/card_collection.dart
+111
-27
text_style.dart
packages/flutter/lib/painting/text_style.dart
+13
-2
box.dart
packages/flutter/lib/rendering/box.dart
+4
-4
flex.dart
packages/flutter/lib/rendering/flex.dart
+46
-15
typography.dart
packages/flutter/lib/theme/typography.dart
+12
-11
basic.dart
packages/flutter/lib/widgets/basic.dart
+4
-1
block_viewport.dart
packages/flutter/lib/widgets/block_viewport.dart
+185
-93
card.dart
packages/flutter/lib/widgets/card.dart
+3
-1
dismissable.dart
packages/flutter/lib/widgets/dismissable.dart
+4
-2
snack_bar.dart
packages/flutter/lib/widgets/snack_bar.dart
+3
-1
tool_bar.dart
packages/flutter/lib/widgets/tool_bar.dart
+6
-4
variable_height_scrollable.dart
packages/flutter/lib/widgets/variable_height_scrollable.dart
+34
-13
No files found.
packages/flutter/BUILD.gn
View file @
90363ee9
...
...
@@ -120,7 +120,7 @@ dart_pkg("sky") {
sdk_ext_mappings = [
"dart:sky,dart_sky.dart",
"dart:sky.internals,sky_internals.dart",
"dart:sky_builtin_nat
vi
es,builtin_natives.dart",
"dart:sky_builtin_nat
iv
es,builtin_natives.dart",
]
}
...
...
packages/flutter/README.md
View file @
90363ee9
...
...
@@ -39,8 +39,8 @@ void main() {
}
```
Execution starts in
`main`
, which runs a new instance of the
`HelloWorldApp`
.
The
`HelloWorldApp`
builds a
`Text`
widget containing the
famous
`Hello, world!`
Execution starts in
`main`
, which
in this example
runs a new instance of the
`HelloWorldApp`
.
The
`HelloWorldApp`
builds a
`Text`
widget containing the
traditional
`Hello, world!`
string and centers it on the screen using a
`Center`
widget. To learn more about
the widget system, please see the
[
widgets tutorial
](
lib/widgets/README.md
)
.
...
...
packages/flutter/example/demo_launcher/lib/main.dart
View file @
90363ee9
...
...
@@ -80,7 +80,7 @@ List<SkyDemo> demos = [
name:
'Asteroids'
,
href:
'../../game/main.dart'
,
bundle:
'game.skyx'
,
description:
'2D game using sprite sheets
to achieve high performance
'
,
description:
'2D game using sprite sheets'
,
textTheme:
typography
.
white
,
decoration:
new
BoxDecoration
(
backgroundImage:
new
BackgroundImage
(
...
...
@@ -93,20 +93,20 @@ List<SkyDemo> demos = [
name:
'Fitness'
,
href:
'../../fitness/lib/main.dart'
,
bundle:
'fitness.skyx'
,
description:
'
Collin should write a nice description
'
,
description:
'
Track progress towards healthy goals
'
,
textTheme:
typography
.
white
,
decoration:
new
BoxDecoration
(
backgroundColor:
co
nst
Color
(
0xFF0081C6
)
backgroundColor:
co
lors
.
Indigo
[
500
]
)
),
new
SkyDemo
(
name:
'
Cards
'
,
name:
'
Swipe Away
'
,
href:
'../../widgets/card_collection.dart'
,
bundle:
'cards.skyx'
,
description:
'
Demo of interactive C
ards'
,
description:
'
Infinite list of swipeable c
ards'
,
textTheme:
typography
.
white
,
decoration:
new
BoxDecoration
(
backgroundColor:
co
nst
Color
(
0xFF0081C6
)
backgroundColor:
co
lors
.
RedAccent
[
200
]
)
),
new
SkyDemo
(
...
...
@@ -127,7 +127,10 @@ List<SkyDemo> demos = [
href:
'../../mine_digger/lib/main.dart'
,
bundle:
'mine_digger.skyx'
,
description:
'Clone of the classic Minesweeper game'
,
textTheme:
typography
.
white
textTheme:
typography
.
white
,
decoration:
new
BoxDecoration
(
backgroundColor:
colors
.
black
)
),
// TODO(jackson): This doesn't seem to be working
...
...
@@ -143,7 +146,7 @@ class DemoList extends Component {
decoration:
demo
.
decoration
,
child:
new
InkWell
(
child:
new
Container
(
margin:
const
EdgeDims
.
all
(
24.0
),
margin:
const
EdgeDims
.
only
(
top:
24.0
,
left:
24.0
),
child:
new
Flex
([
new
Text
(
demo
.
name
,
style:
demo
.
textTheme
.
title
),
new
Flexible
(
...
...
packages/flutter/example/fitness/lib/home.dart
View file @
90363ee9
...
...
@@ -4,6 +4,9 @@
import
'package:sky/painting/text_style.dart'
;
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/card.dart'
;
import
'package:sky/widgets/default_text_style.dart'
;
import
'package:sky/widgets/dismissable.dart'
;
import
'package:sky/widgets/drawer.dart'
;
import
'package:sky/widgets/drawer_divider.dart'
;
import
'package:sky/widgets/drawer_header.dart'
;
...
...
@@ -11,9 +14,11 @@ import 'package:sky/widgets/drawer_item.dart';
import
'package:sky/widgets/floating_action_button.dart'
;
import
'package:sky/widgets/icon_button.dart'
;
import
'package:sky/widgets/icon.dart'
;
import
'package:sky/widgets/ink_well.dart'
;
import
'package:sky/widgets/material.dart'
;
import
'package:sky/widgets/navigator.dart'
;
import
'package:sky/widgets/scaffold.dart'
;
import
'package:sky/widgets/scrollable_list.dart'
;
import
'package:sky/widgets/snack_bar.dart'
;
import
'package:sky/widgets/theme.dart'
;
import
'package:sky/widgets/tool_bar.dart'
;
...
...
@@ -22,12 +27,79 @@ import 'package:sky/widgets/widget.dart';
import
'fitness_types.dart'
;
import
'measurement.dart'
;
class
MeasurementList
extends
Component
{
MeasurementList
({
String
key
,
this
.
measurements
,
this
.
onDismissed
})
:
super
(
key:
key
);
final
List
<
Measurement
>
measurements
;
final
MeasurementHandler
onDismissed
;
Widget
build
()
{
return
new
Material
(
type:
MaterialType
.
canvas
,
child:
new
ScrollableList
<
Measurement
>(
items:
measurements
,
itemHeight:
MeasurementRow
.
kHeight
,
itemBuilder:
(
measurement
)
=>
new
MeasurementRow
(
measurement:
measurement
,
onDismissed:
onDismissed
)
)
);
}
}
class
MeasurementRow
extends
Component
{
MeasurementRow
({
Measurement
measurement
,
this
.
onDismissed
})
:
this
.
measurement
=
measurement
,
super
(
key:
measurement
.
when
.
toString
());
final
Measurement
measurement
;
final
MeasurementHandler
onDismissed
;
static
const
double
kHeight
=
79.0
;
Widget
build
()
{
List
<
Widget
>
children
=
[
new
Flexible
(
child:
new
Text
(
measurement
.
displayWeight
,
style:
const
TextStyle
(
textAlign:
TextAlign
.
right
)
)
),
new
Flexible
(
child:
new
Text
(
measurement
.
displayDate
,
style:
Theme
.
of
(
this
).
text
.
caption
.
copyWith
(
textAlign:
TextAlign
.
right
)
)
)
];
return
new
Dismissable
(
key:
measurement
.
when
.
toString
(),
onDismissed:
()
=>
onDismissed
(
measurement
),
child:
new
Card
(
child:
new
Container
(
height:
kHeight
,
padding:
const
EdgeDims
.
all
(
8.0
),
child:
new
Flex
(
children
,
alignItems:
FlexAlignItems
.
baseline
,
textBaseline:
DefaultTextStyle
.
of
(
this
).
textBaseline
)
)
)
);
}
}
class
HomeFragment
extends
StatefulComponent
{
HomeFragment
(
this
.
navigator
,
this
.
userData
);
HomeFragment
(
{
this
.
navigator
,
this
.
userData
,
this
.
onMeasurementCreated
,
this
.
onMeasurementDeleted
}
);
Navigator
navigator
;
List
<
Measurement
>
userData
;
MeasurementHandler
onMeasurementCreated
;
MeasurementHandler
onMeasurementDeleted
;
FitnessMode
_fitnessMode
=
FitnessMode
.
measure
;
...
...
@@ -40,6 +112,8 @@ class HomeFragment extends StatefulComponent {
void
syncFields
(
HomeFragment
source
)
{
navigator
=
source
.
navigator
;
userData
=
source
.
userData
;
onMeasurementCreated
=
source
.
onMeasurementCreated
;
onMeasurementDeleted
=
source
.
onMeasurementDeleted
;
}
bool
_isShowingSnackBar
=
false
;
...
...
@@ -121,10 +195,26 @@ class HomeFragment extends StatefulComponent {
);
}
// TODO(jackson): Pull from file
Measurement
_undoMeasurement
;
void
_handleMeasurementDismissed
(
Measurement
measurement
)
{
onMeasurementDeleted
(
measurement
);
setState
(()
{
_undoMeasurement
=
measurement
;
_isShowingSnackBar
=
true
;
});
}
Widget
buildBody
()
{
TextStyle
style
=
Theme
.
of
(
this
).
text
.
title
;
switch
(
_fitnessMode
)
{
case
FitnessMode
.
measure
:
if
(
userData
.
length
>
0
)
return
new
MeasurementList
(
measurements:
userData
,
onDismissed:
_handleMeasurementDismissed
);
return
new
Material
(
type:
MaterialType
.
canvas
,
child:
new
Flex
(
...
...
@@ -143,7 +233,9 @@ class HomeFragment extends StatefulComponent {
}
void
_handleUndo
()
{
onMeasurementCreated
(
_undoMeasurement
);
setState
(()
{
_undoMeasurement
=
null
;
_isShowingSnackBar
=
false
;
});
}
...
...
@@ -152,17 +244,11 @@ class HomeFragment extends StatefulComponent {
if
(!
_isShowingSnackBar
)
return
null
;
return
new
SnackBar
(
content:
new
Text
(
"Measurement
added!
"
),
content:
new
Text
(
"Measurement
deleted.
"
),
actions:
[
new
SnackBarAction
(
label:
"UNDO"
,
onPressed:
_handleUndo
)]
);
}
void
_handleMeasurementAdded
()
{
setState
(()
{
_isShowingSnackBar
=
true
;
});
}
void
_handleRunStarted
()
{
setState
(()
{
_isRunning
=
true
;
...
...
@@ -180,7 +266,7 @@ class HomeFragment extends StatefulComponent {
case
FitnessMode
.
measure
:
return
new
FloatingActionButton
(
child:
new
Icon
(
type:
'content/add'
,
size:
24
),
onPressed:
_handleMeasurementAdded
onPressed:
()
=>
navigator
.
pushNamed
(
"/measurements/new"
)
);
case
FitnessMode
.
run
:
return
new
FloatingActionButton
(
...
...
packages/flutter/example/fitness/lib/main.dart
View file @
90363ee9
...
...
@@ -22,7 +22,19 @@ class FitnessApp extends App {
_navigationState
=
new
NavigationState
([
new
Route
(
name:
'/'
,
builder:
(
navigator
,
route
)
=>
new
HomeFragment
(
navigator
,
_userData
)
builder:
(
navigator
,
route
)
=>
new
HomeFragment
(
navigator:
navigator
,
userData:
_userData
,
onMeasurementCreated:
_handleMeasurementCreated
,
onMeasurementDeleted:
_handleMeasurementDeleted
)
),
new
Route
(
name:
'/measurements/new'
,
builder:
(
navigator
,
route
)
=>
new
MeasurementFragment
(
navigator:
navigator
,
onCreated:
_handleMeasurementCreated
)
),
new
Route
(
name:
'/settings'
,
...
...
@@ -42,6 +54,19 @@ class FitnessApp extends App {
}
}
void
_handleMeasurementCreated
(
Measurement
measurement
)
{
setState
(()
{
_userData
.
add
(
measurement
);
_userData
.
sort
((
a
,
b
)
=>
a
.
when
.
compareTo
(
b
.
when
));
});
}
void
_handleMeasurementDeleted
(
Measurement
measurement
)
{
setState
(()
{
_userData
.
remove
(
measurement
);
});
}
BackupMode
backupSetting
=
BackupMode
.
disabled
;
void
settingsUpdater
({
BackupMode
backup
})
{
...
...
@@ -52,7 +77,8 @@ class FitnessApp extends App {
}
final
List
<
Measurement
>
_userData
=
[
new
Measurement
(
when:
new
DateTime
.
now
(),
weight:
400.0
)
new
Measurement
(
weight:
180.0
,
when:
new
DateTime
.
now
().
add
(
const
Duration
(
days:
-
1
))),
new
Measurement
(
weight:
160.0
,
when:
new
DateTime
.
now
()),
];
Widget
build
()
{
...
...
packages/flutter/example/fitness/lib/measurement.dart
View file @
90363ee9
...
...
@@ -2,10 +2,112 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:sky/editing/input.dart'
;
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/flat_button.dart'
;
import
'package:sky/widgets/icon_button.dart'
;
import
'package:sky/widgets/ink_well.dart'
;
import
'package:sky/widgets/material.dart'
;
import
'package:sky/widgets/navigator.dart'
;
import
'package:sky/widgets/scaffold.dart'
;
import
'package:sky/widgets/scrollable_viewport.dart'
;
import
'package:sky/widgets/snack_bar.dart'
;
import
'package:sky/widgets/tool_bar.dart'
;
typedef
void
MeasurementHandler
(
Measurement
measurement
);
class
Measurement
{
Measurement
({
this
.
when
,
this
.
weight
});
final
DateTime
when
;
final
double
weight
;
Measurement
({
this
.
when
,
this
.
weight
});
// TODO(jackson): Internationalize
String
get
displayWeight
=>
"
${weight.toStringAsFixed(2)}
lbs"
;
String
get
displayDate
=>
"
${when.year.toString()}
-
${when.month.toString().padLeft(2,'0')}
-
${when.day.toString().padLeft(2,'0')}
"
;
}
class
MeasurementFragment
extends
StatefulComponent
{
MeasurementFragment
({
this
.
navigator
,
this
.
onCreated
});
Navigator
navigator
;
MeasurementHandler
onCreated
;
void
syncFields
(
MeasurementFragment
source
)
{
navigator
=
source
.
navigator
;
onCreated
=
source
.
onCreated
;
}
String
_weight
=
""
;
String
_errorMessage
=
null
;
void
_handleSave
()
{
double
parsedWeight
;
try
{
parsedWeight
=
double
.
parse
(
_weight
);
}
on
FormatException
{
setState
(()
{
_errorMessage
=
"Save failed"
;
});
return
;
}
onCreated
(
new
Measurement
(
when:
new
DateTime
.
now
(),
weight:
parsedWeight
));
navigator
.
pop
();
}
Widget
buildToolBar
()
{
return
new
ToolBar
(
left:
new
IconButton
(
icon:
"navigation/close"
,
onPressed:
navigator
.
pop
),
center:
new
Text
(
'New Measurement'
),
right:
[
new
InkWell
(
child:
new
Listener
(
onGestureTap:
(
_
)
=>
_handleSave
(),
child:
new
Text
(
'SAVE'
)
)
)]
);
}
void
_handleWeightChanged
(
String
weight
)
{
setState
(()
{
_weight
=
weight
;
});
}
Widget
buildMeasurementPane
()
{
Measurement
measurement
=
new
Measurement
(
when:
new
DateTime
.
now
());
return
new
Material
(
type:
MaterialType
.
canvas
,
child:
new
ScrollableViewport
(
child:
new
Container
(
padding:
const
EdgeDims
.
all
(
20.0
),
child:
new
Block
([
new
Text
(
measurement
.
displayDate
),
new
Input
(
focused:
false
,
placeholder:
'Enter weight'
,
onChanged:
_handleWeightChanged
),
])
)
)
);
}
Widget
buildSnackBar
()
{
if
(
_errorMessage
==
null
)
return
null
;
return
new
SnackBar
(
content:
new
Text
(
_errorMessage
));
}
Widget
build
()
{
return
new
Scaffold
(
toolbar:
buildToolBar
(),
body:
buildMeasurementPane
(),
snackBar:
buildSnackBar
()
);
}
}
packages/flutter/example/raw/mutating-dom.dart
0 → 100644
View file @
90363ee9
// 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:math"
as
math
;
import
'dart:sky'
as
sky
;
const
kMaxIterations
=
100
;
int
peakCount
=
1000
;
// this is the number that must be reached for us to start reporting the peak number of nodes in the tree each frame
void
report
(
String
s
)
{
// uncomment this if you want to see what the mutations are
// print("$s\n");
}
sky
.
LayoutRoot
layoutRoot
=
new
sky
.
LayoutRoot
();
sky
.
Document
document
=
new
sky
.
Document
();
sky
.
Element
root
;
math
.
Random
random
=
new
math
.
Random
();
bool
pickThis
(
double
odds
)
{
return
random
.
nextDouble
()
<
odds
;
}
String
generateCharacter
(
int
min
,
int
max
)
{
String
result
=
new
String
.
fromCharCode
(
random
.
nextInt
(
max
)+
min
);
report
(
"generated character: '
$result
'"
);
return
result
;
}
String
colorToCSSString
(
sky
.
Color
color
)
{
return
'rgba(
${color.red}
,
${color.green}
,
${color.blue}
,
${color.alpha / 255.0}
)'
;
}
void
doFrame
(
double
timeStamp
)
{
// mutate the DOM randomly
int
iterationsLeft
=
kMaxIterations
;
sky
.
Node
node
=
root
;
sky
.
Node
other
=
null
;
while
(
node
!=
null
&&
iterationsLeft
>
0
)
{
iterationsLeft
-=
1
;
if
(
node
is
sky
.
Element
&&
pickThis
(
0.4
))
{
node
=
(
node
as
sky
.
Element
).
firstChild
;
}
else
if
(
node
.
nextSibling
!=
null
&&
pickThis
(
0.5
))
{
node
=
node
.
nextSibling
;
}
else
if
(
other
==
null
&&
node
!=
root
&&
pickThis
(
0.1
))
{
other
=
node
;
node
=
root
;
}
else
if
(
node
!=
root
&&
other
!=
null
&&
pickThis
(
0.1
))
{
report
(
"insertBefore()"
);
node
.
insertBefore
([
other
]);
break
;
}
else
if
(
pickThis
(
0.001
))
{
report
(
"remove()"
);
node
.
remove
();
}
else
if
(
node
is
sky
.
Element
)
{
if
(
pickThis
(
0.1
))
{
report
(
"appending a new text node (ASCII)"
);
node
.
appendChild
(
document
.
createText
(
generateCharacter
(
0x20
,
0x7F
)));
break
;
}
else
if
(
pickThis
(
0.05
))
{
report
(
"appending a new text node (Latin1)"
);
node
.
appendChild
(
document
.
createText
(
generateCharacter
(
0x20
,
0xFF
)));
break
;
}
else
if
(
pickThis
(
0.025
))
{
report
(
"appending a new text node (BMP)"
);
node
.
appendChild
(
document
.
createText
(
generateCharacter
(
0x20
,
0xFFFF
)));
break
;
}
else
if
(
pickThis
(
0.0125
))
{
report
(
"appending a new text node (Unicode)"
);
node
.
appendChild
(
document
.
createText
(
generateCharacter
(
0x20
,
0x10FFFF
)));
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"appending a new Element"
);
node
.
appendChild
(
document
.
createElement
(
't'
));
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: color"
);
node
.
style
[
'color'
]
=
colorToCSSString
(
new
sky
.
Color
(
random
.
nextInt
(
0xFFFFFFFF
)
|
0xC0808080
));
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: font-size"
);
node
.
style
[
'font-size'
]
=
"
${random.nextDouble() * 48.0}
px"
;
break
;
}
else
if
(
pickThis
(
0.2
))
{
report
(
"styling: font-weight"
);
node
.
style
[
'font-weight'
]
=
"
${random.nextInt(8)+1}
00"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: line-height, dynamic"
);
node
.
style
[
'line-height'
]
=
"
${random.nextDouble()*1.5}
"
;
break
;
}
else
if
(
pickThis
(
0.001
))
{
report
(
"styling: line-height, fixed"
);
node
.
style
[
'line-height'
]
=
"
${random.nextDouble()*1.5}
px"
;
break
;
}
else
if
(
pickThis
(
0.025
))
{
report
(
"styling: font-style italic"
);
node
.
style
[
'font-style'
]
=
"italic"
;
break
;
}
else
if
(
pickThis
(
0.05
))
{
report
(
"styling: font-style normal"
);
node
.
style
[
'font-style'
]
=
"normal"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration"
);
node
.
style
[
'text-decoration-line'
]
=
"none"
;
break
;
}
else
if
(
pickThis
(
0.01
))
{
report
(
"styling: text-decoration"
);
node
.
style
[
'text-decoration-line'
]
=
"underline"
;
break
;
}
else
if
(
pickThis
(
0.01
))
{
report
(
"styling: text-decoration"
);
node
.
style
[
'text-decoration-line'
]
=
"overline"
;
break
;
}
else
if
(
pickThis
(
0.01
))
{
report
(
"styling: text-decoration"
);
node
.
style
[
'text-decoration-line'
]
=
"underline overline"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-style: inherit"
);
node
.
style
[
'text-decoration-style'
]
=
"inherit"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-style: solid"
);
node
.
style
[
'text-decoration-style'
]
=
"solid"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-style: double"
);
node
.
style
[
'text-decoration-style'
]
=
"double"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-style: dotted"
);
node
.
style
[
'text-decoration-style'
]
=
"dotted"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-style: dashed"
);
node
.
style
[
'text-decoration-style'
]
=
"dashed"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-style: wavy"
);
node
.
style
[
'text-decoration-style'
]
=
"wavy"
;
break
;
}
else
if
(
pickThis
(
0.1
))
{
report
(
"styling: text-decoration-color"
);
node
.
style
[
'text-decoration-color'
]
=
colorToCSSString
(
new
sky
.
Color
(
random
.
nextInt
(
0xFFFFFFFF
)));
break
;
}
}
else
{
assert
(
node
is
sky
.
Text
);
//
if
(
pickThis
(
0.1
))
{
report
(
"appending a new text node (ASCII)"
);
node
.
appendData
(
generateCharacter
(
0x20
,
0x7F
));
break
;
}
else
if
(
pickThis
(
0.05
))
{
report
(
"appending a new text node (Latin1)"
);
node
.
appendData
(
generateCharacter
(
0x20
,
0xFF
));
break
;
}
else
if
(
pickThis
(
0.025
))
{
report
(
"appending a new text node (BMP)"
);
node
.
appendData
(
generateCharacter
(
0x20
,
0xFFFF
));
break
;
}
else
if
(
pickThis
(
0.0125
))
{
report
(
"appending a new text node (Unicode)"
);
node
.
appendData
(
generateCharacter
(
0x20
,
0x10FFFF
));
break
;
}
else
if
(
node
.
length
>
1
&&
pickThis
(
0.1
))
{
report
(
"deleting character from Text node"
);
node
.
deleteData
(
random
.
nextInt
(
node
.
length
),
1
);
break
;
}
}
}
report
(
"counting..."
);
node
=
root
;
int
count
=
1
;
while
(
node
!=
null
)
{
if
(
node
is
sky
.
Element
&&
node
.
firstChild
!=
null
)
{
node
=
node
.
firstChild
;
count
+=
1
;
}
else
{
while
(
node
!=
null
&&
node
.
nextSibling
==
null
)
node
=
node
.
parentNode
;
if
(
node
!=
null
&&
node
.
nextSibling
!=
null
)
{
node
=
node
.
nextSibling
;
count
+=
1
;
}
}
}
report
(
"node count:
$count
\r
"
);
if
(
count
>
peakCount
)
{
peakCount
=
count
;
print
(
"peak node count so far:
$count
\r
"
);
}
// draw the result
report
(
"recording..."
);
sky
.
PictureRecorder
recorder
=
new
sky
.
PictureRecorder
();
sky
.
Canvas
canvas
=
new
sky
.
Canvas
(
recorder
,
new
sky
.
Rect
.
fromLTWH
(
0.0
,
0.0
,
sky
.
view
.
width
,
sky
.
view
.
height
));
layoutRoot
.
maxWidth
=
sky
.
view
.
width
;
layoutRoot
.
layout
();
layoutRoot
.
paint
(
canvas
);
report
(
"painting..."
);
sky
.
view
.
picture
=
recorder
.
endRecording
();
sky
.
view
.
scheduleFrame
();
}
void
main
(
)
{
root
=
document
.
createElement
(
'p'
);
root
.
style
[
'display'
]
=
'paragraph'
;
root
.
style
[
'color'
]
=
'#FFFFFF'
;
layoutRoot
.
rootElement
=
root
;
sky
.
view
.
setFrameCallback
(
doFrame
);
sky
.
view
.
scheduleFrame
();
}
packages/flutter/example/rendering/align_items.dart
View file @
90363ee9
...
...
@@ -20,7 +20,7 @@ void main() {
TextStyle
style
=
const
TextStyle
(
color:
const
Color
(
0xFF000000
));
RenderParagraph
paragraph
=
new
RenderParagraph
(
new
InlineStyle
(
style
,
[
new
InlineText
(
"
${alignItems}
"
)]));
table
.
add
(
new
RenderPadding
(
child:
paragraph
,
padding:
new
EdgeDims
.
only
(
top:
20.0
)));
var
row
=
new
RenderFlex
(
alignItems:
alignItems
);
var
row
=
new
RenderFlex
(
alignItems:
alignItems
,
baseline:
TextBaseline
.
alphabetic
);
style
=
new
TextStyle
(
fontSize:
15.0
,
color:
const
Color
(
0xFF000000
));
row
.
add
(
new
RenderDecoratedBox
(
...
...
@@ -32,7 +32,7 @@ void main() {
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0x7FCCFFCC
)),
child:
new
RenderParagraph
(
new
InlineStyle
(
style
,
[
new
InlineText
(
'foo foo foo'
)]))
));
var
subrow
=
new
RenderFlex
(
alignItems:
alignItems
);
var
subrow
=
new
RenderFlex
(
alignItems:
alignItems
,
baseline:
TextBaseline
.
alphabetic
);
style
=
new
TextStyle
(
fontSize:
25.0
,
color:
const
Color
(
0xFF000000
));
subrow
.
add
(
new
RenderDecoratedBox
(
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0x7FCCCCFF
)),
...
...
packages/flutter/example/stocks/lib/stock_row.dart
View file @
90363ee9
...
...
@@ -6,6 +6,7 @@ import 'package:sky/painting/text_style.dart';
import
'package:sky/rendering/box.dart'
;
import
'package:sky/widgets/ink_well.dart'
;
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/default_text_style.dart'
;
import
'package:sky/widgets/theme.dart'
;
import
'stock_arrow.dart'
;
...
...
@@ -60,7 +61,11 @@ class StockRow extends Component {
margin:
const
EdgeDims
.
only
(
right:
5.0
)
),
new
Flexible
(
child:
new
Flex
(
children
,
alignItems:
FlexAlignItems
.
baseline
)
child:
new
Flex
(
children
,
alignItems:
FlexAlignItems
.
baseline
,
textBaseline:
DefaultTextStyle
.
of
(
this
).
textBaseline
)
)
])
)
...
...
packages/flutter/example/widgets/block_viewport.dart
View file @
90363ee9
...
...
@@ -15,6 +15,7 @@ import 'package:sky/widgets/widget.dart';
class
BlockViewportApp
extends
App
{
BlockViewportLayoutState
layoutState
=
new
BlockViewportLayoutState
();
List
<
double
>
lengths
=
<
double
>[];
double
offset
=
0.0
;
...
...
@@ -96,7 +97,8 @@ class BlockViewportApp extends App {
child:
new
BlockViewport
(
builder:
builder
,
startOffset:
offset
,
token:
lengths
.
length
token:
lengths
.
length
,
layoutState:
layoutState
)
)
),
...
...
packages/flutter/example/widgets/card_collection.dart
View file @
90363ee9
...
...
@@ -2,62 +2,145 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:sky/animation/animation_performance.dart'
;
import
'package:sky/animation/curves.dart'
;
import
'package:sky/base/lerp.dart'
;
import
'package:sky/painting/text_style.dart'
;
import
'package:sky/theme/colors.dart'
;
import
'package:sky/widgets/animated_component.dart'
;
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/block_viewport.dart'
;
import
'package:sky/widgets/card.dart'
;
import
'package:sky/widgets/dismissable.dart'
;
import
'package:sky/widgets/scaffold.dart'
;
import
'package:sky/widgets/variable_height_scrollable.dart'
;
import
'package:sky/widgets/scaffold.dart'
;
import
'package:sky/widgets/theme.dart'
;
import
'package:sky/widgets/tool_bar.dart'
;
import
'package:sky/widgets/widget.dart'
;
import
'package:sky/theme/colors.dart'
as
colors
;
import
'package:sky/widgets/task_description.dart'
;
class
CardModel
{
CardModel
(
this
.
value
,
this
.
height
,
this
.
color
);
int
value
;
double
height
;
Color
color
;
AnimationPerformance
performance
;
String
get
label
=>
"Item
$value
"
;
String
get
key
=>
value
.
toString
();
bool
operator
==(
other
)
=>
other
is
CardModel
&&
other
.
value
==
value
;
int
get
hashCode
=>
373
*
37
*
value
.
hashCode
;
}
class
ShrinkingCard
extends
AnimatedComponent
{
ShrinkingCard
({
String
key
,
CardModel
this
.
card
,
Function
this
.
onUpdated
,
Function
this
.
onCompleted
})
:
super
(
key:
key
);
CardModel
card
;
Function
onUpdated
;
Function
onCompleted
;
double
get
currentHeight
=>
card
.
performance
.
variable
.
value
;
void
initState
()
{
assert
(
card
.
performance
!=
null
);
card
.
performance
.
addListener
(
handleAnimationProgress
);
watch
(
card
.
performance
);
}
void
handleAnimationProgress
()
{
if
(
card
.
performance
.
isCompleted
)
{
if
(
onCompleted
!=
null
)
onCompleted
();
}
else
if
(
onUpdated
!=
null
)
{
onUpdated
();
}
}
void
syncFields
(
ShrinkingCard
source
)
{
card
=
source
.
card
;
onCompleted
=
source
.
onCompleted
;
onUpdated
=
source
.
onUpdated
;
super
.
syncFields
(
source
);
}
Widget
build
()
=>
new
Container
(
height:
currentHeight
);
}
class
CardCollectionApp
extends
App
{
final
TextStyle
cardLabelStyle
=
new
TextStyle
(
color:
white
,
fontSize:
18.0
,
fontWeight:
bold
);
final
List
<
double
>
cardHeights
=
[
48.0
,
64.0
,
82.0
,
46.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
,
48.0
,
64.0
,
82.0
,
46.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
,
48.0
,
64.0
,
82.0
,
46.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
,
48.0
,
64.0
,
82.0
,
46.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
];
List
<
int
>
visibleCardIndices
;
BlockViewportLayoutState
layoutState
=
new
BlockViewportLayoutState
();
List
<
CardModel
>
cardModels
;
void
initState
()
{
visibleCardIndices
=
new
List
.
generate
(
cardHeights
.
length
,
(
i
)
=>
i
);
List
<
double
>
cardHeights
=
<
double
>[
48.0
,
63.0
,
82.0
,
146.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
,
48.0
,
63.0
,
82.0
,
146.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
,
48.0
,
63.0
,
82.0
,
146.0
,
60.0
,
55.0
,
84.0
,
96.0
,
50.0
];
cardModels
=
new
List
.
generate
(
cardHeights
.
length
,
(
i
)
{
Color
color
=
lerpColor
(
Red
[
300
],
Blue
[
900
],
i
/
cardHeights
.
length
);
return
new
CardModel
(
i
,
cardHeights
[
i
],
color
);
});
super
.
initState
();
}
void
dismissCard
(
int
cardIndex
)
{
void
shrinkCard
(
CardModel
card
,
int
index
)
{
if
(
card
.
performance
!=
null
)
return
;
layoutState
.
invalidate
([
index
]);
setState
(()
{
visibleCardIndices
.
remove
(
cardIndex
);
assert
(
card
.
performance
==
null
);
card
.
performance
=
new
AnimationPerformance
()
..
duration
=
const
Duration
(
milliseconds:
300
)
..
variable
=
new
AnimatedType
<
double
>(
card
.
height
+
kCardMargins
.
top
+
kCardMargins
.
bottom
,
end:
0.0
,
curve:
ease
,
interval:
new
Interval
(
0.5
,
1.0
)
)
..
play
();
});
}
Widget
_builder
(
int
index
)
{
if
(
index
>=
visibleCardIndices
.
length
)
void
dismissCard
(
CardModel
card
)
{
if
(
cardModels
.
contains
(
card
))
{
setState
(()
{
cardModels
.
remove
(
card
);
});
}
}
Widget
builder
(
int
index
)
{
if
(
index
>=
cardModels
.
length
)
return
null
;
CardModel
card
=
cardModels
[
index
];
if
(
card
.
performance
!=
null
)
{
return
new
ShrinkingCard
(
key:
card
.
key
,
card:
card
,
onUpdated:
()
{
layoutState
.
invalidate
([
index
]);
},
onCompleted:
()
{
dismissCard
(
card
);
}
);
}
int
cardIndex
=
visibleCardIndices
[
index
];
Color
color
=
lerpColor
(
Red
[
500
],
Blue
[
500
],
cardIndex
/
cardHeights
.
length
);
Widget
label
=
new
Text
(
"Item
${cardIndex}
"
,
style:
cardLabelStyle
);
return
new
Dismissable
(
key:
card
Index
.
toString
()
,
onDismissed:
()
{
dismissCard
(
cardI
ndex
);
},
key:
card
.
key
,
onDismissed:
()
{
shrinkCard
(
card
,
i
ndex
);
},
child:
new
Card
(
color:
color
,
color:
c
ard
.
c
olor
,
child:
new
Container
(
height:
card
Heights
[
cardIndex
]
,
height:
card
.
height
,
padding:
const
EdgeDims
.
all
(
8.0
),
child:
new
Center
(
child:
label
)
child:
new
Center
(
child:
new
Text
(
card
.
label
,
style:
cardLabelStyle
)
)
)
)
);
...
...
@@ -68,16 +151,17 @@ class CardCollectionApp extends App {
padding:
const
EdgeDims
.
symmetric
(
vertical:
12.0
,
horizontal:
8.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
Theme
.
of
(
this
).
primarySwatch
[
50
]),
child:
new
VariableHeightScrollable
(
builder:
_builder
,
token:
visibleCardIndices
.
length
builder:
builder
,
token:
cardModels
.
length
,
layoutState:
layoutState
)
);
return
new
Theme
(
data:
new
ThemeData
(
brightness:
ThemeBrightness
.
light
,
primarySwatch:
colors
.
Blue
,
accentColor:
colors
.
RedAccent
[
200
]
primarySwatch:
Blue
,
accentColor:
RedAccent
[
200
]
),
child:
new
TaskDescription
(
label:
'Cards'
,
...
...
packages/flutter/lib/painting/text_style.dart
View file @
90363ee9
...
...
@@ -10,6 +10,8 @@ const bold = FontWeight.w700;
enum
TextAlign
{
left
,
right
,
center
}
enum
TextBaseline
{
alphabetic
,
ideographic
}
enum
TextDecoration
{
none
,
underline
,
overline
,
lineThrough
}
const
underline
=
const
<
TextDecoration
>[
TextDecoration
.
underline
];
const
overline
=
const
<
TextDecoration
>[
TextDecoration
.
overline
];
...
...
@@ -24,6 +26,7 @@ class TextStyle {
this
.
fontSize
,
this
.
fontWeight
,
this
.
textAlign
,
this
.
textBaseline
,
this
.
height
,
this
.
decoration
,
this
.
decorationColor
,
...
...
@@ -35,6 +38,7 @@ class TextStyle {
final
double
fontSize
;
// in pixels
final
FontWeight
fontWeight
;
final
TextAlign
textAlign
;
final
TextBaseline
textBaseline
;
final
double
height
;
// multiple of fontSize
final
List
<
TextDecoration
>
decoration
;
// TODO(ianh): Switch this to a Set<> once Dart supports constant Sets
final
Color
decorationColor
;
...
...
@@ -46,6 +50,7 @@ class TextStyle {
double
fontSize
,
FontWeight
fontWeight
,
TextAlign
textAlign
,
TextBaseline
textBaseline
,
double
height
,
List
<
TextDecoration
>
decoration
,
Color
decorationColor
,
...
...
@@ -57,6 +62,7 @@ class TextStyle {
fontSize:
fontSize
!=
null
?
fontSize
:
this
.
fontSize
,
fontWeight:
fontWeight
!=
null
?
fontWeight
:
this
.
fontWeight
,
textAlign:
textAlign
!=
null
?
textAlign
:
this
.
textAlign
,
textBaseline:
textBaseline
!=
null
?
textBaseline
:
this
.
textBaseline
,
height:
height
!=
null
?
height
:
this
.
height
,
decoration:
decoration
!=
null
?
decoration
:
this
.
decoration
,
decorationColor:
decorationColor
!=
null
?
decorationColor
:
this
.
decorationColor
,
...
...
@@ -71,6 +77,7 @@ class TextStyle {
fontSize:
other
.
fontSize
,
fontWeight:
other
.
fontWeight
,
textAlign:
other
.
textAlign
,
textBaseline:
other
.
textBaseline
,
height:
other
.
height
,
decoration:
other
.
decoration
,
decorationColor:
other
.
decorationColor
,
...
...
@@ -157,10 +164,11 @@ class TextStyle {
return
true
;
return
other
is
TextStyle
&&
color
==
other
.
color
&&
fontFamily
==
other
.
fontFamily
&&
fontFamily
==
other
.
fontFamily
&&
fontSize
==
other
.
fontSize
&&
fontWeight
==
other
.
fontWeight
&&
textAlign
==
other
.
textAlign
&&
textAlign
==
other
.
textAlign
&&
textBaseline
==
other
.
textBaseline
&&
decoration
==
other
.
decoration
&&
decorationColor
==
other
.
decorationColor
&&
decorationStyle
==
other
.
decorationStyle
;
...
...
@@ -174,6 +182,7 @@ class TextStyle {
value
=
37
*
value
+
fontSize
.
hashCode
;
value
=
37
*
value
+
fontWeight
.
hashCode
;
value
=
37
*
value
+
textAlign
.
hashCode
;
value
=
37
*
value
+
textBaseline
.
hashCode
;
value
=
37
*
value
+
decoration
.
hashCode
;
value
=
37
*
value
+
decorationColor
.
hashCode
;
value
=
37
*
value
+
decorationStyle
.
hashCode
;
...
...
@@ -193,6 +202,8 @@ class TextStyle {
result
.
add
(
'
${prefix}
fontWeight:
$fontWeight
'
);
if
(
textAlign
!=
null
)
result
.
add
(
'
${prefix}
textAlign:
$textAlign
'
);
if
(
textBaseline
!=
null
)
result
.
add
(
'
${prefix}
textBaseline:
$textBaseline
'
);
if
(
decoration
!=
null
)
result
.
add
(
'
${prefix}
decoration:
$decoration
'
);
if
(
decorationColor
!=
null
)
...
...
packages/flutter/lib/rendering/box.dart
View file @
90363ee9
...
...
@@ -7,10 +7,12 @@ import 'dart:sky' as sky;
import
'package:sky/base/debug.dart'
;
import
'package:sky/painting/box_painter.dart'
;
import
'package:sky/painting/text_style.dart'
;
import
'package:sky/rendering/object.dart'
;
import
'package:vector_math/vector_math.dart'
;
export
'package:sky/painting/box_painter.dart'
;
export
'package:sky/painting/text_style.dart'
show
TextBaseline
;
// GENERIC BOX RENDERING
// Anything that has a concept of x, y, width, height is going to derive from this
...
...
@@ -253,8 +255,6 @@ class BoxParentData extends ParentData {
String
toString
()
=>
'position=
$position
'
;
}
enum
TextBaseline
{
alphabetic
,
ideographic
}
abstract
class
RenderBox
extends
RenderObject
{
void
setupParentData
(
RenderObject
child
)
{
...
...
@@ -1296,7 +1296,7 @@ class RenderImage extends RenderBox {
return
_cachedPaint
;
}
Size
_sizeForConstraints
(
BoxConstraints
innerC
onstraints
)
{
Size
_sizeForConstraints
(
BoxConstraints
c
onstraints
)
{
// If there's no image, we can't size ourselves automatically
if
(
_image
==
null
)
{
double
width
=
requestedSize
.
width
==
null
?
0.0
:
requestedSize
.
width
;
...
...
@@ -1304,7 +1304,7 @@ class RenderImage extends RenderBox {
return
constraints
.
constrain
(
new
Size
(
width
,
height
));
}
if
(!
innerC
onstraints
.
isTight
)
{
if
(!
c
onstraints
.
isTight
)
{
// If neither height nor width are specified, use inherent image
// dimensions. If only one dimension is specified, adjust the
// other dimension to maintain the aspect ratio. In both cases,
...
...
packages/flutter/lib/rendering/flex.dart
View file @
90363ee9
...
...
@@ -47,10 +47,12 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
List
<
RenderBox
>
children
,
FlexDirection
direction:
FlexDirection
.
horizontal
,
FlexJustifyContent
justifyContent:
FlexJustifyContent
.
start
,
FlexAlignItems
alignItems:
FlexAlignItems
.
center
FlexAlignItems
alignItems:
FlexAlignItems
.
center
,
TextBaseline
textBaseline
})
:
_direction
=
direction
,
_justifyContent
=
justifyContent
,
_alignItems
=
alignItems
{
_alignItems
=
alignItems
,
_textBaseline
=
textBaseline
{
addAll
(
children
);
}
...
...
@@ -81,7 +83,17 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
}
bool
_overflowOccurredDuringLayout
=
false
;
TextBaseline
_textBaseline
;
TextBaseline
get
textBaseline
=>
_textBaseline
;
void
set
textBaseline
(
TextBaseline
value
)
{
if
(
_textBaseline
!=
value
)
{
_textBaseline
=
value
;
markNeedsLayout
();
}
}
// Set during layout if overflow occurred on the main axis
double
_overflow
;
void
setupParentData
(
RenderBox
child
)
{
if
(
child
.
parentData
is
!
FlexBoxParentData
)
...
...
@@ -314,6 +326,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
child
=
child
.
parentData
.
nextSibling
;
}
_overflow
=
math
.
max
(
0.0
,
-
freeSpace
);
freeSpace
=
math
.
max
(
0.0
,
freeSpace
);
// Steps 4-5. Distribute remaining space to flexible children.
double
spacePerFlex
=
totalFlex
>
0
?
(
freeSpace
/
totalFlex
)
:
0.0
;
...
...
@@ -342,8 +356,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
crossSize
=
math
.
max
(
crossSize
,
_getCrossSize
(
child
));
}
if
(
alignItems
==
FlexAlignItems
.
baseline
)
{
// TODO(jackson): Support for non-alphabetic baselines
double
distance
=
child
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
,
onlyReal:
true
);
assert
(
textBaseline
!=
null
);
double
distance
=
child
.
getDistanceToBaseline
(
textBaseline
,
onlyReal:
true
);
if
(
distance
!=
null
)
maxBaselineDistance
=
math
.
max
(
maxBaselineDistance
,
distance
);
}
...
...
@@ -351,7 +365,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
child
=
child
.
parentData
.
nextSibling
;
}
// Section 8.2: Axis Alignment using the justify-content property
// Section 8.2:
Main
Axis Alignment using the justify-content property
double
remainingSpace
=
math
.
max
(
0.0
,
freeSpace
-
usedSpace
);
double
leadingSpace
;
double
betweenSpace
;
...
...
@@ -378,20 +392,16 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
break
;
}
Size
desiredSize
;
switch
(
_direction
)
{
case
FlexDirection
.
horizontal
:
desiredSize
=
new
Size
(
mainSize
,
crossSize
);
size
=
constraints
.
constrain
(
desiredSize
);
size
=
constraints
.
constrain
(
new
Size
(
mainSize
,
crossSize
));
crossSize
=
size
.
height
;
break
;
case
FlexDirection
.
vertical
:
desiredSize
=
new
Size
(
crossSize
,
mainSize
);
size
=
constraints
.
constrain
(
new
Size
(
crossSize
,
mainSize
));
crossSize
=
size
.
width
;
break
;
}
_overflowOccurredDuringLayout
=
desiredSize
!=
size
;
// Position elements
double
childMainPosition
=
leadingSpace
;
...
...
@@ -412,10 +422,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
break
;
case
FlexAlignItems
.
baseline
:
childCrossPosition
=
0.0
;
// TODO(jackson): Support for vertical baselines
if
(
_direction
==
FlexDirection
.
horizontal
)
{
// TODO(jackson): Support for non-alphabetic baselines
double
distance
=
child
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
,
onlyReal:
true
);
assert
(
textBaseline
!=
null
);
double
distance
=
child
.
getDistanceToBaseline
(
textBaseline
,
onlyReal:
true
);
if
(
distance
!=
null
)
childCrossPosition
=
maxBaselineDistance
-
distance
;
}
...
...
@@ -439,7 +448,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
void
paint
(
PaintingCanvas
canvas
,
Offset
offset
)
{
if
(
_overflow
OccurredDuringLayout
)
{
if
(
_overflow
>
0
)
{
canvas
.
save
();
canvas
.
clipRect
(
offset
&
size
);
defaultPaint
(
canvas
,
offset
);
...
...
@@ -448,4 +457,26 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
defaultPaint
(
canvas
,
offset
);
}
}
void
debugPaintSize
(
PaintingCanvas
canvas
,
Offset
offset
)
{
super
.
debugPaintSize
(
canvas
,
offset
);
if
(
_overflow
<=
0
)
return
;
// Draw a red rectangle over the overflow area in debug mode
// You should be using a Clip if you want to clip your children
Paint
paint
=
new
Paint
()..
color
=
const
Color
(
0x7FFF0000
);
Rect
overflowRect
;
switch
(
direction
)
{
case
FlexDirection
.
horizontal
:
overflowRect
=
offset
+
new
Offset
(
size
.
width
,
0.0
)
&
new
Size
(
_overflow
,
size
.
height
);
break
;
case
FlexDirection
.
vertical
:
overflowRect
=
offset
+
new
Offset
(
0.0
,
size
.
height
)
&
new
Size
(
size
.
width
,
_overflow
);
break
;
}
canvas
.
drawRect
(
overflowRect
,
paint
);
}
}
packages/flutter/lib/theme/typography.dart
View file @
90363ee9
...
...
@@ -9,20 +9,21 @@ import 'dart:sky';
import
'package:sky/painting/text_style.dart'
;
// TODO(eseidel): Font weights are supposed to be language relative!
// TODO(jackson): Baseline should be language relative!
// These values are for English-like text.
class
TextTheme
{
TextTheme
.
_
(
Color
color54
,
Color
color87
)
:
display4
=
new
TextStyle
(
fontSize:
112.0
,
fontWeight:
FontWeight
.
w100
,
color:
color54
),
display3
=
new
TextStyle
(
fontSize:
56.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
),
display2
=
new
TextStyle
(
fontSize:
45.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
,
height:
48.0
/
45.0
),
display1
=
new
TextStyle
(
fontSize:
34.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
,
height:
40.0
/
34.0
),
headline
=
new
TextStyle
(
fontSize:
24.0
,
fontWeight:
FontWeight
.
w400
,
color:
color87
,
height:
32.0
/
24.0
),
title
=
new
TextStyle
(
fontSize:
20.0
,
fontWeight:
FontWeight
.
w500
,
color:
color87
,
height:
28.0
/
20.0
),
subhead
=
new
TextStyle
(
fontSize:
16.0
,
fontWeight:
FontWeight
.
w400
,
color:
color87
,
height:
24.0
/
16.0
),
body2
=
new
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
w500
,
color:
color87
,
height:
24.0
/
14.0
),
body1
=
new
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
w400
,
color:
color87
,
height:
20.0
/
14.0
),
caption
=
new
TextStyle
(
fontSize:
12.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
),
button
=
new
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
w500
,
color:
color87
);
:
display4
=
new
TextStyle
(
fontSize:
112.0
,
fontWeight:
FontWeight
.
w100
,
color:
color54
,
textBaseline:
TextBaseline
.
alphabetic
),
display3
=
new
TextStyle
(
fontSize:
56.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
,
textBaseline:
TextBaseline
.
alphabetic
),
display2
=
new
TextStyle
(
fontSize:
45.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
,
height:
48.0
/
45.0
,
textBaseline:
TextBaseline
.
alphabetic
),
display1
=
new
TextStyle
(
fontSize:
34.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
,
height:
40.0
/
34.0
,
textBaseline:
TextBaseline
.
alphabetic
),
headline
=
new
TextStyle
(
fontSize:
24.0
,
fontWeight:
FontWeight
.
w400
,
color:
color87
,
height:
32.0
/
24.0
,
textBaseline:
TextBaseline
.
alphabetic
),
title
=
new
TextStyle
(
fontSize:
20.0
,
fontWeight:
FontWeight
.
w500
,
color:
color87
,
height:
28.0
/
20.0
,
textBaseline:
TextBaseline
.
alphabetic
),
subhead
=
new
TextStyle
(
fontSize:
16.0
,
fontWeight:
FontWeight
.
w400
,
color:
color87
,
height:
24.0
/
16.0
,
textBaseline:
TextBaseline
.
alphabetic
),
body2
=
new
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
w500
,
color:
color87
,
height:
24.0
/
14.0
,
textBaseline:
TextBaseline
.
alphabetic
),
body1
=
new
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
w400
,
color:
color87
,
height:
20.0
/
14.0
,
textBaseline:
TextBaseline
.
alphabetic
),
caption
=
new
TextStyle
(
fontSize:
12.0
,
fontWeight:
FontWeight
.
w400
,
color:
color54
,
textBaseline:
TextBaseline
.
alphabetic
),
button
=
new
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
w500
,
color:
color87
,
textBaseline:
TextBaseline
.
alphabetic
);
final
TextStyle
display4
;
final
TextStyle
display3
;
...
...
packages/flutter/lib/widgets/basic.dart
View file @
90363ee9
...
...
@@ -401,12 +401,14 @@ class Flex extends MultiChildRenderObjectWrapper {
String
key
,
this
.
direction
:
FlexDirection
.
horizontal
,
this
.
justifyContent
:
FlexJustifyContent
.
start
,
this
.
alignItems
:
FlexAlignItems
.
center
this
.
alignItems
:
FlexAlignItems
.
center
,
this
.
textBaseline
})
:
super
(
key:
key
,
children:
children
);
final
FlexDirection
direction
;
final
FlexJustifyContent
justifyContent
;
final
FlexAlignItems
alignItems
;
final
TextBaseline
textBaseline
;
RenderFlex
createNode
()
=>
new
RenderFlex
(
direction:
this
.
direction
);
RenderFlex
get
root
=>
super
.
root
;
...
...
@@ -416,6 +418,7 @@ class Flex extends MultiChildRenderObjectWrapper {
root
.
direction
=
direction
;
root
.
justifyContent
=
justifyContent
;
root
.
alignItems
=
alignItems
;
root
.
textBaseline
=
textBaseline
;
}
}
...
...
packages/flutter/lib/widgets/block_viewport.dart
View file @
90363ee9
...
...
@@ -12,13 +12,6 @@ import 'package:sky/widgets/widget.dart';
// return null if index is greater than index of last entry
typedef
Widget
IndexedBuilder
(
int
index
);
typedef
void
LayoutChangedCallback
(
int
firstVisibleChildIndex
,
int
visibleChildCount
,
UnmodifiableListView
<
double
>
childOffsets
,
bool
didReachLastChild
);
class
_Key
{
const
_Key
(
this
.
type
,
this
.
key
);
factory
_Key
.
fromWidget
(
Widget
widget
)
=>
new
_Key
(
widget
.
runtimeType
,
widget
.
key
);
...
...
@@ -26,24 +19,80 @@ class _Key {
final
String
key
;
bool
operator
==(
other
)
=>
other
is
_Key
&&
other
.
type
==
type
&&
other
.
key
==
key
;
int
get
hashCode
=>
373
*
37
*
type
.
hashCode
+
key
.
hashCode
;
String
toString
()
=>
"_Key(type:
$type
, key:
$key
)"
;
}
typedef
void
LayoutChangedCallback
(
);
class
BlockViewportLayoutState
{
BlockViewportLayoutState
()
:
_childOffsets
=
<
double
>[
0.0
],
_firstVisibleChildIndex
=
0
,
_visibleChildCount
=
0
,
_didReachLastChild
=
false
{
_readOnlyChildOffsets
=
new
UnmodifiableListView
<
double
>(
_childOffsets
);
}
Map
<
_Key
,
Widget
>
_childrenByKey
=
new
Map
<
_Key
,
Widget
>();
bool
_dirty
=
true
;
int
_firstVisibleChildIndex
;
int
get
firstVisibleChildIndex
=>
_firstVisibleChildIndex
;
int
_visibleChildCount
;
int
get
visibleChildCount
=>
_visibleChildCount
;
// childOffsets contains the offsets of each child from the top of the
// list up to the last one we've ever created, and the offset of the
// end of the last one. If there are no children, then the only offset
// is 0.0.
List
<
double
>
_childOffsets
;
UnmodifiableListView
<
double
>
_readOnlyChildOffsets
;
UnmodifiableListView
<
double
>
get
childOffsets
=>
_readOnlyChildOffsets
;
double
get
contentsSize
=>
_childOffsets
.
last
;
bool
_didReachLastChild
;
bool
get
didReachLastChild
=>
_didReachLastChild
;
Set
<
int
>
_invalidIndices
=
new
Set
<
int
>();
bool
get
isValid
=>
_invalidIndices
.
length
==
0
;
// Notify the BlockViewport that the children at indices have either
// changed size and/or changed type.
void
invalidate
(
Iterable
<
int
>
indices
)
{
_invalidIndices
.
addAll
(
indices
);
}
final
List
<
Function
>
_listeners
=
new
List
<
Function
>();
void
addListener
(
Function
listener
)
{
_listeners
.
add
(
listener
);
}
void
removeListener
(
Function
listener
)
{
_listeners
.
remove
(
listener
);
}
void
_notifyListeners
()
{
List
<
Function
>
localListeners
=
new
List
<
Function
>.
from
(
_listeners
);
for
(
Function
listener
in
localListeners
)
listener
();
}
}
class
BlockViewport
extends
RenderObjectWrapper
{
BlockViewport
({
this
.
builder
,
this
.
startOffset
,
this
.
token
,
this
.
onLayoutChanged
,
String
key
})
:
super
(
key:
key
);
BlockViewport
({
this
.
builder
,
this
.
startOffset
,
this
.
token
,
this
.
layoutState
,
String
key
})
:
super
(
key:
key
)
{
assert
(
this
.
layoutState
!=
null
);
}
IndexedBuilder
builder
;
double
startOffset
;
Object
token
;
LayoutChangedCallback
onLayoutChanged
;
BlockViewportLayoutState
layoutState
;
RenderBlockViewport
get
root
=>
super
.
root
;
RenderBlockViewport
createNode
()
=>
new
RenderBlockViewport
();
Map
<
_Key
,
Widget
>
_childrenByKey
=
new
Map
<
_Key
,
Widget
>();
void
walkChildren
(
WidgetTreeWalker
walker
)
{
for
(
Widget
child
in
_childrenByKey
.
values
)
for
(
Widget
child
in
layoutState
.
_childrenByKey
.
values
)
walker
(
child
);
}
...
...
@@ -69,7 +118,7 @@ class BlockViewport extends RenderObjectWrapper {
}
void
remove
()
{
for
(
Widget
child
in
_childrenByKey
.
values
)
{
for
(
Widget
child
in
layoutState
.
_childrenByKey
.
values
)
{
assert
(
child
!=
null
);
removeChild
(
child
);
}
...
...
@@ -86,23 +135,15 @@ class BlockViewport extends RenderObjectWrapper {
super
.
didUnmount
();
}
// _offsets contains the offsets of each child from the top of the
// list up to the last one we've ever created, and the offset of the
// end of the last one. If there's no children, then the only offset
// is 0.0.
List
<
double
>
_offsets
=
<
double
>[
0.0
];
int
_currentStartIndex
=
0
;
int
_currentChildCount
=
0
;
bool
_didReachLastChild
=
false
;
int
_findIndexForOffsetBeforeOrAt
(
double
offset
)
{
final
List
<
double
>
offsets
=
layoutState
.
_childOffsets
;
int
left
=
0
;
int
right
=
_
offsets
.
length
-
1
;
int
right
=
offsets
.
length
-
1
;
while
(
right
>=
left
)
{
int
middle
=
left
+
((
right
-
left
)
~/
2
);
if
(
_
offsets
[
middle
]
<
offset
)
{
if
(
offsets
[
middle
]
<
offset
)
{
left
=
middle
+
1
;
}
else
if
(
_
offsets
[
middle
]
>
offset
)
{
}
else
if
(
offsets
[
middle
]
>
offset
)
{
right
=
middle
-
1
;
}
else
{
return
middle
;
...
...
@@ -111,94 +152,154 @@ class BlockViewport extends RenderObjectWrapper {
return
right
;
}
bool
_dirty
=
true
;
bool
retainStatefulNodeIfPossible
(
BlockViewport
newNode
)
{
assert
(
layoutState
==
newNode
.
layoutState
);
retainStatefulRenderObjectWrapper
(
newNode
);
if
(
startOffset
!=
newNode
.
startOffset
)
{
_dirty
=
true
;
layoutState
.
_dirty
=
true
;
startOffset
=
newNode
.
startOffset
;
}
if
(
token
!=
newNode
.
token
||
builder
!=
newNode
.
builder
)
{
_dirty
=
true
;
layoutState
.
_dirty
=
true
;
builder
=
newNode
.
builder
;
token
=
newNode
.
token
;
_offsets
=
<
double
>[
0.0
];
_didReachLastChild
=
false
;
layoutState
.
_didReachLastChild
=
false
;
layoutState
.
_childOffsets
=
<
double
>[
0.0
];
layoutState
.
_invalidIndices
=
new
Set
<
int
>();
}
return
true
;
}
void
syncRenderObject
(
BlockViewport
old
)
{
super
.
syncRenderObject
(
old
);
if
(
_dirty
)
{
if
(
layoutState
.
_dirty
||
!
layoutState
.
isValid
)
{
root
.
markNeedsLayout
();
}
else
{
if
(
_current
ChildCount
>
0
)
{
assert
(
_currentStart
Index
>=
0
);
if
(
layoutState
.
_visible
ChildCount
>
0
)
{
assert
(
layoutState
.
firstVisibleChild
Index
>=
0
);
assert
(
builder
!=
null
);
assert
(
root
!=
null
);
int
lastIndex
=
_currentStartIndex
+
_currentChildCount
-
1
;
for
(
int
index
=
_currentStartIndex
;
index
<=
lastIndex
;
index
+=
1
)
{
final
int
startIndex
=
layoutState
.
_firstVisibleChildIndex
;
int
lastIndex
=
startIndex
+
layoutState
.
_visibleChildCount
-
1
;
for
(
int
index
=
startIndex
;
index
<=
lastIndex
;
index
+=
1
)
{
Widget
widget
=
builder
(
index
);
assert
(
widget
!=
null
);
assert
(
widget
.
key
!=
null
);
_Key
key
=
new
_Key
.
fromWidget
(
widget
);
Widget
oldWidget
=
_childrenByKey
[
key
];
Widget
oldWidget
=
layoutState
.
_childrenByKey
[
key
];
assert
(
oldWidget
!=
null
);
assert
(
oldWidget
.
root
.
parent
==
root
);
widget
=
syncChild
(
widget
,
oldWidget
,
root
.
childAfter
(
oldWidget
.
root
));
assert
(
widget
!=
null
);
_childrenByKey
[
key
]
=
widget
;
layoutState
.
_childrenByKey
[
key
]
=
widget
;
}
}
}
}
// Build the widget at index, and use its maxIntrinsicHeight to fix up
// the offsets from index+1 to endIndex. Return the newWidget.
Widget
_getWidgetAndRecomputeOffsets
(
int
index
,
int
endIndex
,
BoxConstraints
innerConstraints
)
{
final
List
<
double
>
offsets
=
layoutState
.
_childOffsets
;
// Create the newWidget at index.
assert
(
index
>=
0
);
assert
(
endIndex
>
index
);
assert
(
endIndex
<
offsets
.
length
);
assert
(
builder
!=
null
);
Widget
newWidget
=
builder
(
index
);
assert
(
newWidget
!=
null
);
assert
(
newWidget
.
key
!=
null
);
final
_Key
key
=
new
_Key
.
fromWidget
(
newWidget
);
Widget
oldWidget
=
layoutState
.
_childrenByKey
[
key
];
newWidget
=
syncChild
(
newWidget
,
oldWidget
,
_omit
);
assert
(
newWidget
!=
null
);
// Update the offsets based on the newWidget's height.
RenderBox
widgetRoot
=
newWidget
.
root
;
assert
(
widgetRoot
is
RenderBox
);
double
newHeight
=
widgetRoot
.
getMaxIntrinsicHeight
(
innerConstraints
);
double
oldHeight
=
offsets
[
index
+
1
]
-
offsets
[
index
];
double
heightDelta
=
newHeight
-
oldHeight
;
for
(
int
i
=
index
+
1
;
i
<=
endIndex
;
i
++)
offsets
[
i
]
+=
heightDelta
;
return
newWidget
;
}
Widget
_getWidget
(
int
index
,
BoxConstraints
innerConstraints
)
{
final
List
<
double
>
offsets
=
layoutState
.
_childOffsets
;
assert
(
index
>=
0
);
Widget
widget
=
builder
==
null
?
null
:
builder
(
index
);
if
(
widget
==
null
)
return
null
;
assert
(
widget
.
key
!=
null
);
// items in lists must have keys
final
_Key
key
=
new
_Key
.
fromWidget
(
widget
);
Widget
oldWidget
=
layoutState
.
_childrenByKey
[
key
];
widget
=
syncChild
(
widget
,
oldWidget
,
_omit
);
if
(
index
>=
offsets
.
length
-
1
)
{
assert
(
index
==
offsets
.
length
-
1
);
final
double
widgetStartOffset
=
offsets
[
index
];
RenderBox
widgetRoot
=
widget
.
root
;
assert
(
widgetRoot
is
RenderBox
);
final
double
widgetEndOffset
=
widgetStartOffset
+
widgetRoot
.
getMaxIntrinsicHeight
(
innerConstraints
);
offsets
.
add
(
widgetEndOffset
);
}
return
widget
;
}
void
layout
(
BoxConstraints
constraints
)
{
if
(!
layoutState
.
_dirty
&&
layoutState
.
isValid
)
return
;
layoutState
.
_dirty
=
false
;
LayoutCallbackBuilderHandle
handle
=
enterLayoutCallbackBuilder
();
try
{
assert
(
index
>=
0
);
Widget
widget
=
builder
==
null
?
null
:
builder
(
index
);
if
(
widget
==
null
)
return
null
;
assert
(
widget
.
key
!=
null
);
// items in lists must have keys
final
_Key
key
=
new
_Key
.
fromWidget
(
widget
);
Widget
oldWidget
=
_childrenByKey
[
key
];
widget
=
syncChild
(
widget
,
oldWidget
,
_omit
);
if
(
oldWidget
!=
null
)
_childrenByKey
[
key
]
=
widget
;
if
(
index
>=
_offsets
.
length
-
1
)
{
assert
(
index
==
_offsets
.
length
-
1
);
final
double
widgetStartOffset
=
_offsets
[
index
];
RenderBox
widgetRoot
=
widget
.
root
;
assert
(
widgetRoot
is
RenderBox
);
final
double
widgetEndOffset
=
widgetStartOffset
+
widgetRoot
.
getMaxIntrinsicHeight
(
innerConstraints
);
_offsets
.
add
(
widgetEndOffset
);
}
return
widget
;
_doLayout
(
constraints
);
}
finally
{
exitLayoutCallbackBuilder
(
handle
);
}
}
void
layout
(
BoxConstraints
constraints
)
{
if
(!
_dirty
)
return
;
_dirty
=
false
;
layoutState
.
_notifyListeners
();
}
void
_doLayout
(
BoxConstraints
constraints
)
{
Map
<
_Key
,
Widget
>
newChildren
=
new
Map
<
_Key
,
Widget
>();
Map
<
int
,
Widget
>
builtChildren
=
new
Map
<
int
,
Widget
>();
final
List
<
double
>
offsets
=
layoutState
.
_childOffsets
;
final
Map
<
_Key
,
Widget
>
childrenByKey
=
layoutState
.
_childrenByKey
;
final
double
height
=
root
.
size
.
height
;
final
double
endOffset
=
startOffset
+
height
;
BoxConstraints
innerConstraints
=
new
BoxConstraints
.
tightFor
(
width:
constraints
.
constrainWidth
());
// Before doing the actual layout, fix the offsets for the widgets
// whose size or type has changed.
if
(!
layoutState
.
isValid
&&
offsets
.
length
>
0
)
{
List
<
int
>
invalidIndices
=
layoutState
.
_invalidIndices
.
toList
();
invalidIndices
.
sort
();
// Ensure all of the offsets after invalidIndices[0] are updated.
if
(
invalidIndices
.
last
<
offsets
.
length
-
1
)
invalidIndices
.
add
(
offsets
.
length
-
1
);
for
(
int
i
=
0
;
i
<
invalidIndices
.
length
-
1
;
i
+=
1
)
{
int
index
=
invalidIndices
[
i
];
int
endIndex
=
invalidIndices
[
i
+
1
];
Widget
widget
=
_getWidgetAndRecomputeOffsets
(
index
,
endIndex
,
innerConstraints
);
_Key
widgetKey
=
new
_Key
.
fromWidget
(
widget
);
bool
isVisible
=
offsets
[
index
]
<
endOffset
&&
offsets
[
index
+
1
]
>=
startOffset
;
if
(
isVisible
)
{
newChildren
[
widgetKey
]
=
widget
;
builtChildren
[
index
]
=
widget
;
}
else
{
childrenByKey
.
remove
(
widgetKey
);
syncChild
(
null
,
widget
,
null
);
}
}
}
layoutState
.
_invalidIndices
.
clear
();
int
startIndex
;
bool
haveChildren
;
if
(
startOffset
<=
0.0
)
{
startIndex
=
0
;
if
(
_
offsets
.
length
>
1
)
{
if
(
offsets
.
length
>
1
)
{
haveChildren
=
true
;
}
else
{
Widget
widget
=
_getWidget
(
startIndex
,
innerConstraints
);
...
...
@@ -208,41 +309,41 @@ class BlockViewport extends RenderObjectWrapper {
haveChildren
=
true
;
}
else
{
haveChildren
=
false
;
_didReachLastChild
=
true
;
layoutState
.
_didReachLastChild
=
true
;
}
}
}
else
{
startIndex
=
_findIndexForOffsetBeforeOrAt
(
startOffset
);
if
(
startIndex
==
_
offsets
.
length
-
1
)
{
if
(
startIndex
==
offsets
.
length
-
1
)
{
// We don't have an offset on the list that is beyond the start offset.
assert
(
_
offsets
.
last
<=
startOffset
);
assert
(
offsets
.
last
<=
startOffset
);
// Fill the list until this isn't true or until we know that the
// list is complete (and thus we are overscrolled).
while
(
true
)
{
Widget
widget
=
_getWidget
(
startIndex
,
innerConstraints
);
if
(
widget
==
null
)
{
_didReachLastChild
=
true
;
layoutState
.
_didReachLastChild
=
true
;
break
;
}
_Key
widgetKey
=
new
_Key
.
fromWidget
(
widget
);
if
(
_
offsets
.
last
>
startOffset
)
{
if
(
offsets
.
last
>
startOffset
)
{
newChildren
[
widgetKey
]
=
widget
;
builtChildren
[
startIndex
]
=
widget
;
break
;
}
if
(!
_
childrenByKey
.
containsKey
(
widgetKey
))
{
if
(!
childrenByKey
.
containsKey
(
widgetKey
))
{
// we don't actually need this one, release it
syncChild
(
null
,
widget
,
null
);
}
// else we'll get rid of it later, when we remove old children
startIndex
+=
1
;
assert
(
startIndex
==
_
offsets
.
length
-
1
);
assert
(
startIndex
==
offsets
.
length
-
1
);
}
if
(
_
offsets
.
last
>
startOffset
)
{
if
(
offsets
.
last
>
startOffset
)
{
// If we're here, we have at least one child, so our list has
// at least two offsets, the top of the child and the bottom
// of the child.
assert
(
_
offsets
.
length
>=
2
);
assert
(
startIndex
==
_
offsets
.
length
-
2
);
assert
(
offsets
.
length
>=
2
);
assert
(
startIndex
==
offsets
.
length
-
2
);
haveChildren
=
true
;
}
else
{
// If we're here, there are no children to show.
...
...
@@ -253,20 +354,20 @@ class BlockViewport extends RenderObjectWrapper {
}
}
assert
(
haveChildren
!=
null
);
assert
(
haveChildren
||
_didReachLastChild
);
assert
(
haveChildren
||
layoutState
.
_didReachLastChild
);
assert
(
startIndex
>=
0
);
assert
(
startIndex
<
_
offsets
.
length
);
assert
(
startIndex
<
offsets
.
length
);
int
index
=
startIndex
;
if
(
haveChildren
)
{
// Build all the widgets we need.
root
.
startOffset
=
_
offsets
[
index
]
-
startOffset
;
while
(
_
offsets
[
index
]
<
endOffset
)
{
root
.
startOffset
=
offsets
[
index
]
-
startOffset
;
while
(
offsets
[
index
]
<
endOffset
)
{
if
(!
builtChildren
.
containsKey
(
index
))
{
Widget
widget
=
_getWidget
(
index
,
innerConstraints
);
if
(
widget
==
null
)
{
_didReachLastChild
=
true
;
layoutState
.
_didReachLastChild
=
true
;
break
;
}
newChildren
[
new
_Key
.
fromWidget
(
widget
)]
=
widget
;
...
...
@@ -278,9 +379,9 @@ class BlockViewport extends RenderObjectWrapper {
}
// Remove any old children.
for
(
_Key
oldChildKey
in
_
childrenByKey
.
keys
)
{
for
(
_Key
oldChildKey
in
childrenByKey
.
keys
)
{
if
(!
newChildren
.
containsKey
(
oldChildKey
))
syncChild
(
null
,
_
childrenByKey
[
oldChildKey
],
null
);
// calls detachChildRoot()
syncChild
(
null
,
childrenByKey
[
oldChildKey
],
null
);
// calls detachChildRoot()
}
if
(
haveChildren
)
{
...
...
@@ -302,18 +403,9 @@ class BlockViewport extends RenderObjectWrapper {
}
}
_childrenByKey
=
newChildren
;
_currentStartIndex
=
startIndex
;
_currentChildCount
=
_childrenByKey
.
length
;
if
(
onLayoutChanged
!=
null
)
{
onLayoutChanged
(
_currentStartIndex
,
_currentChildCount
,
new
UnmodifiableListView
<
double
>(
_offsets
),
_didReachLastChild
);
}
layoutState
.
_childrenByKey
=
newChildren
;
layoutState
.
_firstVisibleChildIndex
=
startIndex
;
layoutState
.
_visibleChildCount
=
newChildren
.
length
;
}
}
packages/flutter/lib/widgets/card.dart
View file @
90363ee9
...
...
@@ -5,6 +5,8 @@
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/material.dart'
;
const
EdgeDims
kCardMargins
=
const
EdgeDims
.
all
(
4.0
);
/// A material design card
///
/// <https://www.google.com/design/spec/components/cards.html>
...
...
@@ -16,7 +18,7 @@ class Card extends Component {
Widget
build
()
{
return
new
Container
(
margin:
const
EdgeDims
.
all
(
4.0
)
,
margin:
kCardMargins
,
child:
new
Material
(
color:
color
,
type:
MaterialType
.
card
,
...
...
packages/flutter/lib/widgets/dismissable.dart
View file @
90363ee9
...
...
@@ -10,7 +10,7 @@ import 'package:sky/widgets/basic.dart';
import
'package:sky/widgets/widget.dart'
;
import
'package:vector_math/vector_math.dart'
;
const
Duration
_kCardDismissFadeout
=
const
Duration
(
milliseconds:
3
00
);
const
Duration
_kCardDismissFadeout
=
const
Duration
(
milliseconds:
2
00
);
const
double
_kMinFlingVelocity
=
700.0
;
const
double
_kMinFlingVelocityDelta
=
400.0
;
const
double
_kFlingVelocityScale
=
1.0
/
300.0
;
...
...
@@ -64,6 +64,8 @@ class Dismissable extends AnimatedComponent {
}
void
_maybeCallOnDismissed
()
{
_performance
.
stop
();
_performance
.
removeListener
(
_handleAnimationProgressChanged
);
if
(
onDismissed
!=
null
)
onDismissed
();
}
...
...
@@ -112,7 +114,7 @@ class Dismissable extends AnimatedComponent {
if
(
_performance
.
isCompleted
)
_maybeCallOnDismissed
();
else
if
(!
_performance
.
isAnimating
)
_performance
.
progress
=
0.0
;
_performance
.
reverse
()
;
});
}
...
...
packages/flutter/lib/widgets/snack_bar.dart
View file @
90363ee9
...
...
@@ -53,7 +53,9 @@ class SnackBar extends Component {
)
)
)
]..
addAll
(
actions
);
];
if
(
actions
!=
null
)
children
.
addAll
(
actions
);
return
new
Material
(
level:
2
,
color:
const
Color
(
0xFF323232
),
...
...
packages/flutter/lib/widgets/tool_bar.dart
View file @
90363ee9
...
...
@@ -31,12 +31,14 @@ class ToolBar extends Component {
Widget
build
()
{
Color
toolbarColor
=
backgroundColor
;
IconThemeData
iconThemeData
;
TextStyle
defaultTextStyle
=
typography
.
white
.
title
;
TextStyle
centerStyle
=
typography
.
white
.
title
;
TextStyle
sideStyle
=
typography
.
white
.
body1
;
if
(
toolbarColor
==
null
)
{
ThemeData
themeData
=
Theme
.
of
(
this
);
toolbarColor
=
themeData
.
primaryColor
;
if
(
themeData
.
primaryColorBrightness
==
ThemeBrightness
.
light
)
{
defaultTextStyle
=
typography
.
black
.
title
;
centerStyle
=
typography
.
black
.
title
;
sideStyle
=
typography
.
black
.
body2
;
iconThemeData
=
const
IconThemeData
(
color:
IconThemeColor
.
black
);
}
else
{
iconThemeData
=
const
IconThemeData
(
color:
IconThemeColor
.
white
);
...
...
@@ -50,7 +52,7 @@ class ToolBar extends Component {
children
.
add
(
new
Flexible
(
child:
new
Padding
(
child:
center
,
child:
new
DefaultTextStyle
(
child:
center
,
style:
centerStyle
)
,
padding:
new
EdgeDims
.
only
(
left:
24.0
)
)
)
...
...
@@ -61,7 +63,7 @@ class ToolBar extends Component {
Widget
content
=
new
Container
(
child:
new
DefaultTextStyle
(
style:
defaultText
Style
,
style:
side
Style
,
child:
new
Flex
(
[
new
Container
(
child:
new
Flex
(
children
),
height:
kToolBarHeight
)],
alignItems:
FlexAlignItems
.
end
...
...
packages/flutter/lib/widgets/variable_height_scrollable.dart
View file @
90363ee9
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:collection'
;
import
'package:sky/animation/scroll_behavior.dart'
;
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/block_viewport.dart'
;
...
...
@@ -14,18 +12,47 @@ class VariableHeightScrollable extends Scrollable {
VariableHeightScrollable
({
String
key
,
this
.
builder
,
this
.
token
this
.
token
,
this
.
layoutState
})
:
super
(
key:
key
);
IndexedBuilder
builder
;
Object
token
;
BlockViewportLayoutState
layoutState
;
// When the token changes the scrollable's contents may have
// changed. Remember as much so that after the new contents
// have been laid out we can adjust the scrollOffset so that
// the last page of content is still visible.
bool
_contentsChanged
=
true
;
void
initState
()
{
assert
(
layoutState
!=
null
);
super
.
initState
();
}
void
didMount
()
{
layoutState
.
addListener
(
_handleLayoutChanged
);
super
.
didMount
();
}
void
didUnmount
()
{
layoutState
.
removeListener
(
_handleLayoutChanged
);
super
.
didUnmount
();
}
void
syncFields
(
VariableHeightScrollable
source
)
{
builder
=
source
.
builder
;
if
(
token
!=
source
.
token
)
_contentsChanged
=
true
;
token
=
source
.
token
;
if
(
layoutState
!=
source
.
layoutState
)
{
// Warning: this is unlikely to be what you intended.
assert
(
source
.
layoutState
!=
null
);
layoutState
.
removeListener
(
_handleLayoutChanged
);
layoutState
=
source
.
layoutState
;
layoutState
.
addListener
(
_handleLayoutChanged
);
}
super
.
syncFields
(
source
);
}
...
...
@@ -36,15 +63,9 @@ class VariableHeightScrollable extends Scrollable {
scrollBehavior
.
containerSize
=
newSize
.
height
;
}
void
_handleLayoutChanged
(
int
firstVisibleChildIndex
,
int
visibleChildCount
,
UnmodifiableListView
<
double
>
childOffsets
,
bool
didReachLastChild
)
{
assert
(
childOffsets
.
length
>
0
);
if
(
didReachLastChild
)
{
scrollBehavior
.
contentsSize
=
childOffsets
.
last
;
void
_handleLayoutChanged
()
{
if
(
layoutState
.
didReachLastChild
)
{
scrollBehavior
.
contentsSize
=
layoutState
.
contentsSize
;
if
(
_contentsChanged
&&
scrollOffset
>
scrollBehavior
.
maxScrollOffset
)
{
_contentsChanged
=
false
;
settleScrollOffset
();
...
...
@@ -59,7 +80,7 @@ class VariableHeightScrollable extends Scrollable {
callback:
_handleSizeChanged
,
child:
new
BlockViewport
(
builder:
builder
,
onLayoutChanged:
_handleLayoutChanged
,
layoutState:
layoutState
,
startOffset:
scrollOffset
,
token:
token
)
...
...
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