[terminal_settings] Add initial settings container.
Adds a simple widget for managing multiple settings panes.
Change-Id: Ib39e09cad35fb716163c0fb04ad195e5a2a1de6c
diff --git a/bin/BUILD.gn b/bin/BUILD.gn
index b7819db..7bd522a 100644
--- a/bin/BUILD.gn
+++ b/bin/BUILD.gn
@@ -5,6 +5,7 @@
group("bin") {
deps = [
"simple_browser",
+ "terminal_settings",
]
}
@@ -21,5 +22,6 @@
deps = [
"simple_browser:simple_browser_unittests($host_toolchain)",
+ "terminal_settings:terminal_settings_unittests($host_toolchain)",
]
}
diff --git a/bin/terminal_settings/BUILD.gn b/bin/terminal_settings/BUILD.gn
new file mode 100644
index 0000000..2ef473d
--- /dev/null
+++ b/bin/terminal_settings/BUILD.gn
@@ -0,0 +1,43 @@
+# 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("//topaz/runtime/dart/flutter_test.gni")
+import("//topaz/runtime/flutter_runner/flutter_app.gni")
+
+flutter_app("terminal_settings") {
+ main_dart = "lib/main.dart"
+
+ sources = [
+ "src/widgets/settings_container.dart",
+ "src/widgets/settings_pane.dart",
+ ]
+
+ meta = [
+ {
+ path = rebase_path("meta/terminal_settings.cmx")
+ dest = "terminal_settings.cmx"
+ },
+ ]
+
+ package_name = "terminal_settings"
+
+ manifest = "pubspec.yaml"
+
+ deps = [
+ "//third_party/dart-pkg/git/flutter/packages/flutter",
+ "//topaz/public/dart/fuchsia_logger",
+ ]
+}
+
+flutter_test("terminal_settings_unittests") {
+ sources = [
+ "settings_container_test.dart",
+ ]
+
+ deps = [
+ ":terminal_settings_dart_library",
+ "//third_party/dart-pkg/git/flutter/packages/flutter_test",
+ "//third_party/dart-pkg/pub/test",
+ ]
+}
diff --git a/bin/terminal_settings/README.md b/bin/terminal_settings/README.md
new file mode 100644
index 0000000..0ce7f77
--- /dev/null
+++ b/bin/terminal_settings/README.md
@@ -0,0 +1,11 @@
+# Terminal Settings
+
+Module which allows users to update settings which can be read
+from the terminal module.
+
+## Testing
+
+To run unit tests
+
+ fx set workstation.<BOARD> --with //src/experiences:tests
+ fx run-host-tests terminal_settings_unittests
diff --git a/bin/terminal_settings/analysis_options.yaml b/bin/terminal_settings/analysis_options.yaml
new file mode 100644
index 0000000..bebf512
--- /dev/null
+++ b/bin/terminal_settings/analysis_options.yaml
@@ -0,0 +1,5 @@
+# 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.
+
+include: ../../analysis_options.yaml
diff --git a/bin/terminal_settings/lib/main.dart b/bin/terminal_settings/lib/main.dart
new file mode 100644
index 0000000..6267779
--- /dev/null
+++ b/bin/terminal_settings/lib/main.dart
@@ -0,0 +1,39 @@
+// 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 'package:flutter/material.dart';
+import 'package:fuchsia_logger/logger.dart';
+
+import 'src/widgets/settings_container.dart';
+import 'src/widgets/settings_pane.dart';
+
+void main() {
+ setupLogger(name: 'terminal_settings');
+ runApp(
+ MaterialApp(
+ theme: _themeData,
+ home: Scaffold(
+ body: SettingsContainer([
+ ProfilesSetttingsPane(),
+ ]),
+ ),
+ ),
+ );
+}
+
+final _themeData = ThemeData(
+ backgroundColor: Color(0xE6E6E6FF),
+ colorScheme: ColorScheme.light(
+ background: Color(0xE6E6E6FF),
+ primary: Colors.white,
+ secondary: Colors.black,
+ ),
+ fontFamily: 'RobotoMono',
+ dividerTheme: DividerThemeData(
+ color: Colors.black,
+ space: 4.0,
+ endIndent: 16.0,
+ indent: 16.0,
+ ),
+);
diff --git a/bin/terminal_settings/lib/src/widgets/settings_container.dart b/bin/terminal_settings/lib/src/widgets/settings_container.dart
new file mode 100644
index 0000000..71abaee
--- /dev/null
+++ b/bin/terminal_settings/lib/src/widgets/settings_container.dart
@@ -0,0 +1,69 @@
+// 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 'package:flutter/material.dart';
+
+import 'settings_pane.dart';
+
+/// A widget for handling multiple settings panes.
+///
+/// Draws a button bar at the top which allows a user
+/// to select different panes to display and swaps out their
+/// content in the remaining space below.
+class SettingsContainer extends StatelessWidget {
+ final List<SettingsPane> panes;
+ final ValueNotifier<SettingsPane> currentPane =
+ ValueNotifier<SettingsPane>(null);
+
+ SettingsContainer(this.panes) {
+ if (panes.isNotEmpty) {
+ currentPane.value = panes.first;
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) => Container(
+ color: Theme.of(context).colorScheme.background,
+ child: AnimatedBuilder(
+ animation: currentPane,
+ builder: (context, _) => Column(
+ children: [
+ _topBar(context),
+ _bottomContent(context),
+ ],
+ ),
+ ),
+ );
+
+ Widget _topBar(BuildContext context) {
+ final colorScheme = Theme.of(context).colorScheme;
+ return Column(
+ children: [
+ ButtonBar(
+ alignment: MainAxisAlignment.start,
+ children: panes.map((pane) {
+ final selected = currentPane.value == pane;
+ return FlatButton(
+ child: Text(
+ pane.title,
+ ),
+ onPressed: () {
+ currentPane.value = pane;
+ },
+ color: selected ? colorScheme.secondary : colorScheme.background,
+ textColor: selected ? colorScheme.primary : colorScheme.secondary,
+ );
+ }).toList(),
+ ),
+ Divider(),
+ ],
+ );
+ }
+
+ Widget _bottomContent(BuildContext context) => Expanded(
+ child: currentPane.value == null
+ ? Offstage()
+ : currentPane.value.build(context),
+ );
+}
diff --git a/bin/terminal_settings/lib/src/widgets/settings_pane.dart b/bin/terminal_settings/lib/src/widgets/settings_pane.dart
new file mode 100644
index 0000000..5219953
--- /dev/null
+++ b/bin/terminal_settings/lib/src/widgets/settings_pane.dart
@@ -0,0 +1,27 @@
+// 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 'package:flutter/material.dart';
+
+/// A pane to display in the settings container.
+abstract class SettingsPane extends StatelessWidget {
+ /// The title to display as the title of the button in the top bar
+ final String title;
+
+ const SettingsPane({this.title, Key key}) : super(key: key);
+}
+
+class ProfilesSetttingsPane extends SettingsPane {
+ const ProfilesSetttingsPane() : super(title: 'PROFILES');
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ color: Theme.of(context).colorScheme.background,
+ child: Center(
+ child: Text('Terminal Profiles'),
+ ),
+ );
+ }
+}
diff --git a/bin/terminal_settings/meta/terminal_settings.cmx b/bin/terminal_settings/meta/terminal_settings.cmx
new file mode 100644
index 0000000..d73a627
--- /dev/null
+++ b/bin/terminal_settings/meta/terminal_settings.cmx
@@ -0,0 +1,23 @@
+{
+ "program": {
+ "data": "data/terminal_settings"
+ },
+ "sandbox": {
+ "services": [
+ "fuchsia.cobalt.LoggerFactory",
+ "fuchsia.fonts.Provider",
+ "fuchsia.logger.LogSink",
+ "fuchsia.posix.socket.Provider",
+ "fuchsia.net.NameLookup",
+ "fuchsia.netstack.Netstack",
+ "fuchsia.process.Launcher",
+ "fuchsia.sys.Environment",
+ "fuchsia.sys.Launcher",
+ "fuchsia.ui.input.ImeService",
+ "fuchsia.ui.input.ImeVisibilityService",
+ "fuchsia.ui.scenic.Scenic",
+ "fuchsia.ui.policy.Presenter",
+ "fuchsia.web.ContextProvider"
+ ]
+ }
+}
diff --git a/bin/terminal_settings/pubspec.yaml b/bin/terminal_settings/pubspec.yaml
new file mode 100644
index 0000000..34a81eb
--- /dev/null
+++ b/bin/terminal_settings/pubspec.yaml
@@ -0,0 +1,8 @@
+# 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.
+
+name: terminal_settings
+description: Module for updating the terminal settings
+
+flutter:
diff --git a/bin/terminal_settings/test/settings_container_test.dart b/bin/terminal_settings/test/settings_container_test.dart
new file mode 100644
index 0000000..68fdb64
--- /dev/null
+++ b/bin/terminal_settings/test/settings_container_test.dart
@@ -0,0 +1,89 @@
+// 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 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+// ignore_for_file: implementation_imports
+import 'package:terminal_settings/src/widgets/settings_container.dart';
+import 'package:terminal_settings/src/widgets/settings_pane.dart';
+
+void main() {
+ testWidgets('empty pane list does not fail', (tester) async {
+ final widget = _wrapInMaterialApp(SettingsContainer([]));
+ await tester.pumpWidget(widget);
+ // nothing here, test success is not crashing
+ });
+
+ testWidgets('creates button with title', (tester) async {
+ final widget = _wrapInMaterialApp(SettingsContainer([
+ _TestSettingsPane(title: 'foo'),
+ ]));
+
+ await tester.pumpWidget(widget);
+
+ expect(_findMaterialButtonWithText('foo'), findsOneWidget);
+ });
+
+ testWidgets('creates multiple buttons', (tester) async {
+ final widget = _wrapInMaterialApp(SettingsContainer([
+ _TestSettingsPane(title: 'foo'),
+ _TestSettingsPane(title: 'bar'),
+ ]));
+
+ await tester.pumpWidget(widget);
+
+ expect(_findMaterialButtonWithText('foo'), findsOneWidget);
+ expect(_findMaterialButtonWithText('bar'), findsOneWidget);
+ });
+
+ testWidgets('first pane is placed in body', (tester) async {
+ final widget = _wrapInMaterialApp(SettingsContainer([
+ _TestSettingsPane(title: 'foo', body: 'foo pane'),
+ _TestSettingsPane(title: 'bar', body: 'bar pane'),
+ ]));
+
+ await tester.pumpWidget(widget);
+
+ expect(find.text('foo pane'), findsOneWidget);
+ });
+
+ testWidgets('tapping button changes pane', (tester) async {
+ final widget = _wrapInMaterialApp(SettingsContainer([
+ _TestSettingsPane(title: 'foo', body: 'foo pane'),
+ _TestSettingsPane(title: 'bar', body: 'bar pane'),
+ ]));
+
+ await tester.pumpWidget(widget);
+ await tester.tap(_findMaterialButtonWithText('bar'));
+
+ await tester.pump();
+
+ expect(find.text('foo pane'), findsNothing);
+ expect(find.text('bar pane'), findsOneWidget);
+ });
+}
+
+Finder _findMaterialButtonWithText(String text) => find.ancestor(
+ of: find.text(text),
+ matching: find.byWidgetPredicate((w) => w is MaterialButton),
+ );
+
+// our widget needs to be in a material app to layout text.
+Widget _wrapInMaterialApp(Widget w) => MaterialApp(
+ // theme: ThemeData(primaryColor: Colors.yellow),
+ home: Scaffold(
+ body: w,
+ ),
+ );
+
+class _TestSettingsPane extends SettingsPane {
+ final String body;
+ const _TestSettingsPane({String title, this.body}) : super(title: title);
+
+ @override
+ Widget build(BuildContext context) {
+ return Text(body ?? '');
+ }
+}