blob: 4b401c3ed390b971dc4f266643606537dc20f064 [file] [log] [blame]
// Copyright 2018 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.
library flutter_widget;
import 'dart:convert';
import 'package:http/http.dart';
import 'package:meta/meta.dart';
import '../ui/icons.dart';
import '../utils.dart';
class Category {
const Category(this.label, this.icon);
static const Category accessibility =
Category('Accessibility', FlutterIcons.accessibility);
static const Category animationAndMotion =
Category('Animation and Motion', FlutterIcons.animation);
static const Category assetsImagesAndIcons =
Category('Assets, Images, and Icons', FlutterIcons.assets);
static const Category asyncCategory =
Category('Async', FlutterIcons.asyncUrlIcon);
static const Category basics =
Category('Basics', null); // TODO(jacobr): add an icon.
static const Category cupertino = Category(
'Cupertino (iOS-style widgets)', null); // TODO(jacobr): add an icon.
static const Category input = Category('Input', FlutterIcons.input);
static const Category paintingAndEffects =
Category('Painting and effects', FlutterIcons.painting);
static const Category scrolling =
Category('Scrolling', FlutterIcons.scrollbar);
static const Category stack = Category('Stack', FlutterIcons.stack);
static const Category styling = Category('Styling', FlutterIcons.styling);
static const Category text = Category('Text', FlutterIcons.text);
static const List<Category> values = [
accessibility,
animationAndMotion,
assetsImagesAndIcons,
asyncCategory,
basics,
cupertino,
input,
paintingAndEffects,
scrolling,
stack,
styling,
text,
];
final String label;
final Icon icon;
static Map<String, Category> _categories;
static Category forLabel(String label) {
if (_categories == null) {
_categories = {};
for (var category in values) {
_categories[category.label] = category;
}
}
return _categories[label];
}
}
class FlutterWidget {
FlutterWidget(this.json) : icon = initIcon(json);
final Map<String, Object> json;
final Icon icon;
static Icon initIcon(Map<String, Object> json) {
final List<Object> categories = json['categories'];
if (categories != null) {
// TODO(pq): consider priority over first match.
for (String label in categories) {
final Category category = Category.forLabel(label);
if (category != null) {
final Icon icon = category.icon;
if (icon != null) return icon;
}
}
}
return null;
}
String get name => JsonUtils.getStringMember(json, 'name');
List<String> get categories => JsonUtils.getValues(json, 'categories');
List<String> get subCategories => JsonUtils.getValues(json, 'subcategories');
}
/// Catalog of widgets derived from widgets.json.
class Catalog {
Catalog._(this.widgets);
final Map<String, FlutterWidget> widgets;
static Future<Catalog> _cachedCatalog;
static Catalog get instance => _instance;
static Catalog _instance;
static Future<Catalog> load() {
return _cachedCatalog ??= _loadHelper();
}
static Future<Catalog> _loadHelper() async {
// Local copy of: https://github.com/flutter/website/blob/master/src/_data/catalog/widgets.json
final Response response = await get('widgets.json');
_instance = decode(response.body);
return _instance;
}
@visibleForTesting
static void setCatalog(Catalog catalog) {
_instance = catalog;
_cachedCatalog = Future.value(catalog);
}
static Catalog decode(String source) {
final List<Object> json = jsonDecode(source);
final Map<String, FlutterWidget> widgets = {};
for (Map<String, Object> element in json) {
final FlutterWidget widget = FlutterWidget(element);
final String name = widget.name;
// TODO(pq): add validation once json is repaired (https://github.com/flutter/flutter/issues/12930).
// if (widgets.containsKey(name)) throw new IllegalStateException('Unexpected contents: widget `${name}` is duplicated');
widgets[name] = widget;
}
return Catalog._(widgets);
}
List<FlutterWidget> get allWidgets {
return widgets.values.toList();
}
FlutterWidget getWidget(String name) {
return name != null ? widgets[name] : null;
}
String dumpJson() {
return jsonEncode(json);
}
}