blob: a6d59b633f3b0ff41891f6245d0aef90231f5b98 [file] [log] [blame]
// Copyright 2017 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 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import 'launcher.dart';
import 'launcher_toggle.dart';
import 'status_panel.dart';
import 'status_tray.dart';
import 'widgets/system_overlay.dart';
import 'widgets/toggle.dart';
import 'window_playground.dart';
/// Base widget of the session shell.
class RootWidget extends StatefulWidget {
@override
_RootState createState() => new _RootState();
}
class _RootState extends State<RootWidget> with TickerProviderStateMixin {
final GlobalKey<ToggleState> _launcherToggleKey =
new GlobalKey<ToggleState>();
final GlobalKey<SystemOverlayState> _launcherOverlayKey =
new GlobalKey<SystemOverlayState>();
final GlobalKey<ToggleState> _statusToggleKey = new GlobalKey<ToggleState>();
final GlobalKey<SystemOverlayState> _statusOverlayKey =
new GlobalKey<SystemOverlayState>();
final Tween<double> _overlayScaleTween =
new Tween<double>(begin: 0.9, end: 1.0);
final Tween<double> _overlayOpacityTween =
new Tween<double>(begin: 0.0, end: 1.0);
@override
Widget build(BuildContext context) {
return new Stack(
fit: StackFit.passthrough,
children: <Widget>[
// 1 - Desktop background image.
new Image.asset(
'packages/capybara_session_shell/res/background.jpg',
fit: BoxFit.cover,
),
// 2 - The space where windows live.
new WindowPlaygroundWidget(),
// 3 - Launcher panel.
new SystemOverlay(
key: _launcherOverlayKey,
builder: (Animation<double> animation) => new Center(
child: new AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) =>
new FadeTransition(
opacity: _overlayOpacityTween.animate(animation),
child: new ScaleTransition(
scale: _overlayScaleTween.animate(animation),
child: child,
),
),
child: new Launcher(),
),
),
callback: (bool visible) {
_launcherToggleKey.currentState.toggled = visible;
},
),
// 4 - Status panel.
new SystemOverlay(
key: _statusOverlayKey,
builder: (Animation<double> animation) => new Positioned(
right: 0.0,
bottom: 48.0,
child: new AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) =>
new FadeTransition(
opacity: _overlayOpacityTween.animate(animation),
child: new ScaleTransition(
scale: _overlayScaleTween.animate(animation),
alignment: FractionalOffset.bottomRight,
child: child,
),
),
child: new StatusPanel(),
),
),
callback: (bool visible) {
_statusToggleKey.currentState.toggled = visible;
},
),
// 5 - The bottom bar.
new Positioned(
left: 0.0,
right: 0.0,
bottom: 0.0,
child: new GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _hideOverlays,
child: new Container(
height: 48.0,
padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
color: Colors.black87,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new LauncherToggleWidget(
toggleKey: _launcherToggleKey,
callback: (bool toggled) => _setOverlayVisibility(
overlay: _launcherOverlayKey, visible: toggled),
),
new StatusTrayWidget(
toggleKey: _statusToggleKey,
callback: (bool toggled) => _setOverlayVisibility(
overlay: _statusOverlayKey, visible: toggled),
),
],
),
),
),
),
],
);
}
/// Hides all overlays except [except] if applicable.
void _hideOverlays({GlobalKey<SystemOverlayState> except}) {
for (GlobalKey<SystemOverlayState> overlay
in <GlobalKey<SystemOverlayState>>[
_launcherOverlayKey,
_statusOverlayKey,
].where((GlobalKey<SystemOverlayState> overlay) => overlay != except)) {
overlay.currentState.visible = false;
}
}
/// Sets the given [overlay]'s visibility to [visible].
/// When showing an overlay, this also hides every other overlay.
void _setOverlayVisibility({
@required GlobalKey<SystemOverlayState> overlay,
@required bool visible,
}) {
if (visible) {
_hideOverlays(except: overlay);
}
overlay.currentState.visible = visible;
}
}