Hixie 74575775bd Introduce an explicit Key type.
This fixes some theoretical bugs whereby we were using hashCode to try
to get unique keys for objects, but really we wanted object identity.
It also lays the groundwork for a new GlobalKey concept.

I tried to keep the impact on the code minimal, which is why the "Key"
constructor is actually a factory that returns a StringKey. The code
has this class hierarchy:

```
   KeyBase
    |
   Key--------------+---------------+
    |               |               |
   StringKey    ObjectKey       UniqueKey
```

...where the constructors are Key and Key.stringify (StringKey),
Key.fromObjectIdentity (ObjectKey), and Key.unique (UniqueKey).

We could instead of factory methods use regular constructors with the
following hierarchy:

```
   KeyBase
    |
   LocalKey---------+---------------+
    |               |               |
   Key      ObjectIdentityKey   UniqueKey
```

...with constructors Key, Key.stringify, ObjectIdentityKey, and
UniqueKey, but I felt that that was maybe a more confusing hierarchy.
I don't have a strong opinion on this.
2015-07-22 09:14:06 -07:00

72 lines
2.5 KiB
Dart

// 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 'dart:sky' as sky;
import 'package:sky/painting/shadows.dart';
import 'package:sky/rendering/box.dart';
import 'package:sky/theme/shadows.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/toggleable.dart';
export 'package:sky/widgets/toggleable.dart' show ValueChanged;
const sky.Color _kThumbOffColor = const sky.Color(0xFFFAFAFA);
const sky.Color _kTrackOffColor = const sky.Color(0x42000000);
const double _kSwitchWidth = 35.0;
const double _kThumbRadius = 10.0;
const double _kSwitchHeight = _kThumbRadius * 2.0;
const double _kTrackHeight = 14.0;
const double _kTrackRadius = _kTrackHeight / 2.0;
const double _kTrackWidth = _kSwitchWidth - (_kThumbRadius - _kTrackRadius) * 2.0;
class Switch extends Toggleable {
// TODO(jackson): Hit-test the switch so that it can respond to both taps and swipe gestures
Switch({
Key key,
bool value,
ValueChanged onChanged
}) : super(key: key, value: value, onChanged: onChanged);
Size get size => const Size(_kSwitchWidth + 2.0, _kSwitchHeight + 2.0);
void customPaintCallback(sky.Canvas canvas, Size size) {
sky.Color thumbColor = _kThumbOffColor;
sky.Color trackColor = _kTrackOffColor;
if (value) {
thumbColor = Theme.of(this).accentColor;
trackColor = new sky.Color(thumbColor.value & 0x80FFFFFF);
}
// Draw the track rrect
sky.Paint paint = new sky.Paint()..color = trackColor;
paint.setStyle(sky.PaintingStyle.fill);
sky.Rect rect = new sky.Rect.fromLTRB(
0.0,
_kSwitchHeight / 2.0 - _kTrackHeight / 2.0,
_kTrackWidth,
_kSwitchHeight / 2.0 + _kTrackHeight / 2.0
);
sky.RRect rrect = new sky.RRect()..setRectXY(rect, _kTrackRadius, _kTrackRadius);
canvas.drawRRect(rrect, paint);
// Draw the raised thumb with a shadow
paint.color = thumbColor;
var builder = new ShadowDrawLooperBuilder();
for (BoxShadow boxShadow in shadows[1])
builder.addShadow(boxShadow.offset, boxShadow.color, boxShadow.blur);
paint.setDrawLooper(builder.build());
// The thumb contracts slightly during the animation
double inset = 2.0 - (position.value - 0.5).abs() * 2.0;
Point thumbPos = new Point(
_kTrackRadius + position.value * (_kTrackWidth - _kTrackRadius * 2),
_kSwitchHeight / 2.0
);
canvas.drawCircle(thumbPos, _kThumbRadius - inset, paint);
}
}