| // 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'; |
| |
| import 'example_code_parser.dart'; |
| import 'syntax_highlighter.dart'; |
| |
| class ComponentDemoTabData { |
| ComponentDemoTabData({ |
| this.demoWidget, |
| this.exampleCodeTag, |
| this.description, |
| this.tabName |
| }); |
| |
| final Widget demoWidget; |
| final String exampleCodeTag; |
| final String description; |
| final String tabName; |
| |
| @override |
| bool operator==(Object other) { |
| if (other.runtimeType != runtimeType) |
| return false; |
| final ComponentDemoTabData typedOther = other; |
| return typedOther.tabName == tabName && typedOther.description == description; |
| } |
| |
| @override |
| int get hashCode => hashValues(tabName.hashCode, description.hashCode); |
| } |
| |
| class TabbedComponentDemoScaffold extends StatelessWidget { |
| const TabbedComponentDemoScaffold({ |
| this.title, |
| this.demos, |
| this.actions, |
| }); |
| |
| final List<ComponentDemoTabData> demos; |
| final String title; |
| final List<Widget> actions; |
| |
| void _showExampleCode(BuildContext context) { |
| final String tag = demos[DefaultTabController.of(context).index].exampleCodeTag; |
| if (tag != null) { |
| Navigator.push(context, new MaterialPageRoute<FullScreenCodeDialog>( |
| builder: (BuildContext context) => new FullScreenCodeDialog(exampleCodeTag: tag) |
| )); |
| } |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return new DefaultTabController( |
| length: demos.length, |
| child: new Scaffold( |
| appBar: new AppBar( |
| title: new Text(title), |
| 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); |
| }, |
| ); |
| }, |
| ) |
| ], |
| ), |
| bottom: new TabBar( |
| isScrollable: true, |
| tabs: demos.map((ComponentDemoTabData data) => new Tab(text: data.tabName)).toList(), |
| ), |
| ), |
| body: new TabBarView( |
| children: demos.map((ComponentDemoTabData demo) { |
| 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) |
| ], |
| ), |
| ); |
| }).toList(), |
| ), |
| ), |
| ); |
| } |
| } |
| |
| class FullScreenCodeDialog extends StatefulWidget { |
| const FullScreenCodeDialog({ this.exampleCodeTag }); |
| |
| final String exampleCodeTag; |
| |
| @override |
| FullScreenCodeDialogState createState() => new FullScreenCodeDialogState(); |
| } |
| |
| class FullScreenCodeDialogState extends State<FullScreenCodeDialog> { |
| |
| String _exampleCode; |
| |
| @override |
| void didChangeDependencies() { |
| getExampleCode(widget.exampleCodeTag, DefaultAssetBundle.of(context)).then<Null>((String code) { |
| if (mounted) { |
| setState(() { |
| _exampleCode = code ?? 'Example code not found'; |
| }); |
| } |
| }); |
| super.didChangeDependencies(); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| final SyntaxHighlighterStyle style = Theme.of(context).brightness == Brightness.dark |
| ? SyntaxHighlighterStyle.darkThemeStyle() |
| : SyntaxHighlighterStyle.lightThemeStyle(); |
| |
| Widget body; |
| if (_exampleCode == null) { |
| body = const Center( |
| child: const CircularProgressIndicator() |
| ); |
| } else { |
| body = new SingleChildScrollView( |
| child: new Padding( |
| padding: const EdgeInsets.all(16.0), |
| child: new RichText( |
| text: new TextSpan( |
| style: const TextStyle(fontFamily: 'monospace', fontSize: 10.0), |
| children: <TextSpan>[ |
| new DartSyntaxHighlighter(style).format(_exampleCode) |
| ] |
| ) |
| ) |
| ) |
| ); |
| } |
| |
| return new Scaffold( |
| appBar: new AppBar( |
| leading: new IconButton( |
| icon: const Icon( |
| Icons.clear, |
| semanticLabel: 'Close', |
| ), |
| onPressed: () { Navigator.pop(context); } |
| ), |
| title: const Text('Example code') |
| ), |
| body: body |
| ); |
| } |
| } |