-
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* adjusting layout * semantics and test * changelog
- Loading branch information
1 parent
881c265
commit b7c8e1b
Showing
8 changed files
with
380 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:nes_ui/nes_ui.dart'; | ||
|
||
class TooltipsSection extends StatelessWidget { | ||
const TooltipsSection({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
return Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
Text( | ||
'Tooltips', | ||
style: theme.textTheme.displayMedium, | ||
), | ||
const SizedBox(height: 16), | ||
Row( | ||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
children: [ | ||
NesTooltip( | ||
message: 'This is a tooltip', | ||
arrowPlacement: NesTooltipArrowPlacement.left, | ||
child: NesIcon( | ||
iconData: NesIcons.instance.exclamationMarkBlock, | ||
), | ||
), | ||
NesTooltip( | ||
message: 'This is a tooltip', | ||
child: NesIcon( | ||
iconData: NesIcons.instance.exclamationMarkBlock, | ||
), | ||
), | ||
NesTooltip( | ||
message: 'This is a tooltip', | ||
arrowPlacement: NesTooltipArrowPlacement.right, | ||
child: NesIcon( | ||
iconData: NesIcons.instance.exclamationMarkBlock, | ||
), | ||
), | ||
], | ||
), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/semantics.dart'; | ||
import 'package:nes_ui/nes_ui.dart'; | ||
|
||
/// Enum with the possible placements for the arrow of the tooltip. | ||
enum NesTooltipArrowPlacement { | ||
/// The arrow will be placed on the left side of the tooltip. | ||
left, | ||
|
||
/// The arrow will be placed on the middle of the tooltip. | ||
middle, | ||
|
||
/// The arrow will be placed on the right side of the tooltip. | ||
right, | ||
} | ||
|
||
/// {@template nes_tooltip} | ||
/// A tooltip that appears when the user long-presses on a widget, | ||
/// or hovers over it with a mouse. | ||
/// {@endtemplate} | ||
class NesTooltip extends StatefulWidget { | ||
/// {@macro nes_tooltip} | ||
const NesTooltip({ | ||
super.key, | ||
required this.child, | ||
required this.message, | ||
this.arrowPlacement = NesTooltipArrowPlacement.middle, | ||
}); | ||
|
||
/// The Widget that will trigger the tooltip. | ||
final Widget child; | ||
|
||
/// The message to be displayed in the tooltip. | ||
final String message; | ||
|
||
/// The placement of the arrow of the tooltip. | ||
final NesTooltipArrowPlacement arrowPlacement; | ||
|
||
@override | ||
State<NesTooltip> createState() => _NesTooltipState(); | ||
} | ||
|
||
class _NesTooltipState extends State<NesTooltip> { | ||
var _show = false; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final textStyle = | ||
Theme.of(context).textTheme.labelMedium ?? const TextStyle(); | ||
final tooltipTheme = context.nesThemeExtension<NesTooltipTheme>(); | ||
final nesTheme = context.nesThemeExtension<NesTheme>(); | ||
|
||
return CustomPaint( | ||
painter: _show | ||
? _TooltipPainter( | ||
color: tooltipTheme.background, | ||
pixelSize: nesTheme.pixelSize.toDouble(), | ||
arrowPlacement: widget.arrowPlacement, | ||
textStyle: textStyle, | ||
message: widget.message, | ||
textColor: tooltipTheme.textColor, | ||
) | ||
: null, | ||
child: GestureDetector( | ||
onLongPress: () { | ||
setState(() { | ||
_show = true; | ||
}); | ||
}, | ||
onLongPressEnd: (_) { | ||
setState(() { | ||
_show = false; | ||
}); | ||
}, | ||
onLongPressCancel: () { | ||
setState(() { | ||
_show = false; | ||
}); | ||
}, | ||
child: MouseRegion( | ||
onEnter: (_) { | ||
setState(() { | ||
_show = true; | ||
}); | ||
}, | ||
onExit: (_) { | ||
setState(() { | ||
_show = false; | ||
}); | ||
}, | ||
child: widget.child, | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
class _TooltipPainter extends CustomPainter { | ||
_TooltipPainter({ | ||
required this.color, | ||
required this.pixelSize, | ||
required this.arrowPlacement, | ||
required this.textStyle, | ||
required this.textColor, | ||
required this.message, | ||
}); | ||
|
||
final Color color; | ||
final double pixelSize; | ||
final NesTooltipArrowPlacement arrowPlacement; | ||
final TextStyle textStyle; | ||
final Color textColor; | ||
final String message; | ||
|
||
@override | ||
SemanticsBuilderCallback? get semanticsBuilder => (size) { | ||
return [ | ||
CustomPainterSemantics( | ||
rect: Rect.fromLTWH(0, 0, size.width, size.height), | ||
properties: SemanticsProperties( | ||
label: message, | ||
textDirection: TextDirection.ltr, | ||
), | ||
), | ||
]; | ||
}; | ||
|
||
@override | ||
void paint(Canvas canvas, Size childSize) { | ||
final textPainter = TextPainter( | ||
textDirection: TextDirection.ltr, | ||
text: TextSpan( | ||
text: message, | ||
style: textStyle.copyWith( | ||
color: textColor, | ||
), | ||
), | ||
)..layout(); | ||
|
||
final textSize = textPainter.size; | ||
|
||
final paint = Paint()..color = color; | ||
|
||
final size = Size( | ||
textSize.width + pixelSize * 4, | ||
textSize.height + pixelSize * 2, | ||
); | ||
|
||
final arrowOffset = switch (arrowPlacement) { | ||
NesTooltipArrowPlacement.left => pixelSize * 2, | ||
NesTooltipArrowPlacement.middle => size.width / 2 - pixelSize, | ||
NesTooltipArrowPlacement.right => size.width - pixelSize * 4, | ||
}; | ||
|
||
canvas.save(); | ||
|
||
final translateX = switch (arrowPlacement) { | ||
NesTooltipArrowPlacement.left => 0.0, | ||
NesTooltipArrowPlacement.middle => -size.width / 2 + childSize.width / 2, | ||
NesTooltipArrowPlacement.right => -size.width + childSize.width, | ||
}; | ||
|
||
final translateY = -size.height - pixelSize * 4; | ||
|
||
canvas | ||
..translate(translateX, translateY) | ||
..drawRect( | ||
Rect.fromLTWH(0, 0, size.width, size.height), | ||
paint, | ||
) | ||
..drawRect( | ||
Rect.fromLTWH( | ||
pixelSize, | ||
-pixelSize, | ||
size.width - pixelSize * 2, | ||
pixelSize, | ||
), | ||
paint, | ||
) | ||
..drawRect( | ||
Rect.fromLTWH( | ||
pixelSize, | ||
size.height, | ||
size.width - pixelSize * 2, | ||
pixelSize, | ||
), | ||
paint, | ||
); | ||
|
||
textPainter.paint(canvas, Offset(pixelSize * 2, pixelSize)); | ||
|
||
// Arrow | ||
canvas | ||
..drawRect( | ||
Rect.fromLTWH( | ||
arrowOffset, | ||
size.height + pixelSize, | ||
pixelSize * 2, | ||
pixelSize, | ||
), | ||
paint, | ||
) | ||
..drawRect( | ||
Rect.fromLTWH( | ||
arrowOffset + pixelSize / 2, | ||
size.height + pixelSize * 2, | ||
pixelSize, | ||
pixelSize, | ||
), | ||
paint, | ||
) | ||
..restore(); | ||
} | ||
|
||
@override | ||
bool shouldRepaint(_TooltipPainter oldDelegate) => | ||
oldDelegate.color != color || | ||
oldDelegate.pixelSize != pixelSize || | ||
oldDelegate.arrowPlacement != arrowPlacement || | ||
oldDelegate.textColor != textColor || | ||
oldDelegate.message != message || | ||
oldDelegate.textStyle != textStyle; | ||
} |
Oops, something went wrong.