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
ba8f6a01
Commit
ba8f6a01
authored
Nov 20, 2015
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #510 from abarth/custom_paint
Callback identity is too fragile for CustomPaint
parents
ea6292e1
72329cf4
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
461 additions
and
264 deletions
+461
-264
baseline.dart
examples/rendering/baseline.dart
+33
-18
stock_arrow.dart
examples/stocks/lib/stock_arrow.dart
+54
-39
gestures.dart
examples/widgets/gestures.dart
+49
-48
overlay_geometry.dart
examples/widgets/overlay_geometry.dart
+30
-10
dropdown.dart
packages/flutter/lib/src/material/dropdown.dart
+44
-14
popup_menu.dart
packages/flutter/lib/src/material/popup_menu.dart
+38
-12
progress_indicator.dart
packages/flutter/lib/src/material/progress_indicator.dart
+65
-24
radio.dart
packages/flutter/lib/src/material/radio.dart
+42
-23
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+29
-29
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+7
-21
gridpaper.dart
packages/flutter/lib/src/widgets/gridpaper.dart
+35
-13
offstage_test.dart
packages/unit/test/rendering/offstage_test.dart
+4
-4
overflow_test.dart
packages/unit/test/rendering/overflow_test.dart
+12
-8
rendering_tester.dart
packages/unit/test/rendering/rendering_tester.dart
+12
-0
stack_test.dart
packages/unit/test/widget/stack_test.dart
+7
-1
No files found.
examples/rendering/baseline.dart
View file @
ba8f6a01
...
...
@@ -6,6 +6,35 @@ import 'dart:ui' as ui;
import
'package:flutter/rendering.dart'
;
class
_BaselinePainter
extends
CustomPainter
{
const
_BaselinePainter
({
this
.
paragraph
});
final
RenderParagraph
paragraph
;
void
paint
(
Canvas
canvas
,
Size
size
)
{
double
baseline
=
paragraph
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
);
double
w
=
paragraph
.
getMaxIntrinsicWidth
(
new
BoxConstraints
.
loose
(
size
));
double
h
=
paragraph
.
getMaxIntrinsicHeight
(
new
BoxConstraints
.
loose
(
size
));
Path
path
=
new
Path
();
path
.
moveTo
(
0.0
,
0.0
);
path
.
lineTo
(
w
,
0.0
);
path
.
moveTo
(
0.0
,
baseline
);
path
.
lineTo
(
w
,
baseline
);
path
.
moveTo
(
0.0
,
h
);
path
.
lineTo
(
w
,
h
);
Paint
paint
=
new
Paint
()
..
color
=
const
Color
(
0xFFFF9000
)
..
style
=
ui
.
PaintingStyle
.
stroke
..
strokeWidth
=
3.0
;
canvas
.
drawPath
(
path
,
paint
);
}
// TODO(abarth): We have no good way of detecting when the paragraph's intrinsic dimensions change.
bool
shouldRepaint
(
_BaselinePainter
oldPainter
)
=>
true
;
}
RenderBox
getBox
(
double
lh
)
{
RenderParagraph
paragraph
=
new
RenderParagraph
(
new
StyledTextSpan
(
...
...
@@ -36,24 +65,10 @@ RenderBox getBox(double lh) {
child:
new
RenderPadding
(
padding:
new
EdgeDims
.
all
(
10.0
),
child:
new
RenderCustomPaint
(
child:
paragraph
,
onPaint:
(
PaintingCanvas
canvas
,
Size
size
)
{
double
baseline
=
paragraph
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
);
double
w
=
paragraph
.
getMaxIntrinsicWidth
(
new
BoxConstraints
.
loose
(
size
));
double
h
=
paragraph
.
getMaxIntrinsicHeight
(
new
BoxConstraints
.
loose
(
size
));
Path
path
=
new
Path
();
path
.
moveTo
(
0.0
,
0.0
);
path
.
lineTo
(
w
,
0.0
);
path
.
moveTo
(
0.0
,
baseline
);
path
.
lineTo
(
w
,
baseline
);
path
.
moveTo
(
0.0
,
h
);
path
.
lineTo
(
w
,
h
);
Paint
paint
=
new
Paint
()
..
color
=
const
Color
(
0xFFFF9000
)
..
style
=
ui
.
PaintingStyle
.
stroke
..
strokeWidth
=
3.0
;
canvas
.
drawPath
(
path
,
paint
);
}
painter:
new
_BaselinePainter
(
paragraph:
paragraph
),
child:
paragraph
)
)
)
...
...
examples/stocks/lib/stock_arrow.dart
View file @
ba8f6a01
...
...
@@ -4,6 +4,50 @@
part of
stocks
;
class
StockArrowPainter
extends
CustomPainter
{
StockArrowPainter
({
this
.
color
,
this
.
percentChange
});
final
Color
color
;
final
double
percentChange
;
void
paint
(
PaintingCanvas
canvas
,
Size
size
)
{
Paint
paint
=
new
Paint
()..
color
=
color
;
paint
.
strokeWidth
=
1.0
;
const
double
padding
=
2.0
;
assert
(
padding
>
paint
.
strokeWidth
/
2.0
);
// make sure the circle remains inside the box
double
r
=
(
size
-
padding
)
/
2.0
;
// radius of the circle
double
centerX
=
padding
+
r
;
double
centerY
=
padding
+
r
;
// Draw the arrow.
double
w
=
8.0
;
double
h
=
5.0
;
double
arrowY
;
if
(
percentChange
<
0.0
)
{
h
=
-
h
;
arrowY
=
centerX
+
1.0
;
}
else
{
arrowY
=
centerX
-
1.0
;
}
Path
path
=
new
Path
();
path
.
moveTo
(
centerX
,
arrowY
-
h
);
// top of the arrow
path
.
lineTo
(
centerX
+
w
,
arrowY
+
h
);
path
.
lineTo
(
centerX
-
w
,
arrowY
+
h
);
path
.
close
();
paint
.
style
=
ui
.
PaintingStyle
.
fill
;
canvas
.
drawPath
(
path
,
paint
);
// Draw a circle that circumscribes the arrow.
paint
.
style
=
ui
.
PaintingStyle
.
stroke
;
canvas
.
drawCircle
(
new
Point
(
centerX
,
centerY
),
r
,
paint
);
}
bool
shouldRepaint
(
StockArrowPainter
oldPainter
)
{
return
oldPainter
.
color
!=
color
||
oldPainter
.
percentChange
!=
percentChange
;
}
}
class
StockArrow
extends
StatelessComponent
{
StockArrow
({
Key
key
,
this
.
percentChange
})
:
super
(
key:
key
);
...
...
@@ -22,46 +66,17 @@ class StockArrow extends StatelessComponent {
}
Widget
build
(
BuildContext
context
)
{
// TODO(jackson): This should change colors with the theme
Color
color
=
_colorForPercentChange
(
percentChange
);
const
double
kSize
=
40.0
;
var
arrow
=
new
CustomPaint
(
onPaint:
(
ui
.
Canvas
canvas
,
Size
size
)
{
Paint
paint
=
new
Paint
()..
color
=
color
;
paint
.
strokeWidth
=
1.0
;
const
double
padding
=
2.0
;
assert
(
padding
>
paint
.
strokeWidth
/
2.0
);
// make sure the circle remains inside the box
double
r
=
(
kSize
-
padding
)
/
2.0
;
// radius of the circle
double
centerX
=
padding
+
r
;
double
centerY
=
padding
+
r
;
// Draw the arrow.
double
w
=
8.0
;
double
h
=
5.0
;
double
arrowY
;
if
(
percentChange
<
0.0
)
{
h
=
-
h
;
arrowY
=
centerX
+
1.0
;
}
else
{
arrowY
=
centerX
-
1.0
;
}
Path
path
=
new
Path
();
path
.
moveTo
(
centerX
,
arrowY
-
h
);
// top of the arrow
path
.
lineTo
(
centerX
+
w
,
arrowY
+
h
);
path
.
lineTo
(
centerX
-
w
,
arrowY
+
h
);
path
.
close
();
paint
.
style
=
ui
.
PaintingStyle
.
fill
;
canvas
.
drawPath
(
path
,
paint
);
// Draw a circle that circumscribes the arrow.
paint
.
style
=
ui
.
PaintingStyle
.
stroke
;
canvas
.
drawCircle
(
new
Point
(
centerX
,
centerY
),
r
,
paint
);
});
return
new
Container
(
child:
arrow
,
width:
kSize
,
height:
kSize
,
margin:
const
EdgeDims
.
symmetric
(
horizontal:
5.0
)
width:
40.0
,
height:
40.0
,
margin:
const
EdgeDims
.
symmetric
(
horizontal:
5.0
),
child:
new
CustomPaint
(
painter:
new
StockArrowPainter
(
// TODO(jackson): This should change colors with the theme
color:
_colorForPercentChange
(
percentChange
),
percentChange:
percentChange
)
)
);
}
}
examples/widgets/gestures.dart
View file @
ba8f6a01
...
...
@@ -9,42 +9,49 @@ class ScaleApp extends StatefulComponent {
ScaleAppState
createState
()
=>
new
ScaleAppState
();
}
class
GesturesDemoPaintToken
{
GesturesDemoPaintToken
(
this
.
zoom
,
this
.
offset
,
this
.
swatch
,
this
.
forward
,
this
.
flag1
,
this
.
flag2
,
this
.
flag3
,
this
.
flag4
);
final
Offset
offset
;
class
_GesturePainter
extends
CustomPainter
{
const
_GesturePainter
({
this
.
zoom
,
this
.
offset
,
this
.
swatch
,
this
.
forward
,
this
.
scaleEnabled
,
this
.
tapEnabled
,
this
.
doubleTapEnabled
,
this
.
longPressEnabled
});
final
double
zoom
;
final
Offset
offset
;
final
Map
<
int
,
Color
>
swatch
;
final
bool
forward
;
final
bool
flag1
;
final
bool
flag2
;
final
bool
flag3
;
final
bool
flag4
;
bool
operator
==(
dynamic
other
)
{
if
(
identical
(
this
,
other
))
return
true
;
if
(
other
is
!
GesturesDemoPaintToken
)
return
false
;
final
GesturesDemoPaintToken
typedOther
=
other
;
return
offset
==
typedOther
.
offset
&&
zoom
==
typedOther
.
zoom
&&
identical
(
swatch
,
typedOther
.
swatch
)
&&
forward
==
typedOther
.
forward
&&
flag1
==
typedOther
.
flag1
&&
flag2
==
typedOther
.
flag2
&&
flag3
==
typedOther
.
flag3
&&
flag4
==
typedOther
.
flag4
;
final
bool
scaleEnabled
;
final
bool
tapEnabled
;
final
bool
doubleTapEnabled
;
final
bool
longPressEnabled
;
void
paint
(
PaintingCanvas
canvas
,
Size
size
)
{
Point
center
=
(
size
.
center
(
Point
.
origin
).
toOffset
()
*
zoom
+
offset
).
toPoint
();
double
radius
=
size
.
width
/
2.0
*
zoom
;
Gradient
gradient
=
new
RadialGradient
(
center:
center
,
radius:
radius
,
colors:
forward
?
<
Color
>[
swatch
[
50
],
swatch
[
900
]]
:
<
Color
>[
swatch
[
900
],
swatch
[
50
]]
);
Paint
paint
=
new
Paint
()
..
shader
=
gradient
.
createShader
();
canvas
.
drawCircle
(
center
,
radius
,
paint
);
}
int
get
hashCode
{
int
value
=
373
;
value
=
37
*
value
+
offset
.
hashCode
;
value
=
37
*
value
+
zoom
.
hashCode
;
value
=
37
*
value
+
identityHashCode
(
swatch
);
value
=
37
*
value
+
forward
.
hashCode
;
value
=
37
*
value
+
flag1
.
hashCode
;
value
=
37
*
value
+
flag2
.
hashCode
;
value
=
37
*
value
+
flag3
.
hashCode
;
value
=
37
*
value
+
flag4
.
hashCode
;
return
value
;
bool
shouldRepaint
(
_GesturePainter
oldPainter
)
{
return
oldPainter
.
zoom
!=
zoom
||
oldPainter
.
offset
!=
offset
||
oldPainter
.
swatch
!=
swatch
||
oldPainter
.
forward
!=
forward
||
oldPainter
.
scaleEnabled
!=
scaleEnabled
||
oldPainter
.
tapEnabled
!=
tapEnabled
||
oldPainter
.
doubleTapEnabled
!=
doubleTapEnabled
||
oldPainter
.
longPressEnabled
!=
longPressEnabled
;
}
}
...
...
@@ -124,18 +131,6 @@ class ScaleAppState extends State<ScaleApp> {
});
}
void
paint
(
PaintingCanvas
canvas
,
Size
size
)
{
Point
center
=
(
size
.
center
(
Point
.
origin
).
toOffset
()
*
_zoom
+
_offset
).
toPoint
();
double
radius
=
size
.
width
/
2.0
*
_zoom
;
Gradient
gradient
=
new
RadialGradient
(
center:
center
,
radius:
radius
,
colors:
_forward
?
<
Color
>[
_swatch
[
50
],
_swatch
[
900
]]
:
<
Color
>[
_swatch
[
900
],
_swatch
[
50
]]
);
Paint
paint
=
new
Paint
()
..
shader
=
gradient
.
createShader
();
canvas
.
drawCircle
(
center
,
radius
,
paint
);
}
Widget
build
(
BuildContext
context
)
{
return
new
Theme
(
...
...
@@ -151,10 +146,16 @@ class ScaleAppState extends State<ScaleApp> {
onDoubleTap:
_doubleTapEnabled
?
_handleScaleReset
:
null
,
onLongPress:
_longPressEnabled
?
_handleDirectionChange
:
null
,
child:
new
CustomPaint
(
onPaint:
paint
,
token:
new
GesturesDemoPaintToken
(
_zoom
,
_offset
,
_swatch
,
_forward
,
_scaleEnabled
,
_tapEnabled
,
_doubleTapEnabled
,
_longPressEnabled
)
painter:
new
_GesturePainter
(
zoom:
_zoom
,
offset:
_offset
,
swatch:
_swatch
,
forward:
_forward
,
scaleEnabled:
_scaleEnabled
,
tapEnabled:
_tapEnabled
,
doubleTapEnabled:
_doubleTapEnabled
,
longPressEnabled:
_longPressEnabled
)
)
),
new
Positioned
(
...
...
examples/widgets/overlay_geometry.dart
View file @
ba8f6a01
...
...
@@ -19,19 +19,16 @@ class CardModel {
enum
MarkerType
{
topLeft
,
bottomRight
,
touch
}
class
Marker
extends
StatelessComponent
{
Marker
({
this
.
type
:
MarkerType
.
touch
,
this
.
position
,
this
.
size
:
40.0
,
Key
key
})
:
super
(
key:
key
);
class
_MarkerPainter
extends
CustomPainter
{
const
_MarkerPainter
({
this
.
size
,
this
.
type
});
final
Point
position
;
final
double
size
;
final
MarkerType
type
;
void
paint
Marker
(
PaintingCanvas
canvas
,
_
)
{
void
paint
(
PaintingCanvas
canvas
,
_
)
{
Paint
paint
=
new
Paint
()..
color
=
const
Color
(
0x8000FF00
);
double
r
=
size
/
2.0
;
canvas
.
drawCircle
(
new
Point
(
r
,
r
),
r
,
paint
);
...
...
@@ -50,6 +47,24 @@ class Marker extends StatelessComponent {
}
}
bool
shouldRepaint
(
_MarkerPainter
oldPainter
)
{
return
oldPainter
.
size
!=
size
||
oldPainter
.
type
!=
type
;
}
}
class
Marker
extends
StatelessComponent
{
Marker
({
this
.
type
:
MarkerType
.
touch
,
this
.
position
,
this
.
size
:
40.0
,
Key
key
})
:
super
(
key:
key
);
final
Point
position
;
final
double
size
;
final
MarkerType
type
;
Widget
build
(
BuildContext
context
)
{
return
new
Positioned
(
left:
position
.
x
-
size
/
2.0
,
...
...
@@ -57,7 +72,12 @@ class Marker extends StatelessComponent {
width:
size
,
height:
size
,
child:
new
IgnorePointer
(
child:
new
CustomPaint
(
onPaint:
paintMarker
)
child:
new
CustomPaint
(
painter:
new
_MarkerPainter
(
size:
size
,
type:
type
)
)
)
);
}
...
...
packages/flutter/lib/src/material/dropdown.dart
View file @
ba8f6a01
...
...
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/animation.dart'
;
import
'package:flutter/painting.dart'
;
...
...
@@ -21,6 +20,42 @@ const EdgeDims _kMenuHorizontalPadding = const EdgeDims.only(left: 36.0, right:
const
double
_kBaselineOffsetFromBottom
=
20.0
;
const
Border
_kDropdownUnderline
=
const
Border
(
bottom:
const
BorderSide
(
color:
const
Color
(
0xFFBDBDBD
),
width:
2.0
));
class
_DropdownMenuPainter
extends
CustomPainter
{
const
_DropdownMenuPainter
({
this
.
color
,
this
.
elevation
,
this
.
menuTop
,
this
.
menuBottom
,
this
.
renderBox
});
final
Color
color
;
final
int
elevation
;
final
double
menuTop
;
final
double
menuBottom
;
final
RenderBox
renderBox
;
void
paint
(
Canvas
canvas
,
Size
size
)
{
final
BoxPainter
painter
=
new
BoxPainter
(
new
BoxDecoration
(
backgroundColor:
color
,
borderRadius:
2.0
,
boxShadow:
elevationToShadow
[
elevation
]
));
double
top
=
renderBox
.
globalToLocal
(
new
Point
(
0.0
,
menuTop
)).
y
;
double
bottom
=
renderBox
.
globalToLocal
(
new
Point
(
0.0
,
menuBottom
)).
y
;
painter
.
paint
(
canvas
,
new
Rect
.
fromLTRB
(
0.0
,
top
,
size
.
width
,
bottom
));
}
bool
shouldRepaint
(
_DropdownMenuPainter
oldPainter
)
{
return
oldPainter
.
color
!=
color
||
oldPainter
.
elevation
!=
elevation
||
oldPainter
.
menuTop
!=
menuTop
||
oldPainter
.
menuBottom
!=
menuBottom
||
oldPainter
.
renderBox
!=
renderBox
;
}
}
class
_DropdownMenu
extends
StatusTransitionComponent
{
_DropdownMenu
({
Key
key
,
...
...
@@ -82,12 +117,6 @@ class _DropdownMenu extends StatusTransitionComponent {
reverseCurve:
const
Interval
(
0.0
,
0.001
)
);
final
BoxPainter
menuPainter
=
new
BoxPainter
(
new
BoxDecoration
(
backgroundColor:
Theme
.
of
(
context
).
canvasColor
,
borderRadius:
2.0
,
boxShadow:
elevationToShadow
[
route
.
elevation
]
));
final
RenderBox
renderBox
=
Navigator
.
of
(
context
).
context
.
findRenderObject
();
final
Size
navigatorSize
=
renderBox
.
size
;
final
RelativeRect
menuRect
=
new
RelativeRect
.
fromSize
(
route
.
rect
,
navigatorSize
);
...
...
@@ -105,14 +134,15 @@ class _DropdownMenu extends StatusTransitionComponent {
performance:
route
.
performance
,
variables:
<
AnimatedValue
<
double
>>[
menuTop
,
menuBottom
],
builder:
(
BuildContext
context
)
{
RenderBox
renderBox
=
context
.
findRenderObject
();
return
new
CustomPaint
(
child:
new
Block
(
children
),
onPaint:
(
ui
.
Canvas
canvas
,
Size
size
)
{
double
top
=
renderBox
.
globalToLocal
(
new
Point
(
0.0
,
menuTop
.
value
)).
y
;
double
bottom
=
renderBox
.
globalToLocal
(
new
Point
(
0.0
,
menuBottom
.
value
)).
y
;
menuPainter
.
paint
(
canvas
,
new
Rect
.
fromLTRB
(
0.0
,
top
,
size
.
width
,
bottom
));
}
painter:
new
_DropdownMenuPainter
(
color:
Theme
.
of
(
context
).
canvasColor
,
elevation:
route
.
elevation
,
menuTop:
menuTop
.
value
,
menuBottom:
menuBottom
.
value
,
renderBox:
context
.
findRenderObject
()
),
child:
new
Block
(
children
)
);
}
)
...
...
packages/flutter/lib/src/material/popup_menu.dart
View file @
ba8f6a01
...
...
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/animation.dart'
;
import
'package:flutter/painting.dart'
;
...
...
@@ -22,6 +21,38 @@ const double _kMenuMaxWidth = 5.0 * _kMenuWidthStep;
const
double
_kMenuHorizontalPadding
=
16.0
;
const
double
_kMenuVerticalPadding
=
8.0
;
class
_PopupMenuPainter
extends
CustomPainter
{
const
_PopupMenuPainter
({
this
.
color
,
this
.
elevation
,
this
.
width
,
this
.
height
});
final
Color
color
;
final
int
elevation
;
final
double
width
;
final
double
height
;
void
paint
(
Canvas
canvas
,
Size
size
)
{
double
widthValue
=
width
*
size
.
width
;
double
heightValue
=
height
*
size
.
height
;
final
BoxPainter
painter
=
new
BoxPainter
(
new
BoxDecoration
(
backgroundColor:
color
,
borderRadius:
2.0
,
boxShadow:
elevationToShadow
[
elevation
]
));
painter
.
paint
(
canvas
,
new
Rect
.
fromLTWH
(
size
.
width
-
widthValue
,
0.0
,
widthValue
,
heightValue
));
}
bool
shouldRepaint
(
_PopupMenuPainter
oldPainter
)
{
return
oldPainter
.
color
!=
color
||
oldPainter
.
elevation
!=
elevation
||
oldPainter
.
width
!=
width
||
oldPainter
.
height
!=
height
;
}
}
class
_PopupMenu
extends
StatelessComponent
{
_PopupMenu
({
Key
key
,
...
...
@@ -31,12 +62,6 @@ class _PopupMenu extends StatelessComponent {
final
_MenuRoute
route
;
Widget
build
(
BuildContext
context
)
{
final
BoxPainter
painter
=
new
BoxPainter
(
new
BoxDecoration
(
backgroundColor:
Theme
.
of
(
context
).
canvasColor
,
borderRadius:
2.0
,
boxShadow:
elevationToShadow
[
route
.
elevation
]
));
double
unit
=
1.0
/
(
route
.
items
.
length
+
1.5
);
// 1.0 for the width and 0.5 for the last item's fade.
List
<
Widget
>
children
=
<
Widget
>[];
...
...
@@ -64,11 +89,12 @@ class _PopupMenu extends StatelessComponent {
return
new
Opacity
(
opacity:
opacity
.
value
,
child:
new
CustomPaint
(
onPaint:
(
ui
.
Canvas
canvas
,
Size
size
)
{
double
widthValue
=
width
.
value
*
size
.
width
;
double
heightValue
=
height
.
value
*
size
.
height
;
painter
.
paint
(
canvas
,
new
Rect
.
fromLTWH
(
size
.
width
-
widthValue
,
0.0
,
widthValue
,
heightValue
));
},
painter:
new
_PopupMenuPainter
(
color:
Theme
.
of
(
context
).
canvasColor
,
elevation:
route
.
elevation
,
width:
width
.
value
,
height:
height
.
value
),
child:
new
ConstrainedBox
(
constraints:
new
BoxConstraints
(
minWidth:
_kMenuMinWidth
,
...
...
packages/flutter/lib/src/material/progress_indicator.dart
View file @
ba8f6a01
...
...
@@ -26,7 +26,6 @@ abstract class ProgressIndicator extends StatefulComponent {
Color
_getBackgroundColor
(
BuildContext
context
)
=>
Theme
.
of
(
context
).
primarySwatch
[
200
];
Color
_getValueColor
(
BuildContext
context
)
=>
Theme
.
of
(
context
).
primaryColor
;
Object
_getCustomPaintToken
(
double
performanceValue
)
=>
value
!=
null
?
value
:
performanceValue
;
Widget
_buildIndicator
(
BuildContext
context
,
double
performanceValue
);
...
...
@@ -74,19 +73,26 @@ class _ProgressIndicatorState extends State<ProgressIndicator> {
}
}
class
LinearProgressIndicator
extends
ProgressIndicator
{
LinearProgressIndicator
({
Key
key
,
double
value
})
:
super
(
key:
key
,
value:
value
);
class
_LinearProgressIndicatorPainter
extends
CustomPainter
{
const
_LinearProgressIndicatorPainter
({
this
.
backgroundColor
,
this
.
valueColor
,
this
.
value
,
this
.
performanceValue
});
final
Color
backgroundColor
;
final
Color
valueColor
;
final
double
value
;
final
double
performanceValue
;
void
_paint
(
BuildContext
context
,
double
performanceValue
,
Canvas
canvas
,
Size
size
)
{
void
paint
(
Canvas
canvas
,
Size
size
)
{
Paint
paint
=
new
Paint
()
..
color
=
_getBackgroundColor
(
context
)
..
color
=
backgroundColor
..
style
=
ui
.
PaintingStyle
.
fill
;
canvas
.
drawRect
(
Point
.
origin
&
size
,
paint
);
paint
.
color
=
_getValueColor
(
context
)
;
paint
.
color
=
valueColor
;
if
(
value
!=
null
)
{
double
width
=
value
.
clamp
(
0.0
,
1.0
)
*
size
.
width
;
canvas
.
drawRect
(
Point
.
origin
&
new
Size
(
width
,
size
.
height
),
paint
);
...
...
@@ -99,6 +105,20 @@ class LinearProgressIndicator extends ProgressIndicator {
}
}
bool
shouldRepaint
(
_LinearProgressIndicatorPainter
oldPainter
)
{
return
oldPainter
.
backgroundColor
!=
backgroundColor
||
oldPainter
.
valueColor
!=
valueColor
||
oldPainter
.
value
!=
value
||
oldPainter
.
performanceValue
!=
performanceValue
;
}
}
class
LinearProgressIndicator
extends
ProgressIndicator
{
LinearProgressIndicator
({
Key
key
,
double
value
})
:
super
(
key:
key
,
value:
value
);
Widget
_buildIndicator
(
BuildContext
context
,
double
performanceValue
)
{
return
new
Container
(
constraints:
new
BoxConstraints
.
tightFor
(
...
...
@@ -106,30 +126,37 @@ class LinearProgressIndicator extends ProgressIndicator {
height:
_kLinearProgressIndicatorHeight
),
child:
new
CustomPaint
(
token:
_getCustomPaintToken
(
performanceValue
),
onPaint:
(
Canvas
canvas
,
Size
size
)
{
_paint
(
context
,
performanceValue
,
canvas
,
size
);
}
painter:
new
_LinearProgressIndicatorPainter
(
backgroundColor:
_getBackgroundColor
(
context
),
valueColor:
_getValueColor
(
context
),
value:
value
,
performanceValue:
performanceValue
)
)
);
}
}
class
CircularProgressIndicator
extends
ProgressIndicato
r
{
class
_CircularProgressIndicatorPainter
extends
CustomPainte
r
{
static
const
_kTwoPI
=
math
.
PI
*
2.0
;
static
const
_kEpsilon
=
.
0000001
;
// Canavs.drawArc(r, 0, 2*PI) doesn't draw anything, so just get close.
static
const
_kSweep
=
_kTwoPI
-
_kEpsilon
;
static
const
_kStartAngle
=
-
math
.
PI
/
2.0
;
CircularProgressIndicator
({
Key
key
,
double
value
})
:
super
(
key:
key
,
value:
value
);
const
_CircularProgressIndicatorPainter
({
this
.
valueColor
,
this
.
value
,
this
.
performanceValue
});
final
Color
valueColor
;
final
double
value
;
final
double
performanceValue
;
void
_paint
(
BuildContext
context
,
double
performanceValue
,
Canvas
canvas
,
Size
size
)
{
void
paint
(
Canvas
canvas
,
Size
size
)
{
Paint
paint
=
new
Paint
()
..
color
=
_getValueColor
(
context
)
..
color
=
valueColor
..
strokeWidth
=
_kCircularProgressIndicatorStrokeWidth
..
style
=
ui
.
PaintingStyle
.
stroke
;
...
...
@@ -149,6 +176,19 @@ class CircularProgressIndicator extends ProgressIndicator {
}
}
bool
shouldRepaint
(
_LinearProgressIndicatorPainter
oldPainter
)
{
return
oldPainter
.
valueColor
!=
valueColor
||
oldPainter
.
value
!=
value
||
oldPainter
.
performanceValue
!=
performanceValue
;
}
}
class
CircularProgressIndicator
extends
ProgressIndicator
{
CircularProgressIndicator
({
Key
key
,
double
value
})
:
super
(
key:
key
,
value:
value
);
Widget
_buildIndicator
(
BuildContext
context
,
double
performanceValue
)
{
return
new
Container
(
constraints:
new
BoxConstraints
(
...
...
@@ -156,10 +196,11 @@ class CircularProgressIndicator extends ProgressIndicator {
minHeight:
_kMinCircularProgressIndicatorSize
),
child:
new
CustomPaint
(
token:
_getCustomPaintToken
(
performanceValue
),
onPaint:
(
Canvas
canvas
,
Size
size
)
{
_paint
(
context
,
performanceValue
,
canvas
,
size
);
}
painter:
new
_CircularProgressIndicatorPainter
(
valueColor:
_getValueColor
(
context
),
value:
value
,
performanceValue:
performanceValue
)
)
);
}
...
...
packages/flutter/lib/src/material/radio.dart
View file @
ba8f6a01
...
...
@@ -9,6 +9,42 @@ import 'package:flutter/widgets.dart';
import
'colors.dart'
;
import
'theme.dart'
;
const
double
_kDiameter
=
16.0
;
const
double
_kOuterRadius
=
_kDiameter
/
2.0
;
const
double
_kInnerRadius
=
5.0
;
class
_RadioPainter
extends
CustomPainter
{
const
_RadioPainter
({
this
.
color
,
this
.
selected
});
final
Color
color
;
final
bool
selected
;
void
paint
(
Canvas
canvas
,
Size
size
)
{
// TODO(ianh): ink radial reaction
// Draw the outer circle
Paint
paint
=
new
Paint
()
..
color
=
color
..
style
=
ui
.
PaintingStyle
.
stroke
..
strokeWidth
=
2.0
;
canvas
.
drawCircle
(
const
Point
(
_kOuterRadius
,
_kOuterRadius
),
_kOuterRadius
,
paint
);
// Draw the inner circle
if
(
selected
)
{
paint
.
style
=
ui
.
PaintingStyle
.
fill
;
canvas
.
drawCircle
(
const
Point
(
_kOuterRadius
,
_kOuterRadius
),
_kInnerRadius
,
paint
);
}
}
bool
shouldRepaint
(
_RadioPainter
oldPainter
)
{
return
oldPainter
.
color
!=
color
||
oldPainter
.
selected
!=
selected
;
}
}
class
Radio
<
T
>
extends
StatelessComponent
{
Radio
({
Key
key
,
...
...
@@ -33,34 +69,17 @@ class Radio<T> extends StatelessComponent {
}
Widget
build
(
BuildContext
context
)
{
const
double
kDiameter
=
16.0
;
const
double
kOuterRadius
=
kDiameter
/
2
;
const
double
kInnerRadius
=
5.0
;
return
new
GestureDetector
(
onTap:
enabled
?
()
=>
onChanged
(
value
)
:
null
,
child:
new
Container
(
margin:
const
EdgeDims
.
symmetric
(
horizontal:
5.0
),
width:
kDiameter
,
height:
kDiameter
,
width:
_
kDiameter
,
height:
_
kDiameter
,
child:
new
CustomPaint
(
onPaint:
(
Canvas
canvas
,
Size
size
)
{
// TODO(ianh): ink radial reaction
// Draw the outer circle
Paint
paint
=
new
Paint
()
..
color
=
_getColor
(
context
)
..
style
=
ui
.
PaintingStyle
.
stroke
..
strokeWidth
=
2.0
;
canvas
.
drawCircle
(
const
Point
(
kOuterRadius
,
kOuterRadius
),
kOuterRadius
,
paint
);
// Draw the inner circle
if
(
value
==
groupValue
)
{
paint
.
style
=
ui
.
PaintingStyle
.
fill
;
canvas
.
drawCircle
(
const
Point
(
kOuterRadius
,
kOuterRadius
),
kInnerRadius
,
paint
);
}
}
painter:
new
_RadioPainter
(
color:
_getColor
(
context
),
selected:
value
==
groupValue
)
)
)
);
...
...
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
ba8f6a01
...
...
@@ -913,9 +913,13 @@ class RenderSizeObserver extends RenderProxyBox {
}
}
/// Called when its time to paint into the given canvas
typedef
void
CustomPaintCallback
(
PaintingCanvas
canvas
,
Size
size
);
typedef
bool
CustomHitTestCallback
(
Point
position
);
abstract
class
CustomPainter
{
const
CustomPainter
();
void
paint
(
PaintingCanvas
canvas
,
Size
size
);
bool
shouldRepaint
(
CustomPainter
oldDelegate
);
bool
hitTest
(
Point
position
)
=>
true
;
}
/// Delegates its painting to [onPaint]
///
...
...
@@ -932,51 +936,47 @@ typedef bool CustomHitTestCallback(Point position);
class
RenderCustomPaint
extends
RenderProxyBox
{
RenderCustomPaint
({
CustomPaintCallback
onPaint
,
this
.
onHitTest
,
CustomPainter
painter
,
RenderBox
child
})
:
super
(
child
)
{
assert
(
onPaint
!=
null
);
_onPaint
=
onPaint
;
})
:
_painter
=
painter
,
super
(
child
)
{
assert
(
painter
!=
null
);
}
/// The callback to which this render object delegates its painting
///
/// The callback must be non-null whenever the render object is attached to
/// the render tree.
CustomPaintCallback
get
onPaint
=>
_onPaint
;
CustomPaintCallback
_onPaint
;
void
set
onPaint
(
CustomPaintCallback
newCallback
)
{
assert
(
newCallback
!=
null
||
!
attached
);
if
(
_onPaint
==
newCallback
)
CustomPainter
get
painter
=>
_painter
;
CustomPainter
_painter
;
void
set
painter
(
CustomPainter
newPainter
)
{
assert
(
newPainter
!=
null
||
!
attached
);
if
(
_painter
==
newPainter
)
return
;
_onPaint
=
newCallback
;
markNeedsPaint
();
CustomPainter
oldPainter
=
_painter
;
_painter
=
newPainter
;
if
(
newPainter
==
null
)
return
;
if
(
oldPainter
==
null
||
newPainter
.
runtimeType
!=
oldPainter
.
runtimeType
||
newPainter
.
shouldRepaint
(
oldPainter
))
markNeedsPaint
();
}
CustomHitTestCallback
onHitTest
;
void
attach
()
{
assert
(
_
onPaint
!=
null
);
assert
(
_
painter
!=
null
);
super
.
attach
();
}
bool
hitTestSelf
(
Point
position
)
{
return
onHitTest
==
null
||
onH
itTest
(
position
);
return
_painter
.
h
itTest
(
position
);
}
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
assert
(
_
onPaint
!=
null
);
assert
(
_
painter
!=
null
);
context
.
canvas
.
translate
(
offset
.
dx
,
offset
.
dy
);
_onPaint
(
context
.
canvas
,
size
);
// TODO(abarth): We should translate back before calling super because in
// the future, super.paint might switch our compositing layer.
super
.
paint
(
context
,
Offset
.
zero
);
_painter
.
paint
(
context
.
canvas
,
size
);
context
.
canvas
.
translate
(-
offset
.
dx
,
-
offset
.
dy
);
super
.
paint
(
context
,
offset
);
}
}
typedef
void
PointerEventListener
(
PointerInputEvent
e
);
typedef
void
PointerEventListener
(
PointerInputEvent
e
vent
);
enum
HitTestBehavior
{
deferToChild
,
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
ba8f6a01
...
...
@@ -21,6 +21,7 @@ export 'package:flutter/rendering.dart' show
Canvas
,
Color
,
ColorFilter
,
CustomPainter
,
EdgeDims
,
FlexAlignItems
,
FlexDirection
,
...
...
@@ -136,36 +137,21 @@ class DecoratedBox extends OneChildRenderObjectWidget {
}
class
CustomPaint
extends
OneChildRenderObjectWidget
{
CustomPaint
({
Key
key
,
this
.
onPaint
,
this
.
onHitTest
,
this
.
token
,
Widget
child
})
CustomPaint
({
Key
key
,
this
.
painter
,
Widget
child
})
:
super
(
key:
key
,
child:
child
)
{
assert
(
onPaint
!=
null
);
assert
(
painter
!=
null
);
}
/// This widget repaints whenver you supply a new onPaint callback.
///
/// If you use an anonymous closure for the onPaint callback, you'll trigger
/// a repaint every time you build this widget, which might not be what you
/// intend. Instead, consider passing a reference to a member function, which
/// has a more stable identity.
final
CustomPaintCallback
onPaint
;
final
CustomHitTestCallback
onHitTest
;
final
CustomPainter
painter
;
/// This widget repaints whenever you supply a new token.
final
Object
token
;
RenderCustomPaint
createRenderObject
()
=>
new
RenderCustomPaint
(
onPaint:
onPaint
,
onHitTest:
onHitTest
);
RenderCustomPaint
createRenderObject
()
=>
new
RenderCustomPaint
(
painter:
painter
);
void
updateRenderObject
(
RenderCustomPaint
renderObject
,
CustomPaint
oldWidget
)
{
if
(
oldWidget
.
token
!=
token
)
renderObject
.
markNeedsPaint
();
renderObject
.
onPaint
=
onPaint
;
renderObject
.
onHitTest
=
onHitTest
;
renderObject
.
painter
=
painter
;
}
void
didUnmountRenderObject
(
RenderCustomPaint
renderObject
)
{
renderObject
.
onPaint
=
null
;
renderObject
.
onHitTest
=
null
;
renderObject
.
painter
=
null
;
}
}
...
...
packages/flutter/lib/src/widgets/gridpaper.dart
View file @
ba8f6a01
...
...
@@ -7,6 +7,34 @@ import 'package:flutter/rendering.dart';
import
'basic.dart'
;
import
'framework.dart'
;
class
_GridPaperPainter
extends
CustomPainter
{
const
_GridPaperPainter
({
this
.
color
,
this
.
interval
});
final
Color
color
;
final
double
interval
;
void
paint
(
Canvas
canvas
,
Size
size
)
{
Paint
linePaint
=
new
Paint
()
..
color
=
color
;
for
(
double
x
=
0.0
;
x
<=
size
.
width
;
x
+=
interval
/
10.0
)
{
linePaint
.
strokeWidth
=
(
x
%
interval
==
0.0
)
?
1.0
:
(
x
%
(
interval
/
2.0
)
==
0.0
)
?
0.5
:
0.25
;
canvas
.
drawLine
(
new
Point
(
x
,
0.0
),
new
Point
(
x
,
size
.
height
),
linePaint
);
}
for
(
double
y
=
0.0
;
y
<=
size
.
height
;
y
+=
interval
/
10.0
)
{
linePaint
.
strokeWidth
=
(
y
%
interval
==
0.0
)
?
1.0
:
(
y
%
(
interval
/
2.0
)
==
0.0
)
?
0.5
:
0.25
;
canvas
.
drawLine
(
new
Point
(
0.0
,
y
),
new
Point
(
size
.
width
,
y
),
linePaint
);
}
}
bool
shouldRepaint
(
_GridPaperPainter
oldPainter
)
{
return
oldPainter
.
color
!=
color
||
oldPainter
.
interval
!=
interval
;
}
}
class
GridPaper
extends
StatelessComponent
{
GridPaper
({
Key
key
,
...
...
@@ -18,19 +46,13 @@ class GridPaper extends StatelessComponent {
final
double
interval
;
Widget
build
(
BuildContext
context
)
{
return
new
IgnorePointer
(
child:
new
CustomPaint
(
onPaint:
(
PaintingCanvas
canvas
,
Size
size
)
{
Paint
linePaint
=
new
Paint
()
..
color
=
color
;
for
(
double
x
=
0.0
;
x
<=
size
.
width
;
x
+=
interval
/
10.0
)
{
linePaint
.
strokeWidth
=
(
x
%
interval
==
0.0
)
?
1.0
:
(
x
%
(
interval
/
2.0
)
==
0.0
)
?
0.5
:
0.25
;
canvas
.
drawLine
(
new
Point
(
x
,
0.0
),
new
Point
(
x
,
size
.
height
),
linePaint
);
}
for
(
double
y
=
0.0
;
y
<=
size
.
height
;
y
+=
interval
/
10.0
)
{
linePaint
.
strokeWidth
=
(
y
%
interval
==
0.0
)
?
1.0
:
(
y
%
(
interval
/
2.0
)
==
0.0
)
?
0.5
:
0.25
;
canvas
.
drawLine
(
new
Point
(
0.0
,
y
),
new
Point
(
size
.
width
,
y
),
linePaint
);
}
})
return
new
IgnorePointer
(
child:
new
CustomPaint
(
painter:
new
_GridPaperPainter
(
color:
color
,
interval:
interval
)
)
);
}
}
packages/unit/test/rendering/offstage_test.dart
View file @
ba8f6a01
...
...
@@ -13,12 +13,12 @@ void main() {
RenderBox
root
=
new
RenderViewport
(
child:
new
RenderOffStage
(
child:
new
RenderCustomPaint
(
painter:
new
TestCallbackPainter
(
onPaint:
()
{
painted
=
true
;
}
),
child:
child
=
new
RenderConstrainedBox
(
additionalConstraints:
new
BoxConstraints
.
tightFor
(
height:
10.0
,
width:
10.0
)
),
onPaint:
(
PaintingCanvas
canvas
,
Size
size
)
{
painted
=
true
;
}
)
)
)
);
...
...
packages/unit/test/rendering/overflow_test.dart
View file @
ba8f6a01
...
...
@@ -12,10 +12,12 @@ void main() {
root
=
new
RenderPositionedBox
(
child:
new
RenderCustomPaint
(
child:
child
=
text
=
new
RenderParagraph
(
new
PlainTextSpan
(
'Hello World'
)),
onPaint:
(
PaintingCanvas
canvas
,
Size
size
)
{
baseline1
=
child
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
);
height1
=
text
.
size
.
height
;
}
painter:
new
TestCallbackPainter
(
onPaint:
()
{
baseline1
=
child
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
);
height1
=
text
.
size
.
height
;
}
)
)
);
layout
(
root
,
phase:
EnginePhase
.
paint
);
...
...
@@ -26,10 +28,12 @@ void main() {
child:
text
=
new
RenderParagraph
(
new
PlainTextSpan
(
'Hello World'
)),
maxHeight:
height1
/
2.0
),
onPaint:
(
PaintingCanvas
canvas
,
Size
size
)
{
baseline2
=
child
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
);
height2
=
text
.
size
.
height
;
}
painter:
new
TestCallbackPainter
(
onPaint:
()
{
baseline2
=
child
.
getDistanceToBaseline
(
TextBaseline
.
alphabetic
);
height2
=
text
.
size
.
height
;
}
)
)
);
layout
(
root
,
phase:
EnginePhase
.
paint
);
...
...
packages/unit/test/rendering/rendering_tester.dart
View file @
ba8f6a01
...
...
@@ -53,3 +53,15 @@ void pumpFrame({ EnginePhase phase: EnginePhase.layout }) {
return
;
renderView
.
compositeFrame
();
}
class
TestCallbackPainter
extends
CustomPainter
{
const
TestCallbackPainter
({
this
.
onPaint
});
final
VoidCallback
onPaint
;
void
paint
(
Canvas
canvas
,
Size
size
)
{
onPaint
();
}
bool
shouldRepaint
(
TestCallbackPainter
oldPainter
)
=>
true
;
}
packages/unit/test/widget/stack_test.dart
View file @
ba8f6a01
...
...
@@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';
import
'package:test/test.dart'
;
import
'widget_tester.dart'
;
import
'../rendering/rendering_tester.dart'
;
void
main
(
)
{
test
(
'Can construct an empty Stack'
,
()
{
...
...
@@ -150,7 +151,12 @@ void main() {
Widget
buildFrame
(
int
index
)
{
itemsPainted
=
<
int
>[];
List
<
Widget
>
items
=
new
List
<
Widget
>.
generate
(
itemCount
,
(
i
)
{
return
new
CustomPaint
(
child:
new
Text
(
'
$i
'
),
onPaint:
(
_
,
__
)
{
itemsPainted
.
add
(
i
);
});
return
new
CustomPaint
(
child:
new
Text
(
'
$i
'
),
painter:
new
TestCallbackPainter
(
onPaint:
()
{
itemsPainted
.
add
(
i
);
}
)
);
});
return
new
Center
(
child:
new
IndexedStack
(
items
,
index:
index
));
}
...
...
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