| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is hand-formatted. |
| |
| import 'package:flutter/widgets.dart'; |
| |
| import '../dart/model.dart'; |
| import 'content.dart'; |
| import 'runtime.dart'; |
| |
| export '../dart/model.dart' show DynamicMap, LibraryName; |
| |
| /// Injection point for a remote widget. |
| /// |
| /// This widget combines an RFW [Runtime] and [DynamicData], inserting a |
| /// specified [widget] into the tree. |
| class RemoteWidget extends StatefulWidget { |
| /// Inserts the specified [widget] into the tree. |
| /// |
| /// The [onEvent] argument is optional. When omitted, events are discarded. |
| const RemoteWidget({ Key? key, required this.runtime, required this.widget, required this.data, this.onEvent }) : super(key: key); |
| |
| /// The [Runtime] to use to render the widget specified by [widget]. |
| /// |
| /// This should update rarely (doing so is relatively expensive), but it is |
| /// fine to update it. For example, a client could update this on the fly when |
| /// the server deploys a new version of the widget library. |
| /// |
| /// Frequent updates (e.g. animations) should be done by updating [data] instead. |
| final Runtime runtime; |
| |
| /// The name of the widget to display, and the library from which to obtain |
| /// it. |
| /// |
| /// The widget must be declared either in the specified library, or one of its |
| /// dependencies. |
| /// |
| /// The data to show in the widget is specified using [data]. |
| final FullyQualifiedWidgetName widget; |
| |
| /// The data to which the widget specified by [name] will be bound. |
| /// |
| /// This includes data that comes from the application, e.g. a description of |
| /// the user's device, the current time, or an animation controller's value, |
| /// and data that comes from the server, e.g. the contents of the user's |
| /// shopping cart. |
| /// |
| /// This can be updated frequently (once per frame) using |
| /// [DynamicContent.update]. |
| final DynamicContent data; |
| |
| /// Called when there's an event triggered by a remote widget. |
| /// |
| /// If this is null, events are discarded. |
| final RemoteEventHandler? onEvent; |
| |
| @override |
| State<RemoteWidget> createState() => _RemoteWidgetState(); |
| } |
| |
| class _RemoteWidgetState extends State<RemoteWidget> { |
| @override |
| void initState() { |
| super.initState(); |
| widget.runtime.addListener(_runtimeChanged); |
| } |
| |
| @override |
| void didUpdateWidget(RemoteWidget oldWidget) { |
| super.didUpdateWidget(oldWidget); |
| if (oldWidget.runtime != widget.runtime) { |
| oldWidget.runtime.removeListener(_runtimeChanged); |
| widget.runtime.addListener(_runtimeChanged); |
| } |
| } |
| |
| @override |
| void dispose() { |
| widget.runtime.removeListener(_runtimeChanged); |
| super.dispose(); |
| } |
| |
| void _runtimeChanged() { |
| setState(() { /* widget probably changed */ }); |
| } |
| |
| void _eventHandler(String eventName, DynamicMap eventArguments) { |
| if (widget.onEvent != null) { |
| widget.onEvent!(eventName, eventArguments); |
| } |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return widget.runtime.build(context, widget.widget, widget.data, _eventHandler); |
| } |
| } |