Commit 0c229008 authored by Kris Giesing's avatar Kris Giesing

Merge remote-tracking branch 'upstream/master' into events-merge

parents ec205ac5 42469d2c
......@@ -2,12 +2,12 @@ name: asteroids
dependencies:
flutter: ">=0.0.3 <0.1.0"
sky_tools: any
skysprites: any
flutter_sprites: any
box2d: any
dependency_overrides:
material_design_icons:
path: ../../sky/packages/material_design_icons
flutter:
path: ../../sky/packages/sky
skysprites:
flutter_sprites:
path: ../../skysprites
name: raw
name: sky_raw_examples
dependencies:
flutter: ">=0.0.3 <0.1.0"
sky_tools: any
......
This diff is collapsed.
name: rendering
name: flutter_rendering_examples
dependencies:
flutter: ">=0.0.3 <0.1.0"
sky_tools: any
......
This diff is collapsed.
// 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/painting.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new NetworkImage(
src: "http://38.media.tumblr.com/avatar_497c78dc767d_128.png",
fit: ImageFit.contain,
centerSlice: new Rect.fromLTRB(40.0, 40.0, 88.0, 88.0)
));
}
name: widgets
name: sky_widgets_examples
dependencies:
flutter: ">=0.0.3 <0.1.0"
sky_tools: any
flutter_rendering_examples: any
dependency_overrides:
material_design_icons:
path: ../../sky/packages/material_design_icons
flutter:
path: ../../sky/packages/sky
flutter_rendering_examples:
path: ../rendering
......@@ -7,7 +7,7 @@ import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import '../rendering/sector_layout.dart';
import 'package:flutter_rendering_examples/sector_layout.dart';
RenderBox initCircle() {
return new RenderBoxToRenderSectorAdapter(
......@@ -16,10 +16,14 @@ RenderBox initCircle() {
);
}
class SectorApp extends MaterialApp {
class SectorApp extends StatefulComponent {
SectorAppState createState() => new SectorAppState();
}
class SectorAppState extends State<SectorApp> {
RenderBoxToRenderSectorAdapter sectors = initCircle();
math.Random rand = new math.Random(1);
final RenderBoxToRenderSectorAdapter sectors = initCircle();
final math.Random rand = new math.Random(1);
void addSector() {
double deltaTheta;
......@@ -52,27 +56,27 @@ class SectorApp extends MaterialApp {
RenderBoxToRenderSectorAdapter sectorAddIcon = initSector(const Color(0xFF00DD00));
RenderBoxToRenderSectorAdapter sectorRemoveIcon = initSector(const Color(0xFFDD0000));
bool enabledAdd = true;
bool enabledRemove = false;
bool _enabledAdd = true;
bool _enabledRemove = false;
void updateEnabledState() {
setState(() {
var ring = (sectors.child as RenderSectorRing);
SectorDimensions currentSize = ring.getIntrinsicDimensions(const SectorConstraints(), ring.deltaRadius);
enabledAdd = currentSize.deltaTheta < kTwoPi;
enabledRemove = ring.firstChild != null;
_enabledAdd = currentSize.deltaTheta < kTwoPi;
_enabledRemove = ring.firstChild != null;
});
}
Widget buildBody() {
return new Material(
child: new Column([
child: new Column(<Widget>[
new Container(
padding: new EdgeDims.symmetric(horizontal: 8.0, vertical: 25.0),
child: new Row([
child: new Row(<Widget>[
new RaisedButton(
enabled: enabledAdd,
enabled: _enabledAdd,
child: new IntrinsicWidth(
child: new Row([
child: new Row(<Widget>[
new Container(
padding: new EdgeDims.all(4.0),
margin: new EdgeDims.only(right: 10.0),
......@@ -84,9 +88,9 @@ class SectorApp extends MaterialApp {
onPressed: addSector
),
new RaisedButton(
enabled: enabledRemove,
enabled: _enabledRemove,
child: new IntrinsicWidth(
child: new Row([
child: new Row(<Widget>[
new Container(
padding: new EdgeDims.all(4.0),
margin: new EdgeDims.only(right: 10.0),
......@@ -117,18 +121,20 @@ class SectorApp extends MaterialApp {
);
}
Widget build() {
return new Theme(
data: new ThemeData.light(),
child: new Title(
title: 'Sector Layout',
child: new Scaffold(
toolBar: new ToolBar(
center: new Text('Sector Layout in a Widget Tree')
),
body: buildBody()
)
)
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData.light(),
title: 'Sector Layout',
routes: <String, RouteBuilder>{
'/': (RouteArguments args) {
return new Scaffold(
toolBar: new ToolBar(
center: new Text('Sector Layout in a Widget Tree')
),
body: buildBody()
);
}
}
);
}
}
......
......@@ -10,43 +10,47 @@ import 'package:flutter/services.dart';
import 'shadows.dart';
/// An immutable set of offsets in each of the four cardinal directions
/// An immutable set of offsets in each of the four cardinal directions.
///
/// Typically used for an offset from each of the four sides of a box. For
/// example, the padding inside a box can be represented using this class.
class EdgeDims {
/// Constructs an EdgeDims from offsets from the top, right, bottom and left
/// Constructs an EdgeDims from offsets from the top, right, bottom and left.
const EdgeDims.TRBL(this.top, this.right, this.bottom, this.left);
/// Constructs an EdgeDims where all the offsets are value
/// Constructs an EdgeDims where all the offsets are value.
const EdgeDims.all(double value)
: top = value, right = value, bottom = value, left = value;
/// Constructs an EdgeDims with only the given values non-zero
/// Constructs an EdgeDims with only the given values non-zero.
const EdgeDims.only({ this.top: 0.0,
this.right: 0.0,
this.bottom: 0.0,
this.left: 0.0 });
/// Constructs an EdgeDims with symmetrical vertical and horizontal offsets
/// Constructs an EdgeDims with symmetrical vertical and horizontal offsets.
const EdgeDims.symmetric({ double vertical: 0.0,
double horizontal: 0.0 })
: top = vertical, left = horizontal, bottom = vertical, right = horizontal;
/// The offset from the top
/// The offset from the top.
final double top;
/// The offset from the right
/// The offset from the right.
final double right;
/// The offset from the bottom
/// The offset from the bottom.
final double bottom;
/// The offset from the left
/// The offset from the left.
final double left;
/// Whether every dimension is non-negative.
bool get isNonNegative => top >= 0.0 && right >= 0.0 && bottom >= 0.0 && left >= 0.0;
/// The size that this edge dims would occupy with an empty interior.
Size get collapsedSize => new Size(left + right, top + bottom);
EdgeDims operator-(EdgeDims other) {
return new EdgeDims.TRBL(
top - other.top,
......@@ -101,7 +105,7 @@ class EdgeDims {
);
}
/// Linearly interpolate between two EdgeDims
/// Linearly interpolate between two EdgeDims.
///
/// If either is null, this function interpolates from [EdgeDims.zero].
static EdgeDims lerp(EdgeDims a, EdgeDims b, double t) {
......@@ -119,7 +123,7 @@ class EdgeDims {
);
}
/// An EdgeDims with zero offsets in each direction
/// An EdgeDims with zero offsets in each direction.
static const EdgeDims zero = const EdgeDims.TRBL(0.0, 0.0, 0.0, 0.0);
bool operator ==(dynamic other) {
......@@ -416,88 +420,121 @@ void paintImage({
Rect rect,
ui.Image image,
ui.ColorFilter colorFilter,
fit: ImageFit.scaleDown,
ImageFit fit,
repeat: ImageRepeat.noRepeat,
Rect centerSlice,
double positionX: 0.5,
double positionY: 0.5
}) {
Size bounds = rect.size;
Size imageSize = new Size(image.width.toDouble(), image.height.toDouble());
Size outputSize = rect.size;
Size inputSize = new Size(image.width.toDouble(), image.height.toDouble());
Offset sliceBorder;
if (centerSlice != null) {
sliceBorder = new Offset(
centerSlice.left + inputSize.width - centerSlice.right,
centerSlice.top + inputSize.height - centerSlice.bottom
);
outputSize -= sliceBorder;
inputSize -= sliceBorder;
}
Size sourceSize;
Size destinationSize;
switch(fit) {
fit ??= centerSlice == null ? ImageFit.scaleDown : ImageFit.fill;
assert(centerSlice == null || (fit != ImageFit.none && fit != ImageFit.cover));
switch (fit) {
case ImageFit.fill:
sourceSize = imageSize;
destinationSize = bounds;
sourceSize = inputSize;
destinationSize = outputSize;
break;
case ImageFit.contain:
sourceSize = imageSize;
if (bounds.width / bounds.height > sourceSize.width / sourceSize.height)
destinationSize = new Size(sourceSize.width * bounds.height / sourceSize.height, bounds.height);
sourceSize = inputSize;
if (outputSize.width / outputSize.height > sourceSize.width / sourceSize.height)
destinationSize = new Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height);
else
destinationSize = new Size(bounds.width, sourceSize.height * bounds.width / sourceSize.width);
destinationSize = new Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width);
break;
case ImageFit.cover:
if (bounds.width / bounds.height > imageSize.width / imageSize.height)
sourceSize = new Size(imageSize.width, imageSize.width * bounds.height / bounds.width);
if (outputSize.width / outputSize.height > inputSize.width / inputSize.height)
sourceSize = new Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width);
else
sourceSize = new Size(imageSize.height * bounds.width / bounds.height, imageSize.height);
destinationSize = bounds;
sourceSize = new Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height);
destinationSize = outputSize;
break;
case ImageFit.none:
sourceSize = new Size(math.min(imageSize.width, bounds.width),
math.min(imageSize.height, bounds.height));
sourceSize = new Size(math.min(inputSize.width, outputSize.width),
math.min(inputSize.height, outputSize.height));
destinationSize = sourceSize;
break;
case ImageFit.scaleDown:
sourceSize = imageSize;
destinationSize = bounds;
sourceSize = inputSize;
destinationSize = outputSize;
if (sourceSize.height > destinationSize.height)
destinationSize = new Size(sourceSize.width * destinationSize.height / sourceSize.height, sourceSize.height);
if (sourceSize.width > destinationSize.width)
destinationSize = new Size(destinationSize.width, sourceSize.height * destinationSize.width / sourceSize.width);
break;
}
if (centerSlice != null) {
outputSize += sliceBorder;
destinationSize += sliceBorder;
// We don't have the ability to draw a subset of the image at the same time
// as we apply a nine-patch stretch.
assert(sourceSize == inputSize);
}
// TODO(abarth): Implement |repeat|.
Paint paint = new Paint()..isAntiAlias = false;
if (colorFilter != null)
paint.colorFilter = colorFilter;
double dx = (bounds.width - destinationSize.width) * positionX;
double dy = (bounds.height - destinationSize.height) * positionY;
double dx = (outputSize.width - destinationSize.width) * positionX;
double dy = (outputSize.height - destinationSize.height) * positionY;
Point destinationPosition = rect.topLeft + new Offset(dx, dy);
canvas.drawImageRect(image, Point.origin & sourceSize, destinationPosition & destinationSize, paint);
Rect destinationRect = destinationPosition & destinationSize;
if (centerSlice == null)
canvas.drawImageRect(image, Point.origin & sourceSize, destinationRect, paint);
else
canvas.drawImageNine(image, centerSlice, destinationRect, paint);
}
typedef void BackgroundImageChangeListener();
/// A background image for a box
/// A background image for a box.
class BackgroundImage {
/// How the background image should be inscribed into the box
/// How the background image should be inscribed into the box.
final ImageFit fit;
/// How to paint any portions of the box not covered by the background image
/// How to paint any portions of the box not covered by the background image.
final ImageRepeat repeat;
/// A color filter to apply to the background image before painting it
/// The center slice for a nine-patch image.
///
/// The region of the image inside the center slice will be stretched both
/// horizontally and vertically to fit the image into its destination. The
/// region of the image above and below the center slice will be stretched
/// only horizontally and the region of the image to the left and right of
/// the center slice will be stretched only vertically.
final Rect centerSlice;
/// A color filter to apply to the background image before painting it.
final ui.ColorFilter colorFilter;
BackgroundImage({
ImageResource image,
this.fit: ImageFit.scaleDown,
this.fit,
this.repeat: ImageRepeat.noRepeat,
this.centerSlice,
this.colorFilter
}) : _imageResource = image;
ui.Image _image;
/// The image to be painted into the background
/// The image to be painted into the background.
ui.Image get image => _image;
ui.Image _image;
ImageResource _imageResource;
final List<BackgroundImageChangeListener> _listeners =
new List<BackgroundImageChangeListener>();
/// Call listener when the background images changes (e.g., arrives from the network)
/// Call listener when the background images changes (e.g., arrives from the network).
void addChangeListener(BackgroundImageChangeListener listener) {
// We add the listener to the _imageResource first so that the first change
// listener doesn't get callback synchronously if the image resource is
......@@ -507,7 +544,7 @@ class BackgroundImage {
_listeners.add(listener);
}
/// No longer call listener when the background image changes
/// No longer call listener when the background image changes.
void removeChangeListener(BackgroundImageChangeListener listener) {
_listeners.remove(listener);
// We need to remove ourselves as listeners from the _imageResource so that
......
......@@ -633,7 +633,7 @@ abstract class RenderBox extends RenderObject {
}
}
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: $size\n';
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${ hasSize ? size : "MISSING" }\n';
}
/// A mixin that provides useful default behaviors for boxes with children
......
......@@ -9,7 +9,7 @@ import 'package:flutter/painting.dart';
import 'box.dart';
import 'object.dart';
/// An image in the render tree
/// An image in the render tree.
///
/// The render image attempts to find a size for itself that fits in the given
/// constraints and preserves the image's intrinisc aspect ratio.
......@@ -19,18 +19,20 @@ class RenderImage extends RenderBox {
double width,
double height,
ui.ColorFilter colorFilter,
fit: ImageFit.scaleDown,
repeat: ImageRepeat.noRepeat
ImageFit fit,
repeat: ImageRepeat.noRepeat,
Rect centerSlice
}) : _image = image,
_width = width,
_height = height,
_colorFilter = colorFilter,
_fit = fit,
_repeat = repeat;
_repeat = repeat,
_centerSlice = centerSlice;
ui.Image _image;
/// The image to display
/// The image to display.
ui.Image get image => _image;
ui.Image _image;
void set image (ui.Image value) {
if (value == _image)
return;
......@@ -40,9 +42,9 @@ class RenderImage extends RenderBox {
markNeedsLayout();
}
double _width;
/// If non-null, requires the image to have this width
/// If non-null, requires the image to have this width.
double get width => _width;
double _width;
void set width (double value) {
if (value == _width)
return;
......@@ -50,9 +52,9 @@ class RenderImage extends RenderBox {
markNeedsLayout();
}
double _height;
/// If non-null, requires the image to have this height
/// If non-null, requires the image to have this height.
double get height => _height;
double _height;
void set height (double value) {
if (value == _height)
return;
......@@ -60,9 +62,9 @@ class RenderImage extends RenderBox {
markNeedsLayout();
}
ui.ColorFilter _colorFilter;
/// If non-null, apply this color filter to the image before painint.
ui.ColorFilter get colorFilter => _colorFilter;
ui.ColorFilter _colorFilter;
void set colorFilter (ui.ColorFilter value) {
if (value == _colorFilter)
return;
......@@ -70,9 +72,9 @@ class RenderImage extends RenderBox {
markNeedsPaint();
}
ImageFit _fit;
/// How to inscribe the image into the place allocated during layout
/// How to inscribe the image into the place allocated during layout.
ImageFit get fit => _fit;
ImageFit _fit;
void set fit (ImageFit value) {
if (value == _fit)
return;
......@@ -80,9 +82,9 @@ class RenderImage extends RenderBox {
markNeedsPaint();
}
ImageRepeat _repeat;
/// Not yet implemented
/// Not yet implemented.
ImageRepeat get repeat => _repeat;
ImageRepeat _repeat;
void set repeat (ImageRepeat value) {
if (value == _repeat)
return;
......@@ -90,7 +92,23 @@ class RenderImage extends RenderBox {
markNeedsPaint();
}
/// Find a size for the render image within the given constraints
/// The center slice for a nine-patch image.
///
/// The region of the image inside the center slice will be stretched both
/// horizontally and vertically to fit the image into its destination. The
/// region of the image above and below the center slice will be stretched
/// only horizontally and the region of the image to the left and right of
/// the center slice will be stretched only vertically.
Rect get centerSlice => _centerSlice;
Rect _centerSlice;
void set centerSlice (Rect value) {
if (value == _centerSlice)
return;
_centerSlice = value;
markNeedsPaint();
}
/// Find a size for the render image within the given constraints.
///
/// - The dimensions of the RenderImage must fit within the constraints.
/// - The aspect ratio of the RenderImage matches the instrinsic aspect
......@@ -170,6 +188,7 @@ class RenderImage extends RenderBox {
image: _image,
colorFilter: _colorFilter,
fit: _fit,
centerSlice: _centerSlice,
repeat: _repeat
);
}
......
......@@ -809,8 +809,9 @@ class Image extends LeafRenderObjectWidget {
this.width,
this.height,
this.colorFilter,
this.fit: ImageFit.scaleDown,
this.repeat: ImageRepeat.noRepeat
this.fit,
this.repeat: ImageRepeat.noRepeat,
this.centerSlice
}) : super(key: key);
final ui.Image image;
......@@ -819,6 +820,7 @@ class Image extends LeafRenderObjectWidget {
final ui.ColorFilter colorFilter;
final ImageFit fit;
final ImageRepeat repeat;
final Rect centerSlice;
RenderImage createRenderObject() => new RenderImage(
image: image,
......@@ -826,7 +828,8 @@ class Image extends LeafRenderObjectWidget {
height: height,
colorFilter: colorFilter,
fit: fit,
repeat: repeat);
repeat: repeat,
centerSlice: centerSlice);
void updateRenderObject(RenderImage renderObject, Image oldWidget) {
renderObject.image = image;
......@@ -835,6 +838,7 @@ class Image extends LeafRenderObjectWidget {
renderObject.colorFilter = colorFilter;
renderObject.fit = fit;
renderObject.repeat = repeat;
renderObject.centerSlice = centerSlice;
}
}
......@@ -845,8 +849,9 @@ class ImageListener extends StatefulComponent {
this.width,
this.height,
this.colorFilter,
this.fit: ImageFit.scaleDown,
this.repeat: ImageRepeat.noRepeat
this.fit,
this.repeat: ImageRepeat.noRepeat,
this.centerSlice
}) : super(key: key) {
assert(image != null);
}
......@@ -857,6 +862,7 @@ class ImageListener extends StatefulComponent {
final ui.ColorFilter colorFilter;
final ImageFit fit;
final ImageRepeat repeat;
final Rect centerSlice;
_ImageListenerState createState() => new _ImageListenerState();
}
......@@ -894,7 +900,8 @@ class _ImageListenerState extends State<ImageListener> {
height: config.height,
colorFilter: config.colorFilter,
fit: config.fit,
repeat: config.repeat
repeat: config.repeat,
centerSlice: config.centerSlice
);
}
}
......@@ -906,8 +913,9 @@ class NetworkImage extends StatelessComponent {
this.width,
this.height,
this.colorFilter,
this.fit: ImageFit.scaleDown,
this.repeat: ImageRepeat.noRepeat
this.fit,
this.repeat: ImageRepeat.noRepeat,
this.centerSlice
}) : super(key: key);
final String src;
......@@ -916,6 +924,7 @@ class NetworkImage extends StatelessComponent {
final ui.ColorFilter colorFilter;
final ImageFit fit;
final ImageRepeat repeat;
final Rect centerSlice;
Widget build(BuildContext context) {
return new ImageListener(
......@@ -924,7 +933,8 @@ class NetworkImage extends StatelessComponent {
height: height,
colorFilter: colorFilter,
fit: fit,
repeat: repeat
repeat: repeat,
centerSlice: centerSlice
);
}
}
......@@ -937,8 +947,9 @@ class AssetImage extends StatelessComponent {
this.width,
this.height,
this.colorFilter,
this.fit: ImageFit.scaleDown,
this.repeat: ImageRepeat.noRepeat
this.fit,
this.repeat: ImageRepeat.noRepeat,
this.centerSlice
}) : super(key: key);
final String name;
......@@ -948,6 +959,7 @@ class AssetImage extends StatelessComponent {
final ui.ColorFilter colorFilter;
final ImageFit fit;
final ImageRepeat repeat;
final Rect centerSlice;
Widget build(BuildContext context) {
return new ImageListener(
......@@ -956,11 +968,28 @@ class AssetImage extends StatelessComponent {
height: height,
colorFilter: colorFilter,
fit: fit,
repeat: repeat
repeat: repeat,
centerSlice: centerSlice
);
}
}
class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
WidgetToRenderBoxAdapter(RenderBox renderBox)
: renderBox = renderBox,
// WidgetToRenderBoxAdapter objects are keyed to their render box. This
// prevents the widget being used in the widget hierarchy in two different
// places, which would cause the RenderBox to get inserted in multiple
// places in the RenderObject tree.
super(key: new GlobalObjectKey(renderBox)) {
assert(renderBox != null);
}
final RenderBox renderBox;
RenderBox createRenderObject() => renderBox;
}
// EVENT HANDLING
......
part of skysprites;
/// Labels are used to display a string of text in a the node tree. To align
/// the label, the textAlign property of teh [TextStyle] can be set.
/// the label, the textAlign property of the [TextStyle] can be set.
class Label extends Node {
/// Creates a new Label with the provided [_text] and [_textStyle].
Label(this._text, [this._textStyle]) {
......
name: skysprites
name: flutter_sprites
description: A sprite toolkit built on top of Flutter
version: 0.0.1
version: 0.0.2
author: Flutter Authors <flutter-dev@googlegroups.com>
homepage: http://flutter.io
dependencies:
flutter: ">=0.0.3 <0.1.0"
sky_tools: ">=0.0.18 <0.1.0"
box2d: any
dependency_overrides:
flutter:
path: ../sky/packages/sky
box2d: ">=0.2.0 <0.3.0"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment