[story_shell_labs] drop target to remove mods

Removed close button from mod chrome.
Added "remove focused mod" button near suggested layouts.
New button also acts as drop target to remove the mod that is being dragged.

MI4-2434 #done

Change-Id: I3c2fd49c7a814866c51b7dc306377993eac12431
diff --git a/public/dart/story_shell_labs/lib/src/layout/tile_presenter/widgets/editing_tile_chrome.dart b/public/dart/story_shell_labs/lib/src/layout/tile_presenter/widgets/editing_tile_chrome.dart
index 5cd2f32..698256a 100644
--- a/public/dart/story_shell_labs/lib/src/layout/tile_presenter/widgets/editing_tile_chrome.dart
+++ b/public/dart/story_shell_labs/lib/src/layout/tile_presenter/widgets/editing_tile_chrome.dart
@@ -83,69 +83,62 @@
 
   @override
   Widget build(BuildContext context) {
-    return Stack(
-      children: <Widget>[
-        Positioned.fill(
-          child: Draggable(
-            onDragStarted: () {
-              widget.willStartDrag();
-              widget.focusedMod.value = widget.modName;
-              _isDragging.value = true;
-              widget.tilerModel.remove(widget.tile);
-            },
-            onDragEnd: (_) {
-              _isDragging.value = false;
-            },
-            onDraggableCanceled: (_, __) {
-              widget.didCancelDrag();
-            },
-            key: Key(widget.modName),
-            data: widget.tile,
-            feedback: _buildFeedback(),
-            dragAnchor: DragAnchor.pointer,
-            childWhenDragging: const Offstage(),
-            child: Stack(
-              children: [
-                AnimatedBuilder(
-                  animation: _hoverDirection,
-                  builder: (_, child) => AnimatedPositioned(
-                        duration: Duration(milliseconds: 400),
-                        curve: Curves.easeOutExpo,
-                        top: _hoverDirection.value == AxisDirection.up
-                            ? widget.editingSize.height * 0.5 + 12
-                            : 0,
-                        bottom: _hoverDirection.value == AxisDirection.down
-                            ? widget.editingSize.height * 0.5 + 12
-                            : 0,
-                        left: _hoverDirection.value == AxisDirection.left
-                            ? widget.editingSize.width * 0.5 + 12
-                            : 0,
-                        right: _hoverDirection.value == AxisDirection.right
-                            ? widget.editingSize.width * 0.5 + 12
-                            : 0,
-                        child: child,
-                      ),
-                  child: AnimatedBuilder(
-                    animation: widget.focusedMod,
-                    builder: (_, child) => Container(
-                          decoration: BoxDecoration(
-                            border: Border.all(
-                              color: widget.focusedMod.value == widget.modName
-                                  ? Color(0xFFFF8BCB)
-                                  : Colors.black,
-                              width: _kBorderWidth,
-                            ),
-                          ),
-                          child: widget.childView,
-                        ),
-                  ),
+    return Draggable(
+      onDragStarted: () {
+        widget.willStartDrag();
+        widget.focusedMod.value = widget.modName;
+        _isDragging.value = true;
+        widget.tilerModel.remove(widget.tile);
+      },
+      onDragEnd: (_) {
+        _isDragging.value = false;
+      },
+      onDraggableCanceled: (_, __) {
+        widget.didCancelDrag();
+      },
+      key: Key(widget.modName),
+      data: widget.tile,
+      feedback: _buildFeedback(),
+      dragAnchor: DragAnchor.pointer,
+      childWhenDragging: const Offstage(),
+      child: Stack(
+        children: [
+          AnimatedBuilder(
+            animation: _hoverDirection,
+            builder: (_, child) => AnimatedPositioned(
+                  duration: Duration(milliseconds: 400),
+                  curve: Curves.easeOutExpo,
+                  top: _hoverDirection.value == AxisDirection.up
+                      ? widget.editingSize.height * 0.5 + 12
+                      : 0,
+                  bottom: _hoverDirection.value == AxisDirection.down
+                      ? widget.editingSize.height * 0.5 + 12
+                      : 0,
+                  left: _hoverDirection.value == AxisDirection.left
+                      ? widget.editingSize.width * 0.5 + 12
+                      : 0,
+                  right: _hoverDirection.value == AxisDirection.right
+                      ? widget.editingSize.width * 0.5 + 12
+                      : 0,
+                  child: child,
                 ),
-              ]..addAll(_buildSplitTargets(widget.editingSize)),
+            child: AnimatedBuilder(
+              animation: widget.focusedMod,
+              builder: (_, child) => Container(
+                    decoration: BoxDecoration(
+                      border: Border.all(
+                        color: widget.focusedMod.value == widget.modName
+                            ? Color(0xFFFF8BCB)
+                            : Colors.black,
+                        width: _kBorderWidth,
+                      ),
+                    ),
+                    child: widget.childView,
+                  ),
             ),
           ),
-        ),
-        _buildCornerItems(),
-      ],
+        ]..addAll(_buildSplitTargets(widget.editingSize)),
+      ),
     );
   }
 
@@ -192,52 +185,6 @@
     );
   }
 
-  Widget _buildCornerItems() {
-    final parameterIndicators = Row(
-      children: widget.parameterColors
-          .expand((color) => [
-                Material(
-                  elevation: 4.0,
-                  clipBehavior: Clip.antiAlias,
-                  shape: CircleBorder(),
-                  color: color,
-                  child: SizedBox(width: 24, height: 24),
-                ),
-                SizedBox(width: 8.0),
-              ])
-          .toList(),
-    );
-
-    return Positioned(
-      top: 8,
-      right: 8,
-      child: AnimatedBuilder(
-        animation: Listenable.merge([_isDragging, _hoverDirection]),
-        builder: (_, child) => Offstage(
-            offstage: _isDragging.value ||
-                _hoverDirection.value == AxisDirection.up ||
-                _hoverDirection.value == AxisDirection.right,
-            child: child),
-        child: Row(
-          children: <Widget>[
-            parameterIndicators,
-            Material(
-              elevation: 4.0,
-              clipBehavior: Clip.antiAlias,
-              shape: CircleBorder(),
-              child: InkWell(
-                onTap: () {
-                  widget.tilerModel.remove(widget.tile);
-                },
-                child: Icon(Icons.close),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-
   List<Widget> _buildSplitTargets(Size size) => <Widget>[
         _splitTarget(
           nearTile: widget.tile,
diff --git a/shell/story_shell_labs/BUILD.gn b/shell/story_shell_labs/BUILD.gn
index 314188f..4c203b2 100644
--- a/shell/story_shell_labs/BUILD.gn
+++ b/shell/story_shell_labs/BUILD.gn
@@ -19,6 +19,7 @@
   sources = [
     "src/story_shell_impl.dart",
     "src/story_visual_state_watcher_impl.dart",
+    "src/widgets/remove_button_target_widget.dart",
     "src/widgets/story_widget.dart",
   ]
 
diff --git a/shell/story_shell_labs/lib/src/widgets/remove_button_target_widget.dart b/shell/story_shell_labs/lib/src/widgets/remove_button_target_widget.dart
new file mode 100644
index 0000000..b382285
--- /dev/null
+++ b/shell/story_shell_labs/lib/src/widgets/remove_button_target_widget.dart
@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+import 'package:tiler/tiler.dart' show TileModel;
+
+/// Widget that acts as a button to remove currently focused mod's tile,
+/// and drop target to remove a tile by drag-and-drop
+class RemoveButtonTargetWidget extends StatefulWidget {
+  const RemoveButtonTargetWidget({
+    @required this.onTap,
+  });
+
+  /// Callback when button is tapped
+  final VoidCallback onTap;
+
+  @override
+  _RemoveButtonTargetWidgetState createState() =>
+      _RemoveButtonTargetWidgetState();
+}
+
+class _RemoveButtonTargetWidgetState extends State<RemoveButtonTargetWidget> {
+  final _touching = ValueNotifier<bool>(false);
+
+  @override
+  Widget build(BuildContext context) {
+    return DragTarget<TileModel>(
+      builder: (_, candidateData, ___) {
+        return GestureDetector(
+          onTap: widget.onTap,
+          onTapDown: (_) {
+            _touching.value = true;
+          },
+          onTapCancel: () {
+            _touching.value = false;
+          },
+          onTapUp: (_) {
+            _touching.value = false;
+          },
+          child: AnimatedBuilder(
+            animation: _touching,
+            builder: (context, snapshot) {
+              final hovering = candidateData.isNotEmpty || _touching.value;
+              final foreground = hovering ? Colors.white : Colors.black;
+              final background = hovering ? Colors.black : Colors.white;
+              return Material(
+                color: background,
+                elevation: 24,
+                child: AspectRatio(
+                  aspectRatio: 1,
+                  child: Container(
+                    decoration: BoxDecoration(
+                      border: Border.all(
+                        width: 2.0,
+                        color: foreground,
+                      ),
+                    ),
+                    child: FractionallySizedBox(
+                      widthFactor: .75,
+                      child: Center(
+                        child: Container(
+                          height: 2.0,
+                          color: foreground,
+                        ),
+                      ),
+                    ),
+                  ),
+                ),
+              );
+            },
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/shell/story_shell_labs/lib/src/widgets/story_widget.dart b/shell/story_shell_labs/lib/src/widgets/story_widget.dart
index a3da17a..658fb90 100644
--- a/shell/story_shell_labs/lib/src/widgets/story_widget.dart
+++ b/shell/story_shell_labs/lib/src/widgets/story_widget.dart
@@ -11,6 +11,8 @@
 import 'package:story_shell_labs_lib/layout/tile_model.dart';
 import 'package:story_shell_labs_lib/layout/tile_presenter.dart';
 
+import 'remove_button_target_widget.dart';
+
 final List<Color> _kColors = [
   Colors.red,
   Colors.blue,
@@ -116,7 +118,7 @@
                 parametersToColors: _parametersToColors,
                 setTilerModel: (model) {
                   setState(() {
-                    _tilerModel = model;
+                    _tilerModel = cloneTiler(model);
                   });
                 },
               ),
@@ -160,25 +162,36 @@
               alignment: Alignment.bottomCenter,
               child: SizedBox(
                 height: 84,
-                child: LayoutSuggestionsWidget(
-                  presenter: widget.presenter,
-                  focusedMod: _focusedMod,
-                  onSelect: (model) {
-                    setState(() {
-                      _tilerModel = model;
-                    });
-                  },
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  children: <Widget>[
+                    LayoutSuggestionsWidget(
+                      presenter: widget.presenter,
+                      focusedMod: _focusedMod,
+                      onSelect: (model) {
+                        setState(() {
+                          _tilerModel = cloneTiler(model);
+                        });
+                      },
+                    ),
+                    RemoveButtonTargetWidget(
+                      onTap: () {
+                        getTileContent(_tilerModel)
+                            .where((TileModel tile) =>
+                                tile.content.modName == _focusedMod.value)
+                            .forEach(_tilerModel.remove);
+                      },
+                    ),
+                  ],
                 ),
               ),
             ),
           );
         },
       );
-      print('adding overlay $_layoutSuggestionsOverlay');
       Overlay.of(context).insert(_layoutSuggestionsOverlay);
     }
     if (!_isEditing && _layoutSuggestionsOverlay != null) {
-      print('removing overlay $_layoutSuggestionsOverlay');
       _layoutSuggestionsOverlay.remove();
       _layoutSuggestionsOverlay = null;
     }