From 5f8d0af355da39dd2de949af6ba012032f6eae43 Mon Sep 17 00:00:00 2001 From: thenoumandev Date: Tue, 14 Jan 2025 22:03:58 +0500 Subject: [PATCH 1/2] updated tooltip implementation to resemble ensemble structure --- .../lib/framework/ensemble_widget.dart | 13 ++ .../ensemble/lib/framework/widget/widget.dart | 11 ++ modules/ensemble/lib/util/utils.dart | 74 ++++++++ .../lib/widget/helpers/controllers.dart | 20 ++- .../lib/widget/helpers/tooltip_composite.dart | 77 +++++++++ modules/ensemble/lib/widget/tooltip.dart | 163 ------------------ .../ensemble/lib/widget/widget_registry.dart | 2 - 7 files changed, 192 insertions(+), 168 deletions(-) create mode 100644 modules/ensemble/lib/widget/helpers/tooltip_composite.dart delete mode 100644 modules/ensemble/lib/widget/tooltip.dart diff --git a/modules/ensemble/lib/framework/ensemble_widget.dart b/modules/ensemble/lib/framework/ensemble_widget.dart index 0167d5128..32dd318d7 100644 --- a/modules/ensemble/lib/framework/ensemble_widget.dart +++ b/modules/ensemble/lib/framework/ensemble_widget.dart @@ -5,6 +5,7 @@ import 'package:ensemble/framework/error_handling.dart'; import 'package:ensemble/framework/scope.dart'; import 'package:ensemble/framework/studio/studio_debugger.dart'; import 'package:ensemble/framework/view/data_scope_widget.dart'; +import 'package:ensemble/util/utils.dart'; import 'package:ensemble/widget/helpers/controllers.dart'; import 'package:ensemble_ts_interpreter/invokables/invokable.dart'; import 'package:flutter/cupertino.dart'; @@ -67,6 +68,18 @@ abstract class EnsembleWidgetState extends State { child: rtn); } + + // add tooltip handling if tooltip message is specified + if (widgetController.tooltipMessage?.isNotEmpty == true) { + rtn = Utils.getTooltipWidget( + rtn, + widgetController.tooltipMessage!, + widgetController.tooltipStyle, + onTriggered: widgetController.tooltipStyle?.onTriggered, + context: context, + ); + } + // in Web, capture the pointer if overlay on htmlelementview like Maps if (widgetController.captureWebPointer == true) { rtn = PointerInterceptor(child: rtn); diff --git a/modules/ensemble/lib/framework/widget/widget.dart b/modules/ensemble/lib/framework/widget/widget.dart index c724303a3..9e915741c 100644 --- a/modules/ensemble/lib/framework/widget/widget.dart +++ b/modules/ensemble/lib/framework/widget/widget.dart @@ -75,6 +75,17 @@ abstract class EWidgetState child: rtn); } + // add tooltip handling if tooltip message is specified + if (widgetController.tooltipMessage?.isNotEmpty == true) { + rtn = Utils.getTooltipWidget( + rtn, + widgetController.tooltipMessage!, + widgetController.tooltipStyle, + onTriggered: widgetController.tooltipStyle?.onTriggered, + context: context, + ); + } + // in Web, capture the pointer if overlay on htmlelementview like Maps if (widgetController.captureWebPointer == true) { rtn = PointerInterceptor(child: rtn); diff --git a/modules/ensemble/lib/util/utils.dart b/modules/ensemble/lib/util/utils.dart index 0d9bb82cf..8d6fdc5f4 100644 --- a/modules/ensemble/lib/util/utils.dart +++ b/modules/ensemble/lib/util/utils.dart @@ -3,8 +3,11 @@ import 'dart:math'; import 'dart:ui'; import 'package:ensemble/ensemble.dart'; import 'package:ensemble/ensemble_app.dart'; +import 'package:ensemble/framework/action.dart'; import 'package:ensemble/framework/stub/location_manager.dart'; import 'package:ensemble/framework/theme/theme_manager.dart'; +import 'package:ensemble/screen_controller.dart'; +import 'package:ensemble/widget/helpers/tooltip_composite.dart'; import 'package:ensemble_ts_interpreter/invokables/UserLocale.dart'; import 'package:path/path.dart' as p; @@ -488,6 +491,77 @@ class Utils { return null; } + // Creates tooltip composite from inputs + static TooltipStyleComposite? getTooltipStyleComposite( + ChangeNotifier controller, dynamic inputs) { + if (inputs is Map) { + return TooltipStyleComposite(controller, inputs: inputs); + } + return null; + } + + /// Creates tooltip widget with configured styles and behavior + static Widget getTooltipWidget( + Widget child, + String message, + TooltipStyleComposite? style, { + EnsembleAction? onTriggered, + required BuildContext context, + }) { + final tooltipKey = GlobalKey(); + // Start with the original child + Widget tooltipChild = child; + + // Handle web-specific hover case first + if (kIsWeb && style?.triggerMode == null) { + tooltipChild = MouseRegion( + onEnter: (_) { + final dynamic tooltip = tooltipKey.currentState; + tooltip?.ensureTooltipVisible(); + }, + onExit: (_) { + final dynamic tooltip = tooltipKey.currentState; + tooltip?.deactivate(); + }, + child: tooltipChild, + ); + } + + return Tooltip( + key: tooltipKey, + message: message, + textStyle: style?.textStyle, + padding: style?.padding, + margin: style?.margin, + verticalOffset: style?.verticalOffset, + preferBelow: style?.preferBelow, + waitDuration: style?.waitDuration ?? const Duration(milliseconds: 0), + showDuration: style?.showDuration ?? const Duration(milliseconds: 1500), + triggerMode: style?.triggerMode ?? TooltipTriggerMode.tap, + enableFeedback: true, + decoration: BoxDecoration( + color: style?.backgroundColor ?? Colors.grey[700], + borderRadius: style?.borderRadius, + border: (style?.borderColor != null || style?.borderWidth != null) + ? Border.all( + color: style?.borderColor ?? + ThemeManager().getBorderColor(context), + width: (style?.borderWidth ?? + ThemeManager().getBorderThickness(context)) + .toDouble(), + ) + : null, + ), + onTriggered: onTriggered != null + ? () => ScreenController().executeAction( + context, + onTriggered, + ) + : null, + child: tooltipChild, + ); + } + static BoxShadowComposite? getBoxShadowComposite( ChangeNotifier widgetController, dynamic inputs) { if (inputs is Map) { diff --git a/modules/ensemble/lib/widget/helpers/controllers.dart b/modules/ensemble/lib/widget/helpers/controllers.dart index cc4ae0da5..50f1bd7e4 100644 --- a/modules/ensemble/lib/widget/helpers/controllers.dart +++ b/modules/ensemble/lib/widget/helpers/controllers.dart @@ -8,9 +8,11 @@ import 'package:ensemble/model/transform_matrix.dart'; import 'package:ensemble/page_model.dart'; import 'package:ensemble/util/utils.dart'; import 'package:ensemble/widget/helpers/box_animation_composite.dart'; +import 'package:ensemble/widget/helpers/tooltip_composite.dart'; import 'package:ensemble_ts_interpreter/errors.dart'; import 'package:ensemble_ts_interpreter/invokables/invokable.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import '../../model/capabilities.dart'; @@ -223,6 +225,10 @@ abstract class WidgetController extends Controller with HasStyles { // https://pub.dev/packages/pointer_interceptor bool? captureWebPointer; + // properties for tooltip + String? tooltipMessage; + TooltipStyleComposite? tooltipStyle; + // legacy used to show as the form label if used inside Form @Deprecated("don't use anymore") String? label; @@ -279,7 +285,9 @@ abstract class WidgetController extends Controller with HasStyles { 'textDirection': (value) => textDirection = Utils.getTextDirection(value), 'label': (value) => label = Utils.optionalString(value), 'classList': (value) => classList = value, - 'className': (value) => className = value + 'className': (value) => className = value, + 'tooltipMessage': (value) => tooltipMessage = Utils.optionalString(value), + 'tooltipStyle': (value) => tooltipStyle = Utils.getTooltipStyleComposite(this, value), }; } @@ -458,6 +466,10 @@ abstract class EnsembleWidgetController extends EnsembleController // https://pub.dev/packages/pointer_interceptor bool? captureWebPointer; + // properties for tooltip + String? tooltipMessage; + TooltipStyleComposite? tooltipStyle; + @override Map getters() { return { @@ -499,8 +511,10 @@ abstract class EnsembleWidgetController extends EnsembleController 'captureWebPointer': (value) => captureWebPointer = Utils.optionalBool(value), 'classList': (value) => classList = value, - 'className': (value) => className = value - }; + 'className': (value) => className = value, + 'tooltipMessage': (value) => tooltipMessage = Utils.optionalString(value), + 'tooltipStyle': (value) => tooltipStyle = Utils.getTooltipStyleComposite(this, value), + }; } bool hasPositions() { diff --git a/modules/ensemble/lib/widget/helpers/tooltip_composite.dart b/modules/ensemble/lib/widget/helpers/tooltip_composite.dart new file mode 100644 index 000000000..b8718af82 --- /dev/null +++ b/modules/ensemble/lib/widget/helpers/tooltip_composite.dart @@ -0,0 +1,77 @@ +/// This class contains helper controllers for our widgets. +import 'package:ensemble/framework/action.dart'; +import 'package:ensemble/framework/extensions.dart'; +import 'package:ensemble/util/utils.dart'; +import 'package:ensemble/widget/helpers/controllers.dart'; +import 'package:flutter/material.dart'; + +// Composite class to handle tooltip styling and behavior +class TooltipStyleComposite extends WidgetCompositeProperty { + TooltipStyleComposite(super.widgetController, {required Map inputs}) { + textStyle = Utils.getTextStyle(inputs['textStyle']); + verticalOffset = Utils.optionalDouble(inputs['verticalOffset']); + preferBelow = Utils.optionalBool(inputs['preferBelow']); + waitDuration = Utils.getDuration(inputs['waitDuration']); + showDuration = Utils.getDuration(inputs['showDuration']); + triggerMode = TooltipTriggerMode.values.from(inputs['triggerMode']); + backgroundColor = Utils.getColor(inputs['backgroundColor']); + borderRadius = Utils.getBorderRadius(inputs['borderRadius'])?.getValue(); + padding = Utils.optionalInsets(inputs['padding']); + margin = Utils.optionalInsets(inputs['margin']); + onTriggered = inputs['onTriggered'] != null ? + EnsembleAction.from(inputs['onTriggered']) : null; + borderColor = Utils.getColor(inputs['borderColor']); + borderWidth = Utils.optionalInt(inputs['borderWidth']); + } + + TextStyle? textStyle; + double? verticalOffset; + bool? preferBelow; + Duration? waitDuration; + Duration? showDuration; + TooltipTriggerMode? triggerMode; + Color? backgroundColor; + BorderRadius? borderRadius; + EdgeInsets? padding; + EdgeInsets? margin; + EnsembleAction? onTriggered; + Color? borderColor; + int? borderWidth; + + @override + Map setters() { + return { + 'textStyle': (value) => textStyle = Utils.getTextStyle(value), + 'verticalOffset': (value) => verticalOffset = Utils.optionalDouble(value), + 'preferBelow': (value) => preferBelow = Utils.optionalBool(value), + 'waitDuration': (value) => waitDuration = Utils.getDuration(value), + 'showDuration': (value) => showDuration = Utils.getDuration(value), + 'triggerMode': (value) => triggerMode = TooltipTriggerMode.values.from(value), + 'backgroundColor': (value) => backgroundColor = Utils.getColor(value), + 'borderRadius': (value) => borderRadius = Utils.getBorderRadius(value)?.getValue(), + 'padding': (value) => padding = Utils.optionalInsets(value), + 'margin': (value) => margin = Utils.optionalInsets(value), + 'borderColor': (value) => borderColor = Utils.getColor(value), + 'borderWidth': (value) => borderWidth = Utils.optionalInt(value), + 'onTriggered': (value) => onTriggered = value != null ? + EnsembleAction.from(value) : null, + }; + } + + @override + Map getters() => { + 'textStyle': () => textStyle, + 'verticalOffset': () => verticalOffset, + 'preferBelow': () => preferBelow, + 'waitDuration': () => waitDuration, + 'showDuration': () => showDuration, + 'triggerMode': () => triggerMode, + 'backgroundColor': () => backgroundColor, + 'borderRadius': () => borderRadius, + 'padding': () => padding, + 'margin': () => margin, + }; + + @override + Map methods() => {}; +} \ No newline at end of file diff --git a/modules/ensemble/lib/widget/tooltip.dart b/modules/ensemble/lib/widget/tooltip.dart deleted file mode 100644 index e93240a55..000000000 --- a/modules/ensemble/lib/widget/tooltip.dart +++ /dev/null @@ -1,163 +0,0 @@ -import 'package:ensemble/framework/event.dart'; -import 'package:ensemble/framework/extensions.dart'; -import 'package:ensemble/framework/theme/theme_manager.dart'; -import 'package:ensemble/widget/helpers/controllers.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:ensemble/framework/widget/widget.dart'; -import 'package:ensemble/framework/action.dart'; -import 'package:ensemble/screen_controller.dart'; -import 'package:ensemble/util/utils.dart'; -import 'package:ensemble_ts_interpreter/invokables/invokable.dart'; -import 'package:ensemble/framework/widget/has_children.dart'; -import 'package:ensemble/framework/widget/view_util.dart'; - -class ToolTip extends StatefulWidget - with Invokable, HasController { - static const type = 'ToolTip'; - - ToolTip({Key? key}) : super(key: key); - - final ToolTipController _controller = ToolTipController(); - - @override - ToolTipController get controller => _controller; - - @override - State createState() => ToolTipState(); - - @override - Map getters() { - return { - 'isVisible': () => _controller.isVisible, - }; - } - - @override - Map setters() { - return { - 'message': (value) => _controller.message = Utils.optionalString(value), - 'widget': (value) => _controller.widget = value, - 'textStyle': (value) => _controller.textStyle = Utils.getTextStyle(value), - 'verticalOffset': (value) => - _controller.verticalOffset = Utils.optionalDouble(value), - 'preferBelow': (value) => - _controller.preferBelow = Utils.optionalBool(value), - 'waitDuration': (value) => - _controller.waitDuration = Utils.getDuration(value), - 'showDuration': (value) => - _controller.showDuration = Utils.getDuration(value), - 'triggerMode': (value) => - _controller.triggerMode = TooltipTriggerMode.values.from(value), - 'onTriggered': (definition) => _controller.onTriggered = - EnsembleAction.from(definition, initiator: this), - }; - } - - @override - Map methods() { - return { - 'show': () => _controller.show(), - }; - } -} - -class ToolTipController extends BoxController { - String? message; - dynamic widget; - TextStyle? textStyle; - double? verticalOffset; - bool? preferBelow; - Duration? waitDuration; - Duration? showDuration; - TooltipTriggerMode? triggerMode; - bool isVisible = false; - EnsembleAction? onTriggered; - - void show() { - isVisible = true; - notifyListeners(); - } - - void hide() { - isVisible = false; - notifyListeners(); - } -} - -class ToolTipState extends EWidgetState with HasChildren { - final GlobalKey _tooltipKey = GlobalKey(); - - @override - void initState() { - super.initState(); - widget.controller.addListener(() => setState(() {})); - } - - void _showTooltip() { - final dynamic tooltip = _tooltipKey.currentState; - tooltip?.ensureTooltipVisible(); - widget.controller.show(); - } - - void _hideTooltip() { - final dynamic tooltip = _tooltipKey.currentState; - tooltip?.deactivate(); - widget.controller.hide(); - } - - @override - Widget buildWidget(BuildContext context) { - Widget child = widget.controller.widget != null - ? buildChild(ViewUtil.buildModel(widget.controller.widget, null)) - : const SizedBox.shrink(); - - if (kIsWeb && widget.controller.triggerMode == null) { - child = MouseRegion( - onEnter: (_) => _showTooltip(), - onExit: (_) => _hideTooltip(), - child: child, - ); - } - - return Tooltip( - key: _tooltipKey, - message: widget.controller.message ?? '', - textStyle: widget.controller.textStyle, - height: widget.controller.height?.toDouble(), - padding: widget.controller.padding, - margin: widget.controller.margin, - verticalOffset: widget.controller.verticalOffset, - preferBelow: widget.controller.preferBelow, - waitDuration: - widget.controller.waitDuration ?? const Duration(milliseconds: 0), - showDuration: - widget.controller.showDuration ?? const Duration(milliseconds: 1500), - triggerMode: widget.controller.triggerMode ?? - (kIsWeb ? null : TooltipTriggerMode.tap), - enableFeedback: true, - decoration: BoxDecoration( - color: widget._controller.backgroundColor ?? Colors.grey[700], - borderRadius: widget._controller.borderRadius?.getValue(), - border: widget._controller.borderColor != null || - widget._controller.borderWidth != null - ? Border.all( - color: widget._controller.borderColor ?? - ThemeManager().getBorderColor(context), - width: widget._controller.borderWidth?.toDouble() ?? - ThemeManager().getBorderThickness(context), - ) - : null), - onTriggered: () { - if (widget.controller.onTriggered != null) { - ScreenController().executeAction( - context, - widget.controller.onTriggered!, - event: EnsembleEvent(widget), - ); - } - }, - child: child, - ); - } -} diff --git a/modules/ensemble/lib/widget/widget_registry.dart b/modules/ensemble/lib/widget/widget_registry.dart index bb364cf2a..62520967b 100644 --- a/modules/ensemble/lib/widget/widget_registry.dart +++ b/modules/ensemble/lib/widget/widget_registry.dart @@ -59,7 +59,6 @@ import 'package:ensemble/widget/stub_widgets.dart'; import 'package:ensemble/widget/switch.dart'; import 'package:ensemble/widget/text.dart'; import 'package:ensemble/widget/toggle_button.dart'; -import 'package:ensemble/widget/tooltip.dart'; import 'package:ensemble/widget/video.dart'; import 'package:ensemble/widget/slidable.dart'; import 'package:ensemble/widget/accordion.dart'; @@ -139,7 +138,6 @@ class WidgetRegistry { PopupMenu.type: () => PopupMenu(), EnsembleCalendar.type: () => EnsembleCalendar(), Countdown.type: () => Countdown(), - ToolTip.type: () => ToolTip(), EnsembleAccordion.type: () => EnsembleAccordion(), // form fields From 44ebbd6042561a11ff537657263d229df475ac33 Mon Sep 17 00:00:00 2001 From: thenoumandev Date: Fri, 7 Feb 2025 04:19:26 +0500 Subject: [PATCH 2/2] updated tooltip --- .../lib/framework/ensemble_widget.dart | 10 ++-- .../ensemble/lib/framework/widget/widget.dart | 9 ++- modules/ensemble/lib/util/utils.dart | 58 ++++++++++--------- .../lib/widget/helpers/controllers.dart | 13 ++--- .../lib/widget/helpers/tooltip_composite.dart | 31 ++++++++-- 5 files changed, 71 insertions(+), 50 deletions(-) diff --git a/modules/ensemble/lib/framework/ensemble_widget.dart b/modules/ensemble/lib/framework/ensemble_widget.dart index 32dd318d7..0e1b13ad7 100644 --- a/modules/ensemble/lib/framework/ensemble_widget.dart +++ b/modules/ensemble/lib/framework/ensemble_widget.dart @@ -70,13 +70,13 @@ abstract class EnsembleWidgetState extends State { // add tooltip handling if tooltip message is specified - if (widgetController.tooltipMessage?.isNotEmpty == true) { + // add tooltip handling if tooltip message is specified + if (widgetController.toolTip != null) { rtn = Utils.getTooltipWidget( + context, rtn, - widgetController.tooltipMessage!, - widgetController.tooltipStyle, - onTriggered: widgetController.tooltipStyle?.onTriggered, - context: context, + widgetController.toolTip, + widgetController ); } diff --git a/modules/ensemble/lib/framework/widget/widget.dart b/modules/ensemble/lib/framework/widget/widget.dart index 9e915741c..1350014bf 100644 --- a/modules/ensemble/lib/framework/widget/widget.dart +++ b/modules/ensemble/lib/framework/widget/widget.dart @@ -76,13 +76,12 @@ abstract class EWidgetState } // add tooltip handling if tooltip message is specified - if (widgetController.tooltipMessage?.isNotEmpty == true) { + if (widgetController.toolTip != null) { rtn = Utils.getTooltipWidget( + context, rtn, - widgetController.tooltipMessage!, - widgetController.tooltipStyle, - onTriggered: widgetController.tooltipStyle?.onTriggered, - context: context, + widgetController.toolTip, + widgetController ); } diff --git a/modules/ensemble/lib/util/utils.dart b/modules/ensemble/lib/util/utils.dart index 8d6fdc5f4..f8092715a 100644 --- a/modules/ensemble/lib/util/utils.dart +++ b/modules/ensemble/lib/util/utils.dart @@ -502,18 +502,21 @@ class Utils { /// Creates tooltip widget with configured styles and behavior static Widget getTooltipWidget( - Widget child, - String message, - TooltipStyleComposite? style, { - EnsembleAction? onTriggered, - required BuildContext context, - }) { + BuildContext context, + Widget child, + Map? tooltipData, + ChangeNotifier controller +) { + if (tooltipData == null) return child; + + final tooltip = TooltipData.from(tooltipData, controller); + if (tooltip == null) return child; + final tooltipKey = GlobalKey(); // Start with the original child Widget tooltipChild = child; - // Handle web-specific hover case first - if (kIsWeb && style?.triggerMode == null) { + if (kIsWeb && tooltip.styles?.triggerMode == null) { tooltipChild = MouseRegion( onEnter: (_) { final dynamic tooltip = tooltipKey.currentState; @@ -529,34 +532,35 @@ class Utils { return Tooltip( key: tooltipKey, - message: message, - textStyle: style?.textStyle, - padding: style?.padding, - margin: style?.margin, - verticalOffset: style?.verticalOffset, - preferBelow: style?.preferBelow, - waitDuration: style?.waitDuration ?? const Duration(milliseconds: 0), - showDuration: style?.showDuration ?? const Duration(milliseconds: 1500), - triggerMode: style?.triggerMode ?? TooltipTriggerMode.tap, + message: tooltip.message, + textStyle: tooltip.styles?.textStyle, + padding: tooltip.styles?.padding, + margin: tooltip.styles?.margin, + verticalOffset: tooltip.styles?.verticalOffset, + preferBelow: tooltip.styles?.preferBelow, + waitDuration: + tooltip.styles?.waitDuration ?? const Duration(milliseconds: 0), + showDuration: + tooltip.styles?.showDuration ?? const Duration(milliseconds: 1500), + triggerMode: tooltip.styles?.triggerMode ?? TooltipTriggerMode.tap, enableFeedback: true, decoration: BoxDecoration( - color: style?.backgroundColor ?? Colors.grey[700], - borderRadius: style?.borderRadius, - border: (style?.borderColor != null || style?.borderWidth != null) + color: tooltip.styles?.backgroundColor ?? Colors.grey[700], + borderRadius: tooltip.styles?.borderRadius, + border: (tooltip.styles?.borderColor != null || + tooltip.styles?.borderWidth != null) ? Border.all( - color: style?.borderColor ?? + color: tooltip.styles?.borderColor ?? ThemeManager().getBorderColor(context), - width: (style?.borderWidth ?? + width: (tooltip.styles?.borderWidth ?? ThemeManager().getBorderThickness(context)) .toDouble(), ) : null, ), - onTriggered: onTriggered != null - ? () => ScreenController().executeAction( - context, - onTriggered, - ) + onTriggered: tooltip.onTriggered != null + ? () => + ScreenController().executeAction(context, tooltip.onTriggered!) : null, child: tooltipChild, ); diff --git a/modules/ensemble/lib/widget/helpers/controllers.dart b/modules/ensemble/lib/widget/helpers/controllers.dart index 50f1bd7e4..50e47c63f 100644 --- a/modules/ensemble/lib/widget/helpers/controllers.dart +++ b/modules/ensemble/lib/widget/helpers/controllers.dart @@ -226,8 +226,7 @@ abstract class WidgetController extends Controller with HasStyles { bool? captureWebPointer; // properties for tooltip - String? tooltipMessage; - TooltipStyleComposite? tooltipStyle; + Map? toolTip; // legacy used to show as the form label if used inside Form @Deprecated("don't use anymore") @@ -286,8 +285,7 @@ abstract class WidgetController extends Controller with HasStyles { 'label': (value) => label = Utils.optionalString(value), 'classList': (value) => classList = value, 'className': (value) => className = value, - 'tooltipMessage': (value) => tooltipMessage = Utils.optionalString(value), - 'tooltipStyle': (value) => tooltipStyle = Utils.getTooltipStyleComposite(this, value), + 'tooltip': (value) => toolTip = Utils.getMap(value), }; } @@ -467,8 +465,8 @@ abstract class EnsembleWidgetController extends EnsembleController bool? captureWebPointer; // properties for tooltip - String? tooltipMessage; - TooltipStyleComposite? tooltipStyle; + Map? toolTip; + @override Map getters() { @@ -512,8 +510,7 @@ abstract class EnsembleWidgetController extends EnsembleController captureWebPointer = Utils.optionalBool(value), 'classList': (value) => classList = value, 'className': (value) => className = value, - 'tooltipMessage': (value) => tooltipMessage = Utils.optionalString(value), - 'tooltipStyle': (value) => tooltipStyle = Utils.getTooltipStyleComposite(this, value), + 'tooltip': (value) => toolTip = Utils.getMap(value), }; } diff --git a/modules/ensemble/lib/widget/helpers/tooltip_composite.dart b/modules/ensemble/lib/widget/helpers/tooltip_composite.dart index b8718af82..9d9802322 100644 --- a/modules/ensemble/lib/widget/helpers/tooltip_composite.dart +++ b/modules/ensemble/lib/widget/helpers/tooltip_composite.dart @@ -5,6 +5,30 @@ import 'package:ensemble/util/utils.dart'; import 'package:ensemble/widget/helpers/controllers.dart'; import 'package:flutter/material.dart'; +class TooltipData { + final String message; + final TooltipStyleComposite? styles; + final EnsembleAction? onTriggered; + + TooltipData({ + required this.message, + this.styles, + this.onTriggered, + }); + + static TooltipData? from(Map? data, ChangeNotifier controller) { + if (data == null) return null; + + return TooltipData( + message: Utils.getString(data['message'], fallback: ''), + styles: data['styles'] != null ? + TooltipStyleComposite(controller, inputs: data['styles']) : null, + onTriggered: data['onTriggered'] != null ? + EnsembleAction.from(data['onTriggered']) : null, + ); + } +} + // Composite class to handle tooltip styling and behavior class TooltipStyleComposite extends WidgetCompositeProperty { TooltipStyleComposite(super.widgetController, {required Map inputs}) { @@ -18,8 +42,6 @@ class TooltipStyleComposite extends WidgetCompositeProperty { borderRadius = Utils.getBorderRadius(inputs['borderRadius'])?.getValue(); padding = Utils.optionalInsets(inputs['padding']); margin = Utils.optionalInsets(inputs['margin']); - onTriggered = inputs['onTriggered'] != null ? - EnsembleAction.from(inputs['onTriggered']) : null; borderColor = Utils.getColor(inputs['borderColor']); borderWidth = Utils.optionalInt(inputs['borderWidth']); } @@ -34,7 +56,6 @@ class TooltipStyleComposite extends WidgetCompositeProperty { BorderRadius? borderRadius; EdgeInsets? padding; EdgeInsets? margin; - EnsembleAction? onTriggered; Color? borderColor; int? borderWidth; @@ -53,8 +74,6 @@ class TooltipStyleComposite extends WidgetCompositeProperty { 'margin': (value) => margin = Utils.optionalInsets(value), 'borderColor': (value) => borderColor = Utils.getColor(value), 'borderWidth': (value) => borderWidth = Utils.optionalInt(value), - 'onTriggered': (value) => onTriggered = value != null ? - EnsembleAction.from(value) : null, }; } @@ -70,6 +89,8 @@ class TooltipStyleComposite extends WidgetCompositeProperty { 'borderRadius': () => borderRadius, 'padding': () => padding, 'margin': () => margin, + 'borderColor': () => borderColor, + 'borderWidth': () => borderWidth, }; @override