Resolves #120 Horizontal Stack Cards
This commit is contained in:
parent
20b1b90e39
commit
9c403480e2
@ -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";
|
||||
|
@ -29,6 +29,7 @@ class EntityWrapper {
|
||||
}
|
||||
|
||||
void handleTap() {
|
||||
TheLogger.debug(tapAction);
|
||||
switch (tapAction) {
|
||||
case EntityTapAction.toggle: {
|
||||
eventBus.fire(
|
||||
|
45
lib/entity_widgets/button_entity_container.dart
Normal file
45
lib/entity_widgets/button_entity_container.dart
Normal file
@ -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: <Widget>[
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
),
|
||||
|
@ -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<Widget> 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,40 +40,12 @@ 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(
|
||||
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(
|
||||
@ -100,5 +62,23 @@ class GlanceEntityContainer extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
);
|
||||
}
|
||||
}
|
@ -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(
|
||||
|
@ -428,9 +428,6 @@ class HomeAssistant {
|
||||
List<HACard> _createLovelaceCards(List rawCards) {
|
||||
List<HACard> result = [];
|
||||
rawCards.forEach((rawCard){
|
||||
if (rawCard["cards"] != null) {
|
||||
result.addAll(_createLovelaceCards(rawCard["cards"]));
|
||||
} else {
|
||||
HACard card = HACard(
|
||||
id: "card",
|
||||
name: rawCard["title"] ?? rawCard["name"],
|
||||
@ -439,6 +436,9 @@ class HomeAssistant {
|
||||
showName: rawCard['show_name'] ?? true,
|
||||
showState: rawCard['show_state'] ?? true,
|
||||
);
|
||||
if (rawCard["cards"] != null) {
|
||||
card.childCards = _createLovelaceCards(rawCard["cards"]);
|
||||
}
|
||||
rawCard["entities"]?.forEach((rawEntity) {
|
||||
if (rawEntity is String) {
|
||||
if (entities.isExist(rawEntity)) {
|
||||
@ -449,7 +449,7 @@ class HomeAssistant {
|
||||
Entity e = entities.get(rawEntity["entity"]);
|
||||
String tapAction;
|
||||
String holdAction;
|
||||
if (card.type == CardType.glance && card.type == CardType.entityButton) {
|
||||
if (card.type == CardType.glance || card.type == CardType.entityButton) {
|
||||
tapAction = rawEntity["tap_action"] ?? EntityTapAction.moreInfo;
|
||||
holdAction = rawEntity["hold_action"] ?? EntityTapAction.none;
|
||||
} else {
|
||||
@ -476,27 +476,32 @@ class HomeAssistant {
|
||||
String holdAction = rawCard["hold_action"] ?? EntityTapAction.none;
|
||||
if (en is String) {
|
||||
if (entities.isExist(en)) {
|
||||
Entity e = entities.get(en);
|
||||
card.linkedEntityWrapper = EntityWrapper(
|
||||
entity: entities.get(en),
|
||||
entity: e,
|
||||
tapAction: tapAction,
|
||||
holdAction: holdAction
|
||||
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: entities.get(en["entity"]),
|
||||
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);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
@ -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';
|
||||
|
@ -2,6 +2,7 @@ part of '../main.dart';
|
||||
|
||||
class HACard {
|
||||
List<EntityWrapper> entities = [];
|
||||
List<HACard> childCards = [];
|
||||
EntityWrapper linkedEntityWrapper;
|
||||
String name;
|
||||
String id;
|
||||
@ -47,6 +48,27 @@ class HACard {
|
||||
);
|
||||
}
|
||||
|
||||
case CardType.horizontalStack: {
|
||||
if (childCards.isNotEmpty) {
|
||||
List<Widget> 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:
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
),
|
||||
child: ButtonEntityContainer(),
|
||||
handleTap: true
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user