Commit d70365fa authored by Adam Barth's avatar Adam Barth

Merge pull request #1708 from abarth/wm

Make the Mozart demo more like a real window manager
parents 8fdaf4af 657eadcd
...@@ -2,56 +2,192 @@ ...@@ -2,56 +2,192 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
const List<String> _kKnownApps = const <String>[ class LauncherData {
'mojo:noodles_view', const LauncherData({ this.url, this.title });
'mojo:shapes_view', final String url;
final String title;
}
const List<LauncherData> _kLauncherData = const <LauncherData>[
const LauncherData(
url: 'mojo:noodles_view',
title: 'Noodles'
),
const LauncherData(
url: 'mojo:shapes_view',
title: 'Shapes'
),
]; ];
const Size _kSmallWindowSize = const Size(400.0, 400.0); const Size _kInitialWindowSize = const Size(200.0, 200.0);
const Size _kBigWindowSize = const Size(600.0, 600.0); const double _kWindowPadding = 10.0;
enum WindowSide {
topCenter,
topRight,
bottomRight,
}
class WindowDecoration extends StatelessComponent {
WindowDecoration({
Key key,
this.side,
this.color,
this.onTap,
this.onPanUpdate
}) : super(key: key);
final WindowSide side;
final Color color;
final GestureTapCallback onTap;
final GesturePanUpdateCallback onPanUpdate;
Widget build(BuildContext context) {
double top, right, bottom, left, width, height;
height = _kWindowPadding * 2.0;
if (side == WindowSide.topCenter || side == WindowSide.topRight)
top = 0.0;
if (side == WindowSide.topRight || side == WindowSide.bottomRight) {
right = 0.0;
width = _kWindowPadding * 2.0;
}
if (side == WindowSide.topCenter) {
left = _kWindowPadding;
right = _kWindowPadding;
}
if (side == WindowSide.bottomRight)
bottom = 0.0;
return new Positioned(
top: top,
right: right,
bottom: bottom,
left: left,
width: width,
height: height,
child: new GestureDetector(
onTap: onTap,
onPanUpdate: onPanUpdate,
child: new Container(
decoration: new BoxDecoration(
backgroundColor: color
)
)
)
);
}
}
class Window extends StatefulComponent { class Window extends StatefulComponent {
Window({ Key key, this.child }) : super(key: key); Window({ Key key, this.child, this.onClose }) : super(key: key);
final ChildViewConnection child; final ChildViewConnection child;
final ValueChanged<ChildViewConnection> onClose;
_WindowState createState() => new _WindowState(); _WindowState createState() => new _WindowState();
} }
class _WindowState extends State<Window> { class _WindowState extends State<Window> {
Offset _offset = Offset.zero; Offset _offset = Offset.zero;
bool _isSmall = true; Size _size = _kInitialWindowSize;
void _handlePanUpdate(Offset delta) { void _handleResizerDrag(Offset delta) {
setState(() { setState(() {
_offset += delta; _size = new Size(
math.max(0.0, _size.width + delta.dx),
math.max(0.0, _size.height + delta.dy)
);
}); });
} }
void _handleTap() { void _handleRepositionDrag(Offset delta) {
setState(() { setState(() {
_isSmall = !_isSmall; _offset += delta;
}); });
} }
void _handleClose() {
config.onClose(config.child);
}
Widget build(BuildContext context) { Widget build(BuildContext context) {
Size size = _isSmall ? _kSmallWindowSize : _kBigWindowSize;
return new Positioned( return new Positioned(
left: _offset.dx, left: _offset.dx,
top: _offset.dy, top: _offset.dy,
width: size.width, width: _size.width + _kWindowPadding * 2.0,
height: size.height, height: _size.height + _kWindowPadding * 2.0,
child: new GestureDetector( child: new Stack(
onPanUpdate: _handlePanUpdate, children: <Widget>[
onTap: _handleTap, new WindowDecoration(
child: new ChildView(child: config.child) side: WindowSide.topCenter,
onPanUpdate: _handleRepositionDrag,
color: Colors.green[200]
),
new WindowDecoration(
side: WindowSide.topRight,
onTap: _handleClose,
color: Colors.red[200]
),
new WindowDecoration(
side: WindowSide.bottomRight,
onPanUpdate: _handleResizerDrag,
color: Colors.blue[200]
),
new Container(
padding: const EdgeDims.all(_kWindowPadding),
child: new Material(
elevation: 8,
child: new ChildView(child: config.child)
)
)
]
) )
); );
} }
} }
class LauncherItem extends StatelessComponent {
LauncherItem({
Key key,
this.url,
this.child,
this.onLaunch
}) : super(key: key);
final String url;
final Widget child;
final ValueChanged<ChildViewConnection> onLaunch;
Widget build(BuildContext context) {
return new RaisedButton(
onPressed: () { onLaunch(new ChildViewConnection(url: url)); },
child: child
);
}
}
class Launcher extends StatelessComponent {
Launcher({ Key key, this.items }) : super(key: key);
final List<Widget> items;
Widget build(BuildContext context) {
return new Row(
justifyContent: FlexJustifyContent.center,
children: items
);
}
}
class WindowManager extends StatefulComponent { class WindowManager extends StatefulComponent {
_WindowManagerState createState() => new _WindowManagerState(); _WindowManagerState createState() => new _WindowManagerState();
} }
...@@ -59,27 +195,41 @@ class WindowManager extends StatefulComponent { ...@@ -59,27 +195,41 @@ class WindowManager extends StatefulComponent {
class _WindowManagerState extends State<WindowManager> { class _WindowManagerState extends State<WindowManager> {
List<ChildViewConnection> _windows = <ChildViewConnection>[]; List<ChildViewConnection> _windows = <ChildViewConnection>[];
void _handleTap() { void _handleLaunch(ChildViewConnection child) {
setState(() { setState(() {
_windows.add(new ChildViewConnection(url: _kKnownApps[_windows.length % _kKnownApps.length])); _windows.add(child);
});
}
void _handleClose(ChildViewConnection child) {
setState(() {
_windows.remove(child);
}); });
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( return new Material(
onTap: _handleTap, child: new Stack(
child: new Container( children: <Widget>[
decoration: new BoxDecoration( new Positioned(
backgroundColor: Colors.blue[500] left: 0.0,
), right: 0.0,
child: new Stack( bottom: 0.0,
children: _windows.map((ChildViewConnection child) { child: new Launcher(items: _kLauncherData.map((LauncherData data) {
return new Window( return new LauncherItem(
key: new ObjectKey(child), url: data.url,
child: child onLaunch: _handleLaunch,
); child: new Text(data.title)
}).toList() );
) }).toList())
)
]..addAll(_windows.map((ChildViewConnection child) {
return new Window(
key: new ObjectKey(child),
onClose: _handleClose,
child: child
);
}))
) )
); );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment