diff --git a/src/plugins/condition/StyleRuleManager.js b/src/plugins/condition/StyleRuleManager.js index 3da15def85..6d99190f5c 100644 --- a/src/plugins/condition/StyleRuleManager.js +++ b/src/plugins/condition/StyleRuleManager.js @@ -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'; }); } } diff --git a/src/plugins/condition/components/inspector/ConditionalStylesView.vue b/src/plugins/condition/components/inspector/ConditionalStylesView.vue index a960790f87..1d5e0a171f 100644 --- a/src/plugins/condition/components/inspector/ConditionalStylesView.vue +++ b/src/plugins/condition/components/inspector/ConditionalStylesView.vue @@ -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); diff --git a/src/plugins/condition/components/inspector/MultiSelectStylesView.vue b/src/plugins/condition/components/inspector/MultiSelectStylesView.vue new file mode 100644 index 0000000000..2099cfe33a --- /dev/null +++ b/src/plugins/condition/components/inspector/MultiSelectStylesView.vue @@ -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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/inspector/StyleEditor.vue b/src/plugins/condition/components/inspector/StyleEditor.vue index 1828d67348..1818a6df28 100644 --- a/src/plugins/condition/components/inspector/StyleEditor.vue +++ b/src/plugins/condition/components/inspector/StyleEditor.vue @@ -22,12 +22,15 @@ @@ -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: { diff --git a/src/plugins/displayLayout/components/layout-frame.scss b/src/plugins/displayLayout/components/layout-frame.scss index b9bed8dfa8..24a02e3235 100644 --- a/src/plugins/displayLayout/components/layout-frame.scss +++ b/src/plugins/displayLayout/components/layout-frame.scss @@ -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; diff --git a/src/plugins/displayLayout/components/text-view.scss b/src/plugins/displayLayout/components/text-view.scss index 049da2c726..0ea717e7dd 100644 --- a/src/plugins/displayLayout/components/text-view.scss +++ b/src/plugins/displayLayout/components/text-view.scss @@ -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(); diff --git a/src/plugins/displayLayout/mixins/objectStyles-mixin.js b/src/plugins/displayLayout/mixins/objectStyles-mixin.js index 6cb77ec879..ebdfab7b5f 100644 --- a/src/plugins/displayLayout/mixins/objectStyles-mixin.js +++ b/src/plugins/displayLayout/mixins/objectStyles-mixin.js @@ -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; } } }; diff --git a/src/styles/_controls.scss b/src/styles/_controls.scss index 8df0346b5d..9e1aa22c5b 100644 --- a/src/styles/_controls.scss +++ b/src/styles/_controls.scss @@ -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 */ diff --git a/src/styles/_legacy.scss b/src/styles/_legacy.scss index 2856a15c8a..b99591a4a0 100644 --- a/src/styles/_legacy.scss +++ b/src/styles/_legacy.scss @@ -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 { diff --git a/src/styles/_mixins.scss b/src/styles/_mixins.scss index 6e1d7313dd..ecf6ac5074 100644 --- a/src/styles/_mixins.scss +++ b/src/styles/_mixins.scss @@ -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; } diff --git a/src/ui/components/ObjectView.vue b/src/ui/components/ObjectView.vue index cbf8949f14..c6cc21861e 100644 --- a/src/ui/components/ObjectView.vue +++ b/src/ui/components/ObjectView.vue @@ -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] = ''; } diff --git a/src/ui/inspector/StylesInspectorView.vue b/src/ui/inspector/StylesInspectorView.vue index ce8b4f29e8..80aa8d8328 100644 --- a/src/ui/inspector/StylesInspectorView.vue +++ b/src/ui/inspector/StylesInspectorView.vue @@ -26,6 +26,7 @@