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
f4603f76
Commit
f4603f76
authored
Mar 29, 2016
by
Ian Hickson
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2961 from Hixie/table
Table widget
parents
a5ee6e11
baf06515
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
748 additions
and
83 deletions
+748
-83
paragraph.dart
packages/flutter/lib/src/rendering/paragraph.dart
+1
-1
table.dart
packages/flutter/lib/src/rendering/table.dart
+126
-61
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+4
-4
framework.dart
packages/flutter/lib/src/widgets/framework.dart
+25
-17
table.dart
packages/flutter/lib/src/widgets/table.dart
+231
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-0
table_test.dart
packages/flutter/test/rendering/table_test.dart
+16
-0
table_test.dart
packages/flutter/test/widget/table_test.dart
+344
-0
No files found.
packages/flutter/lib/src/rendering/paragraph.dart
View file @
f4603f76
...
...
@@ -131,7 +131,7 @@ class RenderParagraph extends RenderBox {
@override
String
debugDescribeChildren
(
String
prefix
)
{
return
'
$prefix
\
u2558
\
u2550
\
u2566
\
u2550
\
u2550 text
\
u2550
\
u2550
\
u2550
\n
'
'
${text.toString("$prefix \u2551 ")}
\n
'
'
${text.toString("$prefix \u2551 ")}
'
// TextSpan includes a newline
'
$prefix
\
u255A
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\n
'
'
$prefix
\n
'
;
}
...
...
packages/flutter/lib/src/rendering/table.dart
View file @
f4603f76
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/widgets/basic.dart
View file @
f4603f76
...
...
@@ -15,21 +15,19 @@ export 'package:flutter/painting.dart';
export
'package:flutter/rendering.dart'
show
Axis
,
BoxConstraints
,
CrossAxisAlignment
,
CustomClipper
,
CustomPainter
,
FixedColumnCountGridDelegate
,
CrossAxisAlignment
,
FlexDirection
,
MainAxisAlignment
,
FractionalOffsetTween
,
GridDelegate
,
GridDelegateWithInOrderChildPlacement
,
GridSpecification
,
HitTestBehavior
,
MainAxisAlignment
,
MaxTileWidthGridDelegate
,
MultiChildLayoutDelegate
,
SingleChildLayoutDelegate
,
RenderObjectPainter
,
PaintingContext
,
PlainTextSpan
,
PointerCancelEvent
,
...
...
@@ -42,7 +40,9 @@ export 'package:flutter/rendering.dart' show
PointerUpEvent
,
PointerUpEventListener
,
RelativeRect
,
RenderObjectPainter
,
ShaderCallback
,
SingleChildLayoutDelegate
,
ValueChanged
,
ViewportAnchor
,
ViewportDimensions
,
...
...
packages/flutter/lib/src/widgets/framework.dart
View file @
f4603f76
...
...
@@ -20,6 +20,8 @@ export 'package:flutter/services.dart' show FlutterError;
/// original Widget's Key.
///
/// Keys must be unique amongst the Elements with the same parent.
///
/// Subclasses of Key should either subclass [LocalKey] or [GlobalKey].
abstract
class
Key
{
/// Construct a ValueKey<String> with the given String.
/// This is the simplest way to create keys.
...
...
@@ -29,12 +31,18 @@ abstract class Key {
const
Key
.
constructor
();
// so that subclasses can call us, since the Key() factory constructor shadows the implicit constructor
}
/// A key that is not a [GlobalKey].
abstract
class
LocalKey
extends
Key
{
/// Default constructor, used by subclasses.
const
LocalKey
()
:
super
.
constructor
();
}
/// A kind of [Key] that uses a value of a particular type to identify itself.
///
/// For example, a ValueKey<String> is equal to another ValueKey<String> if
/// their values match.
class
ValueKey
<
T
>
extends
Key
{
const
ValueKey
(
this
.
value
)
:
super
.
constructor
()
;
class
ValueKey
<
T
>
extends
Local
Key
{
const
ValueKey
(
this
.
value
);
final
T
value
;
...
...
@@ -54,8 +62,8 @@ class ValueKey<T> extends Key {
}
/// A [Key] that is only equal to itself.
class
UniqueKey
extends
Key
{
const
UniqueKey
()
:
super
.
constructor
()
;
class
UniqueKey
extends
Local
Key
{
const
UniqueKey
();
@override
String
toString
()
=>
'[
$hashCode
]'
;
...
...
@@ -65,8 +73,8 @@ class UniqueKey extends Key {
///
/// Used to tie the identity of a Widget to the identity of an object used to
/// generate that Widget.
class
ObjectKey
extends
Key
{
const
ObjectKey
(
this
.
value
)
:
super
.
constructor
()
;
class
ObjectKey
extends
Local
Key
{
const
ObjectKey
(
this
.
value
);
final
Object
value
;
...
...
@@ -744,7 +752,7 @@ abstract class Element implements BuildContext {
Element
updateChild
(
Element
child
,
Widget
newWidget
,
dynamic
newSlot
)
{
if
(
newWidget
==
null
)
{
if
(
child
!=
null
)
_
deactivateChild
(
child
);
deactivateChild
(
child
);
return
null
;
}
if
(
child
!=
null
)
{
...
...
@@ -760,10 +768,10 @@ abstract class Element implements BuildContext {
assert
(
child
.
widget
==
newWidget
);
return
child
;
}
_
deactivateChild
(
child
);
deactivateChild
(
child
);
assert
(
child
.
_parent
==
null
);
}
return
_
inflateWidget
(
newWidget
,
newSlot
);
return
inflateWidget
(
newWidget
,
newSlot
);
}
static
void
finalizeTree
()
{
...
...
@@ -870,7 +878,7 @@ abstract class Element implements BuildContext {
return
element
;
}
Element
_
inflateWidget
(
Widget
newWidget
,
dynamic
newSlot
)
{
Element
inflateWidget
(
Widget
newWidget
,
dynamic
newSlot
)
{
Key
key
=
newWidget
.
key
;
if
(
key
is
GlobalKey
)
{
Element
newChild
=
_retakeInactiveElement
(
key
,
newWidget
);
...
...
@@ -901,7 +909,7 @@ abstract class Element implements BuildContext {
});
}
void
_
deactivateChild
(
Element
child
)
{
void
deactivateChild
(
Element
child
)
{
assert
(
child
!=
null
);
assert
(
child
.
_parent
==
this
);
child
.
_parent
=
null
;
...
...
@@ -1339,7 +1347,7 @@ abstract class ComponentElement extends BuildableElement {
@override
bool
detachChild
(
Element
child
)
{
assert
(
child
==
_child
);
_
deactivateChild
(
_child
);
deactivateChild
(
_child
);
_child
=
null
;
return
true
;
}
...
...
@@ -1733,7 +1741,7 @@ abstract class RenderObjectElement extends BuildableElement {
if
(
oldChild
.
widget
.
key
!=
null
)
oldKeyedChildren
[
oldChild
.
widget
.
key
]
=
oldChild
;
else
_
deactivateChild
(
oldChild
);
deactivateChild
(
oldChild
);
}
oldChildrenTop
+=
1
;
}
...
...
@@ -1795,7 +1803,7 @@ abstract class RenderObjectElement extends BuildableElement {
if
(
haveOldChildren
&&
oldKeyedChildren
.
isNotEmpty
)
{
for
(
Element
oldChild
in
oldKeyedChildren
.
values
)
{
if
(
detachedChildren
==
null
||
!
detachedChildren
.
contains
(
oldChild
))
_
deactivateChild
(
oldChild
);
deactivateChild
(
oldChild
);
}
}
...
...
@@ -1897,7 +1905,7 @@ class SingleChildRenderObjectElement extends RenderObjectElement {
@override
bool
detachChild
(
Element
child
)
{
assert
(
child
==
_child
);
_
deactivateChild
(
_child
);
deactivateChild
(
_child
);
_child
=
null
;
return
true
;
}
...
...
@@ -1984,7 +1992,7 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
@override
bool
detachChild
(
Element
child
)
{
_detachedChildren
.
add
(
child
);
_
deactivateChild
(
child
);
deactivateChild
(
child
);
return
true
;
}
...
...
@@ -1994,7 +2002,7 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
_children
=
new
List
<
Element
>(
widget
.
children
.
length
);
Element
previousChild
;
for
(
int
i
=
0
;
i
<
_children
.
length
;
++
i
)
{
Element
newChild
=
_
inflateWidget
(
widget
.
children
[
i
],
previousChild
);
Element
newChild
=
inflateWidget
(
widget
.
children
[
i
],
previousChild
);
_children
[
i
]
=
newChild
;
previousChild
=
newChild
;
}
...
...
packages/flutter/lib/src/widgets/table.dart
0 → 100644
View file @
f4603f76
// 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:collection'
;
import
'package:flutter/rendering.dart'
;
import
'debug.dart'
;
import
'framework.dart'
;
export
'package:flutter/rendering.dart'
show
FixedColumnWidth
,
FlexColumnWidth
,
FractionColumnWidth
,
IntrinsicColumnWidth
,
MaxColumnWidth
,
MinColumnWidth
,
TableBorder
,
TableCellVerticalAlignment
,
TableColumnWidth
;
class
TableRow
{
const
TableRow
({
this
.
key
,
this
.
children
});
final
LocalKey
key
;
final
List
<
Widget
>
children
;
}
class
_TableElementRow
{
const
_TableElementRow
({
this
.
key
,
this
.
children
});
final
LocalKey
key
;
final
List
<
Element
>
children
;
}
/// Uses the table layout algorithm for its children.
///
/// For details about the table layout algorithm, see [RenderTable].
/// To control the alignment of children, see [TableCell].
class
Table
extends
RenderObjectWidget
{
Table
({
Key
key
,
this
.
children
:
const
<
TableRow
>[],
this
.
columnWidths
,
this
.
defaultColumnWidth
:
const
FlexColumnWidth
(
1.0
),
this
.
border
,
this
.
defaultVerticalAlignment
:
TableCellVerticalAlignment
.
top
,
this
.
textBaseline
})
:
super
(
key:
key
)
{
assert
(
children
!=
null
);
assert
(
defaultColumnWidth
!=
null
);
assert
(
defaultVerticalAlignment
!=
null
);
assert
(()
{
List
<
Widget
>
flatChildren
=
children
.
expand
((
TableRow
row
)
=>
row
.
children
).
toList
(
growable:
false
);
return
!
debugChildrenHaveDuplicateKeys
(
this
,
flatChildren
);
});
assert
(!
children
.
any
((
TableRow
row1
)
=>
row1
.
key
!=
null
&&
children
.
any
((
TableRow
row2
)
=>
row1
!=
row2
&&
row1
.
key
==
row2
.
key
)));
}
final
List
<
TableRow
>
children
;
final
Map
<
int
,
TableColumnWidth
>
columnWidths
;
final
TableColumnWidth
defaultColumnWidth
;
final
TableBorder
border
;
final
TableCellVerticalAlignment
defaultVerticalAlignment
;
final
TextBaseline
textBaseline
;
@override
_TableElement
createElement
()
=>
new
_TableElement
(
this
);
@override
RenderTable
createRenderObject
(
BuildContext
context
)
{
return
new
RenderTable
(
columns:
children
.
length
>
0
?
children
[
0
].
children
.
length
:
0
,
rows:
children
.
length
,
columnWidths:
columnWidths
,
defaultColumnWidth:
defaultColumnWidth
,
border:
border
,
defaultVerticalAlignment:
defaultVerticalAlignment
,
textBaseline:
textBaseline
);
}
@override
void
updateRenderObject
(
BuildContext
context
,
RenderTable
renderObject
)
{
assert
(
renderObject
.
columns
==
(
children
.
length
>
0
?
children
[
0
].
children
.
length
:
0
));
assert
(
renderObject
.
rows
==
children
.
length
);
renderObject
..
columnWidths
=
columnWidths
..
defaultColumnWidth
=
defaultColumnWidth
..
border
=
border
..
defaultVerticalAlignment
=
defaultVerticalAlignment
..
textBaseline
=
textBaseline
;
}
}
class
_TableElement
extends
RenderObjectElement
{
_TableElement
(
Table
widget
)
:
super
(
widget
);
@override
Table
get
widget
=>
super
.
widget
;
@override
RenderTable
get
renderObject
=>
super
.
renderObject
;
// This class ignores the child's slot entirely.
// Instead of doing incremental updates to the child list, it replaces the entire list each frame.
List
<
_TableElementRow
>
_children
=
const
<
_TableElementRow
>[];
bool
_debugWillReattachChildren
=
false
;
@override
void
mount
(
Element
parent
,
dynamic
newSlot
)
{
super
.
mount
(
parent
,
newSlot
);
assert
(!
_debugWillReattachChildren
);
assert
(()
{
_debugWillReattachChildren
=
true
;
return
true
;
});
_children
=
widget
.
children
.
map
((
TableRow
row
)
{
return
new
_TableElementRow
(
key:
row
.
key
,
children:
row
.
children
.
map
((
Widget
child
)
=>
inflateWidget
(
child
,
null
)).
toList
(
growable:
false
)
);
}).
toList
(
growable:
false
);
assert
(()
{
_debugWillReattachChildren
=
false
;
return
true
;
});
_updateRenderObjectChildren
();
}
@override
void
insertChildRenderObject
(
RenderObject
child
,
Element
slot
)
{
assert
(
_debugWillReattachChildren
);
renderObject
.
setupParentData
(
child
);
}
@override
void
moveChildRenderObject
(
RenderObject
child
,
dynamic
slot
)
{
assert
(
_debugWillReattachChildren
);
}
@override
void
removeChildRenderObject
(
RenderObject
child
)
{
assert
(
_debugWillReattachChildren
);
TableCellParentData
childParentData
=
child
.
parentData
;
renderObject
.
setChild
(
childParentData
.
x
,
childParentData
.
y
,
null
);
}
final
Set
<
Element
>
_detachedChildren
=
new
HashSet
<
Element
>();
@override
void
update
(
Table
newWidget
)
{
assert
(!
_debugWillReattachChildren
);
assert
(()
{
_debugWillReattachChildren
=
true
;
return
true
;
});
Map
<
LocalKey
,
List
<
Element
>>
oldKeyedRows
=
new
Map
<
LocalKey
,
List
<
Element
>>.
fromIterable
(
_children
.
where
((
_TableElementRow
row
)
=>
row
.
key
!=
null
),
key:
(
_TableElementRow
row
)
=>
row
.
key
,
value:
(
_TableElementRow
row
)
=>
row
.
children
);
Iterator
<
_TableElementRow
>
oldUnkeyedRows
=
_children
.
where
((
_TableElementRow
row
)
=>
row
.
key
==
null
).
iterator
;
List
<
_TableElementRow
>
newChildren
=
<
_TableElementRow
>[];
Set
<
List
<
Element
>>
taken
=
new
Set
<
List
<
Element
>>();
for
(
TableRow
row
in
newWidget
.
children
)
{
List
<
Element
>
oldChildren
;
if
(
row
.
key
!=
null
&&
oldKeyedRows
.
containsKey
(
row
.
key
))
{
oldChildren
=
oldKeyedRows
[
row
.
key
];
taken
.
add
(
oldChildren
);
}
else
if
(
row
.
key
==
null
&&
oldUnkeyedRows
.
moveNext
())
{
oldChildren
=
oldUnkeyedRows
.
current
.
children
;
}
else
{
oldChildren
=
const
<
Element
>[];
}
newChildren
.
add
(
new
_TableElementRow
(
key:
row
.
key
,
children:
updateChildren
(
oldChildren
,
row
.
children
,
detachedChildren:
_detachedChildren
)
));
}
while
(
oldUnkeyedRows
.
moveNext
())
updateChildren
(
oldUnkeyedRows
.
current
.
children
,
const
<
Widget
>[],
detachedChildren:
_detachedChildren
);
for
(
List
<
Element
>
oldChildren
in
oldKeyedRows
.
values
.
where
((
List
<
Element
>
list
)
=>
!
taken
.
contains
(
list
)))
updateChildren
(
oldChildren
,
const
<
Widget
>[],
detachedChildren:
_detachedChildren
);
assert
(()
{
_debugWillReattachChildren
=
false
;
return
true
;
});
_children
=
newChildren
;
_updateRenderObjectChildren
();
_detachedChildren
.
clear
();
super
.
update
(
newWidget
);
assert
(
widget
==
newWidget
);
}
void
_updateRenderObjectChildren
()
{
assert
(
renderObject
!=
null
);
renderObject
.
setFlatChildren
(
_children
.
length
>
0
?
_children
[
0
].
children
.
length
:
0
,
_children
.
expand
((
_TableElementRow
row
)
=>
row
.
children
.
map
((
Element
child
)
=>
child
.
renderObject
)).
toList
()
);
}
@override
void
visitChildren
(
ElementVisitor
visitor
)
{
for
(
Element
child
in
_children
.
expand
((
_TableElementRow
row
)
=>
row
.
children
))
{
if
(!
_detachedChildren
.
contains
(
child
))
visitor
(
child
);
}
}
@override
bool
detachChild
(
Element
child
)
{
_detachedChildren
.
add
(
child
);
deactivateChild
(
child
);
return
true
;
}
}
class
TableCell
extends
ParentDataWidget
<
Table
>
{
TableCell
({
Key
key
,
this
.
verticalAlignment
,
Widget
child
})
:
super
(
key:
key
,
child:
child
);
final
TableCellVerticalAlignment
verticalAlignment
;
@override
void
applyParentData
(
RenderObject
renderObject
)
{
final
TableCellParentData
parentData
=
renderObject
.
parentData
;
if
(
parentData
.
verticalAlignment
!=
verticalAlignment
)
{
parentData
.
verticalAlignment
=
verticalAlignment
;
AbstractNode
targetParent
=
renderObject
.
parent
;
if
(
targetParent
is
RenderObject
)
targetParent
.
markNeedsLayout
();
}
}
@override
void
debugFillDescription
(
List
<
String
>
description
)
{
super
.
debugFillDescription
(
description
);
description
.
add
(
'verticalAlignment:
$verticalAlignment
'
);
}
}
packages/flutter/lib/widgets.dart
View file @
f4603f76
...
...
@@ -44,6 +44,7 @@ export 'src/widgets/scrollable_list.dart';
export
'src/widgets/scrollable.dart'
;
export
'src/widgets/semantics_debugger.dart'
;
export
'src/widgets/status_transitions.dart'
;
export
'src/widgets/table.dart'
;
export
'src/widgets/title.dart'
;
export
'src/widgets/transitions.dart'
;
export
'src/widgets/unique_widget.dart'
;
...
...
packages/flutter/test/rendering/table_test.dart
View file @
f4603f76
...
...
@@ -55,4 +55,20 @@ void main() {
expect
(
table
.
size
,
equals
(
new
Size
(
800.0
,
230.0
)));
});
test
(
'Table test: removing cells'
,
()
{
RenderTable
table
;
RenderBox
child
;
table
=
new
RenderTable
(
columns:
5
,
rows:
5
);
table
.
setChild
(
4
,
4
,
child
=
sizedBox
(
10.0
,
10.0
));
layout
(
table
);
expect
(
child
.
attached
,
isTrue
);
table
.
rows
=
4
;
expect
(
child
.
attached
,
isFalse
);
});
}
packages/flutter/test/widget/table_test.dart
0 → 100644
View file @
f4603f76
This diff is collapsed.
Click to expand it.
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