shrine_page.dart 4.56 KB
Newer Older
1 2 3 4
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/foundation.dart';
6 7 8
import 'package:flutter/material.dart';

import 'shrine_theme.dart';
9
import 'shrine_types.dart';
10 11 12 13 14 15 16

enum ShrineAction {
  sortByPrice,
  sortByProduct,
  emptyCart
}

Hans Muller's avatar
Hans Muller committed
17
class ShrinePage extends StatefulWidget {
18
  const ShrinePage({
19
    Key key,
20 21
    @required this.scaffoldKey,
    @required this.body,
22 23 24
    this.floatingActionButton,
    this.products,
    this.shoppingCart
25 26 27
  }) : assert(body != null),
       assert(scaffoldKey != null),
       super(key: key);
28

29
  final GlobalKey<ScaffoldState> scaffoldKey;
30 31
  final Widget body;
  final Widget floatingActionButton;
32 33
  final List<Product> products;
  final Map<Product, Order> shoppingCart;
34

Hans Muller's avatar
Hans Muller committed
35 36 37 38 39 40
  @override
  ShrinePageState createState() => new ShrinePageState();
}

/// Defines the Scaffold, AppBar, etc that the demo pages have in common.
class ShrinePageState extends State<ShrinePage> {
41
  double _appBarElevation = 0.0;
Hans Muller's avatar
Hans Muller committed
42

Adam Barth's avatar
Adam Barth committed
43
  bool _handleScrollNotification(ScrollNotification notification) {
44
    final double elevation = notification.metrics.extentBefore <= 0.0 ? 0.0 : 1.0;
Hans Muller's avatar
Hans Muller committed
45 46 47 48 49 50 51 52
    if (elevation != _appBarElevation) {
      setState(() {
        _appBarElevation = elevation;
      });
    }
    return false;
  }

53
  void _showShoppingCart() {
54
    showModalBottomSheet<Null>(context: context, builder: (BuildContext context) {
55
      if (widget.shoppingCart.isEmpty) {
56
        return const Padding(
57
          padding: const EdgeInsets.all(24.0),
58
          child: const Text('The shopping cart is empty')
59 60
        );
      }
61
      return new ListView(
62
        padding: kMaterialListPadding,
63
        children: widget.shoppingCart.values.map((Order order) {
64
          return new ListTile(
65 66 67 68 69 70
            title: new Text(order.product.name),
            leading: new Text('${order.quantity}'),
            subtitle: new Text(order.product.vendor.name)
          );
        }).toList(),
      );
71 72 73 74
    });
  }

  void _sortByPrice() {
75
    widget.products.sort((Product a, Product b) => a.price.compareTo(b.price));
76 77 78
  }

  void _sortByProduct() {
79
    widget.products.sort((Product a, Product b) => a.name.compareTo(b.name));
80 81 82
  }

  void _emptyCart() {
83
    widget.shoppingCart.clear();
84
    widget.scaffoldKey.currentState.showSnackBar(const SnackBar(content: const Text('Shopping cart is empty')));
85 86
  }

87 88
  @override
  Widget build(BuildContext context) {
89
    final ShrineTheme theme = ShrineTheme.of(context);
90
    return new Scaffold(
91
      key: widget.scaffoldKey,
92
      appBar: new AppBar(
Hans Muller's avatar
Hans Muller committed
93
        elevation: _appBarElevation,
94
        backgroundColor: theme.appBarBackgroundColor,
95 96
        iconTheme: Theme.of(context).iconTheme,
        brightness: Brightness.light,
Hans Muller's avatar
Hans Muller committed
97 98 99
        flexibleSpace: new Container(
          decoration: new BoxDecoration(
            border: new Border(
100
              bottom: new BorderSide(color: theme.dividerColor)
Hans Muller's avatar
Hans Muller committed
101 102 103
            )
          )
        ),
104 105
        title: new Text('SHRINE', style: ShrineTheme.of(context).appBarTitleStyle),
        centerTitle: true,
106
        actions: <Widget>[
107
          new IconButton(
108
            icon: const Icon(Icons.shopping_cart),
109
            tooltip: 'Shopping cart',
110
            onPressed: _showShoppingCart
111 112 113
          ),
          new PopupMenuButton<ShrineAction>(
            itemBuilder: (BuildContext context) => <PopupMenuItem<ShrineAction>>[
114
              const PopupMenuItem<ShrineAction>(
115
                value: ShrineAction.sortByPrice,
116
                child: const Text('Sort by price')
117
              ),
118
              const PopupMenuItem<ShrineAction>(
119
                value: ShrineAction.sortByProduct,
120
                child: const Text('Sort by product')
121
              ),
122
              const PopupMenuItem<ShrineAction>(
123
                value: ShrineAction.emptyCart,
124
                child: const Text('Empty shopping cart')
125
              )
126 127 128 129
            ],
            onSelected: (ShrineAction action) {
              switch (action) {
                case ShrineAction.sortByPrice:
130
                  setState(_sortByPrice);
131 132
                  break;
                case ShrineAction.sortByProduct:
133
                  setState(_sortByProduct);
134 135
                  break;
                case ShrineAction.emptyCart:
136
                  setState(_emptyCart);
137 138 139
                  break;
              }
            }
140 141 142
          )
        ]
      ),
143
      floatingActionButton: widget.floatingActionButton,
Adam Barth's avatar
Adam Barth committed
144
      body: new NotificationListener<ScrollNotification>(
Hans Muller's avatar
Hans Muller committed
145
        onNotification: _handleScrollNotification,
146
        child: widget.body
Hans Muller's avatar
Hans Muller committed
147
      )
148 149 150
    );
  }
}