Resolves #273 New color picker
This commit is contained in:
parent
d8a1d03179
commit
0290cd3a32
@ -37,17 +37,19 @@ class LightEntity extends Entity {
|
|||||||
int get colorTemp => _getIntAttributeValue("color_temp");
|
int get colorTemp => _getIntAttributeValue("color_temp");
|
||||||
double get maxMireds => _getDoubleAttributeValue("max_mireds");
|
double get maxMireds => _getDoubleAttributeValue("max_mireds");
|
||||||
double get minMireds => _getDoubleAttributeValue("min_mireds");
|
double get minMireds => _getDoubleAttributeValue("min_mireds");
|
||||||
Color get color => _getColor();
|
HSVColor get color => _getColor();
|
||||||
bool get isAdditionalControls => ((attributes["supported_features"] != null) && (attributes["supported_features"] != 0));
|
bool get isAdditionalControls => ((attributes["supported_features"] != null) && (attributes["supported_features"] != 0));
|
||||||
List<String> get effectList => getStringListAttributeValue("effect_list");
|
List<String> get effectList => getStringListAttributeValue("effect_list");
|
||||||
|
|
||||||
LightEntity(Map rawData) : super(rawData);
|
LightEntity(Map rawData) : super(rawData);
|
||||||
|
|
||||||
Color _getColor() {
|
HSVColor _getColor() {
|
||||||
List rgb = attributes["rgb_color"];
|
List hs = attributes["hs_color"];
|
||||||
try {
|
try {
|
||||||
if ((rgb != null) && (rgb.length > 0)) {
|
if ((hs != null) && (hs.length > 0)) {
|
||||||
return Color.fromARGB(255, rgb[0], rgb[1], rgb[2]);
|
double sat = hs[1]/100;
|
||||||
|
String ssat = sat.toStringAsFixed(2);
|
||||||
|
return HSVColor.fromAHSV(1.0, hs[0], double.parse(ssat), 1.0);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
87
lib/entity_widgets/common/light_color_picker.dart
Normal file
87
lib/entity_widgets/common/light_color_picker.dart
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
part of '../../main.dart';
|
||||||
|
|
||||||
|
class LightColorPicker extends StatefulWidget {
|
||||||
|
|
||||||
|
final HSVColor color;
|
||||||
|
final onColorSelected;
|
||||||
|
final double hueStep;
|
||||||
|
final double saturationStep;
|
||||||
|
final EdgeInsets padding;
|
||||||
|
|
||||||
|
LightColorPicker({this.color, this.onColorSelected, this.hueStep: 15.0, this.saturationStep: 0.2, this.padding: const EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, 0.0)});
|
||||||
|
|
||||||
|
@override
|
||||||
|
LightColorPickerState createState() => new LightColorPickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LightColorPickerState extends State<LightColorPicker> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Widget> colors = [];
|
||||||
|
Border border;
|
||||||
|
Logger.d("Current colotfor picker: [${widget.color.hue}, ${widget.color.saturation}]");
|
||||||
|
for (double saturation = 1.0; saturation >= (0.0 + widget.saturationStep); saturation = double.parse((saturation - widget.saturationStep).toStringAsFixed(2))) {
|
||||||
|
List<Widget> rowChildren = [];
|
||||||
|
Logger.d("$saturation");
|
||||||
|
for (double hue = 0; hue <= (365 - widget.hueStep);
|
||||||
|
hue += widget.hueStep) {
|
||||||
|
if (widget.color.hue.round() >= hue && widget.color.hue.round() < (hue+widget.hueStep) && widget.color.saturation == saturation) {
|
||||||
|
border = Border.all(
|
||||||
|
width: 2.0,
|
||||||
|
color: Colors.white,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
border = null;
|
||||||
|
}
|
||||||
|
HSVColor currentColor = HSVColor.fromAHSV(1.0, hue, double.parse(saturation.toStringAsFixed(2)), 1.0);
|
||||||
|
rowChildren.add(
|
||||||
|
Flexible(
|
||||||
|
child: GestureDetector(
|
||||||
|
child: Container(
|
||||||
|
height: 40.0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: currentColor.toColor(),
|
||||||
|
border: border,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () => widget.onColorSelected(currentColor),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
colors.add(
|
||||||
|
Row(
|
||||||
|
children: rowChildren,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
colors.add(
|
||||||
|
Flexible(
|
||||||
|
child: GestureDetector(
|
||||||
|
child: Container(
|
||||||
|
height: 40.0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () => widget.onColorSelected(HSVColor.fromAHSV(1.0, 30.0, 0.0, 1.0)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Padding(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: colors,
|
||||||
|
),
|
||||||
|
padding: widget.padding,
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -7,8 +7,8 @@ class ModeSelectorWidget extends StatelessWidget {
|
|||||||
final String value;
|
final String value;
|
||||||
final double captionFontSize;
|
final double captionFontSize;
|
||||||
final double valueFontSize;
|
final double valueFontSize;
|
||||||
final double bottomPadding;
|
|
||||||
final onChange;
|
final onChange;
|
||||||
|
final EdgeInsets padding;
|
||||||
|
|
||||||
ModeSelectorWidget({
|
ModeSelectorWidget({
|
||||||
Key key,
|
Key key,
|
||||||
@ -18,12 +18,14 @@ class ModeSelectorWidget extends StatelessWidget {
|
|||||||
@required this.onChange,
|
@required this.onChange,
|
||||||
this.captionFontSize,
|
this.captionFontSize,
|
||||||
this.valueFontSize,
|
this.valueFontSize,
|
||||||
this.bottomPadding
|
this.padding: const EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, 0.0),
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Padding(
|
||||||
|
padding: padding,
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text("$caption", style: TextStyle(
|
Text("$caption", style: TextStyle(
|
||||||
@ -54,9 +56,9 @@ class ModeSelectorWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
)
|
||||||
Container(height: bottomPadding ?? Sizes.rowPadding,)
|
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,8 +10,9 @@ class UniversalSlider extends StatelessWidget {
|
|||||||
final double min;
|
final double min;
|
||||||
final double max;
|
final double max;
|
||||||
final double value;
|
final double value;
|
||||||
|
final EdgeInsets padding;
|
||||||
|
|
||||||
const UniversalSlider({Key key, this.onChanged, this.onChangeEnd, this.leading, this.closing, this.title, this.min, this.max, this.value}) : super(key: key);
|
const UniversalSlider({Key key, this.onChanged, this.onChangeEnd, this.leading, this.closing, this.title, this.min, this.max, this.value, this.padding: const EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, 0.0)}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -33,7 +34,9 @@ class UniversalSlider extends StatelessWidget {
|
|||||||
if (closing != null) {
|
if (closing != null) {
|
||||||
row.add(closing);
|
row.add(closing);
|
||||||
}
|
}
|
||||||
return Column(
|
return Padding(
|
||||||
|
padding: padding,
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(height: Sizes.rowPadding,),
|
Container(height: Sizes.rowPadding,),
|
||||||
@ -48,6 +51,7 @@ class UniversalSlider extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Container(height: Sizes.rowPadding,)
|
Container(height: Sizes.rowPadding,)
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
|||||||
|
|
||||||
int _tmpBrightness;
|
int _tmpBrightness;
|
||||||
int _tmpColorTemp = 0;
|
int _tmpColorTemp = 0;
|
||||||
Color _tmpColor = Colors.white;
|
HSVColor _tmpColor = HSVColor.fromAHSV(1.0, 30.0, 0.0, 1.0);
|
||||||
bool _changedHere = false;
|
bool _changedHere = false;
|
||||||
String _tmpEffect;
|
String _tmpEffect;
|
||||||
|
|
||||||
@ -48,20 +48,14 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setColor(LightEntity entity, Color color) {
|
void _setColor(LightEntity entity, HSVColor color) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_tmpColor = color;
|
_tmpColor = color;
|
||||||
_changedHere = true;
|
_changedHere = true;
|
||||||
Logger.d( "Color: [${color.red}, ${color.green}, ${color.blue}]");
|
Logger.d( "HS Color: [${color.hue}, ${color.saturation}]");
|
||||||
if ((color == Colors.black) || ((color.red == color.green) && (color.green == color.blue))) {
|
|
||||||
eventBus.fire(new ServiceCallEvent(
|
|
||||||
entity.domain, "turn_off", entity.entityId,
|
|
||||||
null));
|
|
||||||
} else {
|
|
||||||
eventBus.fire(new ServiceCallEvent(
|
eventBus.fire(new ServiceCallEvent(
|
||||||
entity.domain, "turn_on", entity.entityId,
|
entity.domain, "turn_on", entity.entityId,
|
||||||
{"rgb_color": [color.red, color.green, color.blue]}));
|
{"hs_color": [color.hue, color.saturation*100]}));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,25 +136,9 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
|||||||
|
|
||||||
Widget _buildColorControl(LightEntity entity) {
|
Widget _buildColorControl(LightEntity entity) {
|
||||||
if (entity.supportColor) {
|
if (entity.supportColor) {
|
||||||
return Column(
|
return LightColorPicker(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
color: _tmpColor,
|
||||||
children: <Widget>[
|
onColorSelected: (color) => _setColor(entity, color),
|
||||||
Container(height: Sizes.rowPadding,),
|
|
||||||
RaisedButton(
|
|
||||||
onPressed: () => _showColorPicker(entity),
|
|
||||||
color: _tmpColor ?? Colors.black45,
|
|
||||||
child: Text(
|
|
||||||
"COLOR",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 50.0,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.black12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(height: 2*Sizes.rowPadding,),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(width: 0.0, height: 0.0);
|
return Container(width: 0.0, height: 0.0);
|
||||||
@ -174,15 +152,8 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
|||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
titlePadding: EdgeInsets.all(0.0),
|
titlePadding: EdgeInsets.all(0.0),
|
||||||
contentPadding: EdgeInsets.all(0.0),
|
contentPadding: EdgeInsets.all(0.0),
|
||||||
content: SingleChildScrollView(
|
content: LightColorPicker(
|
||||||
child: MaterialPicker(
|
color: _tmpColor,
|
||||||
pickerColor: _tmpColor,
|
|
||||||
onColorChanged: (color) {
|
|
||||||
_setColor(entity, color);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
enableLabel: true,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -12,7 +12,6 @@ import 'package:url_launcher/url_launcher.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:date_format/date_format.dart';
|
import 'package:date_format/date_format.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter_colorpicker/material_picker.dart';
|
|
||||||
import 'package:charts_flutter/flutter.dart' as charts;
|
import 'package:charts_flutter/flutter.dart' as charts;
|
||||||
import 'package:progress_indicators/progress_indicators.dart';
|
import 'package:progress_indicators/progress_indicators.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
@ -50,6 +49,7 @@ part 'entity_widgets/common/mode_swicth.dart';
|
|||||||
part 'entity_widgets/common/mode_selector.dart';
|
part 'entity_widgets/common/mode_selector.dart';
|
||||||
part 'entity_widgets/common/universal_slider.dart';
|
part 'entity_widgets/common/universal_slider.dart';
|
||||||
part 'entity_widgets/common/flat_service_button.dart';
|
part 'entity_widgets/common/flat_service_button.dart';
|
||||||
|
part 'entity_widgets/common/light_color_picker.dart';
|
||||||
part 'entity_widgets/entity_colors.class.dart';
|
part 'entity_widgets/entity_colors.class.dart';
|
||||||
part 'entity_widgets/entity_page_container.dart';
|
part 'entity_widgets/entity_page_container.dart';
|
||||||
part 'entity_widgets/history_chart/entity_history.dart';
|
part 'entity_widgets/history_chart/entity_history.dart';
|
||||||
|
15
pubspec.lock
15
pubspec.lock
@ -112,14 +112,7 @@ packages:
|
|||||||
name: flutter_cache_manager
|
name: flutter_cache_manager
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0-alpha.2"
|
version: "0.3.0-beta.2+1"
|
||||||
flutter_colorpicker:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_colorpicker
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.1"
|
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -159,7 +152,7 @@ packages:
|
|||||||
name: image
|
name: image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.0.7"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -236,7 +229,7 @@ packages:
|
|||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.1+1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -311,7 +304,7 @@ packages:
|
|||||||
name: url_launcher
|
name: url_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "5.0.1"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,6 @@ dependencies:
|
|||||||
cached_network_image: any
|
cached_network_image: any
|
||||||
url_launcher: any
|
url_launcher: any
|
||||||
date_format: any
|
date_format: any
|
||||||
flutter_colorpicker: any
|
|
||||||
charts_flutter: any
|
charts_flutter: any
|
||||||
flutter_markdown: any
|
flutter_markdown: any
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user