diff --git a/dev/benchmarks/complex_layout/.gitignore b/dev/benchmarks/complex_layout/.gitignore new file mode 100644 index 00000000000..14c7d4c3f73 --- /dev/null +++ b/dev/benchmarks/complex_layout/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +.atom/ +.idea +.packages +.pub/ +build/ +ios/.generated/ +packages +pubspec.lock diff --git a/dev/benchmarks/complex_layout/android/AndroidManifest.xml b/dev/benchmarks/complex_layout/android/AndroidManifest.xml new file mode 100644 index 00000000000..794a13f5d7e --- /dev/null +++ b/dev/benchmarks/complex_layout/android/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/dev/benchmarks/complex_layout/android/res/mipmap-hdpi/ic_launcher.png b/dev/benchmarks/complex_layout/android/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000000..f0a55cda78c Binary files /dev/null and b/dev/benchmarks/complex_layout/android/res/mipmap-hdpi/ic_launcher.png differ diff --git a/dev/benchmarks/complex_layout/android/res/mipmap-mdpi/ic_launcher.png b/dev/benchmarks/complex_layout/android/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000000..eb98dc451df Binary files /dev/null and b/dev/benchmarks/complex_layout/android/res/mipmap-mdpi/ic_launcher.png differ diff --git a/dev/benchmarks/complex_layout/android/res/mipmap-xhdpi/ic_launcher.png b/dev/benchmarks/complex_layout/android/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000000..f1783dbbf3c Binary files /dev/null and b/dev/benchmarks/complex_layout/android/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/dev/benchmarks/complex_layout/android/res/mipmap-xxhdpi/ic_launcher.png b/dev/benchmarks/complex_layout/android/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000000..46828a290a7 Binary files /dev/null and b/dev/benchmarks/complex_layout/android/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/dev/benchmarks/complex_layout/android/res/mipmap-xxxhdpi/ic_launcher.png b/dev/benchmarks/complex_layout/android/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000000..a5276715d92 Binary files /dev/null and b/dev/benchmarks/complex_layout/android/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/dev/benchmarks/complex_layout/flutter.yaml b/dev/benchmarks/complex_layout/flutter.yaml new file mode 100644 index 00000000000..16e08e13853 --- /dev/null +++ b/dev/benchmarks/complex_layout/flutter.yaml @@ -0,0 +1,6 @@ +name: complex_layout +uses-material-design: true +assets: + - packages/flutter_gallery_assets/ali_connors.png + - packages/flutter_gallery_assets/ali_connors_sml.png + - packages/flutter_gallery_assets/top_10_australian_beaches.png diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Contents.json b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000..363d1c4ce4f --- /dev/null +++ b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,142 @@ +{ + "images" : [ + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Small@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Small@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-Small.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-Small@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-Small-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-Small-40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16x16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16x16@2x.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32x32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32x32@2x.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128x128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128x128@2x.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256x256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256x256@2x.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512x512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512x512@2x.png", + "scale" : "2x" + } + ] +} \ No newline at end of file diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png new file mode 100644 index 00000000000..9996f5e598a Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100644 index 00000000000..7a543edbdd4 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-76.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100644 index 00000000000..05a82681049 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png new file mode 100644 index 00000000000..bfbca28f5d5 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png new file mode 100644 index 00000000000..c924b8e497d Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png new file mode 100644 index 00000000000..3006f1d348c Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png new file mode 100644 index 00000000000..5f7d22d364d Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png new file mode 100644 index 00000000000..9996f5e598a Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small.png new file mode 100644 index 00000000000..3433da11966 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png new file mode 100644 index 00000000000..f7f9f16d1b4 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png new file mode 100644 index 00000000000..e9c23601cf4 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_128x128.png new file mode 100644 index 00000000000..dd5fccb0a99 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_128x128.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png new file mode 100644 index 00000000000..1909e275118 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_16x16.png new file mode 100644 index 00000000000..40a701b5146 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_16x16.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png new file mode 100644 index 00000000000..06c1a805609 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_256x256.png new file mode 100644 index 00000000000..1909e275118 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_256x256.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png new file mode 100644 index 00000000000..69c96ef1e27 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_32x32.png new file mode 100644 index 00000000000..06c1a805609 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_32x32.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png new file mode 100644 index 00000000000..0f943714603 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_512x512.png new file mode 100644 index 00000000000..69c96ef1e27 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_512x512.png differ diff --git a/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png new file mode 100644 index 00000000000..1d6355f58c8 Binary files /dev/null and b/dev/benchmarks/complex_layout/ios/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png differ diff --git a/dev/benchmarks/complex_layout/ios/Info.plist b/dev/benchmarks/complex_layout/ios/Info.plist new file mode 100644 index 00000000000..9c5e317f536 --- /dev/null +++ b/dev/benchmarks/complex_layout/ios/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + Runner + CFBundleIdentifier + com.yourcompany.complexLayout + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + complex_layout + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/dev/benchmarks/complex_layout/ios/LaunchScreen.storyboard b/dev/benchmarks/complex_layout/ios/LaunchScreen.storyboard new file mode 100644 index 00000000000..78686cd0750 --- /dev/null +++ b/dev/benchmarks/complex_layout/ios/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/benchmarks/complex_layout/lib/main.dart b/dev/benchmarks/complex_layout/lib/main.dart new file mode 100644 index 00000000000..91993a98f4d --- /dev/null +++ b/dev/benchmarks/complex_layout/lib/main.dart @@ -0,0 +1,636 @@ +// Copyright 2015 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 'package:flutter/scheduler.dart' show timeDilation; + +void main() { + runApp( + new ComplexLayoutApp() + ); +} + +class ComplexLayoutApp extends StatefulWidget { + @override + ComplexLayoutAppState createState() => new ComplexLayoutAppState(); + + static ComplexLayoutAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher()); +} + +class ComplexLayoutAppState extends State { + @override + Widget build(BuildContext context) { + return new MaterialApp( + theme: lightTheme ? new ThemeData.light() : new ThemeData.dark(), + title: 'Advanced Layout', + routes: { + '/': (BuildContext context) => new ComplexLayout(), + } + ); + } + + bool _lightTheme = true; + bool get lightTheme => _lightTheme; + void set lightTheme(bool value) { + setState(() { + _lightTheme = value; + }); + } +} + +class ComplexLayout extends StatefulWidget { + ComplexLayout({ Key key }) : super(key: key); + + @override + ComplexLayoutState createState() => new ComplexLayoutState(); + + static ComplexLayoutState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher()); + +} + +class ComplexLayoutState extends State { + @override + Widget build(BuildContext context) { + + return new Scaffold( + appBar: new AppBar( + title: new Text('Advanced Layout'), + actions: [ + new IconButton( + icon: Icons.create, + tooltip: 'Search', + onPressed: () { + print("Pressed search"); + } + ), + new TopBarMenu() + ] + ), + body: new Column( + children: [ + new Flexible( + child: new ScrollableMixedWidgetList( + key: new Key("main-scroll"), + builder: (BuildContext context, int index) { + if (index % 2 == 0) + return new FancyImageItem(index, key: new Key("Item $index")); + else + return new FancyGalleryItem(index, key: new Key("Item $index")); + } + ) + ), + new BottomBar() + ] + ), + drawer: new GalleryDrawer() + ); + } +} + +class TopBarMenu extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new PopupMenuButton( + onSelected: (String value) { print("Selected: $value"); }, + items: >[ + new PopupMenuItem( + value: "Friends", + child: new MenuItemWithIcon(Icons.people, "Friends", "5 new") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.event, "Events", "12 upcoming") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.group, "Groups", "14") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.image, "Pictures", "12") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.near_me, "Nearby", "33") + ), + new PopupMenuItem( + value: "Friends", + child: new MenuItemWithIcon(Icons.people, "Friends", "5") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.event, "Events", "12") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.group, "Groups", "14") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.image, "Pictures", "12") + ), + new PopupMenuItem( + value: "Events", + child: new MenuItemWithIcon(Icons.near_me, "Nearby", "33") + ) + ] + ); + } +} + +class MenuItemWithIcon extends StatelessWidget { + MenuItemWithIcon(this.icon, this.title, this.subtitle); + + final IconData icon; + final String title; + final String subtitle; + + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Icon(icon: icon), + new Padding( + padding: new EdgeInsets.only(left: 8.0, right: 8.0), + child: new Text(title) + ), + new Text(subtitle, style: Theme.of(context).textTheme.caption) + ] + ); + } +} + +class FancyImageItem extends StatelessWidget { + FancyImageItem(this.index, {Key key}) : super(key: key); + + final int index; + + @override + Widget build(BuildContext context) { + return new BlockBody( + children: [ + new UserHeader("Ali Connors $index"), + new ItemDescription(), + new ItemImageBox(), + new InfoBar(), + new Padding( + padding: new EdgeInsets.symmetric(horizontal: 8.0), + child: new Divider() + ), + new IconBar(), + new FatDivider() + ] + ); + } +} + +class FancyGalleryItem extends StatelessWidget { + FancyGalleryItem(this.index, {Key key}) : super(key: key); + + final int index; + @override + Widget build(BuildContext context) { + return new BlockBody( + children: [ + new UserHeader("Ali Connors"), + new ItemGalleryBox(index), + new InfoBar(), + new Padding( + padding: new EdgeInsets.symmetric(horizontal: 8.0), + child: new Divider() + ), + new IconBar(), + new FatDivider() + ] + ); + } +} + +class InfoBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Padding( + padding: new EdgeInsets.all(8.0), + child: new Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new MiniIconWithText(Icons.thumb_up, "42"), + new Text("3 Comments", style: Theme.of(context).textTheme.caption) + ] + ) + ); + } +} + +class IconBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Padding( + padding: new EdgeInsets.only(left: 16.0, right: 16.0), + child: new Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new IconWithText(Icons.thumb_up, "Like"), + new IconWithText(Icons.comment, "Comment"), + new IconWithText(Icons.share, "Share"), + ] + ) + ); + } +} + +class IconWithText extends StatelessWidget { + IconWithText(this.icon, this.title); + + final IconData icon; + final String title; + + @override + Widget build(BuildContext context) { + return new Row( + mainAxisAlignment: MainAxisAlignment.collapse, + children: [ + new IconButton(icon: icon, onPressed: () { print("Pressed $title button"); } ), + new Text(title) + ] + ); + } +} + +class MiniIconWithText extends StatelessWidget { + MiniIconWithText(this.icon, this.title); + + final IconData icon; + final String title; + + @override + Widget build(BuildContext context) { + return new Row( + mainAxisAlignment: MainAxisAlignment.collapse, + children: [ + new Padding( + padding: new EdgeInsets.only(right: 8.0), + child: new Container( + width: 16.0, + height: 16.0, + decoration: new BoxDecoration( + backgroundColor: Theme.of(context).primaryColor, + shape: BoxShape.circle + ), + child: new Icon(icon: icon, color: Colors.white, size: 12.0) + ) + ), + new Text(title, style: Theme.of(context).textTheme.caption) + ] + ); + } +} + +class FatDivider extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container( + height: 8.0, + decoration: new BoxDecoration( + backgroundColor: Theme.of(context).dividerColor + ) + ); + } +} + +class UserHeader extends StatelessWidget { + UserHeader(this.userName); + + final String userName; + + @override + Widget build(BuildContext context) { + return new Padding( + padding: new EdgeInsets.all(8.0), + child: new Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + new Padding( + padding: new EdgeInsets.only(right: 8.0), + child: new AssetImage( + name: "packages/flutter_gallery_assets/ali_connors_sml.png", + width: 32.0, + height: 32.0 + ) + ), + new Flexible( + child: new Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + new RichText(text: new TextSpan( + style: Theme.of(context).textTheme.body1, + children: [ + new TextSpan(text: userName, style: new TextStyle(fontWeight: FontWeight.bold)), + new TextSpan(text: " shared a new "), + new TextSpan(text: "photo", style: new TextStyle(fontWeight: FontWeight.bold)) + ] + )), + new Row( + children: [ + new Text("Yesterday at 11:55 • ", style: Theme.of(context).textTheme.caption), + new Icon(icon: Icons.people, size: 16.0, color: Theme.of(context).textTheme.caption.color) + ] + ) + ] + ) + ), + new TopBarMenu() + ] + ) + ); + } +} + +class ItemDescription extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Padding( + padding: new EdgeInsets.all(8.0), + child: new Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") + ); + } +} + +class ItemImageBox extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Padding( + padding: new EdgeInsets.all(8.0), + child: new Card( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + new Stack( + children: [ + new SizedBox( + height: 230.0, + child: new AssetImage( + name: "packages/flutter_gallery_assets/top_10_australian_beaches.png" + ) + ), + new Theme( + data: new ThemeData.dark(), + child: new Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + new IconButton(icon: Icons.edit, onPressed: () { print("Pressed edit button"); }), + new IconButton(icon: Icons.zoom_in, onPressed: () { print("Pressed zoom button"); }) + ] + ) + ), + new Positioned( + bottom: 4.0, + left: 4.0, + child: new Container( + decoration: new BoxDecoration( + backgroundColor: Colors.black54, + borderRadius: 2.0 + ), + padding: new EdgeInsets.all(4.0), + child: new RichText( + text: new TextSpan( + style: new TextStyle(color: Colors.white), + children: [ + new TextSpan( + text: "Photo by " + ), + new TextSpan( + style: new TextStyle(fontWeight: FontWeight.bold), + text: "Magic Mike" + ) + ] + ) + ) + ) + ) + ] + ) + , + new Padding( + padding: new EdgeInsets.all(8.0), + child: new Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + new Text("Where can you find that amazing sunset?", style: Theme.of(context).textTheme.body2), + new Text("The sun sets over stinson beach", style: Theme.of(context).textTheme.body1), + new Text("flutter.io/amazingsunsets", style: Theme.of(context).textTheme.caption) + ] + ) + ) + ] + ) + ) + ); + } +} + +class ItemGalleryBox extends StatelessWidget { + ItemGalleryBox(this.index); + + final int index; + + @override + Widget build(BuildContext context) { + List tabNames = [ + "A", "B", "C", "D" + ]; + + return new SizedBox( + height: 200.0, + child: new TabBarSelection( + values: tabNames, + child: new Column( + children: [ + new Flexible( + child: new TabBarView( + children: tabNames.map((String tabName) { + return new Container( + key: new Key("Tab $index - $tabName"), + child: new Padding( + padding: new EdgeInsets.all(8.0), + child: new Card( + child: new Column( + children: [ + new Flexible( + child: new Container( + decoration: new BoxDecoration( + backgroundColor: Theme.of(context).primaryColor + ), + child: new Center( + child: new Text(tabName, style: Theme.of(context).textTheme.headline.copyWith(color: Colors.white)) + ) + ) + ), + new Row( + children: [ + new IconButton( + icon: Icons.share, + onPressed: () { print("Pressed share"); } + ), + new IconButton( + icon: Icons.event, + onPressed: () { print("Pressed event"); } + ), + new Flexible( + child: new Padding( + padding: new EdgeInsets.only(left: 8.0), + child: new Text("This is item $tabName") + ) + ) + ] + ) + ] + ) + ) + ) + ); + }).toList() + ) + ), + new Container( + child: new TabPageSelector() + ) + ] + ) + ) + ); + } +} + +class BottomBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container( + decoration: new BoxDecoration( + border: new Border( + top: new BorderSide( + color: Theme.of(context).dividerColor, + width: 1.0 + ) + ) + ), + child: new Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new BottomBarButton(Icons.new_releases, "News"), + new BottomBarButton(Icons.people, "Requests"), + new BottomBarButton(Icons.chat, "Messenger"), + new BottomBarButton(Icons.bookmark, "Bookmark"), + new BottomBarButton(Icons.alarm, "Alarm") + ] + ) + ); + } +} + +class BottomBarButton extends StatelessWidget { + BottomBarButton(this.icon, this.title); + + final IconData icon; + final String title; + + @override + Widget build(BuildContext context) { + return new Padding( + padding: new EdgeInsets.all(8.0), + child: new Column( + children: [ + new IconButton( + icon: icon, + onPressed: () { print("Pressed: $title"); } + ), + new Text(title, style: Theme.of(context).textTheme.caption) + ] + ) + ); + } +} + +class GalleryDrawer extends StatelessWidget { + GalleryDrawer({ Key key }) : super(key: key); + + void _changeTheme(BuildContext context, bool value) { + ComplexLayoutApp.of(context).lightTheme = value; + } + + void _toggleAnimationSpeed(BuildContext context) { + ComplexLayoutApp.of(context).setState(() { + timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0; + }); + } + + @override + Widget build(BuildContext context) { + return new Drawer( + child: new Block( + children: [ + new FancyDrawerHeader(), + new DrawerItem( + icon: Icons.brightness_5, + onPressed: () { _changeTheme(context, true); }, + selected: ComplexLayoutApp.of(context).lightTheme, + child: new Row( + children: [ + new Flexible(child: new Text('Light')), + new Radio( + value: true, + groupValue: ComplexLayoutApp.of(context).lightTheme, + onChanged: (bool value) { _changeTheme(context, value); } + ) + ] + ) + ), + new DrawerItem( + icon: Icons.brightness_7, + onPressed: () { _changeTheme(context, false); }, + selected: !ComplexLayoutApp.of(context).lightTheme, + child: new Row( + children: [ + new Flexible(child: new Text('Dark')), + new Radio( + value: false, + groupValue: ComplexLayoutApp.of(context).lightTheme, + onChanged: (bool value) { _changeTheme(context, value); } + ) + ] + ) + ), + new Divider(), + new DrawerItem( + icon: Icons.hourglass_empty, + selected: timeDilation != 1.0, + onPressed: () { _toggleAnimationSpeed(context); }, + child: new Row( + children: [ + new Flexible(child: new Text('Animate Slowly')), + new Checkbox( + value: timeDilation != 1.0, + onChanged: (bool value) { _toggleAnimationSpeed(context); } + ) + ] + ) + ) + ] + ) + ); + } +} + +class FancyDrawerHeader extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container( + decoration: new BoxDecoration( + backgroundColor: Colors.purple[500] + ), + height: 200.0 + ); + } +} diff --git a/dev/benchmarks/complex_layout/pubspec.yaml b/dev/benchmarks/complex_layout/pubspec.yaml new file mode 100644 index 00000000000..db5f9bf1780 --- /dev/null +++ b/dev/benchmarks/complex_layout/pubspec.yaml @@ -0,0 +1,8 @@ +name: complex_layout +description: A new flutter project. +dependencies: + flutter: + path: ../../../packages/flutter + flutter_driver: + path: ../../../packages/flutter_driver + flutter_gallery_assets: '0.0.14' diff --git a/dev/benchmarks/complex_layout/test_driver/scroll_perf.dart b/dev/benchmarks/complex_layout/test_driver/scroll_perf.dart new file mode 100644 index 00000000000..c8a016b41fb --- /dev/null +++ b/dev/benchmarks/complex_layout/test_driver/scroll_perf.dart @@ -0,0 +1,11 @@ +// 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_driver/driver_extension.dart'; +import 'package:complex_layout/main.dart' as app; + +void main() { + enableFlutterDriverExtension(); + app.main(); +} diff --git a/dev/benchmarks/complex_layout/test_driver/scroll_perf_test.dart b/dev/benchmarks/complex_layout/test_driver/scroll_perf_test.dart new file mode 100644 index 00000000000..5aca2114c83 --- /dev/null +++ b/dev/benchmarks/complex_layout/test_driver/scroll_perf_test.dart @@ -0,0 +1,47 @@ +// 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 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:test/test.dart'; + +void main() { + group('scrolling performance test', () { + FlutterDriver driver; + + setUpAll(() async { + driver = await FlutterDriver.connect(); + }); + + tearDownAll(() async { + if (driver != null) + driver.close(); + }); + + test('measure', () async { + Map profileJson = await driver.traceAction(() async { + // Find the scrollable stock list + ObjectRef stockList = await driver.findByValueKey('main-scroll'); + expect(stockList, isNotNull); + + // Scroll down + for (int i = 0; i < 5; i++) { + await driver.scroll(stockList, 0.0, -300.0, new Duration(milliseconds: 300)); + await new Future.delayed(new Duration(milliseconds: 500)); + } + + // Scroll up + for (int i = 0; i < 5; i++) { + await driver.scroll(stockList, 0.0, 300.0, new Duration(milliseconds: 300)); + await new Future.delayed(new Duration(milliseconds: 500)); + } + }); + + expect(profileJson, isNotNull); + await new File("build/profile.json").writeAsString(JSON.encode(profileJson)); + }); + }); +}