Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
dart_pdf
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Marco Papula
2020-04-14 17:16:39 +0200
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Committed by
David PHAM-VAN
2020-04-25 22:10:15 -0400
Commit
ada72419ab99c58def518e0d2bf3d8bc005e7cef
ada72419
1 parent
6b83d125
Add Chart Widget
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
432 additions
and
0 deletions
pdf/CHANGELOG.md
pdf/lib/widgets.dart
pdf/lib/widgets/chart.dart
pdf/test/widget_chart_test.dart
pdf/CHANGELOG.md
View file @
ada7241
...
...
@@ -6,6 +6,7 @@
-
Fix PdfColors.shade()
-
Add dashed lines to Decoration Widgets
-
Add TableRow decoration
-
Add Chart Widget
[
Marco Papula
]
## 1.6.2
...
...
pdf/lib/widgets.dart
View file @
ada7241
...
...
@@ -54,3 +54,4 @@ part 'widgets/text_style.dart';
part
'widgets/theme.dart'
;
part
'widgets/widget.dart'
;
part
'widgets/wrap.dart'
;
part
'widgets/chart.dart'
;
...
...
pdf/lib/widgets/chart.dart
0 → 100644
View file @
ada7241
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ignore_for_file: omit_local_variable_types
part of
widget
;
bool
_isSortedAscending
(
List
<
double
>
list
)
{
double
prev
=
list
.
first
;
for
(
double
elem
in
list
)
{
if
(
prev
>
elem
)
{
return
false
;
}
prev
=
elem
;
}
return
true
;
}
class
Chart
extends
Widget
{
Chart
({
@required
this
.
grid
,
@required
this
.
data
,
this
.
width
=
500
,
this
.
height
=
250
,
this
.
fit
=
BoxFit
.
contain
,
});
final
double
width
;
final
double
height
;
final
BoxFit
fit
;
final
Grid
grid
;
final
List
<
DataSet
>
data
;
PdfRect
gridBox
;
@override
void
layout
(
Context
context
,
BoxConstraints
constraints
,
{
bool
parentUsesSize
=
false
})
{
final
double
w
=
constraints
.
hasBoundedWidth
?
constraints
.
maxWidth
:
constraints
.
constrainWidth
(
width
.
toDouble
());
final
double
h
=
constraints
.
hasBoundedHeight
?
constraints
.
maxHeight
:
constraints
.
constrainHeight
(
height
.
toDouble
());
final
FittedSizes
sizes
=
applyBoxFit
(
fit
,
PdfPoint
(
width
,
height
),
PdfPoint
(
w
,
h
));
box
=
PdfRect
.
fromPoints
(
PdfPoint
.
zero
,
sizes
.
destination
);
grid
.
layout
(
context
,
box
);
for
(
DataSet
dataSet
in
data
)
{
dataSet
.
layout
(
context
,
grid
.
gridBox
);
}
}
@override
void
paint
(
Context
context
)
{
super
.
paint
(
context
);
final
Matrix4
mat
=
Matrix4
.
identity
();
mat
.
translate
(
box
.
x
,
box
.
y
);
context
.
canvas
..
saveContext
()
..
setTransform
(
mat
);
grid
.
paint
(
context
,
box
);
for
(
DataSet
dataSet
in
data
)
{
dataSet
.
paint
(
context
,
grid
);
}
context
.
canvas
.
restoreContext
();
}
}
abstract
class
Grid
{
PdfRect
gridBox
;
double
xOffset
;
double
xTotal
;
double
yOffset
;
double
yTotal
;
void
layout
(
Context
context
,
PdfRect
box
);
void
paint
(
Context
context
,
PdfRect
box
);
}
class
LinearGrid
extends
Grid
{
LinearGrid
({
@required
this
.
xAxis
,
@required
this
.
yAxis
,
this
.
xMargin
=
10
,
this
.
yMargin
=
2
,
this
.
textStyle
,
this
.
lineWidth
=
1
,
this
.
color
=
PdfColors
.
black
,
this
.
separatorLineWidth
=
1
,
this
.
separatorColor
=
PdfColors
.
grey
,
})
:
assert
(
_isSortedAscending
(
xAxis
)),
assert
(
_isSortedAscending
(
yAxis
));
final
List
<
double
>
xAxis
;
final
List
<
double
>
yAxis
;
final
double
xMargin
;
final
double
yMargin
;
final
TextStyle
textStyle
;
final
double
lineWidth
;
final
PdfColor
color
;
TextStyle
style
;
PdfFont
font
;
PdfFontMetrics
xAxisFontMetric
;
PdfFontMetrics
yAxisFontMetric
;
double
separatorLineWidth
;
PdfColor
separatorColor
;
@override
void
layout
(
Context
context
,
PdfRect
box
)
{
style
=
Theme
.
of
(
context
).
defaultTextStyle
.
merge
(
textStyle
);
font
=
style
.
font
.
getFont
(
context
);
xAxisFontMetric
=
font
.
stringMetrics
(
xAxis
.
reduce
(
math
.
max
).
toStringAsFixed
(
1
))
*
(
style
.
fontSize
);
yAxisFontMetric
=
font
.
stringMetrics
(
yAxis
.
reduce
(
math
.
max
).
toStringAsFixed
(
1
))
*
(
style
.
fontSize
);
gridBox
=
PdfRect
.
fromLTRB
(
box
.
left
+
yAxisFontMetric
.
width
+
xMargin
,
box
.
bottom
+
xAxisFontMetric
.
height
+
yMargin
,
box
.
right
-
xAxisFontMetric
.
width
/
2
,
box
.
top
-
yAxisFontMetric
.
height
/
2
);
xOffset
=
xAxis
.
reduce
(
math
.
min
);
yOffset
=
yAxis
.
reduce
(
math
.
min
);
xTotal
=
xAxis
.
reduce
(
math
.
max
)
-
xOffset
;
yTotal
=
yAxis
.
reduce
(
math
.
max
)
-
yOffset
;
}
@override
void
paint
(
Context
context
,
PdfRect
box
)
{
xAxis
.
asMap
().
forEach
((
int
i
,
double
x
)
{
context
.
canvas
..
setColor
(
style
.
color
)
..
drawString
(
style
.
font
.
getFont
(
context
),
style
.
fontSize
,
x
.
toStringAsFixed
(
1
),
gridBox
.
left
+
gridBox
.
width
*
i
/
(
xAxis
.
length
-
1
)
-
xAxisFontMetric
.
width
/
2
,
0
,
);
});
for
(
double
y
in
yAxis
.
where
((
double
y
)
=>
y
!=
yAxis
.
first
))
{
final
double
textWidth
=
(
font
.
stringMetrics
(
y
.
toStringAsFixed
(
1
))
*
(
style
.
fontSize
)).
width
;
final
double
yPos
=
gridBox
.
bottom
+
gridBox
.
height
*
y
/
yAxis
.
last
;
context
.
canvas
..
setColor
(
style
.
color
)
..
drawString
(
style
.
font
.
getFont
(
context
),
style
.
fontSize
,
y
.
toStringAsFixed
(
1
),
xAxisFontMetric
.
width
/
2
-
textWidth
/
2
,
yPos
-
font
.
ascent
,
);
context
.
canvas
.
drawLine
(
gridBox
.
left
,
yPos
+
font
.
descent
+
font
.
ascent
-
separatorLineWidth
/
2
,
gridBox
.
right
,
yPos
+
font
.
descent
+
font
.
ascent
-
separatorLineWidth
/
2
);
}
context
.
canvas
..
setStrokeColor
(
separatorColor
)
..
setLineWidth
(
separatorLineWidth
)
..
strokePath
();
context
.
canvas
..
setStrokeColor
(
color
)
..
setLineWidth
(
lineWidth
)
..
drawLine
(
gridBox
.
left
,
gridBox
.
bottom
,
gridBox
.
right
,
gridBox
.
bottom
)
..
drawLine
(
gridBox
.
left
,
gridBox
.
bottom
,
gridBox
.
left
,
gridBox
.
top
)
..
strokePath
();
}
}
class
ChartValue
{
ChartValue
(
this
.
x
,
this
.
y
);
final
double
x
;
final
double
y
;
}
abstract
class
DataSet
{
void
layout
(
Context
context
,
PdfRect
box
);
void
paint
(
Context
context
,
Grid
grid
);
}
class
LineDataSet
extends
DataSet
{
LineDataSet
({
@required
this
.
data
,
this
.
pointColor
=
PdfColors
.
green
,
this
.
pointSize
=
8
,
this
.
lineColor
=
PdfColors
.
blue
,
this
.
lineWidth
=
2
,
this
.
drawLine
=
true
,
this
.
drawPoints
=
true
,
this
.
lineStartingPoint
,
})
:
assert
(
drawLine
||
drawPoints
);
final
List
<
ChartValue
>
data
;
final
PdfColor
pointColor
;
final
double
pointSize
;
final
PdfColor
lineColor
;
final
double
lineWidth
;
final
bool
drawLine
;
final
bool
drawPoints
;
final
ChartValue
lineStartingPoint
;
double
maxValue
;
@override
void
layout
(
Context
context
,
PdfRect
box
)
{}
@override
void
paint
(
Context
context
,
Grid
grid
)
{
if
(
drawLine
)
{
ChartValue
lastValue
=
lineStartingPoint
;
for
(
ChartValue
value
in
data
)
{
if
(
lastValue
!=
null
)
{
context
.
canvas
.
drawLine
(
grid
.
gridBox
.
left
+
grid
.
gridBox
.
width
*
(
lastValue
.
x
-
grid
.
xOffset
)
/
grid
.
xTotal
,
grid
.
gridBox
.
bottom
+
grid
.
gridBox
.
height
*
(
lastValue
.
y
-
grid
.
yOffset
)
/
grid
.
yTotal
,
grid
.
gridBox
.
left
+
grid
.
gridBox
.
width
*
(
value
.
x
-
grid
.
xOffset
)
/
grid
.
xTotal
,
grid
.
gridBox
.
bottom
+
grid
.
gridBox
.
height
*
(
value
.
y
-
grid
.
yOffset
)
/
grid
.
yTotal
,
);
}
lastValue
=
value
;
}
context
.
canvas
..
setStrokeColor
(
lineColor
)
..
setLineWidth
(
lineWidth
)
..
setLineCap
(
PdfLineCap
.
joinRound
)
..
setLineJoin
(
PdfLineCap
.
joinRound
)
..
strokePath
();
}
if
(
drawPoints
)
{
for
(
ChartValue
value
in
data
)
{
context
.
canvas
..
setColor
(
pointColor
)
..
drawEllipse
(
grid
.
gridBox
.
left
+
grid
.
gridBox
.
width
*
(
value
.
x
-
grid
.
xOffset
)
/
grid
.
xTotal
,
grid
.
gridBox
.
bottom
+
grid
.
gridBox
.
height
*
(
value
.
y
-
grid
.
yOffset
)
/
grid
.
yTotal
,
pointSize
,
pointSize
)
..
fillPath
();
}
}
}
}
...
...
pdf/test/widget_chart_test.dart
0 → 100644
View file @
ada7241
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ignore_for_file: omit_local_variable_types
import
'dart:io'
;
import
'package:test/test.dart'
;
import
'package:pdf/pdf.dart'
;
import
'package:pdf/widgets.dart'
;
Document
pdf
;
void
main
(
)
{
setUpAll
(()
{
Document
.
debug
=
true
;
pdf
=
Document
();
});
group
(
'LineChart test'
,
()
{
test
(
'Default LineChart'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Chart
(
grid:
LinearGrid
(
xAxis:
<
double
>[
0
,
1
,
2
,
3
,
4
,
5
,
6
],
yAxis:
<
double
>[
0
,
3
,
6
,
9
],
),
data:
<
DataSet
>[
LineDataSet
(
data:
<
ChartValue
>[
ChartValue
(
1
,
1
),
ChartValue
(
2
,
3
),
ChartValue
(
3
,
7
),
],
),
],
),
));
});
test
(
'Default LineChart without lines connecting points'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Chart
(
grid:
LinearGrid
(
xAxis:
<
double
>[
0
,
1
,
2
,
3
,
4
,
5
,
6
],
yAxis:
<
double
>[
0
,
3
,
6
,
9
],
),
data:
<
DataSet
>[
LineDataSet
(
data:
<
ChartValue
>[
ChartValue
(
1
,
1
),
ChartValue
(
2
,
3
),
ChartValue
(
3
,
7
),
],
drawLine:
false
,
),
],
),
));
});
test
(
'Default ScatterChart without dots'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Chart
(
grid:
LinearGrid
(
xAxis:
<
double
>[
0
,
1
,
2
,
3
,
4
,
5
,
6
],
yAxis:
<
double
>[
0
,
3
,
6
,
9
],
),
data:
<
DataSet
>[
LineDataSet
(
data:
<
ChartValue
>[
ChartValue
(
1
,
1
),
ChartValue
(
2
,
3
),
ChartValue
(
3
,
7
),
],
drawPoints:
false
,
),
],
),
));
});
test
(
'ScatterChart with custom points and lines'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Chart
(
grid:
LinearGrid
(
xAxis:
<
double
>[
0
,
1
,
2
,
3
,
4
,
5
,
6
],
yAxis:
<
double
>[
0
,
3
,
6
,
9
],
),
data:
<
DataSet
>[
LineDataSet
(
data:
<
ChartValue
>[
ChartValue
(
1
,
1
),
ChartValue
(
2
,
3
),
ChartValue
(
3
,
7
),
],
drawLine:
false
,
pointColor:
PdfColors
.
red
,
pointSize:
4
,
lineColor:
PdfColors
.
purple
,
lineWidth:
4
,
),
],
),
));
});
test
(
'ScatterChart with custom size'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Chart
(
width:
200
,
height:
100
,
grid:
LinearGrid
(
xAxis:
<
double
>[
0
,
1
,
2
,
3
,
4
,
5
,
6
],
yAxis:
<
double
>[
0
,
3
,
6
,
9
],
),
data:
<
DataSet
>[
LineDataSet
(
data:
<
ChartValue
>[
ChartValue
(
1
,
1
),
ChartValue
(
2
,
3
),
ChartValue
(
3
,
7
),
],
),
],
),
));
});
});
tearDownAll
(()
{
final
File
file
=
File
(
'widgets-chart.pdf'
);
file
.
writeAsBytesSync
(
pdf
.
save
());
});
}
...
...
Please
register
or
login
to post a comment