diff --git a/lib/entity_class/const.dart b/lib/entity_class/const.dart index cb85503..52a0920 100644 --- a/lib/entity_class/const.dart +++ b/lib/entity_class/const.dart @@ -38,6 +38,8 @@ class EntityTapAction { } class CardType { + static const horizontalStack = "horizontal-stack"; + static const verticalStack = "vertical-stack"; static const entities = "entities"; static const glance = "glance"; static const mediaControl = "media-control"; diff --git a/lib/entity_class/entity_wrapper.class.dart b/lib/entity_class/entity_wrapper.class.dart index a36adb9..896bdca 100644 --- a/lib/entity_class/entity_wrapper.class.dart +++ b/lib/entity_class/entity_wrapper.class.dart @@ -29,6 +29,7 @@ class EntityWrapper { } void handleTap() { + TheLogger.debug(tapAction); switch (tapAction) { case EntityTapAction.toggle: { eventBus.fire( diff --git a/lib/entity_widgets/button_entity_container.dart b/lib/entity_widgets/button_entity_container.dart new file mode 100644 index 0000000..373f8d8 --- /dev/null +++ b/lib/entity_widgets/button_entity_container.dart @@ -0,0 +1,45 @@ +part of '../main.dart'; + +class ButtonEntityContainer extends StatelessWidget { + + ButtonEntityContainer({ + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final EntityWrapper entityWrapper = EntityModel.of(context).entityWrapper; + + return InkWell( + onTap: () => entityWrapper.handleTap(), + onLongPress: () => entityWrapper.handleHold(), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FractionallySizedBox( + widthFactor: 0.4, + child: FittedBox( + fit: BoxFit.fitHeight, + child: EntityIcon( + padding: EdgeInsets.fromLTRB(2.0, 6.0, 2.0, 2.0), + iconSize: Sizes.iconSize, + ) + ), + ), + _buildName() + ], + ), + ); + } + + Widget _buildName() { + return EntityName( + padding: EdgeInsets.fromLTRB(Sizes.buttonPadding, 0.0, Sizes.buttonPadding, Sizes.rowPadding), + textOverflow: TextOverflow.ellipsis, + maxLines: 3, + wordsWrap: true, + textAlign: TextAlign.center, + fontSize: Sizes.nameFontSize, + ); + } +} \ No newline at end of file diff --git a/lib/entity_widgets/entity_name.dart b/lib/entity_widgets/entity_name.dart index a2d211f..bd7f829 100644 --- a/lib/entity_widgets/entity_name.dart +++ b/lib/entity_widgets/entity_name.dart @@ -7,8 +7,9 @@ class EntityName extends StatelessWidget { final bool wordsWrap; final double fontSize; final TextAlign textAlign; + final int maxLines; - const EntityName({Key key, this.padding: const EdgeInsets.only(right: 10.0), this.textOverflow: TextOverflow.ellipsis, this.wordsWrap: true, this.fontSize: Sizes.nameFontSize, this.textAlign: TextAlign.left}) : super(key: key); + const EntityName({Key key, this.maxLines, this.padding: const EdgeInsets.only(right: 10.0), this.textOverflow: TextOverflow.ellipsis, this.wordsWrap: true, this.fontSize: Sizes.nameFontSize, this.textAlign: TextAlign.left}) : super(key: key); @override Widget build(BuildContext context) { @@ -19,6 +20,7 @@ class EntityName extends StatelessWidget { "${entityWrapper.displayName}", overflow: textOverflow, softWrap: wordsWrap, + maxLines: maxLines, style: TextStyle(fontSize: fontSize), textAlign: textAlign, ), diff --git a/lib/entity_widgets/glance_entity_container.dart b/lib/entity_widgets/glance_entity_container.dart index 4e73114..6a1837d 100644 --- a/lib/entity_widgets/glance_entity_container.dart +++ b/lib/entity_widgets/glance_entity_container.dart @@ -7,7 +7,7 @@ class GlanceEntityContainer extends StatelessWidget { final bool nameInTheBottom; final double iconSize; final double nameFontSize; - final bool expanded; + final bool wordsWrapInName; GlanceEntityContainer({ Key key, @@ -16,7 +16,7 @@ class GlanceEntityContainer extends StatelessWidget { this.nameInTheBottom: false, this.iconSize: Sizes.iconSize, this.nameFontSize: Sizes.smallFontSize, - this.expanded: false + this.wordsWrapInName: false }) : super(key: key); @override @@ -25,21 +25,11 @@ class GlanceEntityContainer extends StatelessWidget { List result = []; if (!nameInTheBottom) { if (showName) { - result.add(EntityName( - padding: EdgeInsets.only(bottom: Sizes.rowPadding), - textOverflow: TextOverflow.ellipsis, - wordsWrap: false, - textAlign: TextAlign.center, - fontSize: nameFontSize, - )); + result.add(_buildName()); } } else { if (showState) { - result.add(SimpleEntityState( - textAlign: TextAlign.center, - expanded: false, - padding: EdgeInsets.only(top: Sizes.rowPadding), - )); + result.add(_buildState()); } } result.add( @@ -50,55 +40,45 @@ class GlanceEntityContainer extends StatelessWidget { ); if (!nameInTheBottom) { if (showState) { - result.add(SimpleEntityState( - textAlign: TextAlign.center, - expanded: false, - padding: EdgeInsets.only(top: Sizes.rowPadding), - )); + result.add(_buildState()); } } else { - result.add(EntityName( - padding: EdgeInsets.only(bottom: Sizes.rowPadding), - textOverflow: TextOverflow.ellipsis, - wordsWrap: false, - textAlign: TextAlign.center, - fontSize: nameFontSize, - )); + result.add(_buildName()); } - - if (expanded) { - return InkWell( + + return Center( + child: InkResponse( + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: Sizes.iconSize * 2), + child: Column( + mainAxisSize: MainAxisSize.min, + //mainAxisAlignment: MainAxisAlignment.start, + //crossAxisAlignment: CrossAxisAlignment.center, + children: result, + ), + ), onTap: () => entityWrapper.handleTap(), onLongPress: () => entityWrapper.handleHold(), - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: 100.0), - child: FittedBox( - fit: BoxFit.fitHeight, - child: Column( - mainAxisSize: MainAxisSize.min, - //mainAxisAlignment: MainAxisAlignment.start, - //crossAxisAlignment: CrossAxisAlignment.center, - children: result, - ), - ), - ), - ); - } else { - return Center( - child: InkResponse( - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: Sizes.iconSize * 2), - child: Column( - mainAxisSize: MainAxisSize.min, - //mainAxisAlignment: MainAxisAlignment.start, - //crossAxisAlignment: CrossAxisAlignment.center, - children: result, - ), - ), - onTap: () => entityWrapper.handleTap(), - onLongPress: () => entityWrapper.handleHold(), - ), - ); - } + ), + ); + } + + Widget _buildName() { + return EntityName( + padding: EdgeInsets.only(bottom: Sizes.rowPadding), + textOverflow: TextOverflow.ellipsis, + wordsWrap: wordsWrapInName, + textAlign: TextAlign.center, + fontSize: nameFontSize, + ); + } + + Widget _buildState() { + return SimpleEntityState( + textAlign: TextAlign.center, + expanded: false, + maxLines: 1, + padding: EdgeInsets.only(top: Sizes.rowPadding), + ); } } \ No newline at end of file diff --git a/lib/entity_widgets/state/simple_state.dart b/lib/entity_widgets/state/simple_state.dart index e5ab101..05053db 100644 --- a/lib/entity_widgets/state/simple_state.dart +++ b/lib/entity_widgets/state/simple_state.dart @@ -5,8 +5,9 @@ class SimpleEntityState extends StatelessWidget { final bool expanded; final TextAlign textAlign; final EdgeInsetsGeometry padding; + final int maxLines; - const SimpleEntityState({Key key, this.expanded: true, this.textAlign: TextAlign.right, this.padding: const EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0)}) : super(key: key); + const SimpleEntityState({Key key, this.maxLines: 10, this.expanded: true, this.textAlign: TextAlign.right, this.padding: const EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0)}) : super(key: key); @override Widget build(BuildContext context) { @@ -16,7 +17,7 @@ class SimpleEntityState extends StatelessWidget { child: Text( "${entityModel.entityWrapper.entity.state} ${entityModel.entityWrapper.entity.unitOfMeasurement}", textAlign: textAlign, - maxLines: 10, + maxLines: maxLines, overflow: TextOverflow.ellipsis, softWrap: true, style: new TextStyle( diff --git a/lib/home_assistant.class.dart b/lib/home_assistant.class.dart index 5950997..d0e64cb 100644 --- a/lib/home_assistant.class.dart +++ b/lib/home_assistant.class.dart @@ -428,75 +428,80 @@ class HomeAssistant { List _createLovelaceCards(List rawCards) { List result = []; rawCards.forEach((rawCard){ + HACard card = HACard( + id: "card", + name: rawCard["title"] ?? rawCard["name"], + type: rawCard['type'], + columnsCount: rawCard['columns'] ?? 4, + showName: rawCard['show_name'] ?? true, + showState: rawCard['show_state'] ?? true, + ); if (rawCard["cards"] != null) { - result.addAll(_createLovelaceCards(rawCard["cards"])); - } else { - HACard card = HACard( - id: "card", - name: rawCard["title"] ?? rawCard["name"], - type: rawCard['type'], - columnsCount: rawCard['columns'] ?? 4, - showName: rawCard['show_name'] ?? true, - showState: rawCard['show_state'] ?? true, - ); - rawCard["entities"]?.forEach((rawEntity) { - if (rawEntity is String) { - if (entities.isExist(rawEntity)) { - card.entities.add(EntityWrapper(entity: entities.get(rawEntity))); - } - } else { - if (entities.isExist(rawEntity["entity"])) { - Entity e = entities.get(rawEntity["entity"]); - String tapAction; - String holdAction; - if (card.type == CardType.glance && card.type == CardType.entityButton) { - tapAction = rawEntity["tap_action"] ?? EntityTapAction.moreInfo; - holdAction = rawEntity["hold_action"] ?? EntityTapAction.none; - } else { - tapAction = EntityTapAction.moreInfo; - holdAction = EntityTapAction.none; - } - card.entities.add( - EntityWrapper( - entity: e, - displayName: rawEntity["name"], - icon: rawEntity["icon"], - tapAction: tapAction, - holdAction: holdAction, - tapActionService: rawEntity["service"], - tapActionServiceData: rawEntity["service_data"] ?? {"entity_id": e.entityId} - ) - ); - } + card.childCards = _createLovelaceCards(rawCard["cards"]); + } + rawCard["entities"]?.forEach((rawEntity) { + if (rawEntity is String) { + if (entities.isExist(rawEntity)) { + card.entities.add(EntityWrapper(entity: entities.get(rawEntity))); } - }); - if (rawCard["entity"] != null) { - var en = rawCard["entity"]; - String tapAction = rawCard["tap_action"] ?? EntityTapAction.moreInfo; - String holdAction = rawCard["hold_action"] ?? EntityTapAction.none; - if (en is String) { - if (entities.isExist(en)) { - card.linkedEntityWrapper = EntityWrapper( - entity: entities.get(en), - tapAction: tapAction, - holdAction: holdAction - ); + } else { + if (entities.isExist(rawEntity["entity"])) { + Entity e = entities.get(rawEntity["entity"]); + String tapAction; + String holdAction; + if (card.type == CardType.glance || card.type == CardType.entityButton) { + tapAction = rawEntity["tap_action"] ?? EntityTapAction.moreInfo; + holdAction = rawEntity["hold_action"] ?? EntityTapAction.none; + } else { + tapAction = EntityTapAction.moreInfo; + holdAction = EntityTapAction.none; } - } else { - if (entities.isExist(en["entity"])) { - card.linkedEntityWrapper = EntityWrapper( - entity: entities.get(en["entity"]), + card.entities.add( + EntityWrapper( + entity: e, + displayName: rawEntity["name"], + icon: rawEntity["icon"], + tapAction: tapAction, + holdAction: holdAction, + tapActionService: rawEntity["service"], + tapActionServiceData: rawEntity["service_data"] ?? {"entity_id": e.entityId} + ) + ); + } + } + }); + if (rawCard["entity"] != null) { + var en = rawCard["entity"]; + String tapAction = rawCard["tap_action"] ?? EntityTapAction.moreInfo; + String holdAction = rawCard["hold_action"] ?? EntityTapAction.none; + if (en is String) { + if (entities.isExist(en)) { + Entity e = entities.get(en); + card.linkedEntityWrapper = EntityWrapper( + entity: e, + tapAction: tapAction, + holdAction: holdAction, + tapActionService: rawCard["service"], + tapActionServiceData: rawCard["service_data"] ?? {"entity_id": e.entityId} + ); + } + } else { + if (entities.isExist(en["entity"])) { + Entity e = entities.get(en["entity"]); + card.linkedEntityWrapper = EntityWrapper( + entity: e, icon: en["icon"], displayName: en["name"], tapAction: tapAction, - holdAction: holdAction - ); - } + holdAction: holdAction, + tapActionService: rawCard["service"], + tapActionServiceData: rawCard["service_data"] ?? {"entity_id": e.entityId} + ); } - } - result.add(card); + } + result.add(card); }); return result; } diff --git a/lib/main.dart b/lib/main.dart index 678960f..c7ab9eb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -36,6 +36,7 @@ part 'entity_widgets/common/badge.dart'; part 'entity_widgets/model_widgets.dart'; part 'entity_widgets/default_entity_container.dart'; part 'entity_widgets/glance_entity_container.dart'; +part 'entity_widgets/button_entity_container.dart'; part 'entity_widgets/common/entity_attributes_list.dart'; part 'entity_widgets/entity_icon.dart'; part 'entity_widgets/entity_name.dart'; diff --git a/lib/ui_class/card.class.dart b/lib/ui_class/card.class.dart index b2545a0..5f93692 100644 --- a/lib/ui_class/card.class.dart +++ b/lib/ui_class/card.class.dart @@ -2,6 +2,7 @@ part of '../main.dart'; class HACard { List entities = []; + List childCards = []; EntityWrapper linkedEntityWrapper; String name; String id; @@ -47,6 +48,27 @@ class HACard { ); } + case CardType.horizontalStack: { + if (childCards.isNotEmpty) { + List children = []; + childCards.forEach((card) { + children.add( + Flexible( + fit: FlexFit.tight, + child: card.build(context), + ) + ); + }); + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: children, + ); + } + return Container(height: 0.0, width: 0.0,); + } + case CardType.weatherForecast: case CardType.thermostat: case CardType.sensor: diff --git a/lib/ui_class/sizes_class.dart b/lib/ui_class/sizes_class.dart index 12d12f6..69349ad 100644 --- a/lib/ui_class/sizes_class.dart +++ b/lib/ui_class/sizes_class.dart @@ -3,6 +3,7 @@ part of '../main.dart'; class Sizes { static const rightWidgetPadding = 14.0; static const leftWidgetPadding = 8.0; + static const buttonPadding = 4.0; static const extendedWidgetHeight = 50.0; static const iconSize = 28.0; static const largeIconSize = 46.0; diff --git a/lib/ui_widgets/entity_button_card.dart b/lib/ui_widgets/entity_button_card.dart index 176bed2..6a53f3d 100644 --- a/lib/ui_widgets/entity_button_card.dart +++ b/lib/ui_widgets/entity_button_card.dart @@ -14,24 +14,12 @@ class EntityButtonCardWidget extends StatelessWidget { if (card.linkedEntityWrapper!= null && card.linkedEntityWrapper.entity.isHidden) { return Container(width: 0.0, height: 0.0,); } - if (card.name != null) { - card.linkedEntityWrapper.displayName = card.name; - } + card.linkedEntityWrapper.displayName = card.name?.toUpperCase() ?? card.linkedEntityWrapper.displayName.toUpperCase(); return Card( - child: Padding( - padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding), - child: EntityModel( - entityWrapper: card.linkedEntityWrapper, - child: GlanceEntityContainer( - showName: true, - showState: false, - nameInTheBottom: true, - iconSize: Sizes.largeIconSize, - nameFontSize: Sizes.nameFontSize, - expanded: true, - ), - handleTap: true - ), + child: EntityModel( + entityWrapper: card.linkedEntityWrapper, + child: ButtonEntityContainer(), + handleTap: true ) ); }