Handles static and mixed styles for multiple items in a layout (#2907)

* Show non specific styles when updating multiple item styles
* Save sub object styles to it's domain object
* Layout UI tweak
* Fixes flexible layout bug.
* Fixes font size bug in telemetry view
* Fixes issues with newly places TVOs including transparent properties.
* Fixes #2908
* Say NO to 'transparent' === '__no_value'
- Fixes #2895;
* Ensure styles are correctly applied to domain objects and drawing objects when selected individually
* Ensure none treatment is correctly applied to objects when multple selecting
* Fix intial box border
* Tweaks to c-text-view layout
- Vertically center text;
- Normalize padding;
- Overflow: hidden;

* Tweaks to Clock and Timer layout
- Fixes #2893;
- Vertically center text;
- Normalize padding;
- Overflow: hidden;
- `position: absolute` when in Layout;

Co-authored-by: charlesh88 <charlesh88@gmail.com>
Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
Shefali Joshi 2020-04-10 15:22:47 -07:00 committed by GitHub
parent da7b93f9b3
commit 766f48c1ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 508 additions and 112 deletions

View File

@ -109,7 +109,7 @@ export default class StyleRuleManager extends EventEmitter {
} else {
if (this.currentStyle) {
Object.keys(this.currentStyle).forEach(key => {
this.currentStyle[key] = 'transparent';
this.currentStyle[key] = '__no_value';
});
}
}

View File

@ -105,7 +105,7 @@ import ConditionDescription from "@/plugins/condition/components/ConditionDescri
import ConditionError from "@/plugins/condition/components/ConditionError.vue";
import Vue from 'vue';
import PreviewAction from "@/ui/preview/PreviewAction.js";
import {getInitialStyleForItem} from "@/plugins/condition/utils/styleUtils";
import {getApplicableStylesForItem} from "@/plugins/condition/utils/styleUtils";
export default {
name: 'ConditionalStylesView',
@ -130,9 +130,7 @@ export default {
}
},
destroyed() {
if (this.stopObserving) {
this.stopObserving();
}
this.removeListeners();
},
mounted() {
this.itemId = '';
@ -164,7 +162,8 @@ export default {
layoutItem = this.selection[0][0].context.layoutItem;
const item = this.selection[0][0].context.item;
this.canHide = true;
if (item && this.isItemType('subobject-view', layoutItem)) {
if (item &&
(!layoutItem || (this.isItemType('subobject-view', layoutItem)))) {
domainObject = item;
} else {
domainObject = this.selection[0][1].context.item;
@ -176,12 +175,21 @@ export default {
domainObject = this.selection[0][0].context.item;
}
this.domainObject = domainObject;
this.initialStyles = getInitialStyleForItem(domainObject, layoutItem);
this.initialStyles = getApplicableStylesForItem(domainObject, layoutItem);
this.$nextTick(() => {
this.removeListeners();
if (this.domainObject) {
this.stopObserving = this.openmct.objects.observe(this.domainObject, '*', newDomainObject => this.domainObject = newDomainObject);
this.stopObservingItems = this.openmct.objects.observe(this.domainObject, 'configuration.items', this.updateDomainObjectItemStyles);
}
});
},
removeListeners() {
if (this.stopObserving) {
this.stopObserving();
}
if (this.domainObject) {
this.stopObserving = this.openmct.objects.observe(this.domainObject, '*', newDomainObject => this.domainObject = newDomainObject);
if (this.stopObservingItems) {
this.stopObservingItems();
}
},
initialize(conditionSetDomainObject) {
@ -280,6 +288,36 @@ export default {
this.persist(domainObjectStyles);
},
updateDomainObjectItemStyles(newItems) {
//check that all items that have been styles still exist. Otherwise delete those styles
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let itemsToRemove = [];
let keys = Object.keys(domainObjectStyles);
keys.forEach((key) => {
if ((key !== 'styles') &&
(key !== 'staticStyle') &&
(key !== 'conditionSetIdentifier')) {
if (!(newItems.find(item => item.id === key))) {
itemsToRemove.push(key);
}
}
});
if (itemsToRemove.length) {
this.removeItemStyles(itemsToRemove, domainObjectStyles);
}
},
removeItemStyles(itemIds, domainObjectStyles) {
itemIds.forEach(itemId => {
if (domainObjectStyles[itemId]) {
domainObjectStyles[itemId] = undefined;
delete domainObjectStyles[this.itemId];
}
});
if (_.isEmpty(domainObjectStyles)) {
domainObjectStyles = undefined;
}
this.persist(domainObjectStyles);
},
initializeConditionalStyles() {
if (!this.conditions) {
this.conditions = {};
@ -305,9 +343,15 @@ export default {
},
initializeStaticStyle(objectStyles) {
let staticStyle = objectStyles && objectStyles.staticStyle;
this.staticStyle = staticStyle || {
style: Object.assign({}, this.initialStyles)
};
if (staticStyle) {
this.staticStyle = {
style: Object.assign({}, this.initialStyles, staticStyle.style)
};
} else {
this.staticStyle = {
style: Object.assign({}, this.initialStyles)
};
}
},
findStyleByConditionId(id) {
return this.conditionalStyles.find(conditionalStyle => conditionalStyle.conditionId === id);

View File

@ -0,0 +1,269 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
<template>
<div class="c-inspector__styles c-inspect-styles">
<div class="c-inspect-styles__header">
Object Style
</div>
<div class="c-inspect-styles__content">
<div v-if="isStaticAndConditionalStyles"
class="c-inspect-styles__mixed-static-and-conditional u-alert u-alert--block u-alert--with-icon"
>
Your selection includes one or more items that use Conditional Styling. Applying a static style below will replace any Conditional Styling with the new choice.
</div>
<div v-if="staticStyle"
class="c-inspect-styles__style"
>
<style-editor class="c-inspect-styles__editor"
:style-item="staticStyle"
:is-editing="isEditing"
:mixed-styles="mixedStyles"
@persist="updateStaticStyle"
/>
</div>
</div>
</div>
</template>
<script>
import StyleEditor from "./StyleEditor.vue";
import PreviewAction from "@/ui/preview/PreviewAction.js";
import { getApplicableStylesForItem, getConsolidatedStyleValues, getConditionalStyleForItem } from "@/plugins/condition/utils/styleUtils";
export default {
name: 'MultiSelectStylesView',
components: {
StyleEditor
},
inject: [
'openmct',
'selection'
],
data() {
return {
staticStyle: undefined,
isEditing: this.openmct.editor.isEditing(),
mixedStyles: [],
isStaticAndConditionalStyles: false
}
},
destroyed() {
this.removeListeners();
},
mounted() {
this.items = [];
this.previewAction = new PreviewAction(this.openmct);
this.getObjectsAndItemsFromSelection();
this.initializeStaticStyle();
this.openmct.editor.on('isEditing', this.setEditState);
},
methods: {
isItemType(type, item) {
return item && (item.type === type);
},
hasConditionalStyles(domainObject, id) {
return getConditionalStyleForItem(domainObject, id) !== undefined;
},
getObjectsAndItemsFromSelection() {
let domainObject;
let subObjects = [];
//multiple selection
let itemInitialStyles = [];
let itemStyle;
this.selection.forEach((selectionItem) => {
const item = selectionItem[0].context.item;
const layoutItem = selectionItem[0].context.layoutItem;
if (item && this.isItemType('subobject-view', layoutItem)) {
subObjects.push(item);
itemStyle = getApplicableStylesForItem(item);
if (!this.isStaticAndConditionalStyles) {
this.isStaticAndConditionalStyles = this.hasConditionalStyles(item);
}
} else {
domainObject = selectionItem[1].context.item;
itemStyle = getApplicableStylesForItem(domainObject, layoutItem || item);
this.items.push({
id: layoutItem.id,
applicableStyles: itemStyle
});
if (!this.isStaticAndConditionalStyles) {
this.isStaticAndConditionalStyles = this.hasConditionalStyles(domainObject, layoutItem.id);
}
}
itemInitialStyles.push(itemStyle);
});
const {styles, mixedStyles} = getConsolidatedStyleValues(itemInitialStyles);
this.initialStyles = styles;
this.mixedStyles = mixedStyles;
this.domainObject = domainObject;
this.removeListeners();
if (this.domainObject) {
this.stopObserving = this.openmct.objects.observe(this.domainObject, '*', newDomainObject => this.domainObject = newDomainObject);
this.stopObservingItems = this.openmct.objects.observe(this.domainObject, 'configuration.items', this.updateDomainObjectItemStyles);
}
subObjects.forEach(this.registerListener);
},
updateDomainObjectItemStyles(newItems) {
//check that all items that have been styles still exist. Otherwise delete those styles
let keys = Object.keys(this.domainObject.configuration.objectStyles || {});
keys.forEach((key) => {
if ((key !== 'styles') &&
(key !== 'staticStyle') &&
(key !== 'conditionSetIdentifier')) {
if (!(newItems.find(item => item.id === key))) {
this.removeItemStyles(key);
}
}
});
},
registerListener(domainObject) {
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
if (!this.domainObjectsById) {
this.domainObjectsById = {};
}
if (!this.domainObjectsById[id]) {
this.domainObjectsById[id] = domainObject;
this.observeObject(domainObject, id);
}
},
observeObject(domainObject, id) {
let unobserveObject = this.openmct.objects.observe(domainObject, '*', function (newObject) {
this.domainObjectsById[id] = JSON.parse(JSON.stringify(newObject));
}.bind(this));
this.unObserveObjects.push(unobserveObject);
},
removeListeners() {
if (this.stopObserving) {
this.stopObserving();
}
if (this.stopObservingItems) {
this.stopObservingItems();
}
if (this.unObserveObjects) {
this.unObserveObjects.forEach((unObserveObject) => {
unObserveObject();
});
}
this.unObserveObjects = [];
},
removeItemStyles(itemId) {
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
if (itemId && domainObjectStyles[itemId]) {
domainObjectStyles[itemId] = undefined;
delete domainObjectStyles[this.itemId];
if (_.isEmpty(domainObjectStyles)) {
domainObjectStyles = undefined;
}
this.persist(this.domainObject, domainObjectStyles);
}
},
removeConditionalStyles(domainObjectStyles, itemId) {
if (itemId) {
domainObjectStyles[itemId].conditionSetIdentifier = undefined;
delete domainObjectStyles[itemId].conditionSetIdentifier;
domainObjectStyles[itemId].styles = undefined;
delete domainObjectStyles[itemId].styles;
} else {
domainObjectStyles.conditionSetIdentifier = undefined;
delete domainObjectStyles.conditionSetIdentifier;
domainObjectStyles.styles = undefined;
delete domainObjectStyles.styles;
}
},
setEditState(isEditing) {
this.isEditing = isEditing;
},
initializeStaticStyle() {
this.staticStyle = {
style: Object.assign({}, this.initialStyles)
};
},
updateStaticStyle(staticStyle, property) {
//update the static style for each of the layoutItems as well as each sub object item
this.staticStyle = staticStyle;
this.persist(this.domainObject, this.getDomainObjectStyle(this.domainObject, property, this.items));
if (this.domainObjectsById) {
const keys = Object.keys(this.domainObjectsById);
keys.forEach(key => {
let domainObject = this.domainObjectsById[key];
this.persist(domainObject, this.getDomainObjectStyle(domainObject, property));
});
}
this.isStaticAndConditionalStyles = false;
let foundIndex = this.mixedStyles.indexOf(property);
if (foundIndex > -1) {
this.mixedStyles.splice(foundIndex, 1);
}
},
getDomainObjectStyle(domainObject, property, items) {
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
if (items) {
items.forEach(item => {
let itemStaticStyle = {};
if (domainObjectStyles[item.id] && domainObjectStyles[item.id].staticStyle) {
itemStaticStyle = domainObjectStyles[item.id].staticStyle.style;
}
Object.keys(item.applicableStyles).forEach(key => {
if (property === key) {
itemStaticStyle[key] = this.staticStyle.style[key];
}
});
if (this.isStaticAndConditionalStyles) {
this.removeConditionalStyles(domainObjectStyles, item.id);
}
if (_.isEmpty(itemStaticStyle)) {
itemStaticStyle = undefined;
domainObjectStyles[item.id] = undefined;
} else {
domainObjectStyles[item.id] = Object.assign({}, { staticStyle: { style: itemStaticStyle } });
}
});
} else {
if (!domainObjectStyles.staticStyle) {
domainObjectStyles.staticStyle = {
style: {}
}
}
if (this.isStaticAndConditionalStyles) {
this.removeConditionalStyles(domainObjectStyles);
}
domainObjectStyles.staticStyle.style[property] = this.staticStyle.style[property];
}
return domainObjectStyles;
},
persist(domainObject, style) {
this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style);
}
}
}
</script>

View File

@ -22,12 +22,15 @@
<template>
<div class="c-style">
<span class="c-style-thumb"
:class="{ 'is-style-invisible': styleItem.style.isStyleInvisible }"
<span :class="[
{ 'is-style-invisible': styleItem.style.isStyleInvisible },
{ 'c-style-thumb--mixed': mixedStyles.indexOf('backgroundColor') > -1 }
]"
:style="[styleItem.style.imageUrl ? { backgroundImage:'url(' + styleItem.style.imageUrl + ')'} : itemStyle ]"
class="c-style-thumb"
>
<span class="c-style-thumb__text"
:class="{ 'hide-nice': !styleItem.style.color }"
:class="{ 'hide-nice': !hasProperty(styleItem.style.color) }"
>
ABC
</span>
@ -68,6 +71,7 @@ import ToolbarColorPicker from "@/ui/toolbar/components/toolbar-color-picker.vue
import ToolbarButton from "@/ui/toolbar/components/toolbar-button.vue";
import ToolbarToggleButton from "@/ui/toolbar/components/toolbar-toggle-button.vue";
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
import {getStylesWithoutNoneValue} from "@/plugins/condition/utils/styleUtils";
export default {
name: 'StyleEditor',
@ -83,6 +87,12 @@ export default {
isEditing: {
type: Boolean
},
mixedStyles: {
type: Array,
default() {
return [];
}
},
styleItem: {
type: Object,
required: true
@ -90,21 +100,17 @@ export default {
},
computed: {
itemStyle() {
let style = {};
const keys = Object.keys(this.styleItem.style);
keys.forEach(key => {
style[key] = this.normalizeValue(this.styleItem.style[key]);
});
return style;
return getStylesWithoutNoneValue(this.styleItem.style);
},
borderColorOption() {
let value = this.styleItem.style.border.replace('1px solid ', '');
return {
icon: 'icon-line-horz',
title: STYLE_CONSTANTS.borderColorTitle,
value: this.normalizeValue(value),
value: this.normalizeValueForSwatch(value),
property: 'border',
isEditing: this.isEditing
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('border') > -1
}
},
backgroundColorOption() {
@ -112,9 +118,10 @@ export default {
return {
icon: 'icon-paint-bucket',
title: STYLE_CONSTANTS.backgroundColorTitle,
value: this.normalizeValue(value),
value: this.normalizeValueForSwatch(value),
property: 'backgroundColor',
isEditing: this.isEditing
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('backgroundColor') > -1
}
},
colorOption() {
@ -122,9 +129,10 @@ export default {
return {
icon: 'icon-font',
title: STYLE_CONSTANTS.textColorTitle,
value: this.normalizeValue(value),
value: this.normalizeValueForSwatch(value),
property: 'color',
isEditing: this.isEditing
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('color') > -1
}
},
imageUrlOption() {
@ -149,7 +157,8 @@ export default {
property: 'imageUrl',
formKeys: ['url'],
value: {url: this.styleItem.style.imageUrl},
isEditing: this.isEditing
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('imageUrl') > -1
}
},
isStyleInvisibleOption() {
@ -177,13 +186,20 @@ export default {
hasProperty(property) {
return property !== undefined;
},
normalizeValue(value) {
if (!value) {
return 'transparent';
normalizeValueForSwatch(value) {
if (value && value.indexOf('__no_value') > -1) {
return value.replace('__no_value', 'transparent');
}
return value;
},
normalizeValueForStyle(value) {
if (value && value === 'transparent') {
return '__no_value';
}
return value;
},
updateStyleValue(value, item) {
value = this.normalizeValueForStyle(value);
if (item.property === 'border') {
value = '1px solid ' + value;
}
@ -192,7 +208,7 @@ export default {
} else {
this.styleItem.style[item.property] = value;
}
this.$emit('persist', this.styleItem);
this.$emit('persist', this.styleItem, item.property);
}
}
}

View File

@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
const NONE_VALUE = 'transparent';
const NONE_VALUE = '__no_value';
const styleProps = {
backgroundColor: {
@ -46,7 +46,7 @@ const styleProps = {
},
color: {
svgProperty: 'color',
noneValue: 'NONE_VALUE',
noneValue: NONE_VALUE,
applicableForType: type => {
return !type ? true : (type === 'text-view' ||
type === 'telemetry-view'||
@ -62,19 +62,74 @@ const styleProps = {
}
};
const aggregateStyleValues = (accumulator, currentStyle) => {
const styleKeys = Object.keys(currentStyle);
const properties = Object.keys(styleProps);
properties.forEach((property) => {
if (!accumulator[property]) {
accumulator[property] = [];
}
const found = styleKeys.find(key => key === property);
if (found) {
accumulator[property].push(currentStyle[found]);
}
});
return accumulator;
};
// Returns a union of styles used by multiple items.
// Styles that are common to all items but don't have the same value are added to the mixedStyles list
export const getConsolidatedStyleValues = (multipleItemStyles) => {
let aggregatedStyleValues = multipleItemStyles.reduce(aggregateStyleValues, {});
let styleValues = {};
let mixedStyles = [];
const properties = Object.keys(styleProps);
properties.forEach((property) => {
const values = aggregatedStyleValues[property];
if (values.length) {
if (values.every(value => value === values[0])) {
styleValues[property] = values[0];
} else {
styleValues[property] = '';
mixedStyles.push(property);
}
}
});
return {
styles: styleValues,
mixedStyles
};
};
const getStaticStyleForItem = (domainObject, id) => {
let domainObjectStyles = domainObject && domainObject.configuration && domainObject.configuration.objectStyles;
if (domainObjectStyles) {
if (id && domainObjectStyles[id] && domainObjectStyles[id].staticStyle) {
return domainObjectStyles[id].staticStyle.style;
if (id) {
if(domainObjectStyles[id] && domainObjectStyles[id].staticStyle) {
return domainObjectStyles[id].staticStyle.style;
}
} else if (domainObjectStyles.staticStyle) {
return domainObjectStyles.staticStyle.style;
}
}
};
export const getConditionalStyleForItem = (domainObject, id) => {
let domainObjectStyles = domainObject && domainObject.configuration && domainObject.configuration.objectStyles;
if (domainObjectStyles) {
if (id) {
if (domainObjectStyles[id] && domainObjectStyles[id].conditionSetIdentifier) {
return domainObjectStyles[id].styles;
}
} else if (domainObjectStyles.staticStyle) {
return domainObjectStyles.styles;
}
}
};
//Returns either existing static styles or uses SVG defaults if available
export const getInitialStyleForItem = (domainObject, item) => {
export const getApplicableStylesForItem = (domainObject, item) => {
const type = item && item.type;
const id = item && item.id;
let style = {};
@ -97,3 +152,21 @@ export const getInitialStyleForItem = (domainObject, item) => {
return style;
};
export const getStylesWithoutNoneValue = (style) => {
if (_.isEmpty(style) || !style) {
return;
}
let styleObj = {};
const keys = Object.keys(style);
keys.forEach(key => {
if ((typeof style[key] === 'string')) {
if (style[key].indexOf('__no_value') > -1) {
style[key] = '';
} else {
styleObj[key] = style[key];
}
}
});
return styleObj;
};

View File

@ -43,7 +43,7 @@ export default {
makeDefinition() {
return {
fill: '#717171',
stroke: 'transparent',
stroke: '',
x: 1,
y: 1,
width: 10,
@ -74,13 +74,14 @@ export default {
},
computed: {
style() {
return Object.assign({
backgroundColor: this.item.fill,
border: '1px solid ' + this.item.stroke
}, this.itemStyle);
},
styleClass() {
return this.itemStyle && this.itemStyle.isStyleInvisible;
if (this.itemStyle) {
return this.itemStyle;
} else {
return {
backgroundColor: this.item.fill,
border: this.item.stroke ? '1px solid ' + this.item.stroke : ''
};
}
}
},
watch: {

View File

@ -74,13 +74,18 @@ export default {
},
computed: {
style() {
let backgroundImage = 'url(' + this.item.url + ')';
let border = '1px solid ' + this.item.stroke;
if (this.itemStyle) {
if (this.itemStyle.imageUrl !== undefined) {
backgroundImage = 'url(' + this.itemStyle.imageUrl + ')';
}
border = this.itemStyle.border;
}
return {
backgroundImage: this.itemStyle ? ('url(' + this.itemStyle.imageUrl + ')') : 'url(' + this.item.url + ')',
border: (this.itemStyle && this.itemStyle.border) ? this.itemStyle.border : ('1px solid ' + this.item.stroke)
backgroundImage,
border
};
},
styleClass() {
return this.itemStyle && this.itemStyle.isStyleInvisible;
}
},
watch: {

View File

@ -127,8 +127,11 @@ export default {
return {x, y, x2, y2};
},
stroke() {
if (this.itemStyle && this.itemStyle.border) {
return this.itemStyle.border.replace('1px solid ', '');
if (this.itemStyle) {
if (this.itemStyle.border) {
return this.itemStyle.border.replace('1px solid ', '');
}
return '';
} else {
return this.item.stroke;
}
@ -146,9 +149,6 @@ export default {
height: `${height}px`
};
},
styleClass() {
return this.itemStyle && this.itemStyle.isStyleInvisible;
},
startHandleClass() {
return START_HANDLE_QUADRANTS[this.vectorQuadrant];
},

View File

@ -31,7 +31,7 @@
v-if="domainObject"
class="c-telemetry-view"
:class="styleClass"
:style="telemetryObjectStyle || styleObject"
:style="styleObject"
@contextmenu.prevent="showContextMenu"
>
<div
@ -79,8 +79,8 @@ export default {
height: DEFAULT_TELEMETRY_DIMENSIONS[1],
displayMode: 'all',
value: metadata.getDefaultDisplayValue(),
stroke: "transparent",
fill: "transparent",
stroke: "",
fill: "",
color: "",
size: "13px"
};
@ -125,27 +125,10 @@ export default {
return displayMode === 'all' || displayMode === 'value';
},
styleObject() {
return {
backgroundColor: this.item.fill,
borderColor: this.item.stroke,
color: this.item.color,
return Object.assign({}, {
fontSize: this.item.size
}
},
styleClass() {
return this.telemetryObjectStyle && this.telemetryObjectStyle.isStyleInvisible;
},
telemetryObjectStyle() {
let styleObj = Object.assign({}, this.itemStyle);
let keys = Object.keys(styleObj);
keys.forEach(key => {
if ((typeof styleObj[key] === 'string') && (styleObj[key].indexOf('transparent') > -1)) {
if (styleObj[key]) {
styleObj[key] = '';
}
}
});
return styleObj;
}, this.itemStyle);
},
fieldName() {
return this.valueMetadata && this.valueMetadata.name;

View File

@ -32,7 +32,7 @@
:class="[styleClass]"
:style="style"
>
{{ item.text }}
<div class="c-text-view__text">{{ item.text }}</div>
</div>
</layout-frame>
</template>
@ -44,8 +44,8 @@ import conditionalStylesMixin from "../mixins/objectStyles-mixin";
export default {
makeDefinition(openmct, gridSize, element) {
return {
fill: 'transparent',
stroke: 'transparent',
fill: '',
stroke: '',
size: '13px',
color: '',
x: 1,
@ -80,14 +80,8 @@ export default {
computed: {
style() {
return Object.assign({
backgroundColor: this.item.fill,
border: '1px solid ' + this.item.stroke,
color: this.item.color,
fontSize: this.item.size
}, this.itemStyle);
},
styleClass() {
return this.itemStyle && this.itemStyle.isStyleInvisible;
}
},
watch: {

View File

@ -16,6 +16,8 @@
.is-editing {
/******************* STYLES FOR C-FRAME WHILE EDITING */
.c-frame {
border: 1px solid rgba($editFrameColorHov, 0.3);
&:not([s-selected]) {
&:hover {
border: $editFrameBorderHov;

View File

@ -1,6 +1,8 @@
.c-text-view {
display: flex;
align-items: stretch;
align-items: center; // Vertically center text
overflow: hidden;
padding: $interiorMargin;
.c-frame & {
@include abs();

View File

@ -21,12 +21,14 @@
*****************************************************************************/
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
import {getStylesWithoutNoneValue} from "@/plugins/condition/utils/styleUtils";
export default {
inject: ['openmct'],
data() {
return {
itemStyle: this.itemStyle
itemStyle: undefined,
styleClass: ''
}
},
mounted() {
@ -69,13 +71,8 @@ export default {
});
},
updateStyle(style) {
this.itemStyle = style;
let keys = Object.keys(this.itemStyle);
keys.forEach((key) => {
if ((typeof this.itemStyle[key] === 'string') && (this.itemStyle[key].indexOf('transparent') > -1)) {
delete this.itemStyle[key];
}
});
this.itemStyle = getStylesWithoutNoneValue(style);
this.styleClass = this.itemStyle && this.itemStyle.isStyleInvisible;
}
}
};

View File

@ -122,13 +122,8 @@ button {
margin-left: $interiorMargin;
}
$c1: nth($mixedSettingBg, 1);
$c2: nth($mixedSettingBg, 2);
$mixedBgD: $mixedSettingBgSize $mixedSettingBgSize;
&--mixed {
// E.g. click-icons in toolbar that apply to multiple selected items with different settings
@include bgStripes2Color($c1, $c2, $bgSize: $mixedBgD);
@include mixedBg();
}
&--swatched {
@ -151,13 +146,6 @@ button {
flex: 1 1 auto;
font-size: 1.1em;
}
&--mixed {
// Styling for swatched buttons when settings are mixed
> [class*='swatch'] {
@include bgStripes2Color($c1, $c2, $bgSize: $mixedBgD);
}
}
}
}
@ -821,6 +809,10 @@ select {
box-shadow: rgba($colorBodyFg, 0.4) 0 0 3px;
flex: 0 0 auto;
padding: $interiorMargin $interiorMarginLg;
&--mixed {
@include mixedBg();
}
}
/******************************************************** SLIDERS */

View File

@ -72,6 +72,7 @@
display: flex;
align-items: center;
font-size: 1.25em;
overflow: hidden;
> * {
flex: 0 0 auto;
@ -82,6 +83,12 @@
&__value {
color: $colorBodyFgEm;
}
.c-frame & {
// When in a Display or Flexible Layout
@include abs();
padding: $interiorMargin;
}
}
.c-clock {

View File

@ -50,6 +50,14 @@
}
/************************** EFFECTS */
@mixin mixedBg() {
$c1: nth($mixedSettingBg, 1);
$c2: nth($mixedSettingBg, 2);
$mixedBgD: $mixedSettingBgSize $mixedSettingBgSize;
@include bgStripes2Color($c1, $c2, $bgSize: $mixedBgD);
}
@mixin pulse($animName: pulse, $dur: 500ms, $iteration: infinite, $opacity0: 0.5, $opacity100: 1) {
@keyframes #{$animName} {
0% { opacity: $opacity0; }

View File

@ -104,7 +104,7 @@ export default {
keys.forEach(key => {
let firstChild = this.$el.querySelector(':first-child');
if (firstChild) {
if ((typeof styleObj[key] === 'string') && (styleObj[key].indexOf('transparent') > -1)) {
if ((typeof styleObj[key] === 'string') && (styleObj[key].indexOf('__no_value') > -1)) {
if (firstChild.style[key]) {
firstChild.style[key] = '';
}

View File

@ -26,6 +26,7 @@
<script>
import ConditionalStylesView from '../../plugins/condition/components/inspector/ConditionalStylesView.vue';
import MultiSelectStylesView from '../../plugins/condition/components/inspector/MultiSelectStylesView.vue';
import Vue from 'vue';
export default {
@ -45,6 +46,7 @@ export default {
methods: {
updateSelection(selection) {
if (selection.length > 0 && selection[0].length > 0) {
let template = selection.length > 1 ? '<multi-select-styles-view></multi-select-styles-view>' : '<conditional-styles-view></conditional-styles-view>';
if (this.component) {
this.component.$destroy();
this.component = undefined;
@ -59,9 +61,10 @@ export default {
},
el: viewContainer,
components: {
ConditionalStylesView
ConditionalStylesView,
MultiSelectStylesView
},
template: '<conditional-styles-view></conditional-styles-view>'
template: template
});
}
}