demo.dart 4.68 KB
Newer Older
1 2 3 4 5 6
// 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.

import 'package:flutter/material.dart';

7
import 'example_code_parser.dart';
8
import 'syntax_highlighter.dart';
9

10 11
class ComponentDemoTabData {
  ComponentDemoTabData({
12
    this.demoWidget,
13
    this.exampleCodeTag,
14
    this.description,
15
    this.tabName
16 17
  });

18
  final Widget demoWidget;
19
  final String exampleCodeTag;
20 21 22 23 24 25 26
  final String description;
  final String tabName;

  @override
  bool operator==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
27
    final ComponentDemoTabData typedOther = other;
28 29 30 31 32 33 34 35
    return typedOther.tabName == tabName && typedOther.description == description;
  }

  @override
  int get hashCode => hashValues(tabName.hashCode, description.hashCode);
}

class TabbedComponentDemoScaffold extends StatelessWidget {
36
  const TabbedComponentDemoScaffold({
37
    this.title,
38 39
    this.demos,
    this.actions,
40 41 42 43
  });

  final List<ComponentDemoTabData> demos;
  final String title;
44
  final List<Widget> actions;
45

46
  void _showExampleCode(BuildContext context) {
47
    final String tag = demos[DefaultTabController.of(context).index].exampleCodeTag;
48 49 50 51 52 53 54
    if (tag != null) {
      Navigator.push(context, new MaterialPageRoute<FullScreenCodeDialog>(
        builder: (BuildContext context) => new FullScreenCodeDialog(exampleCodeTag: tag)
      ));
    }
  }

55 56
  @override
  Widget build(BuildContext context) {
Hans Muller's avatar
Hans Muller committed
57 58
    return new DefaultTabController(
      length: demos.length,
59 60 61
      child: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
          actions: (actions ?? <Widget>[])..addAll(
            <Widget>[
              new Builder(
                builder: (BuildContext context) {
                  return new IconButton(
                    icon: const Icon(Icons.description),
                    tooltip: 'Show example code',
                    onPressed: () {
                      _showExampleCode(context);
                    },
                  );
                },
              )
            ],
          ),
Hans Muller's avatar
Hans Muller committed
77
          bottom: new TabBar(
78
            isScrollable: true,
Hans Muller's avatar
Hans Muller committed
79 80
            tabs: demos.map((ComponentDemoTabData data) => new Tab(text: data.tabName)).toList(),
          ),
81
        ),
Hans Muller's avatar
Hans Muller committed
82
        body: new TabBarView(
83
          children: demos.map((ComponentDemoTabData demo) {
84 85 86 87 88 89 90 91 92 93 94 95 96 97
            return new SafeArea(
              top: false,
              bottom: false,
              child: new Column(
                children: <Widget>[
                  new Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: new Text(demo.description,
                      style: Theme.of(context).textTheme.subhead
                    )
                  ),
                  new Expanded(child: demo.demoWidget)
                ],
              ),
98
            );
Hans Muller's avatar
Hans Muller committed
99 100 101
          }).toList(),
        ),
      ),
102 103 104 105
    );
  }
}

106
class FullScreenCodeDialog extends StatefulWidget {
107
  const FullScreenCodeDialog({ this.exampleCodeTag });
108 109 110 111 112 113 114 115

  final String exampleCodeTag;

  @override
  FullScreenCodeDialogState createState() => new FullScreenCodeDialogState();
}

class FullScreenCodeDialogState extends State<FullScreenCodeDialog> {
116

117 118 119
  String _exampleCode;

  @override
120
  void didChangeDependencies() {
121
    getExampleCode(widget.exampleCodeTag, DefaultAssetBundle.of(context)).then<Null>((String code) {
122 123
      if (mounted) {
        setState(() {
124
          _exampleCode = code ?? 'Example code not found';
125 126
        });
      }
127
    });
128
    super.didChangeDependencies();
129
  }
130 131 132

  @override
  Widget build(BuildContext context) {
133 134 135 136
    final SyntaxHighlighterStyle style = Theme.of(context).brightness == Brightness.dark
      ? SyntaxHighlighterStyle.darkThemeStyle()
      : SyntaxHighlighterStyle.lightThemeStyle();

137 138
    Widget body;
    if (_exampleCode == null) {
139
      body = const Center(
140
        child: const CircularProgressIndicator()
141 142
      );
    } else {
143
      body = new SingleChildScrollView(
144
        child: new Padding(
145
          padding: const EdgeInsets.all(16.0),
146 147
          child: new RichText(
            text: new TextSpan(
148
              style: const TextStyle(fontFamily: 'monospace', fontSize: 10.0),
149 150 151 152 153
              children: <TextSpan>[
                new DartSyntaxHighlighter(style).format(_exampleCode)
              ]
            )
          )
154 155 156 157
        )
      );
    }

158 159 160
    return new Scaffold(
      appBar: new AppBar(
        leading: new IconButton(
161 162 163 164
          icon: const Icon(
            Icons.clear,
            semanticLabel: 'Close',
          ),
165 166
          onPressed: () { Navigator.pop(context); }
        ),
167
        title: const Text('Example code')
168
      ),
169
      body: body
170 171 172
    );
  }
}