Resolves #154 UI building refactoring
This commit is contained in:
@ -1,562 +0,0 @@
|
||||
part of '../main.dart';
|
||||
|
||||
class Entity {
|
||||
static const STATE_ICONS_COLORS = {
|
||||
"on": Colors.amber,
|
||||
"off": Color.fromRGBO(68, 115, 158, 1.0),
|
||||
"default": Color.fromRGBO(68, 115, 158, 1.0),
|
||||
"unavailable": Colors.black12,
|
||||
"unknown": Colors.black12,
|
||||
"playing": Colors.amber
|
||||
};
|
||||
static const badgeColors = {
|
||||
"default": Color.fromRGBO(223, 76, 30, 1.0),
|
||||
"binary_sensor": Color.fromRGBO(3, 155, 229, 1.0)
|
||||
};
|
||||
static List badgeDomains = [
|
||||
"alarm_control_panel",
|
||||
"binary_sensor",
|
||||
"device_tracker",
|
||||
"updater",
|
||||
"sun",
|
||||
"timer",
|
||||
"sensor"
|
||||
];
|
||||
|
||||
static const rightWidgetPadding = 14.0;
|
||||
static const leftWidgetPadding = 8.0;
|
||||
static const extendedWidgetHeight = 50.0;
|
||||
static const iconSize = 28.0;
|
||||
static const stateFontSize = 16.0;
|
||||
static const nameFontSize = 16.0;
|
||||
static const smallFontSize = 14.0;
|
||||
static const largeFontSize = 24.0;
|
||||
static const inputWidth = 160.0;
|
||||
static const rowPadding = 10.0;
|
||||
|
||||
double widgetHeight = 34.0;
|
||||
|
||||
Map attributes;
|
||||
String domain;
|
||||
String entityId;
|
||||
String state;
|
||||
String assumedState;
|
||||
DateTime _lastUpdated;
|
||||
|
||||
List<Entity> childEntities = [];
|
||||
|
||||
List<String> attributesToShow = ["all"];
|
||||
|
||||
String get displayName =>
|
||||
attributes["friendly_name"] ?? (attributes["name"] ?? "_");
|
||||
|
||||
String get deviceClass => attributes["device_class"] ?? null;
|
||||
bool get isView =>
|
||||
(domain == "group") &&
|
||||
(attributes != null ? attributes["view"] ?? false : false);
|
||||
bool get isGroup => domain == "group";
|
||||
bool get isBadge => Entity.badgeDomains.contains(domain);
|
||||
String get icon => attributes["icon"] ?? "";
|
||||
bool get isOn => state == "on";
|
||||
String get entityPicture => attributes["entity_picture"];
|
||||
String get unitOfMeasurement => attributes["unit_of_measurement"] ?? "";
|
||||
List get childEntityIds => attributes["entity_id"] ?? [];
|
||||
String get lastUpdated => _getLastUpdatedFormatted();
|
||||
bool get isHidden => attributes["hidden"] ?? false;
|
||||
|
||||
Entity(Map rawData) {
|
||||
update(rawData);
|
||||
}
|
||||
|
||||
void update(Map rawData) {
|
||||
attributes = rawData["attributes"] ?? {};
|
||||
domain = rawData["entity_id"].split(".")[0];
|
||||
entityId = rawData["entity_id"];
|
||||
state = rawData["state"];
|
||||
assumedState = state;
|
||||
_lastUpdated = DateTime.tryParse(rawData["last_updated"]);
|
||||
}
|
||||
|
||||
double _getDoubleAttributeValue(String attributeName) {
|
||||
var temp1 = attributes["$attributeName"];
|
||||
if (temp1 is int) {
|
||||
return temp1.toDouble();
|
||||
} else if (temp1 is double) {
|
||||
return temp1;
|
||||
} else {
|
||||
return double.tryParse("$temp1");
|
||||
}
|
||||
}
|
||||
|
||||
int _getIntAttributeValue(String attributeName) {
|
||||
var temp1 = attributes["$attributeName"];
|
||||
if (temp1 is int) {
|
||||
return temp1;
|
||||
} else if (temp1 is double) {
|
||||
return temp1.round();
|
||||
} else {
|
||||
return int.tryParse("$temp1");
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildDefaultWidget(BuildContext context) {
|
||||
return EntityModel(
|
||||
entity: this,
|
||||
child: DefaultEntityContainer(
|
||||
state: _buildStatePart(context),
|
||||
height: widgetHeight,
|
||||
),
|
||||
handleTap: true,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return SimpleEntityState();
|
||||
}
|
||||
|
||||
Widget _buildStatePartForPage(BuildContext context) {
|
||||
return _buildStatePart(context);
|
||||
}
|
||||
|
||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||
return Container(
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildEntityPageWidget(BuildContext context) {
|
||||
return EntityModel(
|
||||
entity: this,
|
||||
child: EntityPageContainer(children: <Widget>[
|
||||
DefaultEntityContainer(state: _buildStatePartForPage(context), height: widgetHeight),
|
||||
LastUpdatedWidget(),
|
||||
Divider(),
|
||||
_buildAdditionalControlsForPage(context),
|
||||
Divider(),
|
||||
EntityAttributesList()
|
||||
]),
|
||||
handleTap: false,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBadgeWidget(BuildContext context) {
|
||||
return EntityModel(
|
||||
entity: this,
|
||||
child: Badge(),
|
||||
handleTap: true,
|
||||
);
|
||||
}
|
||||
|
||||
String getAttribute(String attributeName) {
|
||||
if (attributes != null) {
|
||||
return attributes["$attributeName"];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String _getLastUpdatedFormatted() {
|
||||
if (_lastUpdated == null) {
|
||||
return "-";
|
||||
} else {
|
||||
DateTime now = DateTime.now();
|
||||
Duration d = now.difference(_lastUpdated);
|
||||
String text;
|
||||
int v;
|
||||
if (d.inDays == 0) {
|
||||
if (d.inHours == 0) {
|
||||
if (d.inMinutes == 0) {
|
||||
text = "seconds ago";
|
||||
v = d.inSeconds;
|
||||
} else {
|
||||
text = "minutes ago";
|
||||
v = d.inMinutes;
|
||||
}
|
||||
} else {
|
||||
text = "hours ago";
|
||||
v = d.inHours;
|
||||
}
|
||||
} else {
|
||||
text = "days ago";
|
||||
v = d.inDays;
|
||||
}
|
||||
return "$v $text";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchEntity extends Entity {
|
||||
SwitchEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return SwitchStateWidget();
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonEntity extends Entity {
|
||||
ButtonEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return ButtonStateWidget();
|
||||
}
|
||||
}
|
||||
|
||||
class TextEntity extends Entity {
|
||||
TextEntity(Map rawData) : super(rawData);
|
||||
|
||||
int get valueMinLength => attributes["min"] ?? -1;
|
||||
int get valueMaxLength => attributes["max"] ?? -1;
|
||||
String get valuePattern => attributes["pattern"] ?? null;
|
||||
bool get isTextField => attributes["mode"] == "text";
|
||||
bool get isPasswordField => attributes["mode"] == "password";
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return TextInputStateWidget();
|
||||
}
|
||||
}
|
||||
|
||||
class SunEntity extends Entity {
|
||||
SunEntity(Map rawData) : super(rawData);
|
||||
}
|
||||
|
||||
class SliderEntity extends Entity {
|
||||
SliderEntity(Map rawData) : super(rawData);
|
||||
|
||||
double get minValue => attributes["min"] ?? 0.0;
|
||||
double get maxValue => attributes["max"] ?? 100.0;
|
||||
double get valueStep => attributes["step"] ?? 1.0;
|
||||
double get doubleState => double.tryParse(state) ?? 0.0;
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return Expanded(
|
||||
//width: 200.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
SliderStateWidget(
|
||||
expanded: true,
|
||||
),
|
||||
SimpleEntityState(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildStatePartForPage(BuildContext context) {
|
||||
return SimpleEntityState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||
return SliderStateWidget(
|
||||
expanded: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ClimateEntity extends Entity {
|
||||
@override
|
||||
double widgetHeight = 38.0;
|
||||
|
||||
static const SUPPORT_TARGET_TEMPERATURE = 1;
|
||||
static const SUPPORT_TARGET_TEMPERATURE_HIGH = 2;
|
||||
static const SUPPORT_TARGET_TEMPERATURE_LOW = 4;
|
||||
static const SUPPORT_TARGET_HUMIDITY = 8;
|
||||
static const SUPPORT_TARGET_HUMIDITY_HIGH = 16;
|
||||
static const SUPPORT_TARGET_HUMIDITY_LOW = 32;
|
||||
static const SUPPORT_FAN_MODE = 64;
|
||||
static const SUPPORT_OPERATION_MODE = 128;
|
||||
static const SUPPORT_HOLD_MODE = 256;
|
||||
static const SUPPORT_SWING_MODE = 512;
|
||||
static const SUPPORT_AWAY_MODE = 1024;
|
||||
static const SUPPORT_AUX_HEAT = 2048;
|
||||
static const SUPPORT_ON_OFF = 4096;
|
||||
|
||||
bool get supportTargetTemperature => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE) ==
|
||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE);
|
||||
bool get supportTargetTemperatureHigh => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_HIGH) ==
|
||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_HIGH);
|
||||
bool get supportTargetTemperatureLow => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_LOW) ==
|
||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_LOW);
|
||||
bool get supportTargetHumidity => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY) ==
|
||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY);
|
||||
bool get supportTargetHumidityHigh => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_HIGH) ==
|
||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_HIGH);
|
||||
bool get supportTargetHumidityLow => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_LOW) ==
|
||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_LOW);
|
||||
bool get supportFanMode =>
|
||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_FAN_MODE) ==
|
||||
ClimateEntity.SUPPORT_FAN_MODE);
|
||||
bool get supportOperationMode => ((attributes["supported_features"] &
|
||||
ClimateEntity.SUPPORT_OPERATION_MODE) ==
|
||||
ClimateEntity.SUPPORT_OPERATION_MODE);
|
||||
bool get supportHoldMode =>
|
||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_HOLD_MODE) ==
|
||||
ClimateEntity.SUPPORT_HOLD_MODE);
|
||||
bool get supportSwingMode =>
|
||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_SWING_MODE) ==
|
||||
ClimateEntity.SUPPORT_SWING_MODE);
|
||||
bool get supportAwayMode =>
|
||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_AWAY_MODE) ==
|
||||
ClimateEntity.SUPPORT_AWAY_MODE);
|
||||
bool get supportAuxHeat =>
|
||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_AUX_HEAT) ==
|
||||
ClimateEntity.SUPPORT_AUX_HEAT);
|
||||
bool get supportOnOff =>
|
||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_ON_OFF) ==
|
||||
ClimateEntity.SUPPORT_ON_OFF);
|
||||
|
||||
List<String> get operationList => attributes["operation_list"] != null
|
||||
? (attributes["operation_list"] as List).cast<String>()
|
||||
: null;
|
||||
List<String> get fanList => attributes["fan_list"] != null
|
||||
? (attributes["fan_list"] as List).cast<String>()
|
||||
: null;
|
||||
List<String> get swingList => attributes["swing_list"] != null
|
||||
? (attributes["swing_list"] as List).cast<String>()
|
||||
: null;
|
||||
double get temperature => _getDoubleAttributeValue('temperature');
|
||||
double get targetHigh => _getDoubleAttributeValue('target_temp_high');
|
||||
double get targetLow => _getDoubleAttributeValue('target_temp_low');
|
||||
double get maxTemp => _getDoubleAttributeValue('max_temp') ?? 100.0;
|
||||
double get minTemp => _getDoubleAttributeValue('min_temp') ?? -100.0;
|
||||
double get targetHumidity => _getDoubleAttributeValue('humidity');
|
||||
double get maxHumidity => _getDoubleAttributeValue('max_humidity');
|
||||
double get minHumidity => _getDoubleAttributeValue('min_humidity');
|
||||
String get operationMode => attributes['operation_mode'];
|
||||
String get fanMode => attributes['fan_mode'];
|
||||
String get swingMode => attributes['swing_mode'];
|
||||
bool get awayMode => attributes['away_mode'] == "on";
|
||||
bool get isOff => state == "off";
|
||||
bool get auxHeat => attributes['aux_heat'] == "on";
|
||||
|
||||
ClimateEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return ClimateStateWidget();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||
return ClimateControlWidget();
|
||||
}
|
||||
|
||||
@override
|
||||
double _getDoubleAttributeValue(String attributeName) {
|
||||
var temp1 = attributes["$attributeName"];
|
||||
if (temp1 is int) {
|
||||
return temp1.toDouble();
|
||||
} else if (temp1 is double) {
|
||||
return temp1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SelectEntity extends Entity {
|
||||
List<String> get listOptions => attributes["options"] != null
|
||||
? (attributes["options"] as List).cast<String>()
|
||||
: [];
|
||||
|
||||
SelectEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return SelectControlWidget();
|
||||
}
|
||||
}
|
||||
|
||||
class DateTimeEntity extends Entity {
|
||||
bool get hasDate => attributes["has_date"] ?? false;
|
||||
bool get hasTime => attributes["has_time"] ?? false;
|
||||
int get year => attributes["year"] ?? 1970;
|
||||
int get month => attributes["month"] ?? 1;
|
||||
int get day => attributes["day"] ?? 1;
|
||||
int get hour => attributes["hour"] ?? 0;
|
||||
int get minute => attributes["minute"] ?? 0;
|
||||
int get second => attributes["second"] ?? 0;
|
||||
String get formattedState => _getFormattedState();
|
||||
DateTime get dateTimeState => _getDateTimeState();
|
||||
|
||||
DateTimeEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return DateTimeStateWidget();
|
||||
}
|
||||
|
||||
DateTime _getDateTimeState() {
|
||||
return DateTime(
|
||||
this.year, this.month, this.day, this.hour, this.minute, this.second);
|
||||
}
|
||||
|
||||
String _getFormattedState() {
|
||||
String formattedState = "";
|
||||
if (this.hasDate) {
|
||||
formattedState += formatDate(dateTimeState, [M, ' ', d, ', ', yyyy]);
|
||||
}
|
||||
if (this.hasTime) {
|
||||
formattedState += " " + formatDate(dateTimeState, [HH, ':', nn]);
|
||||
}
|
||||
return formattedState;
|
||||
}
|
||||
|
||||
void setNewState(newValue) {
|
||||
eventBus
|
||||
.fire(new ServiceCallEvent(domain, "set_datetime", entityId, newValue));
|
||||
}
|
||||
}
|
||||
|
||||
class CoverEntity extends Entity {
|
||||
@override
|
||||
double widgetHeight = 38.0;
|
||||
|
||||
static const SUPPORT_OPEN = 1;
|
||||
static const SUPPORT_CLOSE = 2;
|
||||
static const SUPPORT_SET_POSITION = 4;
|
||||
static const SUPPORT_STOP = 8;
|
||||
static const SUPPORT_OPEN_TILT = 16;
|
||||
static const SUPPORT_CLOSE_TILT = 32;
|
||||
static const SUPPORT_STOP_TILT = 64;
|
||||
static const SUPPORT_SET_TILT_POSITION = 128;
|
||||
|
||||
bool get supportOpen => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_OPEN) ==
|
||||
CoverEntity.SUPPORT_OPEN);
|
||||
bool get supportClose => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_CLOSE) ==
|
||||
CoverEntity.SUPPORT_CLOSE);
|
||||
bool get supportSetPosition => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_SET_POSITION) ==
|
||||
CoverEntity.SUPPORT_SET_POSITION);
|
||||
bool get supportStop => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_STOP) ==
|
||||
CoverEntity.SUPPORT_STOP);
|
||||
|
||||
bool get supportOpenTilt => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_OPEN_TILT) ==
|
||||
CoverEntity.SUPPORT_OPEN_TILT);
|
||||
bool get supportCloseTilt => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_CLOSE_TILT) ==
|
||||
CoverEntity.SUPPORT_CLOSE_TILT);
|
||||
bool get supportStopTilt => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_STOP_TILT) ==
|
||||
CoverEntity.SUPPORT_STOP_TILT);
|
||||
bool get supportSetTiltPosition => ((attributes["supported_features"] &
|
||||
CoverEntity.SUPPORT_SET_TILT_POSITION) ==
|
||||
CoverEntity.SUPPORT_SET_TILT_POSITION);
|
||||
|
||||
|
||||
double get currentPosition => _getDoubleAttributeValue('current_position');
|
||||
double get currentTiltPosition => _getDoubleAttributeValue('current_tilt_position');
|
||||
bool get canBeOpened => ((state != "opening") && (state != "open"));
|
||||
bool get canBeClosed => ((state != "closing") && (state != "closed"));
|
||||
bool get canTiltBeOpened => currentPosition < 100;
|
||||
bool get canTiltBeClosed => currentPosition > 0;
|
||||
|
||||
CoverEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return CoverEntityControlState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||
return CoverControlWidget();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LightEntity extends Entity {
|
||||
|
||||
static const SUPPORT_BRIGHTNESS = 1;
|
||||
static const SUPPORT_COLOR_TEMP = 2;
|
||||
static const SUPPORT_EFFECT = 4;
|
||||
static const SUPPORT_FLASH = 8;
|
||||
static const SUPPORT_COLOR = 16;
|
||||
static const SUPPORT_TRANSITION = 32;
|
||||
static const SUPPORT_WHITE_VALUE = 128;
|
||||
|
||||
bool get supportBrightness => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_BRIGHTNESS) ==
|
||||
LightEntity.SUPPORT_BRIGHTNESS);
|
||||
bool get supportColorTemp => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_COLOR_TEMP) ==
|
||||
LightEntity.SUPPORT_COLOR_TEMP);
|
||||
bool get supportEffect => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_EFFECT) ==
|
||||
LightEntity.SUPPORT_EFFECT);
|
||||
bool get supportFlash => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_FLASH) ==
|
||||
LightEntity.SUPPORT_FLASH);
|
||||
bool get supportColor => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_COLOR) ==
|
||||
LightEntity.SUPPORT_COLOR);
|
||||
bool get supportTransition => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_TRANSITION) ==
|
||||
LightEntity.SUPPORT_TRANSITION);
|
||||
bool get supportWhiteValue => ((attributes["supported_features"] &
|
||||
LightEntity.SUPPORT_WHITE_VALUE) ==
|
||||
LightEntity.SUPPORT_WHITE_VALUE);
|
||||
|
||||
int get brightness => _getIntAttributeValue("brightness");
|
||||
int get colorTemp => _getIntAttributeValue("color_temp");
|
||||
double get maxMireds => _getDoubleAttributeValue("max_mireds");
|
||||
double get minMireds => _getDoubleAttributeValue("min_mireds");
|
||||
Color get color => _getColor();
|
||||
bool get isAdditionalControls => ((attributes["supported_features"] != null) && (attributes["supported_features"] != 0));
|
||||
List<String> get effectList => _getEffectList();
|
||||
|
||||
LightEntity(Map rawData) : super(rawData);
|
||||
|
||||
Color _getColor() {
|
||||
List rgb = attributes["rgb_color"];
|
||||
try {
|
||||
if ((rgb != null) && (rgb.length > 0)) {
|
||||
return Color.fromARGB(255, rgb[0], rgb[1], rgb[2]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<String> _getEffectList() {
|
||||
if (attributes["effect_list"] != null) {
|
||||
List<String> result = (attributes["effect_list"] as List).cast<String>();
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildStatePart(BuildContext context) {
|
||||
return SwitchStateWidget();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||
if (!isAdditionalControls) {
|
||||
return Container(height: 0.0, width: 0.0);
|
||||
} else {
|
||||
return LightControlsWidget();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,775 +0,0 @@
|
||||
part of '../main.dart';
|
||||
|
||||
class EntityWidgetsSizes {}
|
||||
|
||||
class EntityModel extends InheritedWidget {
|
||||
const EntityModel({
|
||||
Key key,
|
||||
@required this.entity,
|
||||
@required this.handleTap,
|
||||
@required Widget child,
|
||||
}) : super(key: key, child: child);
|
||||
|
||||
final Entity entity;
|
||||
final bool handleTap;
|
||||
|
||||
static EntityModel of(BuildContext context) {
|
||||
return context.inheritFromWidgetOfExactType(EntityModel);
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(InheritedWidget oldWidget) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultEntityContainer extends StatelessWidget {
|
||||
DefaultEntityContainer({
|
||||
Key key,
|
||||
@required this.state,
|
||||
@required this.height
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget state;
|
||||
final double height;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: height,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
EntityIcon(),
|
||||
Expanded(
|
||||
child: EntityName(),
|
||||
),
|
||||
state
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EntityPageContainer extends StatelessWidget {
|
||||
EntityPageContainer({Key key, @required this.children}) : super(key: key);
|
||||
|
||||
final List<Widget> children;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: children,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleEntityState extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
"${entityModel.entity.state}${entityModel.entity.unitOfMeasurement}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
)),
|
||||
onTap: () => entityModel.handleTap
|
||||
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||
: null,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class EntityName extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
return GestureDetector(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 10.0),
|
||||
child: Text(
|
||||
"${entityModel.entity.displayName}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: TextStyle(fontSize: Entity.nameFontSize),
|
||||
),
|
||||
),
|
||||
onTap: () => entityModel.handleTap
|
||||
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EntityIcon extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
return GestureDetector(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Entity.leftWidgetPadding, 0.0, 12.0, 0.0),
|
||||
//TODO: move createIconWidgetFromEntityData into this widget
|
||||
child: MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||
entityModel.entity,
|
||||
Entity.iconSize,
|
||||
Entity.STATE_ICONS_COLORS[entityModel.entity.state] ??
|
||||
Entity.STATE_ICONS_COLORS["default"]),
|
||||
),
|
||||
onTap: () => entityModel.handleTap
|
||||
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LastUpdatedWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Entity.leftWidgetPadding, 0.0, 0.0, 0.0),
|
||||
child: Text(
|
||||
'${entityModel.entity.lastUpdated}',
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: Entity.smallFontSize, color: Colors.black26),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EntityAttributesList extends StatelessWidget {
|
||||
EntityAttributesList({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
List<Widget> attrs = [];
|
||||
if ((entityModel.entity.attributesToShow == null) ||
|
||||
(entityModel.entity.attributesToShow.contains("all"))) {
|
||||
entityModel.entity.attributes.forEach((name, value) {
|
||||
attrs.add(_buildSingleAttribute("$name", "$value"));
|
||||
});
|
||||
} else {
|
||||
entityModel.entity.attributesToShow.forEach((String attr) {
|
||||
String attrValue = entityModel.entity.getAttribute("$attr");
|
||||
if (attrValue != null) {
|
||||
attrs.add(
|
||||
_buildSingleAttribute("$attr", "$attrValue"));
|
||||
}
|
||||
});
|
||||
}
|
||||
return Column(
|
||||
children: attrs,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSingleAttribute(String name, String value) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Entity.leftWidgetPadding, Entity.rowPadding, 0.0, 0.0),
|
||||
child: Text(
|
||||
"$name",
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||
child: Text(
|
||||
"$value",
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Badge extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
double iconSize = 26.0;
|
||||
Widget badgeIcon;
|
||||
String onBadgeTextValue;
|
||||
Color iconColor = Entity.badgeColors[entityModel.entity.domain] ??
|
||||
Entity.badgeColors["default"];
|
||||
switch (entityModel.entity.domain) {
|
||||
case "sun":
|
||||
{
|
||||
badgeIcon = entityModel.entity.state == "below_horizon"
|
||||
? Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconCode(0xf0dc),
|
||||
size: iconSize,
|
||||
)
|
||||
: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconCode(0xf5a8),
|
||||
size: iconSize,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "sensor":
|
||||
{
|
||||
onBadgeTextValue = entityModel.entity.unitOfMeasurement;
|
||||
badgeIcon = Center(
|
||||
child: Text(
|
||||
"${entityModel.entity.state}",
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 17.0),
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "device_tracker":
|
||||
{
|
||||
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||
entityModel.entity, iconSize, Colors.black);
|
||||
onBadgeTextValue = entityModel.entity.state;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||
entityModel.entity, iconSize, Colors.black);
|
||||
}
|
||||
}
|
||||
Widget onBadgeText;
|
||||
if (onBadgeTextValue == null || onBadgeTextValue.length == 0) {
|
||||
onBadgeText = Container(width: 0.0, height: 0.0);
|
||||
} else {
|
||||
onBadgeText = Container(
|
||||
padding: EdgeInsets.fromLTRB(6.0, 2.0, 6.0, 2.0),
|
||||
child: Text("$onBadgeTextValue",
|
||||
style: TextStyle(fontSize: 12.0, color: Colors.white),
|
||||
textAlign: TextAlign.center,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade),
|
||||
decoration: new BoxDecoration(
|
||||
// Circle shape
|
||||
//shape: BoxShape.circle,
|
||||
color: iconColor,
|
||||
borderRadius: BorderRadius.circular(9.0),
|
||||
));
|
||||
}
|
||||
return GestureDetector(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
|
||||
width: 50.0,
|
||||
height: 50.0,
|
||||
decoration: new BoxDecoration(
|
||||
// Circle shape
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.white,
|
||||
// The border you want
|
||||
border: new Border.all(
|
||||
width: 2.0,
|
||||
color: iconColor,
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
overflow: Overflow.visible,
|
||||
children: <Widget>[
|
||||
Positioned(
|
||||
width: 46.0,
|
||||
height: 46.0,
|
||||
top: 0.0,
|
||||
left: 0.0,
|
||||
child: badgeIcon,
|
||||
),
|
||||
Positioned(
|
||||
//width: 50.0,
|
||||
bottom: -9.0,
|
||||
left: -10.0,
|
||||
right: -10.0,
|
||||
child: Center(
|
||||
child: onBadgeText,
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 60.0,
|
||||
child: Text(
|
||||
"${entityModel.entity.displayName}",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 12.0),
|
||||
softWrap: true,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () =>
|
||||
eventBus.fire(new ShowEntityPageEvent(entityModel.entity)));
|
||||
}
|
||||
}
|
||||
|
||||
class ClimateStateWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
final ClimateEntity entity = entityModel.entity;
|
||||
String targetTemp = "-";
|
||||
if ((entity.supportTargetTemperature) && (entity.temperature != null)) {
|
||||
targetTemp = "${entity.temperature}";
|
||||
} else if ((entity.supportTargetTemperatureLow) &&
|
||||
(entity.targetLow != null)) {
|
||||
targetTemp = "${entity.targetLow}";
|
||||
if ((entity.supportTargetTemperatureHigh) &&
|
||||
(entity.targetHigh != null)) {
|
||||
targetTemp += " - ${entity.targetHigh}";
|
||||
}
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||
child: GestureDetector(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text("${entity.state}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: Entity.stateFontSize,
|
||||
)),
|
||||
Text(" $targetTemp",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
))
|
||||
],
|
||||
),
|
||||
entity.attributes["current_temperature"] != null ?
|
||||
Text("Currently: ${entity.attributes["current_temperature"]}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
color: Colors.black45)
|
||||
) :
|
||||
Container(height: 0.0,)
|
||||
],
|
||||
),
|
||||
onTap: () => entityModel.handleTap
|
||||
? eventBus.fire(new ShowEntityPageEvent(entity))
|
||||
: null,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class TemperatureControlWidget extends StatelessWidget {
|
||||
final double value;
|
||||
final double fontSize;
|
||||
final Color fontColor;
|
||||
final onSmallInc;
|
||||
final onLargeInc;
|
||||
final onSmallDec;
|
||||
final onLargeDec;
|
||||
|
||||
TemperatureControlWidget(
|
||||
{Key key,
|
||||
@required this.value,
|
||||
@required this.onSmallInc,
|
||||
@required this.onSmallDec,
|
||||
@required this.onLargeInc,
|
||||
@required this.onLargeDec,
|
||||
this.fontSize,
|
||||
this.fontColor})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"$value",
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? 24.0,
|
||||
color: fontColor ?? Colors.black
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||
'mdi:chevron-up')),
|
||||
iconSize: 30.0,
|
||||
onPressed: () => onSmallInc(),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||
'mdi:chevron-down')),
|
||||
iconSize: 30.0,
|
||||
onPressed: () => onSmallDec(),
|
||||
)
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||
'mdi:chevron-double-up')),
|
||||
iconSize: 30.0,
|
||||
onPressed: () => onLargeInc(),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||
'mdi:chevron-double-down')),
|
||||
iconSize: 30.0,
|
||||
onPressed: () => onLargeDec(),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DateTimeStateWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
final DateTimeEntity entity = entityModel.entity;
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||
child: GestureDetector(
|
||||
child: Text("${entity.formattedState}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
)),
|
||||
onTap: () => _handleStateTap(context, entity),
|
||||
));
|
||||
}
|
||||
|
||||
void _handleStateTap(BuildContext context, DateTimeEntity entity) {
|
||||
if (entity.hasDate) {
|
||||
_showDatePicker(context, entity).then((date) {
|
||||
if (date != null) {
|
||||
if (entity.hasTime) {
|
||||
_showTimePicker(context, entity).then((time) {
|
||||
entity.setNewState({
|
||||
"date": "${formatDate(date, [yyyy, '-', mm, '-', dd])}",
|
||||
"time":
|
||||
"${formatDate(DateTime(1970, 1, 1, time.hour, time.minute), [
|
||||
HH,
|
||||
':',
|
||||
nn
|
||||
])}"
|
||||
});
|
||||
});
|
||||
} else {
|
||||
entity.setNewState({
|
||||
"date": "${formatDate(date, [yyyy, '-', mm, '-', dd])}"
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (entity.hasTime) {
|
||||
_showTimePicker(context, entity).then((time) {
|
||||
if (time != null) {
|
||||
entity.setNewState({
|
||||
"time":
|
||||
"${formatDate(DateTime(1970, 1, 1, time.hour, time.minute), [
|
||||
HH,
|
||||
':',
|
||||
nn
|
||||
])}"
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
TheLogger.log("Warning", "${entity.entityId} has no date and no time");
|
||||
}
|
||||
}
|
||||
|
||||
Future _showDatePicker(BuildContext context, DateTimeEntity entity) {
|
||||
return showDatePicker(
|
||||
context: context,
|
||||
initialDate: entity.dateTimeState,
|
||||
firstDate: DateTime(1970),
|
||||
lastDate: DateTime(2037) //Unix timestamp will finish at Jan 19, 2038
|
||||
);
|
||||
}
|
||||
|
||||
Future _showTimePicker(BuildContext context, DateTimeEntity entity) {
|
||||
return showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.fromDateTime(entity.dateTimeState));
|
||||
}
|
||||
}
|
||||
|
||||
class CoverEntityControlState extends StatelessWidget {
|
||||
void _open(CoverEntity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(
|
||||
entity.domain, "open_cover", entity.entityId, null));
|
||||
}
|
||||
|
||||
void _close(CoverEntity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(
|
||||
entity.domain, "close_cover", entity.entityId, null));
|
||||
}
|
||||
|
||||
void _stop(CoverEntity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(
|
||||
entity.domain, "stop_cover", entity.entityId, null));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
final CoverEntity entity = entityModel.entity;
|
||||
List<Widget> buttons = [];
|
||||
if (entity.supportOpen) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-up"),
|
||||
size: Entity.iconSize,
|
||||
),
|
||||
onPressed: entity.canBeOpened ? () => _open(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportStop) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
||||
size: Entity.iconSize,
|
||||
),
|
||||
onPressed: () => _stop(entity)));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportClose) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-down"),
|
||||
size: Entity.iconSize,
|
||||
),
|
||||
onPressed: entity.canBeClosed ? () => _close(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
|
||||
return Row(
|
||||
children: buttons,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CoverEntityTiltControlButtons extends StatelessWidget {
|
||||
void _open(CoverEntity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(
|
||||
entity.domain, "open_cover_tilt", entity.entityId, null));
|
||||
}
|
||||
|
||||
void _close(CoverEntity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(
|
||||
entity.domain, "close_cover_tilt", entity.entityId, null));
|
||||
}
|
||||
|
||||
void _stop(CoverEntity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(
|
||||
entity.domain, "stop_cover_tilt", entity.entityId, null));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
final CoverEntity entity = entityModel.entity;
|
||||
List<Widget> buttons = [];
|
||||
if (entity.supportOpenTilt) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName(
|
||||
"mdi:arrow-top-right"),
|
||||
size: Entity.iconSize,
|
||||
),
|
||||
onPressed: entity.canTiltBeOpened ? () => _open(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportStopTilt) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
||||
size: Entity.iconSize,
|
||||
),
|
||||
onPressed: () => _stop(entity)));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportCloseTilt) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName(
|
||||
"mdi:arrow-bottom-left"),
|
||||
size: Entity.iconSize,
|
||||
),
|
||||
onPressed: entity.canTiltBeClosed ? () => _close(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
|
||||
return Row(
|
||||
children: buttons,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonStateWidget extends StatelessWidget {
|
||||
|
||||
void _setNewState(Entity entity) {
|
||||
eventBus.fire(new ServiceCallEvent(entity.domain, "turn_on", entity.entityId, null));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
return FlatButton(
|
||||
onPressed: (() {
|
||||
_setNewState(entityModel.entity);
|
||||
}),
|
||||
child: Text(
|
||||
"EXECUTE",
|
||||
textAlign: TextAlign.right,
|
||||
style:
|
||||
new TextStyle(fontSize: Entity.stateFontSize, color: Colors.blue),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ModeSelectorWidget extends StatelessWidget {
|
||||
|
||||
final String caption;
|
||||
final List<String> options;
|
||||
final String value;
|
||||
final double captionFontSize;
|
||||
final double valueFontSize;
|
||||
final double bottomPadding;
|
||||
final onChange;
|
||||
|
||||
ModeSelectorWidget({
|
||||
Key key,
|
||||
this.caption,
|
||||
@required this.options,
|
||||
this.value,
|
||||
@required this.onChange,
|
||||
this.captionFontSize,
|
||||
this.valueFontSize,
|
||||
this.bottomPadding
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text("$caption", style: TextStyle(
|
||||
fontSize: captionFontSize ?? Entity.stateFontSize
|
||||
)),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ButtonTheme(
|
||||
alignedDropdown: true,
|
||||
child: DropdownButton<String>(
|
||||
value: value,
|
||||
iconSize: 30.0,
|
||||
isExpanded: true,
|
||||
style: TextStyle(
|
||||
fontSize: valueFontSize ?? Entity.largeFontSize,
|
||||
color: Colors.black,
|
||||
),
|
||||
hint: Text("Select ${caption.toLowerCase()}"),
|
||||
items: options.map((String value) {
|
||||
return new DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (mode) => onChange(mode),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(height: bottomPadding ?? Entity.rowPadding,)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ModeSwitchWidget extends StatelessWidget {
|
||||
|
||||
final String caption;
|
||||
final onChange;
|
||||
final double captionFontSize;
|
||||
final bool value;
|
||||
|
||||
ModeSwitchWidget({
|
||||
Key key,
|
||||
@required this.caption,
|
||||
@required this.onChange,
|
||||
this.captionFontSize,
|
||||
this.value
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
"$caption",
|
||||
style: TextStyle(
|
||||
fontSize: captionFontSize ?? Entity.stateFontSize
|
||||
),
|
||||
),
|
||||
),
|
||||
Switch(
|
||||
onChanged: (value) => onChange(value),
|
||||
value: value ?? false,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user