blob: 4cc9dab95d0705dccacc4b0895394f87cc093fbe [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:fidl/fidl.dart' show InterfaceRequest, InterfaceHandle;
import 'package:fidl_fuchsia_modular/fidl_async.dart' as modular;
import 'package:fuchsia_modular/lifecycle.dart';
import 'package:fuchsia_scenic_flutter/child_view_connection.dart';
import '../../story_shell.dart';
import '../../surface.dart';
/// Defines an implementation of [modular.StoryShell].
///
/// This class overrides the FIDL methods of [modular.StoryShell] and forwards
/// them to instance of [StoryShell] provided in its constructor.
class ModularStoryShellImpl extends modular.StoryShell {
final _binding = modular.StoryShellBinding();
final _storyShellContext = modular.StoryShellContextProxy();
final _focusEventStreamController = StreamController<String>.broadcast();
final _surfacesById = <String, Surface>{};
/// The [StoryShell] that receives calls from this modular story shell impl.
final StoryShell storyShell;
/// Constructor.
ModularStoryShellImpl(this.storyShell) {
Lifecycle().addTerminateListener(_onTerminate);
}
/// Binds this instance to receive messages from the FIDL channel.
void bind(InterfaceRequest<modular.StoryShell> request) {
if (request != null) {
_binding.bind(this, request);
}
}
@override
Future<void> initialize(
InterfaceHandle<modular.StoryShellContext> context) async {
_storyShellContext.ctrl.bind(context);
}
@override
Future<void> addSurface(modular.ViewConnection viewConnection,
modular.SurfaceInfo surfaceInfo) async {
// Deprecated. Transitioning to addSurface3 (which will later be renamed
// addSurface, replacing this method with updated parameter list/types)
final view = newChildViewConnection(viewConnection);
final surface = Surface(
id: viewConnection.surfaceId,
info: surfaceInfo,
childViewConnection: view,
);
_surfacesById[viewConnection.surfaceId] = surface;
storyShell.onSurfaceAdded(surface);
}
@override
Future<void> addSurface2(modular.ViewConnection2 viewConnection,
modular.SurfaceInfo surfaceInfo) async {
return addSurface(
modular.ViewConnection(
surfaceId: viewConnection.surfaceId,
viewHolderToken: viewConnection.viewHolderToken),
surfaceInfo);
}
@override
Future<void> addSurface3(modular.ViewConnection viewConnection,
modular.SurfaceInfo2 surfaceInfo2) async {
final view = newChildViewConnection(viewConnection);
final surfaceInfo = modular.SurfaceInfo(
parentId: surfaceInfo2.parentId,
surfaceRelation: surfaceInfo2.surfaceRelation,
moduleManifest: surfaceInfo2.moduleManifest,
moduleSource: surfaceInfo2.moduleSource,
);
final surface = Surface(
id: viewConnection.surfaceId,
info: surfaceInfo,
childViewConnection: view,
);
_surfacesById[viewConnection.surfaceId] = surface;
storyShell.onSurfaceAdded(surface);
}
@override
Future<void> addContainer(
String containerName,
String parentId,
modular.SurfaceRelation relation,
List<modular.ContainerLayout> layout,
List<modular.ContainerRelationEntry> relationships,
List<modular.ContainerView> views) async {}
@override
Future<void> removeSurface(String surfaceId) async {
final surface = _surfacesById[surfaceId];
storyShell.onSurfaceRemoved(surface);
}
@override
Future<void> focusSurface(String surfaceId) async {
final surface = _surfacesById[surfaceId];
storyShell.onSurfaceFocusChange(surface, focus: true);
}
@override
Future<void> defocusSurface(String surfaceId) async {
final surface = _surfacesById[surfaceId];
storyShell.onSurfaceFocusChange(surface, focus: false);
}
@override
Stream<String> get onSurfaceFocused => _focusEventStreamController.stream;
@override
Future<void> reconnectView(modular.ViewConnection viewConnection) async {}
@override
Future<void> updateSurface(modular.ViewConnection viewConnection,
modular.SurfaceInfo surfaceInfo) async {}
/// Returns a new instance of [ChildViewConnection]. Used for testing.
@visibleForTesting
ChildViewConnection newChildViewConnection(
modular.ViewConnection viewConnection) {
return ChildViewConnection(viewConnection.viewHolderToken);
}
Future<void> _onTerminate() async {
if (_binding.isBound) {
_binding.unbind();
}
_storyShellContext.ctrl.close();
await _focusEventStreamController.close();
}
}