Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix padding and margin for LineLabels and Tooltips #824 #1587

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
## newVersion
* **BUGFIX** Fix a memory leak issue in the axis-based charts, there was a logic to calculate and cache the minX, maxX, minY and maxY properties to reduce the computation cost. But it caused some memory issues, as we don't have a quick solution for this, we disabled the caching logic for now, later we can move the calculation logic to the render objects to keep and update them only when the data is changed, #1106, #1693
* **BUGFIX** Fix showing grid lines even when there is no line to show in the LineChart, #1691
* **IMPROVEMENT** (by @k0psutin) Add `tooltipPadding` to BarTouchTooltipData, LineTouchTooltipData and ScatterTouchTooltipData, #824
* **BREAKING** (by @k0psutin) Remove `margin` from HorizontalLineLabel and VerticalLineLabel, #824
* **BREAKING** (by @k0psutin) Remove `bottomMargin` from ScatterTooltipItem , #824
* **IMPROVEMENT** (by @k0psutin) Add `verticalOFfset` and `horizontalOffset` to HorizontalLineLabel and VerticalLineLabel to replace `margin`, #824
* **BREAKING** (by @k0psutin) Remove `tooltipMargin` from HorizontalLineLabel and VerticalLineLabel, #824
* **BREAKING** (by @kopsutin) Add property `tooltipVerticalOffset` to BarTouchTooltipData, LineTouchTooltipData and ScatterTooltipItem to replace `tooltipMargin`, #824
* **BUGFIX** (by @k0psutin) Fix `padding` to apply padding correctly in HorizontalLineLabel and VerticalLineLabel, #824


```dart
/// Migration guide:
/// Old way:
BarTouchTooltipData(
tooltipMargin: -10,
)

/// New way:
BarTouchTooltipData(
tooltipVerticalOffset: -10, // same effect as old tooltipMargin
tooltipPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), // Adds padding to tooltip
)
```
* **BREAKING** (by @k0psutin) Remove `tooltipMargin` property from ScatterTooltipItem, #824
```dart
/// Migration guide:
/// Old way:
ScatterTooltipItem(
bottomMargin: 10,
)

/// New way:
ScatterTouchTooltipData(
tooltipVerticalOffset: 10, // same effect as old tooltipMargin
tooltipPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), // Adds padding to tooltip
)
```

## 0.68.0
* **Improvement** (by @imaNNeo) Update LineChartSample6 to implement a way to show a tooltip on a single spot, #1620
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class BarChartSample1State extends State<BarChartSample1> {
touchTooltipData: BarTouchTooltipData(
getTooltipColor: (_) => Colors.blueGrey,
tooltipHorizontalAlignment: FLHorizontalAlignment.right,
tooltipMargin: -10,
tooltipVerticalOffset: -10,
getTooltipItem: (group, groupIndex, rod, rodIndex) {
String weekDay;
switch (group.x) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class _BarChart extends StatelessWidget {
touchTooltipData: BarTouchTooltipData(
getTooltipColor: (group) => Colors.transparent,
tooltipPadding: EdgeInsets.zero,
tooltipMargin: 8,
tooltipVerticalOffset: 8,
getTooltipItem: (
BarChartGroupData group,
int groupIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ class _BarChartSample7State extends State<BarChartSample7> {
enabled: true,
handleBuiltInTouches: false,
touchTooltipData: BarTouchTooltipData(
tooltipVerticalOffset: 0,
getTooltipColor: (group) => Colors.transparent,
tooltipMargin: 0,
getTooltipItem: (
BarChartGroupData group,
int groupIndex,
Expand Down
6 changes: 4 additions & 2 deletions example/lib/presentation/samples/line/line_chart_sample8.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ class _LineChartSample8State extends State<LineChartSample8> {
label: HorizontalLineLabel(
show: true,
alignment: Alignment.topRight,
padding: const EdgeInsets.only(right: 5, bottom: 5),
verticalOffset: 5,
horizontalOffset: -5,
style: const TextStyle(
fontSize: 9,
fontWeight: FontWeight.bold,
Expand All @@ -167,8 +168,9 @@ class _LineChartSample8State extends State<LineChartSample8> {
dashArray: [5, 10],
label: VerticalLineLabel(
show: true,
verticalOffset: 5,
horizontalOffset: -5,
alignment: Alignment.bottomRight,
padding: const EdgeInsets.only(left: 5, bottom: 5),
style: const TextStyle(
fontSize: 9,
fontWeight: FontWeight.bold,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class _ScatterChartSample2State extends State {
: SystemMouseCursors.click;
},
touchTooltipData: ScatterTouchTooltipData(
tooltipVerticalOffset: 10,
getTooltipColor: (ScatterSpot touchedBarSpot) {
return touchedBarSpot.dotPainter.mainColor;
},
Expand Down Expand Up @@ -155,7 +156,6 @@ class _ScatterChartSample2State extends State {
color: color1,
fontStyle: FontStyle.italic,
),
bottomMargin: 10,
children: [
TextSpan(
text: '${touchedBarSpot.x.toInt()} \n',
Expand Down
17 changes: 9 additions & 8 deletions lib/src/chart/bar_chart/bar_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -692,8 +692,9 @@ class BarTouchTooltipData with EquatableMixin {
/// otherwise you can show it manually using [BarChartGroupData.showingTooltipIndicators].
/// Tooltip shows on top of rods, with [getTooltipColor] as a background color,
/// and you can set corner radius using [tooltipRoundedRadius].
/// If you want to have a padding inside the tooltip, fill [tooltipPadding],
/// or If you want to have a bottom margin, set [tooltipMargin].
/// If you want to have tooltip padding, fill [tooltipPadding],
/// If you want to adjust tooltip vertical position, set [tooltipVerticalOffset]
/// If you want to adjust tooltip horizontal position, set [tooltipHorizontalOffset]
/// Content of the tooltip will provide using [getTooltipItem] callback, you can override it
/// and pass your custom data to show in the tooltip.
/// You can restrict the tooltip's width using [maxContentWidth].
Expand All @@ -703,8 +704,8 @@ class BarTouchTooltipData with EquatableMixin {
BarTouchTooltipData({
double? tooltipRoundedRadius,
EdgeInsets? tooltipPadding,
double? tooltipMargin,
FLHorizontalAlignment? tooltipHorizontalAlignment,
double? tooltipVerticalOffset,
double? tooltipHorizontalOffset,
double? maxContentWidth,
GetBarTooltipItem? getTooltipItem,
Expand All @@ -717,7 +718,7 @@ class BarTouchTooltipData with EquatableMixin {
}) : tooltipRoundedRadius = tooltipRoundedRadius ?? 4,
tooltipPadding = tooltipPadding ??
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
tooltipMargin = tooltipMargin ?? 16,
tooltipVerticalOffset = tooltipVerticalOffset ?? 16,
tooltipHorizontalAlignment =
tooltipHorizontalAlignment ?? FLHorizontalAlignment.center,
tooltipHorizontalOffset = tooltipHorizontalOffset ?? 0,
Expand All @@ -737,15 +738,15 @@ class BarTouchTooltipData with EquatableMixin {
/// Applies a padding for showing contents inside the tooltip.
final EdgeInsets tooltipPadding;

/// Applies a bottom margin for showing tooltip on top of rods.
final double tooltipMargin;

/// Controls showing tooltip on left side, right side or center aligned with rod, default is center
final FLHorizontalAlignment tooltipHorizontalAlignment;

/// Applies horizontal offset for showing tooltip, default is zero.
final double tooltipHorizontalOffset;

/// Adds a offset for tooltip vertical position (offset is applied to bottom of the tooltip) for showing tooltip on top of rods.
final double tooltipVerticalOffset;
k0psutin marked this conversation as resolved.
Show resolved Hide resolved

/// Restricts the tooltip's width.
final double maxContentWidth;

Expand Down Expand Up @@ -775,7 +776,7 @@ class BarTouchTooltipData with EquatableMixin {
List<Object?> get props => [
tooltipRoundedRadius,
tooltipPadding,
tooltipMargin,
tooltipVerticalOffset,
tooltipHorizontalAlignment,
tooltipHorizontalOffset,
maxContentWidth,
Expand Down
35 changes: 13 additions & 22 deletions lib/src/chart/bar_chart/bar_chart_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart';
import 'package:fl_chart/src/extensions/bar_chart_data_extension.dart';
import 'package:fl_chart/src/extensions/paint_extension.dart';
import 'package:fl_chart/src/extensions/path_extension.dart';
import 'package:fl_chart/src/extensions/rect_extension.dart';
import 'package:fl_chart/src/extensions/rrect_extension.dart';
import 'package:fl_chart/src/utils/canvas_wrapper.dart';
import 'package:fl_chart/src/utils/utils.dart';
Expand Down Expand Up @@ -344,8 +345,6 @@ class BarChartPainter extends AxisChartPainter<BarChartData> {
) {
final viewSize = canvasWrapper.size;

const textsBelowMargin = 4;

final tooltipItem = tooltipData.getTooltipItem(
showOnBarGroup,
barGroupIndex,
Expand Down Expand Up @@ -373,16 +372,6 @@ class BarChartPainter extends AxisChartPainter<BarChartData> {
/// creating TextPainters to calculate the width and height of the tooltip
final drawingTextPainter = tp;

/// biggerWidth
/// some texts maybe larger, then we should
/// draw the tooltip' width as wide as biggerWidth
///
/// sumTextsHeight
/// sum up all Texts height, then we should
/// draw the tooltip's height as tall as sumTextsHeight
final textWidth = drawingTextPainter.width;
final textHeight = drawingTextPainter.height + textsBelowMargin;

/// if we have multiple bar lines,
/// there are more than one FlCandidate on touch area,
/// we should get the most top FlSpot Offset to draw the tooltip on top of it
Expand All @@ -395,34 +384,36 @@ class BarChartPainter extends AxisChartPainter<BarChartData> {
groupPositions[barGroupIndex].barsX[barRodIndex],
getPixelY(showOnRodData.fromY, viewSize, holder),
);

final tooltipWidth = textWidth + tooltipData.tooltipPadding.horizontal;
final tooltipHeight = textHeight + tooltipData.tooltipPadding.vertical;
final tooltipWidth = drawingTextPainter.width;
final tooltipHeight = drawingTextPainter.height;

final barTopY = min(barToYPixel.dy, barFromYPixel.dy);
final barBottomY = max(barToYPixel.dy, barFromYPixel.dy);
final drawTooltipOnTop = tooltipData.direction == TooltipDirection.top ||
(tooltipData.direction == TooltipDirection.auto &&
showOnRodData.isUpward());
final tooltipTop = drawTooltipOnTop
? barTopY - tooltipHeight - tooltipData.tooltipMargin
: barBottomY + tooltipData.tooltipMargin;

? barTopY -
tooltipHeight -
tooltipData.tooltipVerticalOffset -
(tooltipData.tooltipPadding.vertical / 2)
: barBottomY +
tooltipData.tooltipVerticalOffset +
(tooltipData.tooltipPadding.vertical / 2);
final tooltipLeft = getTooltipLeft(
barToYPixel.dx,
tooltipWidth,
tooltipData.tooltipHorizontalAlignment,
tooltipData.tooltipHorizontalOffset,
tooltipData.tooltipPadding,
);

/// draw the background rect with rounded radius
// ignore: omit_local_variable_types
Rect rect = Rect.fromLTWH(
var rect = Rect.fromLTWH(
tooltipLeft,
tooltipTop,
tooltipWidth,
tooltipHeight,
);
).applyPadding(tooltipData.tooltipPadding);

if (tooltipData.fitInsideHorizontally) {
if (rect.left < 0) {
Expand Down
26 changes: 18 additions & 8 deletions lib/src/chart/base/axis_chart/axis_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1129,14 +1129,16 @@ class VerticalLine extends FlLine with EquatableMixin {
/// Draws a title on the [HorizontalLine]
class HorizontalLineLabel extends FlLineLabel with EquatableMixin {
/// Draws a title on the [HorizontalLine], align it with [alignment] over the line,
/// applies [padding] for spaces, and applies [style for changing color,
/// applies [padding] for label padding, applies [verticalOffset] and [horizontalOffset] for label space and applies [style] for changing color,
/// size, ... of the text.
/// Drawing text will retrieve through [labelResolver],
/// you can override it with your custom data.
/// [show] determines showing label or not.
/// [direction] determines if the direction of the text should be horizontal or vertical.
HorizontalLineLabel({
super.padding = const EdgeInsets.all(6),
super.padding = const EdgeInsets.all(2),
super.horizontalOffset = 0.0,
super.verticalOffset = 0.0,
super.style,
super.alignment = Alignment.topLeft,
super.show = false,
Expand All @@ -1158,8 +1160,9 @@ class HorizontalLineLabel extends FlLineLabel with EquatableMixin {
double t,
) {
return HorizontalLineLabel(
padding:
EdgeInsets.lerp(a.padding as EdgeInsets, b.padding as EdgeInsets, t)!,
padding: EdgeInsets.lerp(a.padding, b.padding, t)!,
horizontalOffset: lerpDouble(a.horizontalOffset, b.horizontalOffset, t)!,
verticalOffset: lerpDouble(a.verticalOffset, b.verticalOffset, t)!,
style: TextStyle.lerp(a.style, b.style, t),
alignment: Alignment.lerp(a.alignment, b.alignment, t)!,
labelResolver: b.labelResolver,
Expand All @@ -1174,6 +1177,8 @@ class HorizontalLineLabel extends FlLineLabel with EquatableMixin {
labelResolver,
show,
padding,
horizontalOffset,
verticalOffset,
style,
alignment,
direction,
Expand All @@ -1183,14 +1188,16 @@ class HorizontalLineLabel extends FlLineLabel with EquatableMixin {
/// Draws a title on the [VerticalLine]
class VerticalLineLabel extends FlLineLabel with EquatableMixin {
/// Draws a title on the [VerticalLine], align it with [alignment] over the line,
/// applies [padding] for spaces, and applies [style for changing color,
/// applies [padding] for label padding, applies [verticalOffset] and [horizontalOffset] for label space and applies [style] for changing color,
/// size, ... of the text.
/// Drawing text will retrieve through [labelResolver],
/// you can override it with your custom data.
/// [show] determines showing label or not.
/// [direction] determines if the direction of the text should be horizontal or vertical.
VerticalLineLabel({
super.padding = const EdgeInsets.all(6),
super.padding = const EdgeInsets.all(2),
super.horizontalOffset = 0.0,
super.verticalOffset = 0.0,
super.style = const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
Expand All @@ -1216,8 +1223,9 @@ class VerticalLineLabel extends FlLineLabel with EquatableMixin {
double t,
) {
return VerticalLineLabel(
padding:
EdgeInsets.lerp(a.padding as EdgeInsets, b.padding as EdgeInsets, t)!,
padding: EdgeInsets.lerp(a.padding, b.padding, t)!,
horizontalOffset: lerpDouble(a.horizontalOffset, b.horizontalOffset, t)!,
verticalOffset: lerpDouble(a.verticalOffset, b.verticalOffset, t)!,
style: TextStyle.lerp(a.style, b.style, t),
alignment: Alignment.lerp(a.alignment, b.alignment, t)!,
labelResolver: b.labelResolver,
Expand All @@ -1232,6 +1240,8 @@ class VerticalLineLabel extends FlLineLabel with EquatableMixin {
labelResolver,
show,
padding,
horizontalOffset,
verticalOffset,
style,
alignment,
direction,
Expand Down
Loading