diff --git a/lib/flutter_sdui.dart b/lib/flutter_sdui.dart index 5376a46..5b5c8a9 100644 --- a/lib/flutter_sdui.dart +++ b/lib/flutter_sdui.dart @@ -38,6 +38,7 @@ export 'src/widgets/sdui_container.dart'; export 'src/widgets/sdui_scaffold.dart'; export 'src/widgets/sdui_spacer.dart'; export 'src/widgets/sdui_icon.dart'; +export 'src/widgets/sdui_appbar.dart'; // Network communication export 'src/service/sdui_grpc_client.dart'; diff --git a/lib/src/generated/sdui.pbenum.dart b/lib/src/generated/sdui.pbenum.dart index cd5fe13..d30d668 100644 --- a/lib/src/generated/sdui.pbenum.dart +++ b/lib/src/generated/sdui.pbenum.dart @@ -14,6 +14,7 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; /// Enum for Widget Types +/// class WidgetType extends $pb.ProtobufEnum { static const WidgetType WIDGET_TYPE_UNSPECIFIED = WidgetType._(0, _omitEnumNames ? '' : 'WIDGET_TYPE_UNSPECIFIED'); @@ -32,6 +33,7 @@ class WidgetType extends $pb.ProtobufEnum { static const WidgetType SPACER = WidgetType._(8, _omitEnumNames ? '' : 'SPACER'); static const WidgetType ICON = WidgetType._(9, _omitEnumNames ? '' : 'ICON'); + static const WidgetType APPBAR = WidgetType._(10, _omitEnumNames ? '' : 'APPBAR'); static const $core.List values = [ WIDGET_TYPE_UNSPECIFIED, @@ -44,10 +46,11 @@ class WidgetType extends $pb.ProtobufEnum { SCAFFOLD, SPACER, ICON, + APPBAR, ]; static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 9); + $pb.ProtobufEnum.$_initByValueList(values, 10); static WidgetType? valueOf($core.int value) => value < 0 || value >= _byValue.length ? null : _byValue[value]; diff --git a/lib/src/parser/flutter_to_sdui.dart b/lib/src/parser/flutter_to_sdui.dart index 8ed0903..db0b29c 100644 --- a/lib/src/parser/flutter_to_sdui.dart +++ b/lib/src/parser/flutter_to_sdui.dart @@ -8,6 +8,7 @@ import 'package:flutter_sdui/src/widgets/sdui_container.dart'; import 'package:flutter_sdui/src/widgets/sdui_scaffold.dart'; import 'package:flutter_sdui/src/widgets/sdui_spacer.dart'; import 'package:flutter_sdui/src/widgets/sdui_icon.dart'; +import 'package:flutter_sdui/src/widgets/sdui_appbar.dart'; import 'package:flutter_sdui/src/widgets/sdui_widget.dart'; SduiWidget flutterToSdui(Widget widget) { @@ -135,7 +136,25 @@ SduiWidget flutterToSdui(Widget widget) { applyTextScaling: widget.applyTextScaling, shadows: widget.shadows, ); + } else if (widget is AppBar) { + return SduiAppBar( + title: widget.title is Text ? (widget.title as Text).data : null, + backgroundColor: widget.backgroundColor, + foregroundColor: widget.foregroundColor, + elevation: widget.elevation, + centerTitle: widget.centerTitle, + actions: widget.actions, + leading: widget.leading, + bottom: widget.bottom, + toolbarHeight: widget.toolbarHeight, + leadingWidth: widget.leadingWidth, + automaticallyImplyLeading: widget.automaticallyImplyLeading, + flexibleSpace: widget.flexibleSpace, + titleSpacing: widget.titleSpacing, + toolbarOpacity: widget.toolbarOpacity, + bottomOpacity: widget.bottomOpacity, + ); } throw UnimplementedError( - 'Conversion for ${widget.runtimeType} is not implemented'); + 'Conversion for ${widget.runtimeType} is not implemented'); } diff --git a/lib/src/parser/sdui_proto_parser.dart b/lib/src/parser/sdui_proto_parser.dart index ed34f5b..d9cb940 100644 --- a/lib/src/parser/sdui_proto_parser.dart +++ b/lib/src/parser/sdui_proto_parser.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_sdui/src/generated/sdui.pb.dart'; +import 'package:flutter_sdui/src/widgets/sdui_appbar.dart'; import 'package:flutter_sdui/src/widgets/sdui_column.dart'; import 'package:flutter_sdui/src/widgets/sdui_container.dart'; import 'package:flutter_sdui/src/widgets/sdui_icon.dart'; @@ -55,6 +56,8 @@ class SduiParser { return _parseJsonSpacer(data); case 'icon': return _parseJsonIcon(data); + case 'appbar': + return _parseJsonAppBar(data); default: return SduiContainer(); } @@ -91,6 +94,8 @@ class SduiParser { return _parseProtoSpacer(data); case WidgetType.ICON: return _parseProtoIcon(data); + case WidgetType.APPBAR: + return _parseProtoAppBar(data); default: log('Unsupported widget type: ${data.type}'); return SduiContainer(); @@ -407,6 +412,33 @@ class SduiParser { ); } + static SduiAppBar _parseProtoAppBar(SduiWidgetData data) { + String? title = data.stringAttributes['title']; + Color? backgroundColor = data.hasBackgroundColor() + ? _parseProtoColor(data.backgroundColor) + : null; + double? elevation = data.doubleAttributes['elevation']; + bool? centerTitle = data.boolAttributes['centerTitle']; + + return SduiAppBar( + title: title, + backgroundColor: backgroundColor, + foregroundColor: null, + elevation: elevation, + centerTitle: centerTitle, + actions: null, + leading: null, + bottom: null, + toolbarHeight: null, + leadingWidth: null, + automaticallyImplyLeading: null, + flexibleSpace: null, + titleSpacing: null, + toolbarOpacity: null, + bottomOpacity: null, + ); + } + /// Helper methods for parsing protobuf attribute types into Flutter types. /// Parses a string value into a [BoxFit] enum. @@ -1223,6 +1255,60 @@ class SduiParser { ); } + static SduiAppBar _parseJsonAppBar(Map data) { + List? actions; + if (data['actions'] is List) { + actions = (data['actions'] as List) + .map((a) => SduiParser.parseJSON(a as Map).toFlutterWidget()) + .toList(); + } + + Widget? leading; + if (data['leading'] != null) { + leading = SduiParser.parseJSON(data['leading'] as Map) + .toFlutterWidget(); + } + + Widget? flexibleSpace; + if (data['flexibleSpace'] != null) { + flexibleSpace = + SduiParser.parseJSON(data['flexibleSpace'] as Map) + .toFlutterWidget(); + } + + return SduiAppBar( + title: data['title']?.toString(), + backgroundColor: _parseJsonColor(data['backgroundColor']), + foregroundColor: _parseJsonColor(data['foregroundColor']), + elevation: (data['elevation'] is num) + ? (data['elevation'] as num).toDouble() + : null, + centerTitle: data['centerTitle'] is bool ? data['centerTitle'] : null, + actions: actions, + leading: leading, + bottom: null, // Complex widget, needs special handling + toolbarHeight: (data['toolbarHeight'] is num) + ? (data['toolbarHeight'] as num).toDouble() + : null, + leadingWidth: (data['leadingWidth'] is num) + ? (data['leadingWidth'] as num).toDouble() + : null, + automaticallyImplyLeading: data['automaticallyImplyLeading'] is bool + ? data['automaticallyImplyLeading'] + : null, + flexibleSpace: flexibleSpace, + titleSpacing: (data['titleSpacing'] is num) + ? (data['titleSpacing'] as num).toDouble() + : null, + toolbarOpacity: (data['toolbarOpacity'] is num) + ? (data['toolbarOpacity'] as num).toDouble() + : null, + bottomOpacity: (data['bottomOpacity'] is num) + ? (data['bottomOpacity'] as num).toDouble() + : null, + ); + } + // --- JSON attribute helpers (implement as needed, similar to proto helpers) --- static TextStyle? _parseJsonTextStyle(dynamic value) { if (value is! Map) return null; diff --git a/lib/src/protos/sdui.proto b/lib/src/protos/sdui.proto index 5158e71..697fcd2 100644 --- a/lib/src/protos/sdui.proto +++ b/lib/src/protos/sdui.proto @@ -14,6 +14,7 @@ enum WidgetType { SCAFFOLD = 7; SPACER = 8; ICON = 9; + APPBAR = 10; // Add other widget types here } @@ -101,6 +102,20 @@ message SduiWidgetData { double opacity = 62; bool apply_text_scaling = 63; repeated ShadowData shadows = 64; + + // AppBar specific attributes + SduiWidgetData title_widget = 65; // For custom title widget + ColorData foreground_color = 66; + repeated SduiWidgetData actions = 67; + SduiWidgetData leading = 68; + SduiWidgetData bottom = 69; + double toolbar_height = 70; + double leading_width = 71; + bool automatically_imply_leading = 72; + SduiWidgetData flexible_space = 73; + double title_spacing = 74; + double toolbar_opacity = 75; + double bottom_opacity = 76; } // Message for Color diff --git a/lib/src/widgets/sdui_appbar.dart b/lib/src/widgets/sdui_appbar.dart new file mode 100644 index 0000000..e730a8d --- /dev/null +++ b/lib/src/widgets/sdui_appbar.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_sdui/src/widgets/sdui_widget.dart'; + +/// Represents an AppBar widget in SDUI. +class SduiAppBar extends SduiWidget { + final String? title; + final Color? backgroundColor; + final Color? foregroundColor; + final double? elevation; + final bool? centerTitle; + final List? actions; + final Widget? leading; + final PreferredSizeWidget? bottom; + final double? toolbarHeight; + final double? leadingWidth; + final bool? automaticallyImplyLeading; + final Widget? flexibleSpace; + final double? titleSpacing; + final double? toolbarOpacity; + final double? bottomOpacity; + + SduiAppBar({ + this.title, + this.backgroundColor, + this.foregroundColor, + this.elevation, + this.centerTitle, + this.actions, + this.leading, + this.bottom, + this.toolbarHeight, + this.leadingWidth, + this.automaticallyImplyLeading, + this.flexibleSpace, + this.titleSpacing, + this.toolbarOpacity, + this.bottomOpacity, + }); + + @override + Widget toFlutterWidget() { + return AppBar( + title: title != null ? Text(title!) : null, + backgroundColor: backgroundColor, + foregroundColor: foregroundColor, + elevation: elevation, + centerTitle: centerTitle, + actions: actions, + leading: leading, + bottom: bottom, + toolbarHeight: toolbarHeight, + leadingWidth: leadingWidth, + automaticallyImplyLeading: automaticallyImplyLeading ?? true, + flexibleSpace: flexibleSpace, + titleSpacing: titleSpacing, + toolbarOpacity: toolbarOpacity ?? 1.0, + bottomOpacity: bottomOpacity ?? 1.0, + ); + } +}