mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 10:44:21 +00:00
Compare commits
40 Commits
tables-rem
...
tcr-fixes-
Author | SHA1 | Date | |
---|---|---|---|
07c2b0820a | |||
a0d2cd5711 | |||
2d8f58573d | |||
e4e7ecd74e | |||
f148583318 | |||
514896884f | |||
fc024e583e | |||
7f2f060417 | |||
a94d50226a | |||
6eda100af8 | |||
782ee9aa37 | |||
29e94befe8 | |||
24a1e9ba75 | |||
edeefe8f2f | |||
d263723a0c | |||
666bb41697 | |||
b74c14b334 | |||
d8f733d424 | |||
b39f3fab3f | |||
4912188fe4 | |||
e254fafb5c | |||
1dc1cc6c24 | |||
baa5d10009 | |||
58048d44b2 | |||
775e93484e | |||
0e27234389 | |||
ac2b9acccb | |||
075d4deecb | |||
ac11f898d4 | |||
dd31de6935 | |||
15d4b1a8e5 | |||
9e811e722f | |||
8ef53d85c4 | |||
abcc5cb023 | |||
931871ff95 | |||
6b1e8862ef | |||
00ce246fc5 | |||
c0c7d96429 | |||
92b2582d0d | |||
4084a1ac86 |
@ -43,15 +43,14 @@ define([
|
||||
form: [
|
||||
{
|
||||
name: "State Duration (seconds)",
|
||||
control: "textfield",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "duration",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"duration"
|
||||
],
|
||||
pattern: "^\\d*(\\.\\d*)?$"
|
||||
]
|
||||
}
|
||||
],
|
||||
initialize: function (object) {
|
||||
|
@ -49,7 +49,6 @@
|
||||
openmct.install(openmct.plugins.ExampleImagery());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
openmct.install(openmct.plugins.ImportExport());
|
||||
openmct.install(openmct.plugins.FixedView());
|
||||
openmct.install(openmct.plugins.AutoflowView({
|
||||
type: "telemetry.panel"
|
||||
}));
|
||||
|
@ -25,7 +25,7 @@
|
||||
"eventemitter3": "^1.2.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"express": "^4.13.1",
|
||||
"fast-sass-loader": "^1.4.5",
|
||||
"fast-sass-loader": "1.4.6",
|
||||
"file-loader": "^1.1.11",
|
||||
"file-saver": "^1.3.8",
|
||||
"git-rev-sync": "^1.4.0",
|
||||
|
@ -92,16 +92,7 @@ function (
|
||||
* @memberof platform/commonUI/edit.SaveAction#
|
||||
*/
|
||||
SaveAsAction.prototype.perform = function () {
|
||||
// Discard the current root view (which will be the editing
|
||||
// UI, which will have been pushed atop the Browse UI.)
|
||||
function returnToBrowse(object) {
|
||||
if (object) {
|
||||
object.getCapability("action").perform("navigate");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
return this.save().then(returnToBrowse);
|
||||
return this.save();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -169,15 +160,17 @@ function (
|
||||
}
|
||||
|
||||
function saveAfterClone(clonedObject) {
|
||||
return domainObject.getCapability("editor").save()
|
||||
.then(resolveWith(clonedObject));
|
||||
return this.openmct.editor.save().then(() => {
|
||||
// Force mutation for search indexing
|
||||
clonedObject.useCapability('mutation', (model) => {
|
||||
return model;
|
||||
});
|
||||
return clonedObject;
|
||||
})
|
||||
}
|
||||
|
||||
function finishEditing(clonedObject) {
|
||||
return domainObject.getCapability("editor").finish()
|
||||
.then(function () {
|
||||
return fetchObject(clonedObject.getId());
|
||||
});
|
||||
return fetchObject(clonedObject.getId())
|
||||
}
|
||||
|
||||
function onSuccess(object) {
|
||||
@ -190,7 +183,7 @@ function (
|
||||
if (reason !== "user canceled") {
|
||||
self.notificationService.error("Save Failed");
|
||||
}
|
||||
return false;
|
||||
throw reason;
|
||||
}
|
||||
|
||||
return getParent(domainObject)
|
||||
|
@ -65,24 +65,33 @@ define(
|
||||
CreateAction.prototype.perform = function () {
|
||||
var newModel = this.type.getInitialModel(),
|
||||
openmct = this.openmct,
|
||||
newObject,
|
||||
editAction;
|
||||
|
||||
function onSave() {
|
||||
openmct.editor.save();
|
||||
}
|
||||
newObject;
|
||||
|
||||
function onCancel() {
|
||||
openmct.editor.cancel();
|
||||
}
|
||||
|
||||
function navigateAndEdit(object) {
|
||||
let objectPath = object.getCapability('context').getPath(),
|
||||
url = '#/browse/' + objectPath
|
||||
.map(function (o) {
|
||||
return o && openmct.objects.makeKeyString(o.getId())
|
||||
})
|
||||
.join('/');
|
||||
|
||||
window.location.href = url;
|
||||
|
||||
openmct.editor.edit();
|
||||
}
|
||||
|
||||
newModel.type = this.type.getKey();
|
||||
newModel.location = this.parent.getId();
|
||||
newObject = this.parent.useCapability('instantiation', newModel);
|
||||
|
||||
openmct.editor.edit();
|
||||
editAction = newObject.getCapability("action").getActions("edit")[0];
|
||||
newObject.getCapability("action").perform("save-as").then(onSave, onCancel);
|
||||
newObject.getCapability("action").perform("save-as")
|
||||
.then(navigateAndEdit, onCancel)
|
||||
|
||||
// TODO: support editing object without saving object first.
|
||||
// Which means we have to toggle createwizard afterwards. For now,
|
||||
// We will disable this.
|
||||
|
@ -1,475 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
"./src/FixedController",
|
||||
"./templates/fixed.html",
|
||||
"./templates/frame.html",
|
||||
"./templates/elements/telemetry.html",
|
||||
"./templates/elements/box.html",
|
||||
"./templates/elements/line.html",
|
||||
"./templates/elements/text.html",
|
||||
"./templates/elements/image.html",
|
||||
"legacyRegistry"
|
||||
], function (
|
||||
FixedController,
|
||||
fixedTemplate,
|
||||
frameTemplate,
|
||||
telemetryTemplate,
|
||||
boxTemplate,
|
||||
lineTemplate,
|
||||
textTemplate,
|
||||
imageTemplate,
|
||||
legacyRegistry
|
||||
) {
|
||||
return function() {
|
||||
return function (openmct) {
|
||||
openmct.legacyRegistry.register("platform/features/fixed", {
|
||||
"name": "Fixed position components.",
|
||||
"description": "Plug in adding Fixed Position object type.",
|
||||
"extensions": {
|
||||
"views": [
|
||||
{
|
||||
"key": "fixed-display",
|
||||
"name": "Fixed Position Display",
|
||||
"cssClass": "icon-box-with-dashed-lines",
|
||||
"type": "telemetry.fixed",
|
||||
"template": fixedTemplate,
|
||||
"uses": ["composition"],
|
||||
"editable": true
|
||||
}
|
||||
],
|
||||
"templates": [
|
||||
{
|
||||
"key": "fixed.telemetry",
|
||||
"template": telemetryTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.box",
|
||||
"template": boxTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.line",
|
||||
"template": lineTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.text",
|
||||
"template": textTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.image",
|
||||
"template": imageTemplate
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "FixedController",
|
||||
"implementation": FixedController,
|
||||
"depends": [
|
||||
"$scope",
|
||||
"$q",
|
||||
"dialogService",
|
||||
"openmct",
|
||||
"$element"
|
||||
]
|
||||
}
|
||||
],
|
||||
"toolbars": [
|
||||
{
|
||||
name: "Fixed Position Toolbar",
|
||||
key: "fixed.position",
|
||||
description: "Toolbar for the selected element inside a fixed position display.",
|
||||
forSelection: function (selection) {
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (openmct.editor.isEditing() &&
|
||||
selection[0] && selection[0].context.elementProxy &&
|
||||
((selection[1] && selection[1].context.item.type === 'telemetry.fixed') ||
|
||||
(selection[0] && selection[0].context.item && selection[0].context.item.type === 'telemetry.fixed')));
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
var imageProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "url"];
|
||||
var boxProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "fill"];
|
||||
var textProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "fill", "color", "size", "text"];
|
||||
var lineProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "x2", "y2"];
|
||||
var telemetryProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "fill", "color", "size", "titled"];
|
||||
var fixedPageProperties = ["add"];
|
||||
|
||||
var properties = [],
|
||||
fixedItem = selection[0] && selection[0].context.item,
|
||||
elementProxy = selection[0] && selection[0].context.elementProxy,
|
||||
domainObject = selection[1] && selection[1].context.item,
|
||||
path;
|
||||
|
||||
if (elementProxy) {
|
||||
var type = elementProxy.element.type;
|
||||
path = "configuration['fixed-display'].elements[" + elementProxy.index + "]";
|
||||
properties =
|
||||
type === 'fixed.image' ? imageProperties :
|
||||
type === 'fixed.text' ? textProperties :
|
||||
type === 'fixed.box' ? boxProperties :
|
||||
type === 'fixed.line' ? lineProperties :
|
||||
type === 'fixed.telemetry' ? telemetryProperties : [];
|
||||
} else if (fixedItem) {
|
||||
properties = domainObject && domainObject.type === 'layout' ? [] : fixedPageProperties;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
control: "menu",
|
||||
domainObject: domainObject || selection[0].context.item,
|
||||
method: function (option) {
|
||||
selection[0].context.fixedController.add(option.key);
|
||||
},
|
||||
key: "add",
|
||||
icon: "icon-plus",
|
||||
label: "Add",
|
||||
options: [
|
||||
{
|
||||
"name": "Box",
|
||||
"class": "icon-box",
|
||||
"key": "fixed.box"
|
||||
},
|
||||
{
|
||||
"name": "Line",
|
||||
"class": "icon-line-horz",
|
||||
"key": "fixed.line"
|
||||
},
|
||||
{
|
||||
"name": "Text",
|
||||
"class": "icon-T",
|
||||
"key": "fixed.text"
|
||||
},
|
||||
{
|
||||
"name": "Image",
|
||||
"class": "icon-image",
|
||||
"key": "fixed.image"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "menu",
|
||||
domainObject: domainObject,
|
||||
method: function (option) {
|
||||
console.log('option', option)
|
||||
selection[0].context.fixedController.order(
|
||||
selection[0].context.elementProxy,
|
||||
option.key
|
||||
);
|
||||
},
|
||||
key: "order",
|
||||
icon: "icon-layers",
|
||||
title: "Move the selected object above or below other objects",
|
||||
options: [
|
||||
{
|
||||
"name": "Move to Top",
|
||||
"class": "icon-arrow-double-up",
|
||||
"key": "top"
|
||||
},
|
||||
{
|
||||
"name": "Move Up",
|
||||
"class": "icon-arrow-up",
|
||||
"key": "up"
|
||||
},
|
||||
{
|
||||
"name": "Move Down",
|
||||
"class": "icon-arrow-down",
|
||||
"key": "down"
|
||||
},
|
||||
{
|
||||
"name": "Move to Bottom",
|
||||
"class": "icon-arrow-double-down",
|
||||
"key": "bottom"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "color-picker",
|
||||
domainObject: domainObject,
|
||||
property: path + ".fill",
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color",
|
||||
key: 'fill'
|
||||
},
|
||||
{
|
||||
control: "color-picker",
|
||||
domainObject: domainObject,
|
||||
property: path + ".stroke",
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color",
|
||||
key: 'stroke'
|
||||
},
|
||||
{
|
||||
control: "button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".url",
|
||||
icon: "icon-image",
|
||||
title: "Edit image properties",
|
||||
key: 'url',
|
||||
dialog: {
|
||||
control: "input",
|
||||
type: "text",
|
||||
name: "Image URL",
|
||||
class: "l-input-lg",
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
control: "color-picker",
|
||||
domainObject: domainObject,
|
||||
property: path + ".color",
|
||||
icon: "icon-T",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
key: 'color'
|
||||
},
|
||||
{
|
||||
control: "select-menu",
|
||||
domainObject: domainObject,
|
||||
property: path + ".size",
|
||||
title: "Set text size",
|
||||
key: 'size',
|
||||
options: [9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96].map(function (size) {
|
||||
return { "value": size + "px"};
|
||||
})
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".x",
|
||||
label: "X",
|
||||
title: "X position",
|
||||
key: "x",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".y",
|
||||
label: "Y",
|
||||
title: "Y position",
|
||||
key: "y",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".x",
|
||||
label: "X1",
|
||||
title: "X1 position",
|
||||
key: "x1",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".y",
|
||||
label: "Y1",
|
||||
title: "Y1 position",
|
||||
key: "y1",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".x2",
|
||||
label: "X2",
|
||||
title: "X2 position",
|
||||
key: "x2",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".y2",
|
||||
label: "Y2",
|
||||
title: "Y2 position",
|
||||
key: "y2",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".height",
|
||||
label: "H",
|
||||
title: "Resize object height",
|
||||
key: "height",
|
||||
class: "l-input-sm",
|
||||
min: "1"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".width",
|
||||
label: "W",
|
||||
title: "Resize object width",
|
||||
key: "width",
|
||||
class: "l-input-sm",
|
||||
min: "1"
|
||||
},
|
||||
{
|
||||
control: "toggle-button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".useGrid",
|
||||
key: "useGrid",
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-grid-snap-to',
|
||||
title: 'Snap to grid'
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-grid-snap-no',
|
||||
title: "Do not snap to grid"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".text",
|
||||
icon: "icon-gear",
|
||||
title: "Edit text properties",
|
||||
key: "text",
|
||||
dialog: {
|
||||
control: "input",
|
||||
type: "text",
|
||||
name: "Text",
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
control: "toggle-button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".titled",
|
||||
key: "titled",
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-two-parts-both',
|
||||
title: 'Show label'
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-two-parts-one-only',
|
||||
title: "Hide label"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "button",
|
||||
domainObject: domainObject,
|
||||
method: function () {
|
||||
selection[0].context.fixedController.remove(
|
||||
selection[0].context.elementProxy
|
||||
);
|
||||
},
|
||||
key: "remove",
|
||||
icon: "icon-trash"
|
||||
}
|
||||
].filter(function (item) {
|
||||
var filtered;
|
||||
|
||||
properties.forEach(function (property) {
|
||||
if (item.property && item.key === property ||
|
||||
item.method && item.key === property) {
|
||||
filtered = item;
|
||||
}
|
||||
});
|
||||
|
||||
return filtered;
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"key": "telemetry.fixed",
|
||||
"name": "Fixed Position Display",
|
||||
"cssClass": "icon-box-with-dashed-lines",
|
||||
"description": "Collect and display telemetry elements in " +
|
||||
"alphanumeric format in a simple canvas workspace. " +
|
||||
"Elements can be positioned and sized. " +
|
||||
"Lines, boxes and images can be added as well.",
|
||||
"priority": 899,
|
||||
"delegates": [
|
||||
"telemetry"
|
||||
],
|
||||
"features": "creation",
|
||||
"contains": [
|
||||
{
|
||||
"has": "telemetry"
|
||||
}
|
||||
],
|
||||
"model": {
|
||||
"layoutGrid": [64, 16],
|
||||
"composition": []
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "Layout Grid",
|
||||
"control": "composite",
|
||||
"items": [
|
||||
{
|
||||
"name": "Horizontal grid (px)",
|
||||
"control": "textfield",
|
||||
"cssClass": "l-input-sm l-numeric"
|
||||
},
|
||||
{
|
||||
"name": "Vertical grid (px)",
|
||||
"control": "textfield",
|
||||
"cssClass": "l-input-sm l-numeric"
|
||||
}
|
||||
],
|
||||
"pattern": "^(\\d*[1-9]\\d*)?$",
|
||||
"property": "layoutGrid",
|
||||
"conversion": "number[]"
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
"fixed-display"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
openmct.legacyRegistry.enable("platform/features/fixed");
|
||||
}
|
||||
}
|
||||
});
|
@ -1,720 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[
|
||||
'lodash',
|
||||
'./FixedProxy',
|
||||
'./elements/ElementProxies',
|
||||
'./FixedDragHandle',
|
||||
'../../../../src/api/objects/object-utils'
|
||||
],
|
||||
function (
|
||||
_,
|
||||
FixedProxy,
|
||||
ElementProxies,
|
||||
FixedDragHandle,
|
||||
objectUtils
|
||||
) {
|
||||
|
||||
var DEFAULT_DIMENSIONS = [2, 1];
|
||||
|
||||
// Convert from element x/y/width/height to an
|
||||
// appropriate ng-style argument, to position elements.
|
||||
function convertPosition(elementProxy) {
|
||||
if (elementProxy.getStyle) {
|
||||
return elementProxy.getStyle();
|
||||
}
|
||||
|
||||
var gridSize = elementProxy.getGridSize();
|
||||
|
||||
// Multiply position/dimensions by grid size
|
||||
return {
|
||||
left: (gridSize[0] * elementProxy.element.x) + 'px',
|
||||
top: (gridSize[1] * elementProxy.element.y) + 'px',
|
||||
width: (gridSize[0] * elementProxy.element.width) + 'px',
|
||||
height: (gridSize[1] * elementProxy.element.height) + 'px'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The FixedController is responsible for supporting the
|
||||
* Fixed Position view. It arranges frames according to saved
|
||||
* configuration and provides methods for updating these based on
|
||||
* mouse movement.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {Scope} $scope the controller's Angular scope
|
||||
*/
|
||||
function FixedController($scope, $q, dialogService, openmct, $element) {
|
||||
this.names = {}; // Cache names by ID
|
||||
this.values = {}; // Cache values by ID
|
||||
this.elementProxiesById = {};
|
||||
this.telemetryObjects = {};
|
||||
this.subscriptions = {};
|
||||
this.openmct = openmct;
|
||||
this.$element = $element;
|
||||
this.$scope = $scope;
|
||||
this.dialogService = dialogService;
|
||||
this.$q = $q;
|
||||
this.newDomainObject = $scope.domainObject.useCapability('adapter');
|
||||
this.fixedViewSelectable = false;
|
||||
|
||||
var self = this;
|
||||
[
|
||||
'digest',
|
||||
'fetchHistoricalData',
|
||||
'getTelemetry',
|
||||
'setDisplayedValue',
|
||||
'subscribeToObject',
|
||||
'unsubscribe',
|
||||
'updateView'
|
||||
].forEach(function (name) {
|
||||
self[name] = self[name].bind(self);
|
||||
});
|
||||
|
||||
// Decorate an element for display
|
||||
function makeProxyElement(element, index, elements) {
|
||||
var ElementProxy = ElementProxies[element.type],
|
||||
e = ElementProxy && new ElementProxy(element, index, elements, self.gridSize);
|
||||
|
||||
if (e) {
|
||||
// Provide a displayable position (convert from grid to px)
|
||||
e.style = convertPosition(e);
|
||||
// Template names are same as type names, presently
|
||||
e.template = element.type;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
// Decorate elements in the current configuration
|
||||
function refreshElements() {
|
||||
var elements = (((self.newDomainObject.configuration || {})['fixed-display'] || {}).elements || []);
|
||||
|
||||
// Create the new proxies...
|
||||
self.elementProxies = elements.map(makeProxyElement);
|
||||
|
||||
if (self.selectedElementProxy) {
|
||||
// If selection is not in array, select parent.
|
||||
// Otherwise, set the element to select after refresh.
|
||||
var index = elements.indexOf(self.selectedElementProxy.element);
|
||||
if (index === -1) {
|
||||
self.$element[0].click();
|
||||
} else if (!self.elementToSelectAfterRefresh) {
|
||||
self.elementToSelectAfterRefresh = self.elementProxies[index].element;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, rebuild lists of elements by id to
|
||||
// facilitate faster update when new telemetry comes in.
|
||||
self.elementProxiesById = {};
|
||||
self.elementProxies.forEach(function (elementProxy) {
|
||||
var id = elementProxy.id;
|
||||
if (elementProxy.element.type === 'fixed.telemetry') {
|
||||
// Provide it a cached name/value to avoid flashing
|
||||
elementProxy.name = self.names[id];
|
||||
elementProxy.value = self.values[id];
|
||||
self.elementProxiesById[id] = self.elementProxiesById[id] || [];
|
||||
self.elementProxiesById[id].push(elementProxy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger a new query for telemetry data
|
||||
function updateDisplayBounds(bounds, isTick) {
|
||||
if (!isTick) {
|
||||
//Reset values
|
||||
self.values = {};
|
||||
refreshElements();
|
||||
|
||||
//Fetch new data
|
||||
Object.values(self.telemetryObjects).forEach(function (object) {
|
||||
self.fetchHistoricalData(object);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add an element to this view
|
||||
function addElement(element) {
|
||||
var index;
|
||||
var elements = (((self.newDomainObject.configuration || {})['fixed-display'] || {}).elements || []);
|
||||
elements.push(element);
|
||||
|
||||
if (self.selectedElementProxy) {
|
||||
index = elements.indexOf(self.selectedElementProxy.element);
|
||||
}
|
||||
|
||||
self.mutate("configuration['fixed-display'].elements", elements);
|
||||
elements = (self.newDomainObject.configuration)['fixed-display'].elements || [];
|
||||
self.elementToSelectAfterRefresh = elements[elements.length - 1];
|
||||
|
||||
if (self.selectedElementProxy) {
|
||||
// Update the selected element with the new
|
||||
// value since newDomainOject is mutated.
|
||||
self.selectedElementProxy.element = elements[index];
|
||||
}
|
||||
refreshElements();
|
||||
}
|
||||
|
||||
// Position a panel after a drop event
|
||||
function handleDrop(e, id, position) {
|
||||
// Don't handle this event if it has already been handled
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Store the position of this element.
|
||||
// color is set to "" to let the CSS theme determine the default color
|
||||
addElement({
|
||||
type: "fixed.telemetry",
|
||||
x: Math.floor(position.x / self.gridSize[0]),
|
||||
y: Math.floor(position.y / self.gridSize[1]),
|
||||
id: id,
|
||||
stroke: "transparent",
|
||||
color: "",
|
||||
titled: true,
|
||||
width: DEFAULT_DIMENSIONS[0],
|
||||
height: DEFAULT_DIMENSIONS[1],
|
||||
useGrid: true
|
||||
});
|
||||
|
||||
// Subscribe to the new object to get telemetry
|
||||
self.openmct.objects.get(id).then(function (object) {
|
||||
self.getTelemetry(object);
|
||||
});
|
||||
}
|
||||
|
||||
this.elementProxies = [];
|
||||
this.addElement = addElement;
|
||||
this.refreshElements = refreshElements;
|
||||
this.fixedProxy = new FixedProxy(this.addElement, this.$q, this.dialogService);
|
||||
|
||||
this.composition = this.openmct.composition.get(this.newDomainObject);
|
||||
this.composition.on('add', this.onCompositionAdd, this);
|
||||
this.composition.on('remove', this.onCompositionRemove, this);
|
||||
this.composition.load();
|
||||
|
||||
// Position panes where they are dropped
|
||||
$scope.$on("mctDrop", handleDrop);
|
||||
|
||||
$scope.$on("$destroy", this.destroy.bind(this));
|
||||
|
||||
// Respond to external bounds changes
|
||||
this.openmct.time.on("bounds", updateDisplayBounds);
|
||||
|
||||
this.openmct.selection.on('change', this.setSelection.bind(this));
|
||||
this.openmct.editor.on('isEditing', this.handleEditing.bind(this));
|
||||
|
||||
this.$element.on('click', this.bypassSelection.bind(this));
|
||||
this.unlisten = this.openmct.objects.observe(this.newDomainObject, '*', function (obj) {
|
||||
this.newDomainObject = JSON.parse(JSON.stringify(obj));
|
||||
this.updateElementPositions(this.newDomainObject.layoutGrid);
|
||||
}.bind(this));
|
||||
|
||||
this.updateElementPositions(this.newDomainObject.layoutGrid);
|
||||
refreshElements();
|
||||
}
|
||||
|
||||
FixedController.prototype.updateElementPositions = function (layoutGrid) {
|
||||
this.gridSize = layoutGrid;
|
||||
|
||||
this.elementProxies.forEach(function (elementProxy) {
|
||||
elementProxy.setGridSize(this.gridSize);
|
||||
elementProxy.style = convertPosition(elementProxy);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
FixedController.prototype.onCompositionAdd = function (object) {
|
||||
this.getTelemetry(object);
|
||||
};
|
||||
|
||||
FixedController.prototype.onCompositionRemove = function (identifier) {
|
||||
// Defer mutation of newDomainObject to prevent mutating an
|
||||
// outdated version since this is triggered by a composition change.
|
||||
setTimeout(function () {
|
||||
var id = objectUtils.makeKeyString(identifier);
|
||||
var elements = this.newDomainObject.configuration['fixed-display'].elements || [];
|
||||
var newElements = elements.filter(function (proxy) {
|
||||
return proxy.id !== id;
|
||||
});
|
||||
this.mutate("configuration['fixed-display'].elements", newElements);
|
||||
|
||||
if (this.subscriptions[id]) {
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
}
|
||||
|
||||
delete this.telemetryObjects[id];
|
||||
this.refreshElements();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes an element from the view.
|
||||
*
|
||||
* @param {Object} elementProxy the element proxy to remove.
|
||||
*/
|
||||
FixedController.prototype.remove = function (elementProxy) {
|
||||
var element = elementProxy.element;
|
||||
var elements = this.newDomainObject.configuration['fixed-display'].elements || [];
|
||||
elements.splice(elements.indexOf(element), 1);
|
||||
|
||||
if (element.type === 'fixed.telemetry') {
|
||||
this.newDomainObject.composition = this.newDomainObject.composition.filter(function (identifier) {
|
||||
return objectUtils.makeKeyString(identifier) !== element.id;
|
||||
});
|
||||
}
|
||||
|
||||
this.mutate("configuration['fixed-display'].elements", elements);
|
||||
this.refreshElements();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a new element to the view.
|
||||
*
|
||||
* @param {string} type the type of element to add. Supported types are:
|
||||
* `fixed.image`
|
||||
* `fixed.box`
|
||||
* `fixed.text`
|
||||
* `fixed.line`
|
||||
*/
|
||||
FixedController.prototype.add = function (type) {
|
||||
this.fixedProxy.add(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the display order of the element proxy.
|
||||
*/
|
||||
FixedController.prototype.order = function (elementProxy, position) {
|
||||
var elements = elementProxy.order(position);
|
||||
|
||||
// Find the selected element index in the updated array.
|
||||
var selectedElemenetIndex = elements.indexOf(this.selectedElementProxy.element);
|
||||
|
||||
this.mutate("configuration['fixed-display'].elements", elements);
|
||||
elements = (this.newDomainObject.configuration)['fixed-display'].elements || [];
|
||||
|
||||
// Update the selected element with the new
|
||||
// value since newDomainOject is mutated.
|
||||
this.selectedElementProxy.element = elements[selectedElemenetIndex];
|
||||
this.refreshElements();
|
||||
};
|
||||
|
||||
FixedController.prototype.generateDragHandle = function (elementProxy, elementHandle) {
|
||||
var index = this.elementProxies.indexOf(elementProxy);
|
||||
|
||||
if (elementHandle) {
|
||||
elementHandle.element = elementProxy.element;
|
||||
elementProxy = elementHandle;
|
||||
}
|
||||
|
||||
return new FixedDragHandle(
|
||||
elementProxy,
|
||||
"configuration['fixed-display'].elements[" + index + "]",
|
||||
this
|
||||
);
|
||||
};
|
||||
|
||||
FixedController.prototype.generateDragHandles = function (elementProxy) {
|
||||
return elementProxy.handles().map(function (handle) {
|
||||
return this.generateDragHandle(elementProxy, handle);
|
||||
}, this);
|
||||
};
|
||||
|
||||
FixedController.prototype.updateSelectionStyle = function () {
|
||||
this.selectedElementProxy.style = convertPosition(this.selectedElementProxy);
|
||||
};
|
||||
|
||||
FixedController.prototype.setSelection = function (selectable) {
|
||||
var selection = selectable[0];
|
||||
|
||||
if (this.selectionListeners) {
|
||||
this.selectionListeners.forEach(function (l) {
|
||||
l();
|
||||
});
|
||||
}
|
||||
|
||||
this.selectionListeners = [];
|
||||
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection.context.elementProxy) {
|
||||
this.selectedElementProxy = selection.context.elementProxy;
|
||||
this.attachSelectionListeners();
|
||||
this.mvHandle = this.generateDragHandle(this.selectedElementProxy);
|
||||
this.resizeHandles = this.generateDragHandles(this.selectedElementProxy);
|
||||
} else {
|
||||
// Make fixed view selectable if it's not already.
|
||||
if (!this.fixedViewSelectable && selectable.length === 1) {
|
||||
this.fixedViewSelectable = true;
|
||||
selection.context.fixedController = this;
|
||||
this.openmct.selection.select(selection);
|
||||
}
|
||||
|
||||
this.resizeHandles = [];
|
||||
this.mvHandle = undefined;
|
||||
this.selectedElementProxy = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
FixedController.prototype.attachSelectionListeners = function () {
|
||||
var index = this.elementProxies.indexOf(this.selectedElementProxy);
|
||||
var path = "configuration['fixed-display'].elements[" + index + "]";
|
||||
|
||||
this.selectionListeners.push(this.openmct.objects.observe(this.newDomainObject, path + ".useGrid", function (newValue) {
|
||||
if (this.selectedElementProxy.useGrid() !== newValue) {
|
||||
this.selectedElementProxy.useGrid(newValue);
|
||||
this.updateSelectionStyle();
|
||||
this.openmct.objects.mutate(this.newDomainObject, path, this.selectedElementProxy.element);
|
||||
}
|
||||
}.bind(this)));
|
||||
[
|
||||
"width",
|
||||
"height",
|
||||
"stroke",
|
||||
"fill",
|
||||
"x",
|
||||
"y",
|
||||
"x1",
|
||||
"y1",
|
||||
"x2",
|
||||
"y2",
|
||||
"color",
|
||||
"size",
|
||||
"text",
|
||||
"titled"
|
||||
].forEach(function (property) {
|
||||
this.selectionListeners.push(this.openmct.objects.observe(this.newDomainObject, path + "." + property, function (newValue) {
|
||||
this.selectedElementProxy.element[property] = newValue;
|
||||
this.updateSelectionStyle();
|
||||
}.bind(this)));
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
FixedController.prototype.destroy = function () {
|
||||
this.unsubscribe();
|
||||
this.unlisten();
|
||||
this.openmct.time.off("bounds", this.updateDisplayBounds);
|
||||
this.openmct.selection.off("change", this.setSelection);
|
||||
this.composition.off('add', this.onCompositionAdd, this);
|
||||
this.composition.off('remove', this.onCompositionRemove, this);
|
||||
this.openmct.editor.off('isEditing', this.handleEditing, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* A rate-limited digest function. Caps digests at 60Hz
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.digest = function () {
|
||||
var self = this;
|
||||
|
||||
if (!this.digesting) {
|
||||
this.digesting = true;
|
||||
requestAnimationFrame(function () {
|
||||
self.$scope.$digest();
|
||||
self.digesting = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unsubscribe all listeners
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.unsubscribe = function () {
|
||||
Object.values(this.subscriptions).forEach(function (unsubscribeFunc) {
|
||||
unsubscribeFunc();
|
||||
});
|
||||
this.subscriptions = {};
|
||||
this.telemetryObjects = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribe to the given domain object
|
||||
* @private
|
||||
* @param {object} object Domain object to subscribe to
|
||||
* @returns {object} The provided object, for chaining.
|
||||
*/
|
||||
FixedController.prototype.subscribeToObject = function (object) {
|
||||
var self = this;
|
||||
var timeAPI = this.openmct.time;
|
||||
var id = objectUtils.makeKeyString(object.identifier);
|
||||
this.subscriptions[id] = self.openmct.telemetry.subscribe(object, function (datum) {
|
||||
if (timeAPI.clock() !== undefined) {
|
||||
self.updateView(object, datum);
|
||||
}
|
||||
}, {});
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
/**
|
||||
* Print the values from the given datum against the provided object in the view.
|
||||
* @private
|
||||
* @param {object} telemetryObject The domain object associated with the given telemetry data
|
||||
* @param {object} datum The telemetry datum containing the values to print
|
||||
*/
|
||||
FixedController.prototype.updateView = function (telemetryObject, datum) {
|
||||
var metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
var valueMetadata = this.chooseValueMetadataToDisplay(metadata);
|
||||
var formattedTelemetryValue = this.getFormattedTelemetryValueForKey(valueMetadata, datum);
|
||||
var limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
||||
var alarm = limitEvaluator && limitEvaluator.evaluate(datum, valueMetadata);
|
||||
|
||||
this.setDisplayedValue(
|
||||
telemetryObject,
|
||||
formattedTelemetryValue,
|
||||
alarm && alarm.cssClass
|
||||
);
|
||||
this.digest();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.getFormattedTelemetryValueForKey = function (valueMetadata, datum) {
|
||||
var formatter = this.openmct.telemetry.getValueFormatter(valueMetadata);
|
||||
|
||||
return formatter.format(datum);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.chooseValueMetadataToDisplay = function (metadata) {
|
||||
// If there is a range value, show that preferentially
|
||||
var valueMetadata = metadata.valuesForHints(['range'])[0];
|
||||
|
||||
// If no range is defined, default to the highest priority non time-domain data.
|
||||
if (valueMetadata === undefined) {
|
||||
var valuesOrderedByPriority = metadata.values();
|
||||
valueMetadata = valuesOrderedByPriority.filter(function (values) {
|
||||
return !(values.hints.domain);
|
||||
})[0];
|
||||
}
|
||||
|
||||
return valueMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the last historical data point for the given domain object
|
||||
* @param {object} object
|
||||
* @returns {object} the provided object for chaining.
|
||||
*/
|
||||
FixedController.prototype.fetchHistoricalData = function (object) {
|
||||
var bounds = this.openmct.time.bounds();
|
||||
var self = this;
|
||||
|
||||
self.openmct.telemetry.request(object, {start: bounds.start, end: bounds.end, size: 1})
|
||||
.then(function (data) {
|
||||
if (data.length > 0) {
|
||||
self.updateView(object, data[data.length - 1]);
|
||||
}
|
||||
});
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Print a value to the onscreen element associated with a given telemetry object.
|
||||
* @private
|
||||
* @param {object} telemetryObject The telemetry object associated with the value
|
||||
* @param {string | number} value The value to print to screen
|
||||
* @param {string} [cssClass] an optional CSS class to apply to the onscreen element.
|
||||
*/
|
||||
FixedController.prototype.setDisplayedValue = function (telemetryObject, value, cssClass) {
|
||||
var id = objectUtils.makeKeyString(telemetryObject.identifier);
|
||||
var self = this;
|
||||
|
||||
(self.elementProxiesById[id] || []).forEach(function (element) {
|
||||
self.names[id] = telemetryObject.name;
|
||||
self.values[id] = value;
|
||||
element.name = self.names[id];
|
||||
element.value = self.values[id];
|
||||
element.cssClass = cssClass;
|
||||
});
|
||||
};
|
||||
|
||||
FixedController.prototype.getTelemetry = function (domainObject) {
|
||||
var id = objectUtils.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (this.subscriptions[id]) {
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
}
|
||||
delete this.telemetryObjects[id];
|
||||
|
||||
if (!this.openmct.telemetry.isTelemetryObject(domainObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize display
|
||||
this.telemetryObjects[id] = domainObject;
|
||||
this.setDisplayedValue(domainObject, "");
|
||||
|
||||
return Promise.resolve(domainObject)
|
||||
.then(this.fetchHistoricalData)
|
||||
.then(this.subscribeToObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of the grid, in pixels. The returned array
|
||||
* is in the form `[x, y]`.
|
||||
* @returns {number[]} the grid size
|
||||
* @memberof platform/features/layout.FixedController#
|
||||
*/
|
||||
FixedController.prototype.getGridSize = function () {
|
||||
return this.gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an array of elements in this panel; these are
|
||||
* decorated proxies for both selection and display.
|
||||
* @returns {Array} elements in this panel
|
||||
*/
|
||||
FixedController.prototype.getElements = function () {
|
||||
return this.elementProxies;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the element should be selected or not.
|
||||
*
|
||||
* @param elementProxy the element to check
|
||||
* @returns {boolean} true if the element should be selected.
|
||||
*/
|
||||
FixedController.prototype.shouldSelect = function (elementProxy) {
|
||||
if (elementProxy.element === this.elementToSelectAfterRefresh) {
|
||||
delete this.elementToSelectAfterRefresh;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if an element is currently selected.
|
||||
*
|
||||
* @returns {boolean} true if an element is selected.
|
||||
*/
|
||||
FixedController.prototype.isElementSelected = function () {
|
||||
return (this.selectedElementProxy) ? true : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the style for the selected element.
|
||||
*
|
||||
* @returns {string} element style
|
||||
*/
|
||||
FixedController.prototype.getSelectedElementStyle = function () {
|
||||
return (this.selectedElementProxy) ? this.selectedElementProxy.style : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the selected element.
|
||||
*
|
||||
* @returns the selected element
|
||||
*/
|
||||
FixedController.prototype.getSelectedElement = function () {
|
||||
return this.selectedElementProxy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prevents the event from bubbling up if drag is in progress.
|
||||
*/
|
||||
FixedController.prototype.bypassSelection = function ($event) {
|
||||
if (this.dragInProgress) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get drag handles.
|
||||
* @returns {platform/features/layout.FixedDragHandle[]}
|
||||
* drag handles for the current selection
|
||||
*/
|
||||
FixedController.prototype.handles = function () {
|
||||
return this.resizeHandles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the handle to handle dragging to reposition an element.
|
||||
* @returns {platform/features/layout.FixedDragHandle} the drag handle
|
||||
*/
|
||||
FixedController.prototype.moveHandle = function () {
|
||||
return this.mvHandle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the selection context.
|
||||
*
|
||||
* @param elementProxy the element proxy
|
||||
* @returns {object} the context object which includes elementProxy
|
||||
*/
|
||||
FixedController.prototype.getContext = function (elementProxy) {
|
||||
return {
|
||||
elementProxy: elementProxy,
|
||||
fixedController: this
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* End drag.
|
||||
*
|
||||
* @param handle the resize handle
|
||||
*/
|
||||
FixedController.prototype.endDrag = function (handle) {
|
||||
this.dragInProgress = true;
|
||||
|
||||
setTimeout(function () {
|
||||
this.dragInProgress = false;
|
||||
}.bind(this), 0);
|
||||
|
||||
if (handle) {
|
||||
handle.endDrag();
|
||||
} else {
|
||||
this.moveHandle().endDrag();
|
||||
}
|
||||
};
|
||||
|
||||
FixedController.prototype.mutate = function (path, value) {
|
||||
this.openmct.objects.mutate(this.newDomainObject, path, value);
|
||||
};
|
||||
|
||||
FixedController.prototype.handleEditing = function (isEditing) {
|
||||
// Listen for edit mode changes and update selection if necessary.
|
||||
// Mainly to ensure fixedController is on the selection context when editing.
|
||||
this.setSelection(this.openmct.selection.get());
|
||||
}
|
||||
|
||||
return FixedController;
|
||||
}
|
||||
);
|
@ -1,110 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
// Drag handle dimensions
|
||||
var DRAG_HANDLE_SIZE = [6, 6];
|
||||
|
||||
/**
|
||||
* Template-displayable drag handle for an element in fixed
|
||||
* position mode.
|
||||
*
|
||||
* @param elementHandle the element handle
|
||||
* @param configPath the configuration path of an element
|
||||
* @param {Object} fixedControl the fixed controller
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
*/
|
||||
function FixedDragHandle(elementHandle, configPath, fixedControl) {
|
||||
this.elementHandle = elementHandle;
|
||||
this.configPath = configPath;
|
||||
this.fixedControl = fixedControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a CSS style to position this drag handle.
|
||||
*
|
||||
* @returns CSS style object (for `ng-style`)
|
||||
* @memberof platform/features/layout.FixedDragHandle#
|
||||
*/
|
||||
FixedDragHandle.prototype.style = function () {
|
||||
var gridSize = this.elementHandle.getGridSize();
|
||||
|
||||
// Adjust from grid to pixel coordinates
|
||||
var x = this.elementHandle.x() * gridSize[0],
|
||||
y = this.elementHandle.y() * gridSize[1];
|
||||
|
||||
// Convert to a CSS style centered on that point
|
||||
return {
|
||||
left: (x - DRAG_HANDLE_SIZE[0] / 2) + 'px',
|
||||
top: (y - DRAG_HANDLE_SIZE[1] / 2) + 'px',
|
||||
width: DRAG_HANDLE_SIZE[0] + 'px',
|
||||
height: DRAG_HANDLE_SIZE[1] + 'px'
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a drag gesture. This should be called when a drag
|
||||
* begins to track initial state.
|
||||
*/
|
||||
FixedDragHandle.prototype.startDrag = function () {
|
||||
// Cache initial x/y positions
|
||||
this.dragging = {
|
||||
x: this.elementHandle.x(),
|
||||
y: this.elementHandle.y()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Continue a drag gesture; update x/y positions.
|
||||
*
|
||||
* @param {number[]} delta x/y pixel difference since drag started
|
||||
*/
|
||||
FixedDragHandle.prototype.continueDrag = function (delta) {
|
||||
var gridSize = this.elementHandle.getGridSize();
|
||||
|
||||
if (this.dragging) {
|
||||
// Update x/y positions (snapping to grid)
|
||||
var newX = this.dragging.x + Math.round(delta[0] / gridSize[0]);
|
||||
var newY = this.dragging.y + Math.round(delta[1] / gridSize[1]);
|
||||
|
||||
this.elementHandle.x(Math.max(0, newX));
|
||||
this.elementHandle.y(Math.max(0, newY));
|
||||
this.fixedControl.updateSelectionStyle();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End a drag gesture. This should be called when a drag
|
||||
* concludes to trigger commit of changes.
|
||||
*/
|
||||
FixedDragHandle.prototype.endDrag = function () {
|
||||
this.dragging = undefined;
|
||||
this.fixedControl.mutate(this.configPath, this.elementHandle.element);
|
||||
};
|
||||
|
||||
return FixedDragHandle;
|
||||
}
|
||||
);
|
@ -1,76 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./elements/ElementFactory'],
|
||||
function (ElementFactory) {
|
||||
|
||||
/**
|
||||
* Proxy for configuring a fixed position view via the toolbar.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {Function} addElementCallback callback to invoke when
|
||||
* elements are created
|
||||
* @param $q Angular's $q, for promise-handling
|
||||
* @param {DialogService} dialogService dialog service to use
|
||||
* when adding a new element will require user input
|
||||
*/
|
||||
function FixedProxy(addElementCallback, $q, dialogService) {
|
||||
this.factory = new ElementFactory(dialogService);
|
||||
this.$q = $q;
|
||||
this.addElementCallback = addElementCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new visual element to this view. Supported types are:
|
||||
*
|
||||
* * `fixed.image`
|
||||
* * `fixed.box`
|
||||
* * `fixed.text`
|
||||
* * `fixed.line`
|
||||
*
|
||||
* @param {string} type the type of element to add
|
||||
*/
|
||||
FixedProxy.prototype.add = function (type) {
|
||||
var addElementCallback = this.addElementCallback;
|
||||
|
||||
// Place a configured element into the view configuration
|
||||
function addElement(element) {
|
||||
// Configure common properties of the element
|
||||
element.x = element.x || 0;
|
||||
element.y = element.y || 0;
|
||||
element.width = element.width || 1;
|
||||
element.height = element.height || 1;
|
||||
element.type = type;
|
||||
element.useGrid = true;
|
||||
|
||||
// Finally, add it to the view's configuration
|
||||
addElementCallback(element);
|
||||
}
|
||||
|
||||
// Defer creation to the factory
|
||||
this.$q.when(this.factory.createElement(type)).then(addElement);
|
||||
};
|
||||
|
||||
return FixedProxy;
|
||||
}
|
||||
);
|
@ -1,115 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Handles drag interactions on frames in layouts. This will
|
||||
* provides new positions/dimensions for frames based on
|
||||
* relative pixel positions provided; these will take into account
|
||||
* the grid size (in a snap-to sense) and will enforce some minimums
|
||||
* on both position and dimensions.
|
||||
*
|
||||
* The provided position and dimensions factors will determine
|
||||
* whether this is a move or a resize, and what type of resize it
|
||||
* will be. For instance, a position factor of [1, 1]
|
||||
* will move a frame along with the mouse as the drag
|
||||
* proceeds, while a dimension factor of [0, 0] will leave
|
||||
* dimensions unchanged. Combining these in different
|
||||
* ways results in different handles; a position factor of
|
||||
* [1, 0] and a dimensions factor of [-1, 0] will implement
|
||||
* a left-edge resize, as the horizontal position will move
|
||||
* with the mouse while the horizontal dimensions shrink in
|
||||
* kind (and vertical properties remain unmodified.)
|
||||
*
|
||||
* @param {object} rawPosition the initial position/dimensions
|
||||
* of the frame being interacted with
|
||||
* @param {number[]} posFactor the position factor
|
||||
* @param {number[]} dimFactor the dimensions factor
|
||||
* @param {number[]} the size of each grid element, in pixels
|
||||
* @constructor
|
||||
* @memberof platform/features/layout
|
||||
*/
|
||||
function LayoutDrag(rawPosition, posFactor, dimFactor, gridSize) {
|
||||
this.rawPosition = rawPosition;
|
||||
this.posFactor = posFactor;
|
||||
this.dimFactor = dimFactor;
|
||||
this.gridSize = gridSize;
|
||||
}
|
||||
|
||||
// Convert a delta from pixel coordinates to grid coordinates,
|
||||
// rounding to whole-number grid coordinates.
|
||||
function toGridDelta(gridSize, pixelDelta) {
|
||||
return pixelDelta.map(function (v, i) {
|
||||
return Math.round(v / gridSize[i]);
|
||||
});
|
||||
}
|
||||
|
||||
// Utility function to perform element-by-element multiplication
|
||||
function multiply(array, factors) {
|
||||
return array.map(function (v, i) {
|
||||
return v * factors[i];
|
||||
});
|
||||
}
|
||||
|
||||
// Utility function to perform element-by-element addition
|
||||
function add(array, other) {
|
||||
return array.map(function (v, i) {
|
||||
return v + other[i];
|
||||
});
|
||||
}
|
||||
|
||||
// Utility function to perform element-by-element max-choosing
|
||||
function max(array, other) {
|
||||
return array.map(function (v, i) {
|
||||
return Math.max(v, other[i]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a new position object in grid coordinates, with
|
||||
* position and dimensions both offset appropriately
|
||||
* according to the factors supplied in the constructor.
|
||||
* @param {number[]} pixelDelta the offset from the
|
||||
* original position, in pixels
|
||||
*/
|
||||
LayoutDrag.prototype.getAdjustedPosition = function (pixelDelta) {
|
||||
var gridDelta = toGridDelta(this.gridSize, pixelDelta);
|
||||
return {
|
||||
position: max(add(
|
||||
this.rawPosition.position,
|
||||
multiply(gridDelta, this.posFactor)
|
||||
), [0, 0]),
|
||||
dimensions: max(add(
|
||||
this.rawPosition.dimensions,
|
||||
multiply(gridDelta, this.dimFactor)
|
||||
), [1, 1])
|
||||
};
|
||||
};
|
||||
|
||||
return LayoutDrag;
|
||||
|
||||
}
|
||||
);
|
@ -1,105 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'zepto',
|
||||
'../../../commonUI/general/src/services/Overlay'
|
||||
], function (
|
||||
$,
|
||||
Overlay
|
||||
) {
|
||||
/**
|
||||
* MCT Trigger Modal is intended for use in only one location: inside the
|
||||
* object-header to allow views in a layout to be popped out in a modal.
|
||||
* Users can close the modal and go back to normal, and everything generally
|
||||
* just works fine.
|
||||
*
|
||||
* This code is sensitive to how our html is constructed-- particularly with
|
||||
* how it locates the the container of an element in a layout. However, it
|
||||
* should be able to handle slight relocations so long as it is always a
|
||||
* descendent of a `.frame` element.
|
||||
*/
|
||||
function MCTTriggerModal($document) {
|
||||
|
||||
function link($scope, $element) {
|
||||
var actions = $scope.domainObject.getCapability('action'),
|
||||
notebookAction = actions.getActions({key: 'notebook-new-entry'})[0];
|
||||
|
||||
var frame = $element.parent();
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
if (frame.hasClass('frame')) {
|
||||
break;
|
||||
}
|
||||
frame = frame.parent();
|
||||
}
|
||||
if (!frame.hasClass('frame')) {
|
||||
$element.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
frame = frame[0];
|
||||
|
||||
var layoutContainer = frame.parentElement;
|
||||
|
||||
var notebookButton = notebookAction ?
|
||||
[
|
||||
{
|
||||
class: 'icon-notebook new-notebook-entry',
|
||||
title: 'New Notebook Entry',
|
||||
clickHandler: function (event) {
|
||||
event.stopPropagation();
|
||||
notebookAction.perform();
|
||||
}
|
||||
}
|
||||
] : [];
|
||||
|
||||
var overlayService = new Overlay ({
|
||||
$document: $document,
|
||||
$scope: $scope,
|
||||
$element: frame,
|
||||
overlayWillMount: function () {
|
||||
$(frame).removeClass('frame frame-template');
|
||||
layoutContainer.removeChild(frame);
|
||||
},
|
||||
overlayDidUnmount: function () {
|
||||
$(frame).addClass('frame frame-template');
|
||||
layoutContainer.appendChild(frame);
|
||||
},
|
||||
browseBarButtons: notebookButton
|
||||
});
|
||||
|
||||
$element.on('click', overlayService.toggleOverlay);
|
||||
$scope.$on('$destroy', function () {
|
||||
$element.off('click', overlayService.toggleOverlay);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: link
|
||||
};
|
||||
}
|
||||
|
||||
return MCTTriggerModal;
|
||||
|
||||
});
|
@ -1,58 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Utility function for creating getter-setter functions,
|
||||
* since these are frequently useful for element proxies.
|
||||
*
|
||||
* An optional third argument may be supplied in order to
|
||||
* constrain or modify arguments when using as a setter;
|
||||
* this argument is a function which takes two arguments
|
||||
* (the current value for the property, and the requested
|
||||
* new value.) This is useful when values need to be kept
|
||||
* in certain ranges; specifically, to keep x/y positions
|
||||
* non-negative in a fixed position view.
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {Object} object the object to get/set values upon
|
||||
* @param {string} key the property to get/set
|
||||
* @param {function} [updater] function used to process updates
|
||||
*/
|
||||
function AccessorMutator(object, key, updater) {
|
||||
return function (value) {
|
||||
if (arguments.length > 0) {
|
||||
object[key] = updater ?
|
||||
updater(value, object[key]) :
|
||||
value;
|
||||
}
|
||||
return object[key];
|
||||
};
|
||||
}
|
||||
|
||||
return AccessorMutator;
|
||||
}
|
||||
);
|
@ -1,61 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./ElementProxy', './AccessorMutator'],
|
||||
function (ElementProxy, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection proxy for Box elements in a fixed position view.
|
||||
* Also serves as a superclass for Text elements, since those
|
||||
* elements have a superset of Box properties.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @param {Array} elements the full array of elements
|
||||
*/
|
||||
function BoxProxy(element, index, elements, gridSize) {
|
||||
var proxy = new ElementProxy(element, index, elements, gridSize);
|
||||
|
||||
/**
|
||||
* Get/set this element's fill color. (Omitting the
|
||||
* argument makes this act as a getter.)
|
||||
* @method
|
||||
* @param {string} fill the new fill color
|
||||
* @returns {string} the fill color
|
||||
* @memberof platform/features/layout.BoxProxy#
|
||||
*/
|
||||
proxy.fill = new AccessorMutator(element, 'fill');
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return BoxProxy;
|
||||
}
|
||||
);
|
@ -1,115 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
var INITIAL_STATES = {
|
||||
"fixed.image": {
|
||||
stroke: "transparent"
|
||||
},
|
||||
"fixed.box": {
|
||||
fill: "#717171",
|
||||
border: "transparent",
|
||||
stroke: "transparent"
|
||||
},
|
||||
"fixed.line": {
|
||||
x: 5,
|
||||
y: 9,
|
||||
x2: 6,
|
||||
y2: 6,
|
||||
stroke: "#717171"
|
||||
},
|
||||
"fixed.text": {
|
||||
fill: "transparent",
|
||||
stroke: "transparent",
|
||||
size: "13px"
|
||||
}
|
||||
},
|
||||
DIALOGS = {
|
||||
"fixed.image": {
|
||||
name: "Image Properties",
|
||||
sections: [
|
||||
{
|
||||
rows: [
|
||||
{
|
||||
key: "url",
|
||||
control: "textfield",
|
||||
name: "Image URL",
|
||||
"cssClass": "l-input-lg",
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"fixed.text": {
|
||||
name: "Text Element Properties",
|
||||
sections: [
|
||||
{
|
||||
rows: [
|
||||
{
|
||||
key: "text",
|
||||
control: "textfield",
|
||||
name: "Text",
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The ElementFactory creates new instances of elements for the
|
||||
* fixed position view, prompting for user input where necessary.
|
||||
* @param {DialogService} dialogService service to request user input
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
*/
|
||||
function ElementFactory(dialogService) {
|
||||
this.dialogService = dialogService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new element for the fixed position view.
|
||||
* @param {string} type the type of element to create
|
||||
* @returns {Promise|object} the created element, or a promise
|
||||
* for that element
|
||||
*/
|
||||
ElementFactory.prototype.createElement = function (type) {
|
||||
var initialState = INITIAL_STATES[type] || {};
|
||||
|
||||
// Clone that state
|
||||
initialState = JSON.parse(JSON.stringify(initialState));
|
||||
|
||||
// Show a dialog to configure initial state, if appropriate
|
||||
return DIALOGS[type] ? this.dialogService.getUserInput(
|
||||
DIALOGS[type],
|
||||
initialState
|
||||
) : initialState;
|
||||
};
|
||||
|
||||
return ElementFactory;
|
||||
}
|
||||
);
|
@ -1,35 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./TelemetryProxy', './ImageProxy', './LineProxy', './BoxProxy', './TextProxy'],
|
||||
function (TelemetryProxy, ImageProxy, LineProxy, BoxProxy, TextProxy) {
|
||||
|
||||
return {
|
||||
"fixed.telemetry": TelemetryProxy,
|
||||
"fixed.line": LineProxy,
|
||||
"fixed.box": BoxProxy,
|
||||
"fixed.image": ImageProxy,
|
||||
"fixed.text": TextProxy
|
||||
};
|
||||
}
|
||||
);
|
@ -1,209 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./AccessorMutator', './ResizeHandle', './UnitAccessorMutator'],
|
||||
function (AccessorMutator, ResizeHandle, UnitAccessorMutator) {
|
||||
|
||||
// Index deltas for changes in order
|
||||
var ORDERS = {
|
||||
top: Number.POSITIVE_INFINITY,
|
||||
up: 1,
|
||||
down: -1,
|
||||
bottom: Number.NEGATIVE_INFINITY
|
||||
};
|
||||
|
||||
// Mininmum pixel height and width for objects
|
||||
var MIN_WIDTH = 10;
|
||||
var MIN_HEIGHT = 10;
|
||||
|
||||
// Ensure a value is non-negative (for x/y setters)
|
||||
function clamp(value) {
|
||||
return Math.max(value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract superclass for other classes which provide useful
|
||||
* interfaces upon an elements in a fixed position view.
|
||||
* This handles the generic operations (e.g. remove) so that
|
||||
* subclasses only need to implement element-specific behaviors.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
*/
|
||||
function ElementProxy(element, index, elements, gridSize) {
|
||||
/**
|
||||
* The element as stored in the view configuration.
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.element = element;
|
||||
|
||||
/**
|
||||
* The current grid size of the layout.
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.gridSize = gridSize || [1,1]; //Ensure a reasonable default
|
||||
|
||||
/**
|
||||
* Get and/or set the x position of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [x] the new x position (if setting)
|
||||
* @returns {number} the x position
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.x = new AccessorMutator(element, 'x', clamp);
|
||||
|
||||
/**
|
||||
* Get and/or set the y position of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [y] the new y position (if setting)
|
||||
* @returns {number} the y position
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.y = new AccessorMutator(element, 'y', clamp);
|
||||
|
||||
/**
|
||||
* Get and/or set the stroke color of this element.
|
||||
* @param {string} [stroke] the new stroke color (if setting)
|
||||
* @returns {string} the stroke color
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.stroke = new AccessorMutator(element, 'stroke');
|
||||
|
||||
/**
|
||||
* Get and/or set the width of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [w] the new width (if setting)
|
||||
* @returns {number} the width
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.width = new AccessorMutator(element, 'width');
|
||||
|
||||
/**
|
||||
* Get and/or set the height of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [h] the new height (if setting)
|
||||
* @returns {number} the height
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.height = new AccessorMutator(element, 'height');
|
||||
|
||||
this.useGrid = new UnitAccessorMutator(this);
|
||||
this.index = index;
|
||||
this.elements = elements;
|
||||
this.resizeHandles = [new ResizeHandle(this, this.element)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the display order of this element.
|
||||
* @param {string} o where to move this element;
|
||||
* one of "top", "up", "down", or "bottom"
|
||||
* @return {Array} the full array of elements
|
||||
*/
|
||||
ElementProxy.prototype.order = function (o) {
|
||||
var index = this.index,
|
||||
elements = this.elements,
|
||||
element = this.element,
|
||||
delta = ORDERS[o] || 0,
|
||||
desired = Math.max(
|
||||
Math.min(index + delta, elements.length - 1),
|
||||
0
|
||||
);
|
||||
// Move to the desired index, if this is a change
|
||||
if ((desired !== index) && (elements[index] === element)) {
|
||||
// Splice out the current element
|
||||
elements.splice(index, 1);
|
||||
// Splice it back in at the correct index
|
||||
elements.splice(desired, 0, element);
|
||||
// Track change in index (proxy should be recreated
|
||||
// anyway, but be consistent)
|
||||
this.index = desired;
|
||||
}
|
||||
|
||||
return elements;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get handles to control specific features of this element,
|
||||
* e.g. corner size.
|
||||
* @return {platform/features/layout.ElementHandle[]} handles
|
||||
* for moving/resizing this element
|
||||
*/
|
||||
ElementProxy.prototype.handles = function () {
|
||||
return this.resizeHandles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns which grid size the element is currently using.
|
||||
* @return {number[]} The current grid size in [x,y] form if the element
|
||||
* is currently using the grid, [1,1] if it is using
|
||||
* pixels.
|
||||
*/
|
||||
ElementProxy.prototype.getGridSize = function () {
|
||||
var gridSize;
|
||||
// Default to using the grid if useGrid was not defined
|
||||
if (typeof this.element.useGrid === 'undefined') {
|
||||
this.element.useGrid = true;
|
||||
}
|
||||
if (this.element.useGrid) {
|
||||
gridSize = this.gridSize;
|
||||
} else {
|
||||
gridSize = [1,1];
|
||||
}
|
||||
return gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the current grid size stored by this element proxy
|
||||
* @param {number[]} gridSize The current layout grid size in [x,y] form
|
||||
*/
|
||||
ElementProxy.prototype.setGridSize = function (gridSize) {
|
||||
this.gridSize = gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current minimum element width in grid units
|
||||
* @return {number} The current minimum element width
|
||||
*/
|
||||
ElementProxy.prototype.getMinWidth = function () {
|
||||
return Math.ceil(MIN_WIDTH / this.getGridSize()[0]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current minimum element height in grid units
|
||||
* @return {number} The current minimum element height
|
||||
*/
|
||||
ElementProxy.prototype.getMinHeight = function () {
|
||||
return Math.ceil(MIN_HEIGHT / this.getGridSize()[1]);
|
||||
};
|
||||
|
||||
return ElementProxy;
|
||||
}
|
||||
);
|
@ -1,58 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./ElementProxy', './AccessorMutator'],
|
||||
function (ElementProxy, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection proxy for Image elements in a fixed position view.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function ImageProxy(element, index, elements, gridSize) {
|
||||
var proxy = new ElementProxy(element, index, elements, gridSize);
|
||||
|
||||
/**
|
||||
* Get and/or set the displayed text of this element.
|
||||
* @param {string} [text] the new text (if setting)
|
||||
* @returns {string} the text
|
||||
* @memberof platform/features/layout.ImageProxy#
|
||||
*/
|
||||
proxy.url = new AccessorMutator(element, 'url');
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return ImageProxy;
|
||||
}
|
||||
);
|
@ -1,94 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Handle for changing x/y position of a line's end point.
|
||||
* This is used to support drag handles for line elements
|
||||
* in a fixed position view. Field names for opposite ends
|
||||
* are provided to avoid zero-length lines.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the line element
|
||||
* @param {string} xProperty field which stores x position
|
||||
* @param {string} yProperty field which stores y position
|
||||
* @param {string} xOther field which stores x of other end
|
||||
* @param {string} yOther field which stores y of other end
|
||||
* @implements {platform/features/layout.ElementHandle}
|
||||
*/
|
||||
function LineHandle(element, elementProxy, xProperty, yProperty, xOther, yOther) {
|
||||
this.elementProxy = elementProxy;
|
||||
this.element = element;
|
||||
this.xProperty = xProperty;
|
||||
this.yProperty = yProperty;
|
||||
this.xOther = xOther;
|
||||
this.yOther = yOther;
|
||||
}
|
||||
|
||||
LineHandle.prototype.x = function (value) {
|
||||
var element = this.element,
|
||||
xProperty = this.xProperty,
|
||||
yProperty = this.yProperty,
|
||||
xOther = this.xOther,
|
||||
yOther = this.yOther;
|
||||
|
||||
if (arguments.length > 0) {
|
||||
// Ensure we stay in view
|
||||
value = Math.max(value, 0);
|
||||
// Make sure end points will still be different
|
||||
if (element[yOther] !== element[yProperty] ||
|
||||
element[xOther] !== value) {
|
||||
element[xProperty] = value;
|
||||
}
|
||||
}
|
||||
return element[xProperty];
|
||||
};
|
||||
|
||||
LineHandle.prototype.y = function (value) {
|
||||
var element = this.element,
|
||||
xProperty = this.xProperty,
|
||||
yProperty = this.yProperty,
|
||||
xOther = this.xOther,
|
||||
yOther = this.yOther;
|
||||
|
||||
if (arguments.length > 0) {
|
||||
// Ensure we stay in view
|
||||
value = Math.max(value, 0);
|
||||
// Make sure end points will still be different
|
||||
if (element[xOther] !== element[xProperty] ||
|
||||
element[yOther] !== value) {
|
||||
element[yProperty] = value;
|
||||
}
|
||||
}
|
||||
return element[yProperty];
|
||||
};
|
||||
|
||||
LineHandle.prototype.getGridSize = function () {
|
||||
return this.elementProxy.getGridSize();
|
||||
};
|
||||
|
||||
return LineHandle;
|
||||
|
||||
}
|
||||
);
|
@ -1,171 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./ElementProxy', './LineHandle', './AccessorMutator'],
|
||||
function (ElementProxy, LineHandle, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection/diplay proxy for line elements of a fixed position
|
||||
* view.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function LineProxy(element, index, elements, gridSize) {
|
||||
var proxy = new ElementProxy(element, index, elements, gridSize),
|
||||
handles = [
|
||||
new LineHandle(element, proxy, 'x', 'y', 'x2', 'y2'),
|
||||
new LineHandle(element, proxy, 'x2', 'y2', 'x', 'y')
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets style specific to line proxy.
|
||||
*/
|
||||
proxy.getStyle = function () {
|
||||
var layoutGridSize = proxy.getGridSize();
|
||||
|
||||
return {
|
||||
left: (layoutGridSize[0] * proxy.x()) + 'px',
|
||||
top: (layoutGridSize[1] * proxy.y()) + 'px',
|
||||
width: (layoutGridSize[0] * proxy.width()) + 'px',
|
||||
height: (layoutGridSize[1] * proxy.height()) + 'px'
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the top-left x coordinate, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the x coordinate
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.x = function (v) {
|
||||
var x = Math.min(element.x, element.x2),
|
||||
delta = Math.max(v, 0) - x;
|
||||
if (arguments.length > 0 && delta) {
|
||||
element.x += delta;
|
||||
element.x2 += delta;
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the top-left y coordinate, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the y coordinate
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.y = function (v) {
|
||||
var y = Math.min(element.y, element.y2),
|
||||
delta = Math.max(v, 0) - y;
|
||||
if (arguments.length > 0 && delta) {
|
||||
element.y += delta;
|
||||
element.y2 += delta;
|
||||
}
|
||||
return y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the width, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the width
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.width = function () {
|
||||
return Math.max(Math.abs(element.x - element.x2), 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the height, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the height
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.height = function () {
|
||||
return Math.max(Math.abs(element.y - element.y2), 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the x position, in grid units relative to
|
||||
* the top-left corner, of the first point in this line
|
||||
* segment.
|
||||
* @returns {number} the x position of the first point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.x1 = function () {
|
||||
return element.x - proxy.x();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the y position, in grid units relative to
|
||||
* the top-left corner, of the first point in this line
|
||||
* segment.
|
||||
* @returns {number} the y position of the first point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.y1 = function () {
|
||||
return element.y - proxy.y();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the x position, in grid units relative to
|
||||
* the top-left corner, of the second point in this line
|
||||
* segment.
|
||||
* @returns {number} the x position of the second point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.x2 = function () {
|
||||
return element.x2 - proxy.x();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the y position, in grid units relative to
|
||||
* the top-left corner, of the second point in this line
|
||||
* segment.
|
||||
* @returns {number} the y position of the second point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.y2 = function () {
|
||||
return element.y2 - proxy.y();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get element handles for changing the position of end
|
||||
* points of this line.
|
||||
* @returns {LineHandle[]} line handles for both end points
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.handles = function () {
|
||||
return handles;
|
||||
};
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return LineProxy;
|
||||
}
|
||||
);
|
@ -1,72 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* @interface platform/features/layout.ElementHandle
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle for changing width/height properties of an element.
|
||||
* This is used to support drag handles for different
|
||||
* element types in a fixed position view.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
*/
|
||||
function ResizeHandle(elementProxy, element) {
|
||||
this.elementProxy = elementProxy;
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
ResizeHandle.prototype.x = function (value) {
|
||||
var element = this.element;
|
||||
if (arguments.length > 0) {
|
||||
element.width = Math.max(
|
||||
this.elementProxy.getMinWidth(),
|
||||
value - element.x
|
||||
);
|
||||
}
|
||||
return element.x + element.width;
|
||||
};
|
||||
|
||||
ResizeHandle.prototype.y = function (value) {
|
||||
var element = this.element;
|
||||
if (arguments.length > 0) {
|
||||
element.height = Math.max(
|
||||
this.elementProxy.getMinHeight(),
|
||||
value - element.y
|
||||
);
|
||||
}
|
||||
return element.y + element.height;
|
||||
};
|
||||
|
||||
ResizeHandle.prototype.getGridSize = function () {
|
||||
return this.elementProxy.getGridSize();
|
||||
};
|
||||
|
||||
return ResizeHandle;
|
||||
|
||||
}
|
||||
);
|
@ -1,56 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./TextProxy'],
|
||||
function (TextProxy) {
|
||||
|
||||
/**
|
||||
* Selection proxy for telemetry elements in a fixed position view.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] form
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function TelemetryProxy(element, index, elements, gridSize) {
|
||||
var proxy = new TextProxy(element, index, elements, gridSize);
|
||||
|
||||
// Expose the domain object identifier
|
||||
proxy.id = element.id;
|
||||
|
||||
// Don't expose text configuration
|
||||
delete proxy.text;
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return TelemetryProxy;
|
||||
}
|
||||
);
|
@ -1,75 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./BoxProxy', './AccessorMutator'],
|
||||
function (BoxProxy, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection proxy for Text elements in a fixed position view.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function TextProxy(element, index, elements, gridSize) {
|
||||
var proxy = new BoxProxy(element, index, elements, gridSize);
|
||||
|
||||
/**
|
||||
* Get and/or set the text color of this element.
|
||||
* @param {string} [color] the new text color (if setting)
|
||||
* @returns {string} the text color
|
||||
* @memberof platform/features/layout.TextProxy#
|
||||
*/
|
||||
proxy.color = new AccessorMutator(element, 'color');
|
||||
|
||||
/**
|
||||
* Get and/or set the displayed text of this element.
|
||||
* @param {string} [text] the new text (if setting)
|
||||
* @returns {string} the text
|
||||
* @memberof platform/features/layout.TextProxy#
|
||||
*/
|
||||
proxy.text = new AccessorMutator(element, 'text');
|
||||
|
||||
/**
|
||||
* Get and/or set the text size of this element.
|
||||
*
|
||||
* @param {string} [size] the new text size (if setting)
|
||||
* @returns {string} the text size
|
||||
* @memberof platform/features/layout.TextProxy#
|
||||
*/
|
||||
proxy.size = new AccessorMutator(element, 'size');
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return TextProxy;
|
||||
}
|
||||
);
|
@ -1,92 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Variant of AccessorMutator to handle the specific case of updating
|
||||
* useGrid, in order update the positions appropriately from within
|
||||
* the scope of UnitAccessorMutator
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {ElementProxy} proxy ElementProxy object to perform the update
|
||||
* upon
|
||||
*/
|
||||
function UnitAccessorMutator(elementProxy) {
|
||||
var self = this;
|
||||
|
||||
this.elementProxy = elementProxy;
|
||||
return function (useGrid) {
|
||||
var current = elementProxy.element.useGrid;
|
||||
if (arguments.length > 0) {
|
||||
elementProxy.element.useGrid = useGrid;
|
||||
if (useGrid && !current) {
|
||||
self.convertCoordsTo('grid');
|
||||
} else if (!useGrid && current) {
|
||||
self.convertCoordsTo('px');
|
||||
}
|
||||
}
|
||||
|
||||
return elementProxy.element.useGrid;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* For the elementProxy object called upon, convert its element's
|
||||
* coordinates and size from pixels to grid units, or vice-versa.
|
||||
* @param {string} unit When called with 'px', converts grid units to
|
||||
* pixels; when called with 'grid', snaps element
|
||||
* to grid units
|
||||
*/
|
||||
UnitAccessorMutator.prototype.convertCoordsTo = function (unit) {
|
||||
var proxy = this.elementProxy,
|
||||
gridSize = proxy.gridSize,
|
||||
element = proxy.element,
|
||||
minWidth = proxy.getMinWidth(),
|
||||
minHeight = proxy.getMinHeight();
|
||||
if (unit === 'px') {
|
||||
element.x = element.x * gridSize[0];
|
||||
element.y = element.y * gridSize[1];
|
||||
element.width = element.width * gridSize[0];
|
||||
element.height = element.height * gridSize[1];
|
||||
if (element.x2 && element.y2) {
|
||||
element.x2 = element.x2 * gridSize[0];
|
||||
element.y2 = element.y2 * gridSize[1];
|
||||
}
|
||||
} else if (unit === 'grid') {
|
||||
element.x = Math.round(element.x / gridSize[0]);
|
||||
element.y = Math.round(element.y / gridSize[1]);
|
||||
element.width = Math.max(Math.round(element.width / gridSize[0]), minWidth);
|
||||
element.height = Math.max(Math.round(element.height / gridSize[1]), minHeight);
|
||||
if (element.x2 && element.y2) {
|
||||
element.x2 = Math.round(element.x2 / gridSize[0]);
|
||||
element.y2 = Math.round(element.y2 / gridSize[1]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return UnitAccessorMutator;
|
||||
}
|
||||
);
|
@ -1,26 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<div
|
||||
class="l-fixed-position-box"
|
||||
ng-style="{ background: ngModel.fill(), border: '1px ' + ngModel.stroke() + ' solid' }"
|
||||
>
|
||||
</div>
|
@ -1,26 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<div
|
||||
ng-style="{ 'background-image': 'url(' + ngModel.element.url + ')', border: '1px solid ' + ngModel.stroke() }"
|
||||
class="l-fixed-position-image"
|
||||
>
|
||||
</div>
|
@ -1,31 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<svg ng-attr-width="{{ngModel.getGridSize()[0] * ngModel.width()}}"
|
||||
ng-attr-height="{{ngModel.getGridSize()[1] * ngModel.height()}}">
|
||||
<line ng-attr-x1="{{ngModel.getGridSize()[0] * ngModel.x1() + 1}}"
|
||||
ng-attr-y1="{{ngModel.getGridSize()[1] * ngModel.y1() + 1}}"
|
||||
ng-attr-x2="{{ngModel.getGridSize()[0] * ngModel.x2() + 1}}"
|
||||
ng-attr-y2="{{ngModel.getGridSize()[1] * ngModel.y2() + 1}}"
|
||||
ng-attr-stroke="{{ngModel.stroke()}}"
|
||||
stroke-width="2">
|
||||
</line>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,39 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<div
|
||||
class="l-fixed-position-text l-telemetry"
|
||||
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color(), 'font-size': ngModel.size() }"
|
||||
>
|
||||
<span
|
||||
class="l-elem l-value l-obj-val-format"
|
||||
data-value="{{ngModel.value}}"
|
||||
ng-class="ngModel.cssClass"
|
||||
>
|
||||
{{ngModel.value}}
|
||||
</span>
|
||||
<span
|
||||
class="l-elem l-title"
|
||||
ng-show="ngModel.element.titled"
|
||||
>
|
||||
{{ngModel.name}}
|
||||
</span>
|
||||
</div>
|
@ -1,27 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<div
|
||||
class="l-fixed-position-text l-static-text"
|
||||
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color(), 'font-size': ngModel.size() }"
|
||||
>
|
||||
{{ngModel.element.text}}
|
||||
</div>
|
@ -1,62 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<div class="t-fixed-position l-fixed-position"
|
||||
ng-controller="FixedController as controller">
|
||||
|
||||
<!-- Background grid -->
|
||||
<div class="l-fixed-position__grid-holder l-grid-holder c-grid" ng-click="controller.bypassSelection($event)">
|
||||
<div class="c-grid__x l-grid l-grid-x"
|
||||
ng-if="!controller.getGridSize()[0] < 3"
|
||||
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
||||
<div class="c-grid__y l-grid l-grid-y"
|
||||
ng-if="!controller.getGridSize()[1] < 3"
|
||||
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
|
||||
</div>
|
||||
|
||||
<!-- Fixed position elements -->
|
||||
<div ng-repeat="element in controller.getElements()"
|
||||
class="l-fixed-position-item s-selectable s-moveable is-selectable is-moveable"
|
||||
ng-style="element.style"
|
||||
mct-selectable="controller.getContext(element)"
|
||||
mct-init-select="controller.shouldSelect(element)">
|
||||
<mct-include key="element.template"
|
||||
parameters="{ gridSize: controller.getGridSize() }"
|
||||
ng-model="element">
|
||||
</mct-include>
|
||||
</div>
|
||||
<!-- Selection highlight, handles -->
|
||||
<span class="c-frame-edit" ng-if="controller.isElementSelected()">
|
||||
<div class="c-frame-edit__move"
|
||||
mct-drag-down="controller.moveHandle().startDrag()"
|
||||
mct-drag="controller.moveHandle().continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()"
|
||||
ng-style="controller.getSelectedElementStyle()">
|
||||
</div>
|
||||
<div ng-repeat="handle in controller.handles()"
|
||||
class="c-frame-edit__handle c-frame-edit__handle--nwse"
|
||||
ng-style="handle.style()"
|
||||
mct-drag-down="handle.startDrag()"
|
||||
mct-drag="handle.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag(handle)">
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
@ -1,49 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<div class="frame frame-template t-frame-inner abs has-local-controls t-object-type-{{ domainObject.getModel().type }}">
|
||||
<div class="abs object-browse-bar l-flex-row">
|
||||
<div class="left flex-elem l-flex-row grows">
|
||||
<mct-representation
|
||||
key="'object-header-frame'"
|
||||
mct-object="domainObject"
|
||||
class="l-flex-row flex-elem object-header grows">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed h-local-controls local-controls-hidden">
|
||||
<mct-representation
|
||||
key="'switcher'"
|
||||
ng-model="representation"
|
||||
mct-object="domainObject">
|
||||
</mct-representation>
|
||||
<a class="s-button icon-expand t-btn-view-large"
|
||||
title="View large"
|
||||
mct-trigger-modal>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs object-holder">
|
||||
<mct-representation
|
||||
key="representation.selected.key"
|
||||
mct-object="representation.selected.key && domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
@ -1,641 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[
|
||||
"../src/FixedController",
|
||||
"zepto"
|
||||
],
|
||||
function (
|
||||
FixedController,
|
||||
$
|
||||
) {
|
||||
|
||||
describe("The Fixed Position controller", function () {
|
||||
var mockScope,
|
||||
mockQ,
|
||||
mockDialogService,
|
||||
mockFormatter,
|
||||
mockDomainObject,
|
||||
mockEvent,
|
||||
testGrid,
|
||||
testModel,
|
||||
testConfiguration,
|
||||
mockOpenMCT,
|
||||
mockTelemetryAPI,
|
||||
mockCompositionAPI,
|
||||
mockCompositionCollection,
|
||||
mockChildren,
|
||||
mockConductor,
|
||||
mockMetadata,
|
||||
mockTimeSystem,
|
||||
mockLimitEvaluator,
|
||||
mockSelection,
|
||||
mockObjects,
|
||||
mockNewDomainObject,
|
||||
unlistenFunc,
|
||||
$element = [],
|
||||
selectable = [],
|
||||
controller;
|
||||
|
||||
// Utility function; find a $on calls for a given expression.
|
||||
function findOn(expr) {
|
||||
var on;
|
||||
mockScope.$on.calls.all().forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
on = call.args[1];
|
||||
}
|
||||
});
|
||||
return on;
|
||||
}
|
||||
|
||||
function makeMockDomainObject(id) {
|
||||
return {
|
||||
identifier: {
|
||||
key: "domainObject-" + id,
|
||||
namespace: ""
|
||||
},
|
||||
name: "Point " + id
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
'$scope',
|
||||
["$on", "$watch", "$digest", "commit"]
|
||||
);
|
||||
mockQ = jasmine.createSpyObj('$q', ['when']);
|
||||
mockDialogService = jasmine.createSpyObj(
|
||||
'dialogService',
|
||||
['getUserInput']
|
||||
);
|
||||
mockFormatter = jasmine.createSpyObj(
|
||||
'telemetryFormatter',
|
||||
['format']
|
||||
);
|
||||
mockFormatter.format.and.callFake(function (valueMetadata) {
|
||||
return "Formatted " + valueMetadata.value;
|
||||
});
|
||||
|
||||
mockConductor = jasmine.createSpyObj('conductor', [
|
||||
'on',
|
||||
'off',
|
||||
'bounds',
|
||||
'timeSystem',
|
||||
'clock'
|
||||
]);
|
||||
mockConductor.bounds.and.returnValue({});
|
||||
mockTimeSystem = {
|
||||
metadata: {
|
||||
key: 'key'
|
||||
}
|
||||
};
|
||||
mockConductor.timeSystem.and.returnValue(mockTimeSystem);
|
||||
|
||||
mockEvent = jasmine.createSpyObj(
|
||||
'event',
|
||||
['preventDefault']
|
||||
);
|
||||
|
||||
mockTelemetryAPI = jasmine.createSpyObj('telemetry',
|
||||
[
|
||||
'subscribe',
|
||||
'request',
|
||||
'isTelemetryObject',
|
||||
'getMetadata',
|
||||
'limitEvaluator',
|
||||
'getValueFormatter'
|
||||
]
|
||||
);
|
||||
mockTelemetryAPI.isTelemetryObject.and.returnValue(true);
|
||||
mockTelemetryAPI.request.and.returnValue(Promise.resolve([]));
|
||||
|
||||
testGrid = [123, 456];
|
||||
testModel = {
|
||||
composition: ['a', 'b', 'c'],
|
||||
layoutGrid: testGrid
|
||||
};
|
||||
testConfiguration = { elements: [
|
||||
{ type: "fixed.telemetry", id: 'a', x: 1, y: 1, useGrid: true},
|
||||
{ type: "fixed.telemetry", id: 'b', x: 1, y: 1, useGrid: true},
|
||||
{ type: "fixed.telemetry", id: 'c', x: 1, y: 1, useGrid: true}
|
||||
]};
|
||||
|
||||
mockChildren = testModel.composition.map(makeMockDomainObject);
|
||||
mockCompositionCollection = jasmine.createSpyObj('compositionCollection', [
|
||||
'load',
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
mockCompositionAPI = jasmine.createSpyObj('composition', [
|
||||
'get'
|
||||
]);
|
||||
mockCompositionAPI.get.and.returnValue(mockCompositionCollection);
|
||||
mockCompositionCollection.load.and.returnValue(
|
||||
Promise.resolve(mockChildren)
|
||||
);
|
||||
|
||||
mockScope.model = testModel;
|
||||
mockScope.configuration = testConfiguration;
|
||||
|
||||
mockNewDomainObject = jasmine.createSpyObj("newDomainObject", [
|
||||
'layoutGrid',
|
||||
'configuration',
|
||||
'composition'
|
||||
]);
|
||||
mockNewDomainObject.layoutGrid = testGrid;
|
||||
mockNewDomainObject.configuration = {
|
||||
'fixed-display': testConfiguration
|
||||
};
|
||||
mockNewDomainObject.composition = ['a', 'b', 'c'];
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getId', 'getModel', 'getCapability', 'useCapability']
|
||||
);
|
||||
mockDomainObject.useCapability.and.returnValue(mockNewDomainObject);
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
selectable[0] = {
|
||||
context: {
|
||||
oldItem: mockDomainObject
|
||||
}
|
||||
};
|
||||
mockSelection = jasmine.createSpyObj("selection", [
|
||||
'select',
|
||||
'on',
|
||||
'off',
|
||||
'get'
|
||||
]);
|
||||
mockSelection.get.and.returnValue([]);
|
||||
|
||||
unlistenFunc = jasmine.createSpy("unlisten");
|
||||
mockObjects = jasmine.createSpyObj('objects', [
|
||||
'observe',
|
||||
'get'
|
||||
]);
|
||||
mockObjects.observe.and.returnValue(unlistenFunc);
|
||||
|
||||
mockOpenMCT = {
|
||||
time: mockConductor,
|
||||
telemetry: mockTelemetryAPI,
|
||||
composition: mockCompositionAPI,
|
||||
selection: mockSelection,
|
||||
objects: mockObjects
|
||||
};
|
||||
|
||||
$element = $('<div></div>');
|
||||
spyOn($element[0], 'click');
|
||||
|
||||
mockMetadata = jasmine.createSpyObj('mockMetadata', [
|
||||
'valuesForHints',
|
||||
'value',
|
||||
'values'
|
||||
]);
|
||||
mockMetadata.value.and.returnValue({
|
||||
key: 'value'
|
||||
});
|
||||
|
||||
mockMetadata.valuesForHints.and.callFake(function (hints) {
|
||||
if (hints === ['domain']) {
|
||||
return [{
|
||||
key: 'time'
|
||||
}];
|
||||
} else {
|
||||
return [{
|
||||
key: 'value'
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
mockLimitEvaluator = jasmine.createSpyObj('limitEvaluator', [
|
||||
'evaluate'
|
||||
]);
|
||||
|
||||
mockLimitEvaluator.evaluate.and.returnValue({});
|
||||
|
||||
mockTelemetryAPI.getMetadata.and.returnValue(mockMetadata);
|
||||
mockTelemetryAPI.limitEvaluator.and.returnValue(mockLimitEvaluator);
|
||||
mockTelemetryAPI.getValueFormatter.and.returnValue(mockFormatter);
|
||||
|
||||
controller = new FixedController(
|
||||
mockScope,
|
||||
mockQ,
|
||||
mockDialogService,
|
||||
mockOpenMCT,
|
||||
$element
|
||||
);
|
||||
spyOn(controller, "mutate");
|
||||
});
|
||||
|
||||
it("subscribes a domain object", function () {
|
||||
var object = makeMockDomainObject("mock");
|
||||
|
||||
return controller.getTelemetry(object).then(function () {
|
||||
expect(mockTelemetryAPI.subscribe).toHaveBeenCalledWith(
|
||||
object,
|
||||
jasmine.any(Function),
|
||||
jasmine.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("releases subscription when a domain objects is removed", function () {
|
||||
var unsubscribe = jasmine.createSpy('unsubscribe');
|
||||
var unsubscribePromise = new Promise(function (resolve) {
|
||||
unsubscribe.and.callFake(resolve);
|
||||
});
|
||||
var object = makeMockDomainObject("mock");
|
||||
|
||||
mockTelemetryAPI.subscribe.and.returnValue(unsubscribe);
|
||||
return controller.getTelemetry(object).then(function () {
|
||||
controller.onCompositionRemove(object.identifier);
|
||||
return unsubscribePromise;
|
||||
}).then(function () {
|
||||
expect(unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes visible elements based on configuration", function () {
|
||||
var elements = controller.getElements();
|
||||
|
||||
expect(elements.length).toEqual(3);
|
||||
expect(elements[0].id).toEqual('a');
|
||||
expect(elements[1].id).toEqual('b');
|
||||
expect(elements[2].id).toEqual('c');
|
||||
});
|
||||
|
||||
it("allows elements to be selected", function () {
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
expect(controller.isElementSelected()).toBe(true);
|
||||
});
|
||||
|
||||
it("allows selection retrieval", function () {
|
||||
var elements = controller.getElements();
|
||||
selectable[0].context.elementProxy = elements[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
expect(controller.getSelectedElement()).toEqual(elements[1]);
|
||||
});
|
||||
|
||||
it("selects the parent view when selected element is removed", function () {
|
||||
var elements = controller.getElements();
|
||||
selectable[0].context.elementProxy = elements[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
controller.remove(elements[1]);
|
||||
|
||||
expect($element[0].click).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("retains selections during refresh", function () {
|
||||
// Get elements; remove one of them; trigger refresh.
|
||||
// Same element (at least by index) should still be selected.
|
||||
var elements = controller.getElements();
|
||||
selectable[0].context.elementProxy = elements[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
expect(controller.getSelectedElement()).toEqual(elements[1]);
|
||||
|
||||
controller.remove(elements[2]);
|
||||
elements = controller.getElements();
|
||||
|
||||
// Verify removal, as test assumes this
|
||||
expect(elements.length).toEqual(2);
|
||||
|
||||
expect(controller.shouldSelect(elements[1])).toBe(true);
|
||||
});
|
||||
|
||||
it("Displays received values for telemetry elements", function () {
|
||||
var elements;
|
||||
var mockTelemetry = {
|
||||
time: 100,
|
||||
value: 200
|
||||
};
|
||||
var testElement = {};
|
||||
var telemetryObject = {
|
||||
identifier: {
|
||||
key: '12345'
|
||||
}
|
||||
};
|
||||
mockConductor.clock.and.returnValue({});
|
||||
controller.elementProxiesById = {};
|
||||
controller.elementProxiesById['12345'] = [testElement];
|
||||
controller.elementProxies = [testElement];
|
||||
|
||||
controller.subscribeToObject(telemetryObject);
|
||||
mockTelemetryAPI.subscribe.calls.mostRecent().args[1](mockTelemetry);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
mockScope.$digest.and.callFake(resolve);
|
||||
}).then(function () {
|
||||
// Get elements that controller is now exposing
|
||||
elements = controller.getElements();
|
||||
|
||||
// Formatted values should be available
|
||||
expect(elements[0].value).toEqual("Formatted 200");
|
||||
});
|
||||
});
|
||||
|
||||
it("updates elements styles when grid size changes", function () {
|
||||
// Grid size is initially set to testGrid which is [123, 456]
|
||||
var originalLeft = controller.getElements()[0].style.left;
|
||||
|
||||
// Change the grid size
|
||||
controller.updateElementPositions([20, 20]);
|
||||
|
||||
expect(controller.getElements()[0].style.left).not.toEqual(originalLeft);
|
||||
});
|
||||
|
||||
it("listens for drop events", function () {
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
mockScope.model = testModel;
|
||||
|
||||
// Layout should position panels according to
|
||||
// where the user dropped them, so it needs to
|
||||
// listen for drop events.
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
'mctDrop',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
// Verify precondition
|
||||
expect(testConfiguration.elements.length).toEqual(3);
|
||||
|
||||
// Notify that a drop occurred
|
||||
testModel.composition.push('d');
|
||||
|
||||
mockObjects.get.and.returnValue(Promise.resolve([]));
|
||||
|
||||
findOn('mctDrop')(
|
||||
mockEvent,
|
||||
'd',
|
||||
{ x: 300, y: 100 }
|
||||
);
|
||||
|
||||
// Should have added an element
|
||||
expect(testConfiguration.elements.length).toEqual(4);
|
||||
|
||||
// ...and prevented default...
|
||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("ignores drops when default has been prevented", function () {
|
||||
// Avoids redundant drop-handling, WTD-1233
|
||||
mockEvent.defaultPrevented = true;
|
||||
|
||||
// Notify that a drop occurred
|
||||
testModel.composition.push('d');
|
||||
findOn('mctDrop')(
|
||||
mockEvent,
|
||||
'd',
|
||||
{ x: 300, y: 100 }
|
||||
);
|
||||
|
||||
// Should NOT have added an element
|
||||
expect(testConfiguration.elements.length).toEqual(3);
|
||||
});
|
||||
|
||||
it("unsubscribes when destroyed", function () {
|
||||
var unsubscribe = jasmine.createSpy('unsubscribe');
|
||||
var object = makeMockDomainObject("mock");
|
||||
|
||||
mockTelemetryAPI.subscribe.and.returnValue(unsubscribe);
|
||||
|
||||
return controller.getTelemetry(object).then(function () {
|
||||
expect(unsubscribe).not.toHaveBeenCalled();
|
||||
// Destroy the scope
|
||||
findOn('$destroy')();
|
||||
|
||||
expect(unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes its grid size", function () {
|
||||
expect(controller.getGridSize()).toEqual(testGrid);
|
||||
});
|
||||
|
||||
it("exposes drag handles", function () {
|
||||
var handles;
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
// Should have a non-empty array of handles
|
||||
handles = controller.handles();
|
||||
|
||||
expect(handles).toEqual(jasmine.any(Array));
|
||||
expect(handles.length).not.toEqual(0);
|
||||
|
||||
// And they should have start/continue/end drag methods
|
||||
handles.forEach(function (handle) {
|
||||
expect(handle.startDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.continueDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.endDrag).toEqual(jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes a move handle", function () {
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
// Should have a move handle
|
||||
var handle = controller.moveHandle();
|
||||
|
||||
// And it should have start/continue/end drag methods
|
||||
expect(handle.startDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.continueDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.endDrag).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("updates selection style during drag", function () {
|
||||
var oldStyle;
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
// Get style
|
||||
oldStyle = controller.getSelectedElementStyle();
|
||||
|
||||
// Start a drag gesture
|
||||
controller.moveHandle().startDrag();
|
||||
|
||||
// Haven't moved yet; style shouldn't have updated yet
|
||||
expect(controller.getSelectedElementStyle()).toEqual(oldStyle);
|
||||
|
||||
// Drag a little
|
||||
controller.moveHandle().continueDrag([1000, 100]);
|
||||
|
||||
// Style should have been updated
|
||||
expect(controller.getSelectedElementStyle()).not.toEqual(oldStyle);
|
||||
});
|
||||
|
||||
it("cleans up selection on scope destroy", function () {
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
'$destroy',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
mockScope.$on.calls.mostRecent().args[1]();
|
||||
|
||||
expect(mockOpenMCT.selection.off).toHaveBeenCalledWith(
|
||||
'change',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
describe("on display bounds changes", function () {
|
||||
var testBounds;
|
||||
var boundsChangeCallback;
|
||||
var objectOne;
|
||||
var objectTwo;
|
||||
|
||||
beforeEach(function () {
|
||||
testBounds = { start: 123, end: 321 };
|
||||
boundsChangeCallback = mockConductor.on.calls.mostRecent().args[1];
|
||||
objectOne = {};
|
||||
objectTwo = {};
|
||||
controller.telemetryObjects = [
|
||||
objectOne,
|
||||
objectTwo
|
||||
];
|
||||
spyOn(controller, "fetchHistoricalData");
|
||||
controller.fetchHistoricalData.and.callThrough();
|
||||
});
|
||||
|
||||
it("registers a bounds change listener", function () {
|
||||
expect(mockConductor.on).toHaveBeenCalledWith("bounds", jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("requests only a single point", function () {
|
||||
mockConductor.clock.and.returnValue(undefined);
|
||||
boundsChangeCallback(testBounds);
|
||||
expect(mockTelemetryAPI.request.calls.count()).toBe(2);
|
||||
|
||||
mockTelemetryAPI.request.calls.all().forEach(function (call) {
|
||||
expect(call.args[1].size).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("Does not fetch historical data on tick", function () {
|
||||
boundsChangeCallback(testBounds, true);
|
||||
expect(mockTelemetryAPI.request.calls.count()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("on receipt of telemetry", function () {
|
||||
var mockTelemetryObject;
|
||||
var testValue;
|
||||
var testElement;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTelemetryObject = {
|
||||
identifier: {
|
||||
key: '12345'
|
||||
}
|
||||
};
|
||||
testValue = 30;
|
||||
testElement = {};
|
||||
|
||||
controller.elementProxiesById = {};
|
||||
controller.elementProxiesById['12345'] = [testElement];
|
||||
controller.elementProxies = [testElement];
|
||||
});
|
||||
|
||||
it("updates displayed values from historical telemetry", function () {
|
||||
spyOn(controller, "updateView");
|
||||
controller.updateView.and.callThrough();
|
||||
|
||||
mockTelemetryAPI.request.and.returnValue(Promise.resolve([{
|
||||
time: 100,
|
||||
value: testValue
|
||||
}]));
|
||||
|
||||
controller.fetchHistoricalData(mockTelemetryObject);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
mockScope.$digest.and.callFake(resolve);
|
||||
}).then(function () {
|
||||
expect(controller.updateView).toHaveBeenCalled();
|
||||
expect(controller.getElements()[0].value)
|
||||
.toEqual("Formatted " + testValue);
|
||||
});
|
||||
});
|
||||
|
||||
it("selects an range value to display, if available", function () {
|
||||
mockMetadata.valuesForHints.and.returnValue([
|
||||
{
|
||||
key: 'range',
|
||||
source: 'range'
|
||||
}
|
||||
]);
|
||||
var key = controller.chooseValueMetadataToDisplay(mockMetadata).source;
|
||||
expect(key).toEqual('range');
|
||||
});
|
||||
|
||||
it("selects the first non-domain value to display, if no range available", function () {
|
||||
mockMetadata.valuesForHints.and.returnValue([]);
|
||||
mockMetadata.values.and.returnValue([
|
||||
{
|
||||
key: 'domain',
|
||||
source: 'domain',
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'image',
|
||||
source: 'image',
|
||||
hints: {
|
||||
image: 1
|
||||
}
|
||||
}
|
||||
]);
|
||||
var key = controller.chooseValueMetadataToDisplay(mockMetadata).source;
|
||||
expect(key).toEqual('image');
|
||||
});
|
||||
|
||||
it("reflects limit status", function () {
|
||||
mockLimitEvaluator.evaluate.and.returnValue({cssClass: "alarm-a"});
|
||||
controller.updateView(mockTelemetryObject, [{
|
||||
time: 100,
|
||||
value: testValue
|
||||
}]);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
mockScope.$digest.and.callFake(resolve);
|
||||
}).then(function () {
|
||||
// Limit-based CSS classes should be available
|
||||
expect(controller.getElements()[0].cssClass).toEqual("alarm-a");
|
||||
});
|
||||
});
|
||||
|
||||
it("listens for selection change events", function () {
|
||||
expect(mockOpenMCT.selection.on).toHaveBeenCalledWith(
|
||||
'change',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,92 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../src/FixedDragHandle'],
|
||||
function (FixedDragHandle) {
|
||||
|
||||
var TEST_GRID_SIZE = [13, 33];
|
||||
|
||||
describe("A fixed position drag handle", function () {
|
||||
var mockElementHandle,
|
||||
mockConfigPath,
|
||||
mockFixedControl,
|
||||
handle;
|
||||
|
||||
beforeEach(function () {
|
||||
mockElementHandle = jasmine.createSpyObj(
|
||||
'elementHandle',
|
||||
['x', 'y','getGridSize']
|
||||
);
|
||||
mockElementHandle.x.and.returnValue(6);
|
||||
mockElementHandle.y.and.returnValue(8);
|
||||
mockElementHandle.getGridSize.and.returnValue(TEST_GRID_SIZE);
|
||||
|
||||
mockFixedControl = jasmine.createSpyObj(
|
||||
'fixedControl',
|
||||
['updateSelectionStyle', 'mutate']
|
||||
);
|
||||
mockFixedControl.updateSelectionStyle.and.returnValue();
|
||||
mockFixedControl.mutate.and.returnValue();
|
||||
|
||||
mockConfigPath = jasmine.createSpy('configPath');
|
||||
|
||||
handle = new FixedDragHandle(
|
||||
mockElementHandle,
|
||||
mockConfigPath,
|
||||
mockFixedControl
|
||||
);
|
||||
});
|
||||
|
||||
it("provides a style for positioning", function () {
|
||||
var style = handle.style();
|
||||
// 6 grid coords * 13 pixels - 3 pixels for centering
|
||||
expect(style.left).toEqual('75px');
|
||||
// 8 grid coords * 33 pixels - 3 pixels for centering
|
||||
expect(style.top).toEqual('261px');
|
||||
});
|
||||
|
||||
it("allows handles to be dragged", function () {
|
||||
handle.startDrag();
|
||||
handle.continueDrag([16, 8]);
|
||||
|
||||
// Should update x/y, snapped to grid
|
||||
expect(mockElementHandle.x).toHaveBeenCalledWith(7);
|
||||
expect(mockElementHandle.y).toHaveBeenCalledWith(8);
|
||||
|
||||
handle.continueDrag([-16, -35]);
|
||||
|
||||
// Should have interpreted relative to initial state
|
||||
expect(mockElementHandle.x).toHaveBeenCalledWith(5);
|
||||
expect(mockElementHandle.y).toHaveBeenCalledWith(7);
|
||||
|
||||
// Should have called updateSelectionStyle once per continueDrag
|
||||
expect(mockFixedControl.updateSelectionStyle.calls.count()).toEqual(2);
|
||||
|
||||
// Finally, ending drag should mutate
|
||||
handle.endDrag();
|
||||
expect(mockFixedControl.mutate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,71 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../src/FixedProxy'],
|
||||
function (FixedProxy) {
|
||||
|
||||
describe("Fixed Position view's selection proxy", function () {
|
||||
var mockCallback,
|
||||
mockQ,
|
||||
mockDialogService,
|
||||
mockPromise,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
mockQ = jasmine.createSpyObj('$q', ['when']);
|
||||
mockDialogService = jasmine.createSpyObj('dialogService', ['getUserInput']);
|
||||
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
||||
|
||||
mockQ.when.and.returnValue(mockPromise);
|
||||
|
||||
proxy = new FixedProxy(mockCallback, mockQ, mockDialogService);
|
||||
});
|
||||
|
||||
it("handles promised element creation", function () {
|
||||
// The element factory may return promises (e.g. if
|
||||
// user input is required) so make sure proxy is wrapping these
|
||||
proxy.add("fixed.box");
|
||||
expect(mockQ.when).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("notifies its callback when an element is created", function () {
|
||||
proxy.add("fixed.box");
|
||||
// Callback should not have been invoked yet
|
||||
expect(mockCallback).not.toHaveBeenCalled();
|
||||
// Resolve the promise
|
||||
mockPromise.then.calls.mostRecent().args[0]({});
|
||||
// Should have fired the callback
|
||||
expect(mockCallback).toHaveBeenCalledWith({
|
||||
type: "fixed.box",
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 1,
|
||||
useGrid: true
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,81 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["../src/LayoutDrag"],
|
||||
function (LayoutDrag) {
|
||||
|
||||
describe("A Layout drag handler", function () {
|
||||
var testPosition = {
|
||||
position: [8, 11],
|
||||
dimensions: [3, 2]
|
||||
};
|
||||
|
||||
it("changes position by a supplied factor, rounding by grid size", function () {
|
||||
var handler = new LayoutDrag(
|
||||
testPosition,
|
||||
[1, 1],
|
||||
[0, 0],
|
||||
[10, 20]
|
||||
);
|
||||
|
||||
expect(handler.getAdjustedPosition([37, 84])).toEqual({
|
||||
position: [12, 15],
|
||||
dimensions: [3, 2]
|
||||
});
|
||||
expect(handler.getAdjustedPosition([-37, 84])).toEqual({
|
||||
position: [4, 15],
|
||||
dimensions: [3, 2]
|
||||
});
|
||||
});
|
||||
|
||||
it("changes dimensions by a supplied factor, rounding by grid size", function () {
|
||||
var handler = new LayoutDrag(
|
||||
testPosition,
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[10, 20]
|
||||
);
|
||||
|
||||
expect(handler.getAdjustedPosition([37, 84])).toEqual({
|
||||
position: [8, 11],
|
||||
dimensions: [7, 6]
|
||||
});
|
||||
});
|
||||
|
||||
it("allows mixing dimension and position factors", function () {
|
||||
var handler = new LayoutDrag(
|
||||
testPosition,
|
||||
[0, 1],
|
||||
[-1, 0],
|
||||
[10, 20]
|
||||
);
|
||||
|
||||
expect(handler.getAdjustedPosition([11, 84])).toEqual({
|
||||
position: [8, 15],
|
||||
dimensions: [2, 2]
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,128 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../src/MCTTriggerModal'
|
||||
], function (
|
||||
MCTTriggerModal
|
||||
) {
|
||||
describe('MCTTriggerModal', function () {
|
||||
var $scope,
|
||||
$element,
|
||||
frame,
|
||||
layoutContainer,
|
||||
$document,
|
||||
mctTriggerModal;
|
||||
|
||||
function makeElement(classes, parentEl) {
|
||||
var elem = jasmine.createSpyObj('element.' + classes.join('.'), [
|
||||
'hasClass',
|
||||
'parent'
|
||||
]);
|
||||
elem.hasClass.and.callFake(function (className) {
|
||||
return classes.indexOf(className) !== -1;
|
||||
});
|
||||
elem.parent.and.returnValue(parentEl);
|
||||
var div = document.createElement('div');
|
||||
div.className = classes.join(' ');
|
||||
parentEl[0].appendChild(div);
|
||||
elem[0] = div;
|
||||
return elem;
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
$scope = jasmine.createSpyObj('$scope', ['$on']);
|
||||
$scope.domainObject = { getCapability: function () {
|
||||
return { getActions: function () {
|
||||
return [];
|
||||
}};
|
||||
}};
|
||||
|
||||
$element = jasmine.createSpyObj('$element', [
|
||||
'parent',
|
||||
'remove',
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
layoutContainer = document.createElement('div');
|
||||
frame = makeElement(['frame'], [layoutContainer]);
|
||||
var child = makeElement([], frame);
|
||||
for (var i = 0; i < 5; i++) {
|
||||
child = makeElement([], child);
|
||||
}
|
||||
$element.parent.and.returnValue(child);
|
||||
$document = [jasmine.createSpyObj('document', ['createElement'])];
|
||||
$document[0].body = document.createElement('div');
|
||||
$document[0].createElement.and.callFake(function (tag) {
|
||||
return document.createElement(tag);
|
||||
});
|
||||
|
||||
mctTriggerModal = new MCTTriggerModal($document);
|
||||
});
|
||||
|
||||
it('is a directive definition', function () {
|
||||
expect(mctTriggerModal.restrict).toBe('A');
|
||||
expect(mctTriggerModal.link).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
describe('link', function () {
|
||||
beforeEach(function () {
|
||||
mctTriggerModal.link($scope, $element);
|
||||
});
|
||||
|
||||
it('attaches handlers to $element', function () {
|
||||
expect($element.on).toHaveBeenCalledWith(
|
||||
'click',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('cleans up on $scope $destroy', function () {
|
||||
expect($scope.$on).toHaveBeenCalledWith(
|
||||
'$destroy',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
$scope.$on.calls.mostRecent().args[1]();
|
||||
expect($element.off).toHaveBeenCalledWith(
|
||||
'click',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('opens and closes overlays', function () {
|
||||
[
|
||||
'a.close', 'a.t-done', '.abs.blocker'
|
||||
].forEach(function (selector) {
|
||||
$element.on.calls.mostRecent().args[1]();
|
||||
var container = $document[0].body.querySelector('.t-contents');
|
||||
expect(container.children[0]).toBe(frame[0]);
|
||||
expect(layoutContainer.children[0]).not.toBe(frame[0]);
|
||||
$document[0].body.querySelector(selector)
|
||||
.dispatchEvent(new Event('click'));
|
||||
expect(container.children[0]).not.toBe(frame[0]);
|
||||
expect(layoutContainer.children[0]).toBe(frame[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,50 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/AccessorMutator'],
|
||||
function (AccessorMutator) {
|
||||
|
||||
describe("An accessor-mutator", function () {
|
||||
var testObject,
|
||||
am;
|
||||
|
||||
beforeEach(function () {
|
||||
testObject = { t: 42, other: 100 };
|
||||
am = new AccessorMutator(testObject, 't');
|
||||
});
|
||||
|
||||
it("allows access to a property", function () {
|
||||
expect(am()).toEqual(42);
|
||||
});
|
||||
|
||||
it("allows mutation of a property", function () {
|
||||
expect(am("some other value")).toEqual("some other value");
|
||||
expect(testObject).toEqual({
|
||||
t: "some other value",
|
||||
other: 100
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,55 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/BoxProxy'],
|
||||
function (BoxProxy) {
|
||||
|
||||
describe("A fixed position box proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
width: 42,
|
||||
height: 24,
|
||||
fill: "transparent"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new BoxProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("provides getter/setter for fill color", function () {
|
||||
expect(proxy.fill()).toEqual('transparent');
|
||||
expect(proxy.fill('#FFF')).toEqual('#FFF');
|
||||
expect(proxy.fill()).toEqual('#FFF');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,69 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ElementFactory'],
|
||||
function (ElementFactory) {
|
||||
|
||||
var DIALOG_ELEMENTS = ['image', 'text'],
|
||||
NON_DIALOG_ELEMENTS = ['box', 'line'];
|
||||
|
||||
describe("The fixed position element factory", function () {
|
||||
var mockDialogService,
|
||||
mockPromise,
|
||||
factory;
|
||||
|
||||
beforeEach(function () {
|
||||
mockDialogService = jasmine.createSpyObj(
|
||||
'dialogService',
|
||||
['getUserInput']
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
'promise',
|
||||
['then']
|
||||
);
|
||||
|
||||
mockDialogService.getUserInput.and.returnValue(mockPromise);
|
||||
mockPromise.then.and.returnValue(mockPromise);
|
||||
|
||||
factory = new ElementFactory(mockDialogService);
|
||||
});
|
||||
|
||||
DIALOG_ELEMENTS.forEach(function (type) {
|
||||
it("shows a dialog for " + type + " elements", function () {
|
||||
expect(factory.createElement('fixed.' + type))
|
||||
.toEqual(mockPromise);
|
||||
expect(mockDialogService.getUserInput).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
NON_DIALOG_ELEMENTS.forEach(function (type) {
|
||||
it("immediately provides " + type + " elements", function () {
|
||||
var result = factory.createElement('fixed.' + type);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).not.toEqual(mockPromise);
|
||||
expect(mockDialogService.getUserInput).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,51 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ElementProxies'],
|
||||
function (ElementProxies) {
|
||||
|
||||
// Expect these element types to have proxies
|
||||
var ELEMENT_TYPES = [
|
||||
"fixed.telemetry",
|
||||
"fixed.line",
|
||||
"fixed.box",
|
||||
"fixed.text",
|
||||
"fixed.image"
|
||||
];
|
||||
|
||||
// Verify that the set of proxies exposed matches the specific
|
||||
// list above.
|
||||
describe("The set of element proxies", function () {
|
||||
ELEMENT_TYPES.forEach(function (t) {
|
||||
it("exposes a proxy wrapper for " + t + " elements", function () {
|
||||
expect(typeof ElementProxies[t]).toEqual('function');
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes no additional wrappers", function () {
|
||||
expect(Object.keys(ElementProxies).length)
|
||||
.toEqual(ELEMENT_TYPES.length);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,98 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ElementProxy'],
|
||||
function (ElementProxy) {
|
||||
|
||||
describe("A fixed position element proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
stroke: '#717171',
|
||||
width: 42,
|
||||
height: 24,
|
||||
useGrid: true
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new ElementProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements,
|
||||
[13,21]
|
||||
);
|
||||
});
|
||||
|
||||
it("exposes element properties", function () {
|
||||
Object.keys(testElement).forEach(function (k) {
|
||||
expect(proxy[k]()).toEqual(testElement[k]);
|
||||
});
|
||||
});
|
||||
|
||||
it("allows order to be changed", function () {
|
||||
proxy.order("down");
|
||||
expect(testElements).toEqual([{}, testElement, {}, {}]);
|
||||
proxy.order("up");
|
||||
expect(testElements).toEqual([{}, {}, testElement, {}]);
|
||||
proxy.order("bottom");
|
||||
expect(testElements).toEqual([testElement, {}, {}, {}]);
|
||||
proxy.order("top");
|
||||
expect(testElements).toEqual([{}, {}, {}, testElement]);
|
||||
});
|
||||
|
||||
it("ensures x/y values are non-negative", function () {
|
||||
proxy.x(-1);
|
||||
proxy.y(-400);
|
||||
expect(proxy.x()).toEqual(0);
|
||||
expect(proxy.y()).toEqual(0);
|
||||
});
|
||||
|
||||
it("allows modifying the current grid size", function () {
|
||||
proxy.setGridSize([112,420]);
|
||||
expect(proxy.gridSize).toEqual([112,420]);
|
||||
});
|
||||
|
||||
it("returns the current grid size only if the element snaps to grid", function () {
|
||||
expect(proxy.getGridSize()).toEqual([13,21]);
|
||||
proxy.useGrid(false);
|
||||
expect(proxy.getGridSize()).toEqual([1,1]);
|
||||
});
|
||||
|
||||
it("returns the mininum height and width of an element currently used units", function () {
|
||||
// Assumes mininum height and width are 10, in pixels
|
||||
expect(proxy.getMinWidth()).toEqual(1);
|
||||
expect(proxy.getMinHeight()).toEqual(1);
|
||||
proxy.setGridSize([7,4]);
|
||||
expect(proxy.getMinWidth()).toEqual(2);
|
||||
expect(proxy.getMinHeight()).toEqual(3);
|
||||
proxy.useGrid(false);
|
||||
expect(proxy.getMinWidth()).toEqual(10);
|
||||
expect(proxy.getMinHeight()).toEqual(10);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,56 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ImageProxy'],
|
||||
function (ImageProxy) {
|
||||
|
||||
describe("A fixed position image proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
width: 42,
|
||||
height: 24,
|
||||
url: "http://www.nasa.gov"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new ImageProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("provides getter/setter for image URL", function () {
|
||||
expect(proxy.url()).toEqual("http://www.nasa.gov");
|
||||
expect(proxy.url("http://www.nasa.gov/some.jpg"))
|
||||
.toEqual("http://www.nasa.gov/some.jpg");
|
||||
expect(proxy.url()).toEqual("http://www.nasa.gov/some.jpg");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,81 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/LineHandle'],
|
||||
function (LineHandle) {
|
||||
|
||||
describe("A fixed position drag handle", function () {
|
||||
var testElement,
|
||||
mockElementProxy,
|
||||
handle,
|
||||
TEST_GRID_SIZE = [45, 21];
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 3,
|
||||
y: 42,
|
||||
x2: 8,
|
||||
y2: 11,
|
||||
useGrid: true
|
||||
};
|
||||
mockElementProxy = jasmine.createSpyObj('elementProxy', ['getGridSize']);
|
||||
mockElementProxy.getGridSize.and.returnValue(TEST_GRID_SIZE);
|
||||
|
||||
handle = new LineHandle(testElement, mockElementProxy, 'x', 'y', 'x2', 'y2');
|
||||
});
|
||||
|
||||
it("provides x/y grid coordinates for its corner", function () {
|
||||
expect(handle.x()).toEqual(3);
|
||||
expect(handle.y()).toEqual(42);
|
||||
});
|
||||
|
||||
it("changes x and y positions", function () {
|
||||
handle.x(30);
|
||||
expect(testElement.x).toEqual(30);
|
||||
handle.y(40);
|
||||
expect(testElement.y).toEqual(40);
|
||||
});
|
||||
|
||||
it("disallows values less than zero", function () {
|
||||
handle.x(-1);
|
||||
handle.y(-400);
|
||||
expect(testElement.x).toEqual(0);
|
||||
expect(testElement.y).toEqual(0);
|
||||
});
|
||||
|
||||
it("ensures that end points remain different", function () {
|
||||
handle.x(testElement.x2);
|
||||
handle.y(testElement.y2);
|
||||
// First change should have been fine, because y was different
|
||||
expect(testElement.x).toEqual(testElement.x2);
|
||||
// Second change should have been rejected
|
||||
expect(testElement.y).not.toEqual(testElement.y2);
|
||||
});
|
||||
|
||||
it("returns the correct grid size", function () {
|
||||
expect(handle.getGridSize()).toEqual(TEST_GRID_SIZE);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,95 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/LineProxy'],
|
||||
function (LineProxy) {
|
||||
|
||||
describe("A fixed position line proxy", function () {
|
||||
var vertical, horizontal, diagonal, reversed;
|
||||
|
||||
beforeEach(function () {
|
||||
vertical = { x: 1, y: 4, x2: 1, y2: 8};
|
||||
horizontal = { x: 3, y: 3, x2: 12, y2: 3};
|
||||
diagonal = { x: 3, y: 8, x2: 5, y2: 11};
|
||||
reversed = { x2: 3, y2: 8, x: 5, y: 11};
|
||||
});
|
||||
|
||||
it("ensures visible width for vertical lines", function () {
|
||||
expect(new LineProxy(vertical).width()).toEqual(1);
|
||||
});
|
||||
|
||||
it("ensures visible height for horizontal lines", function () {
|
||||
expect(new LineProxy(horizontal).height()).toEqual(1);
|
||||
});
|
||||
|
||||
it("provides a bounding box for lines", function () {
|
||||
var proxy = new LineProxy(diagonal);
|
||||
expect(proxy.x()).toEqual(3);
|
||||
expect(proxy.y()).toEqual(8);
|
||||
expect(proxy.width()).toEqual(2);
|
||||
expect(proxy.height()).toEqual(3);
|
||||
});
|
||||
|
||||
it("bounds lines identically regardless of point order", function () {
|
||||
// That is, x(), width(), y(), and height() should always give
|
||||
// the same results for the same line segments, regardless of
|
||||
// which point is x,y and which is x2,y2
|
||||
['x', 'y', 'width', 'height'].forEach(function (method) {
|
||||
expect(new LineProxy(diagonal)[method]())
|
||||
.toEqual(new LineProxy(reversed)[method]());
|
||||
});
|
||||
});
|
||||
|
||||
it("adjusts both ends when mutating x", function () {
|
||||
var proxy = new LineProxy(diagonal);
|
||||
proxy.x(6);
|
||||
expect(diagonal).toEqual({ x: 6, y: 8, x2: 8, y2: 11});
|
||||
});
|
||||
|
||||
it("adjusts both ends when mutating y", function () {
|
||||
var proxy = new LineProxy(diagonal);
|
||||
proxy.y(6);
|
||||
expect(diagonal).toEqual({ x: 3, y: 6, x2: 5, y2: 9});
|
||||
});
|
||||
|
||||
it("provides internal positions for SVG lines", function () {
|
||||
var proxy;
|
||||
proxy = new LineProxy(diagonal);
|
||||
expect(proxy.x1()).toEqual(0);
|
||||
expect(proxy.y1()).toEqual(0);
|
||||
expect(proxy.x2()).toEqual(2);
|
||||
expect(proxy.y2()).toEqual(3);
|
||||
proxy = new LineProxy(reversed);
|
||||
expect(proxy.x1()).toEqual(2);
|
||||
expect(proxy.y1()).toEqual(3);
|
||||
expect(proxy.x2()).toEqual(0);
|
||||
expect(proxy.y2()).toEqual(0);
|
||||
});
|
||||
|
||||
it("provides handles for both ends", function () {
|
||||
expect(new LineProxy(diagonal).handles().length).toEqual(2);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,93 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ResizeHandle'],
|
||||
function (ResizeHandle) {
|
||||
|
||||
var TEST_MIN_WIDTH = 4,
|
||||
TEST_MIN_HEIGHT = 2,
|
||||
TEST_GRID_SIZE = [34, 81];
|
||||
|
||||
describe("A fixed position drag handle", function () {
|
||||
var testElement,
|
||||
mockElementProxy,
|
||||
handle;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 3,
|
||||
y: 42,
|
||||
width: 30,
|
||||
height: 36,
|
||||
useGrid: true
|
||||
};
|
||||
mockElementProxy = jasmine.createSpyObj('elementProxy', [
|
||||
'getGridSize',
|
||||
'getMinWidth',
|
||||
'getMinHeight'
|
||||
]);
|
||||
mockElementProxy.getGridSize.and.returnValue(TEST_GRID_SIZE);
|
||||
mockElementProxy.getMinWidth.and.returnValue(TEST_MIN_WIDTH);
|
||||
mockElementProxy.getMinHeight.and.returnValue(TEST_MIN_HEIGHT);
|
||||
|
||||
handle = new ResizeHandle(
|
||||
mockElementProxy,
|
||||
testElement
|
||||
);
|
||||
});
|
||||
|
||||
it("provides x/y grid coordinates for lower-right corner", function () {
|
||||
expect(handle.x()).toEqual(33);
|
||||
expect(handle.y()).toEqual(78);
|
||||
});
|
||||
|
||||
it("changes width of an element", function () {
|
||||
handle.x(30);
|
||||
// Should change width, not x
|
||||
expect(testElement.x).toEqual(3);
|
||||
expect(testElement.width).toEqual(27);
|
||||
});
|
||||
|
||||
it("changes height of an element", function () {
|
||||
handle.y(60);
|
||||
// Should change height, not y
|
||||
expect(testElement.y).toEqual(42);
|
||||
expect(testElement.height).toEqual(18);
|
||||
});
|
||||
|
||||
it("enforces minimum width/height", function () {
|
||||
handle.x(testElement.x);
|
||||
handle.y(testElement.y);
|
||||
expect(testElement.x).toEqual(3);
|
||||
expect(testElement.y).toEqual(42);
|
||||
expect(testElement.width).toEqual(TEST_MIN_WIDTH);
|
||||
expect(testElement.height).toEqual(TEST_MIN_HEIGHT);
|
||||
});
|
||||
|
||||
it("returns the correct grid size", function () {
|
||||
expect(handle.getGridSize()).toEqual(TEST_GRID_SIZE);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,54 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/TelemetryProxy'],
|
||||
function (TelemetryProxy) {
|
||||
|
||||
describe("A fixed position telemetry proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
z: 3,
|
||||
width: 42,
|
||||
height: 24,
|
||||
id: "test-id"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new TelemetryProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("exposes the element's id", function () {
|
||||
expect(proxy.id).toEqual('test-id');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,70 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/TextProxy'],
|
||||
function (TextProxy) {
|
||||
|
||||
describe("A fixed position text proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
width: 42,
|
||||
height: 24,
|
||||
fill: "transparent",
|
||||
size: "20px"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new TextProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("provides getter/setter for fill color", function () {
|
||||
expect(proxy.fill()).toEqual('transparent');
|
||||
expect(proxy.fill('#FFF')).toEqual('#FFF');
|
||||
expect(proxy.fill()).toEqual('#FFF');
|
||||
});
|
||||
|
||||
it("provides getter/setter for text size", function () {
|
||||
expect(proxy.size()).toEqual('20px');
|
||||
expect(proxy.size('12px')).toEqual('12px');
|
||||
expect(proxy.size()).toEqual('12px');
|
||||
});
|
||||
|
||||
it("defaults to 13px for unspecified text size", function () {
|
||||
testElement = {x: 1, y: 2};
|
||||
proxy = new TextProxy(testElement, 0, [testElement]);
|
||||
|
||||
expect(proxy.size()).toEqual('13px');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,157 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/UnitAccessorMutator'],
|
||||
function (UnitAccessorMutator) {
|
||||
|
||||
var GRID_SIZE = [13,17];
|
||||
|
||||
describe("An elementProxy.gridSize accessor-mutator", function () {
|
||||
var mockElementProxy,
|
||||
testElement,
|
||||
mockLineProxy,
|
||||
testLine,
|
||||
uAM,
|
||||
uAMLine;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 2,
|
||||
y: 3,
|
||||
width: 4,
|
||||
height: 5,
|
||||
useGrid: true
|
||||
};
|
||||
|
||||
mockElementProxy = {
|
||||
element: testElement,
|
||||
gridSize: GRID_SIZE,
|
||||
getMinHeight: jasmine.createSpy('minHeight'),
|
||||
getMinWidth: jasmine.createSpy('minWidth')
|
||||
};
|
||||
|
||||
testLine = {
|
||||
x: 7,
|
||||
y: 8,
|
||||
x2: 9,
|
||||
y2: 10,
|
||||
width: 11,
|
||||
height: 12,
|
||||
useGrid: true
|
||||
};
|
||||
|
||||
mockLineProxy = {
|
||||
element: testLine,
|
||||
gridSize: GRID_SIZE,
|
||||
getMinHeight: jasmine.createSpy('minHeight'),
|
||||
getMinWidth: jasmine.createSpy('minWidth')
|
||||
};
|
||||
|
||||
|
||||
|
||||
uAM = new UnitAccessorMutator(mockElementProxy);
|
||||
uAMLine = new UnitAccessorMutator(mockLineProxy);
|
||||
|
||||
mockElementProxy.getMinWidth.and.returnValue(1);
|
||||
mockElementProxy.getMinHeight.and.returnValue(1);
|
||||
|
||||
mockLineProxy.getMinWidth.and.returnValue(1);
|
||||
mockLineProxy.getMinHeight.and.returnValue(1);
|
||||
});
|
||||
|
||||
it("allows access to useGrid", function () {
|
||||
expect(uAM()).toEqual(mockElementProxy.element.useGrid);
|
||||
});
|
||||
|
||||
it("allows mutation of useGrid", function () {
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.useGrid).toEqual(false);
|
||||
});
|
||||
|
||||
it("converts coordinates appropriately for a box", function () {
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.x).toEqual(26);
|
||||
expect(mockElementProxy.element.y).toEqual(51);
|
||||
expect(mockElementProxy.element.width).toEqual(52);
|
||||
expect(mockElementProxy.element.height).toEqual(85);
|
||||
uAM(true);
|
||||
expect(mockElementProxy.element.x).toEqual(2);
|
||||
expect(mockElementProxy.element.y).toEqual(3);
|
||||
expect(mockElementProxy.element.width).toEqual(4);
|
||||
expect(mockElementProxy.element.height).toEqual(5);
|
||||
});
|
||||
|
||||
it("converts coordinates appropriately for a line", function () {
|
||||
uAMLine(false);
|
||||
expect(mockLineProxy.element.x).toEqual(91);
|
||||
expect(mockLineProxy.element.y).toEqual(136);
|
||||
expect(mockLineProxy.element.x2).toEqual(117);
|
||||
expect(mockLineProxy.element.y2).toEqual(170);
|
||||
expect(mockLineProxy.element.width).toEqual(143);
|
||||
expect(mockLineProxy.element.height).toEqual(204);
|
||||
uAMLine(true);
|
||||
expect(mockLineProxy.element.x).toEqual(7);
|
||||
expect(mockLineProxy.element.y).toEqual(8);
|
||||
expect(mockLineProxy.element.x2).toEqual(9);
|
||||
expect(mockLineProxy.element.y2).toEqual(10);
|
||||
expect(mockLineProxy.element.width).toEqual(11);
|
||||
expect(mockLineProxy.element.height).toEqual(12);
|
||||
});
|
||||
|
||||
it("doesn't covert coordinates unecessarily", function () {
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.x).toEqual(26);
|
||||
expect(mockElementProxy.element.y).toEqual(51);
|
||||
expect(mockElementProxy.element.width).toEqual(52);
|
||||
expect(mockElementProxy.element.height).toEqual(85);
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.x).toEqual(26);
|
||||
expect(mockElementProxy.element.y).toEqual(51);
|
||||
expect(mockElementProxy.element.width).toEqual(52);
|
||||
expect(mockElementProxy.element.height).toEqual(85);
|
||||
});
|
||||
|
||||
it("snaps coordinates onto the grid", function () {
|
||||
uAM(false);
|
||||
mockElementProxy.element.x += 11;
|
||||
mockElementProxy.element.y -= 27;
|
||||
mockElementProxy.element.width -= 14;
|
||||
mockElementProxy.element.height += 4;
|
||||
uAM(true);
|
||||
expect(mockElementProxy.element.x).toEqual(3);
|
||||
expect(mockElementProxy.element.y).toEqual(1);
|
||||
expect(mockElementProxy.element.width).toEqual(3);
|
||||
expect(mockElementProxy.element.height).toEqual(5);
|
||||
});
|
||||
|
||||
it("enforces a minimum height and width", function () {
|
||||
uAM(false);
|
||||
mockElementProxy.element.width = 4;
|
||||
mockElementProxy.element.height = 4;
|
||||
uAM(true);
|
||||
expect(mockElementProxy.element.width).toEqual(1);
|
||||
expect(mockElementProxy.element.height).toEqual(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -29,13 +29,22 @@ define(
|
||||
function SnapshotPreviewController($scope, openmct) {
|
||||
|
||||
$scope.previewImage = function (imageUrl) {
|
||||
var image = document.createElement('img');
|
||||
image.src = imageUrl;
|
||||
let imageDiv = document.createElement('div');
|
||||
imageDiv.classList = 'image-main s-image-main';
|
||||
imageDiv.style.backgroundImage = `url(${imageUrl})`;
|
||||
|
||||
openmct.overlays.overlay(
|
||||
let previewImageOverlay = openmct.overlays.overlay(
|
||||
{
|
||||
element: image,
|
||||
size: 'large'
|
||||
element: imageDiv,
|
||||
size: 'large',
|
||||
buttons: [
|
||||
{
|
||||
label: 'Done',
|
||||
callback: function () {
|
||||
previewImageOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -43,13 +52,13 @@ define(
|
||||
$scope.annotateImage = function (ngModel, field, imageUrl) {
|
||||
$scope.imageUrl = imageUrl;
|
||||
|
||||
var div = document.createElement('div'),
|
||||
let div = document.createElement('div'),
|
||||
painterroInstance = {},
|
||||
save = false;
|
||||
|
||||
div.id = 'snap-annotation';
|
||||
|
||||
openmct.overlays.overlay(
|
||||
let annotateImageOverlay = openmct.overlays.overlay(
|
||||
{
|
||||
element: div,
|
||||
size: 'large',
|
||||
@ -59,6 +68,7 @@ define(
|
||||
callback: function () {
|
||||
save = false;
|
||||
painterroInstance.save();
|
||||
annotateImageOverlay.dismiss();
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -66,6 +76,7 @@ define(
|
||||
callback: function () {
|
||||
save = true;
|
||||
painterroInstance.save();
|
||||
annotateImageOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -97,7 +108,7 @@ define(
|
||||
},
|
||||
saveHandler: function (image, done) {
|
||||
if (save) {
|
||||
var url = image.asBlob(),
|
||||
let url = image.asBlob(),
|
||||
reader = new window.FileReader();
|
||||
|
||||
reader.readAsDataURL(url);
|
||||
|
@ -43,6 +43,7 @@ define([
|
||||
'./ui/layout/Layout.vue',
|
||||
'../platform/core/src/objects/DomainObjectImpl',
|
||||
'../platform/core/src/capabilities/ContextualDomainObject',
|
||||
'./ui/preview/plugin',
|
||||
'vue'
|
||||
], function (
|
||||
EventEmitter,
|
||||
@ -67,6 +68,7 @@ define([
|
||||
Layout,
|
||||
DomainObjectImpl,
|
||||
ContextualDomainObject,
|
||||
PreviewPlugin,
|
||||
Vue
|
||||
) {
|
||||
/**
|
||||
@ -230,7 +232,7 @@ define([
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
this.install(this.plugins.DisplayLayout());
|
||||
this.install(this.plugins.Preview());
|
||||
this.install(PreviewPlugin.default());
|
||||
|
||||
if (typeof BUILD_CONSTANTS !== 'undefined') {
|
||||
this.install(buildInfoPlugin(BUILD_CONSTANTS));
|
||||
|
@ -58,11 +58,8 @@ define([
|
||||
|
||||
handleLegacyMutation = function (legacyObject) {
|
||||
var newStyleObject = utils.toNewFormat(legacyObject.getModel(), legacyObject.getId());
|
||||
|
||||
//Don't trigger self
|
||||
this.eventEmitter.off('mutation', handleMutation);
|
||||
this.eventEmitter.emit(newStyleObject.identifier.key + ":*", newStyleObject);
|
||||
this.eventEmitter.on('mutation', handleMutation);
|
||||
this.eventEmitter.emit('mutation', newStyleObject);
|
||||
}.bind(this);
|
||||
|
||||
this.eventEmitter.on('mutation', handleMutation);
|
||||
|
@ -28,6 +28,11 @@ export default class Editor extends EventEmitter {
|
||||
super();
|
||||
this.editing = false;
|
||||
this.openmct = openmct;
|
||||
document.addEventListener('drop', (event) => {
|
||||
if (!this.isEditing()) {
|
||||
this.edit();
|
||||
}
|
||||
}, {capture: true});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,6 +46,7 @@ define([
|
||||
function DefaultCompositionProvider(publicAPI, compositionAPI) {
|
||||
this.publicAPI = publicAPI;
|
||||
this.listeningTo = {};
|
||||
this.onMutation = this.onMutation.bind(this);
|
||||
|
||||
this.cannotContainDuplicates = this.cannotContainDuplicates.bind(this);
|
||||
this.cannotContainItself = this.cannotContainItself.bind(this);
|
||||
@ -177,8 +178,12 @@ define([
|
||||
* @method remove
|
||||
*/
|
||||
DefaultCompositionProvider.prototype.remove = function (domainObject, childId) {
|
||||
// TODO: this needs to be synchronized via mutation.
|
||||
throw new Error('Default Provider does not implement removal.');
|
||||
let composition = domainObject.composition.filter(function (child) {
|
||||
return !(childId.namespace === child.namespace &&
|
||||
childId.key === child.key);
|
||||
});
|
||||
|
||||
this.publicAPI.objects.mutate(domainObject, 'composition', composition);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -208,9 +213,10 @@ define([
|
||||
if (this.topicListener) {
|
||||
return;
|
||||
}
|
||||
var topic = this.publicAPI.$injector.get('topic');
|
||||
var mutation = topic('mutation');
|
||||
this.topicListener = mutation.listen(this.onMutation.bind(this));
|
||||
this.publicAPI.objects.eventEmitter.on('mutation', this.onMutation);
|
||||
this.topicListener = () => {
|
||||
this.publicAPI.objects.eventEmitter.off('mutation', this.onMutation)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -220,7 +226,7 @@ define([
|
||||
* @private
|
||||
*/
|
||||
DefaultCompositionProvider.prototype.onMutation = function (oldDomainObject) {
|
||||
var id = oldDomainObject.getId();
|
||||
var id = objectUtils.makeKeyString(oldDomainObject.identifier);
|
||||
var listeners = this.listeningTo[id];
|
||||
|
||||
if (!listeners) {
|
||||
@ -228,7 +234,7 @@ define([
|
||||
}
|
||||
|
||||
var oldComposition = listeners.composition.map(objectUtils.makeKeyString);
|
||||
var newComposition = oldDomainObject.getModel().composition.map(objectUtils.makeKeyString);
|
||||
var newComposition = oldDomainObject.composition.map(objectUtils.makeKeyString);
|
||||
|
||||
var added = _.difference(newComposition, oldComposition).map(objectUtils.parseKeyString);
|
||||
var removed = _.difference(oldComposition, newComposition).map(objectUtils.parseKeyString);
|
||||
|
@ -83,18 +83,15 @@ define([
|
||||
this.object = newObject;
|
||||
}.bind(this);
|
||||
|
||||
this.eventEmitter.on(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
|
||||
//Emit event specific to property
|
||||
this.eventEmitter.emit(qualifiedEventName(this.object, path), value);
|
||||
|
||||
this.eventEmitter.off(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
|
||||
//Emit wildcare event
|
||||
//Emit wildcard event
|
||||
this.eventEmitter.emit(qualifiedEventName(this.object, '*'), this.object);
|
||||
|
||||
//Emit a general "any object" event
|
||||
this.eventEmitter.emit(ANY_OBJECT_EVENT, this.object);
|
||||
|
||||
this.eventEmitter.on(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
//Emit event specific to property
|
||||
this.eventEmitter.emit(qualifiedEventName(this.object, path), value);
|
||||
this.eventEmitter.off(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
};
|
||||
|
||||
return MutableObject;
|
||||
|
@ -22,7 +22,7 @@ class Dialog extends Overlay {
|
||||
super({
|
||||
element: component.$el,
|
||||
size: 'fit',
|
||||
notDismissable: true,
|
||||
dismissable: false,
|
||||
...options
|
||||
});
|
||||
|
||||
|
@ -12,6 +12,7 @@ class Overlay extends EventEmitter {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
this.dismissable = options.dismissable !== false ? true : false;
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add('l-overlay-wrapper', cssClasses[options.size]);
|
||||
|
||||
@ -20,7 +21,7 @@ class Overlay extends EventEmitter {
|
||||
dismiss: this.dismiss.bind(this),
|
||||
element: options.element,
|
||||
buttons: options.buttons,
|
||||
notDismissable: options.notDismissable ? true : false
|
||||
dismissable: this.dismissable
|
||||
},
|
||||
components: {
|
||||
OverlayComponent: OverlayComponent
|
||||
@ -35,8 +36,8 @@ class Overlay extends EventEmitter {
|
||||
|
||||
dismiss() {
|
||||
this.emit('destroy');
|
||||
this.component.$destroy();
|
||||
document.body.removeChild(this.container);
|
||||
this.component.$destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,14 @@ import ProgressDialog from './ProgressDialog';
|
||||
class OverlayAPI {
|
||||
constructor() {
|
||||
this.activeOverlays = [];
|
||||
|
||||
this.dismissLastOverlay = this.dismissLastOverlay.bind(this);
|
||||
|
||||
document.addEventListener('keyup', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
this.dismissLastOverlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,14 +46,24 @@ class OverlayAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
] * A description of option properties that can be passed into the overlay
|
||||
* @typedef options
|
||||
* private
|
||||
*/
|
||||
dismissLastOverlay() {
|
||||
let lastOverlay = this.activeOverlays[this.activeOverlays.length - 1];
|
||||
if (lastOverlay && lastOverlay.dismissable) {
|
||||
lastOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of option properties that can be passed into the overlay
|
||||
* @typedef options
|
||||
* @property {object} element DOMElement that is to be inserted/shown on the overlay
|
||||
* @property {string} size prefered size of the overlay (large, small, fit)
|
||||
* @property {array} buttons optional button objects with label and callback properties
|
||||
* @property {function} onDestroy callback to be called when overlay is destroyed
|
||||
* @property {boolean} notDismissable to prevent user from dismissing the overlay, calling code
|
||||
* will need to explicitly dismiss the overlay.
|
||||
* @property {boolean} dismissable allow user to dismiss overlay by using esc, and clicking away
|
||||
* from overlay. Unless set to false, all overlays will be dismissable by default.
|
||||
*/
|
||||
overlay(options) {
|
||||
let overlay = new Overlay(options);
|
||||
|
@ -25,7 +25,7 @@ class ProgressDialog extends Overlay {
|
||||
super({
|
||||
element: component.$el,
|
||||
size: 'fit',
|
||||
notDismissable: true,
|
||||
dismissable: false,
|
||||
...options
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<div class="c-overlay__outer">
|
||||
<button class="c-click-icon c-overlay__close-button icon-x-in-circle"
|
||||
v-if="!notDismissable"
|
||||
v-if="dismissable"
|
||||
@click="destroy">
|
||||
</button>
|
||||
<div class="c-overlay__contents" ref="element"></div>
|
||||
@ -129,19 +129,19 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: ['dismiss', 'element', 'buttons', 'notDismissable'],
|
||||
inject: ['dismiss', 'element', 'buttons', 'dismissable'],
|
||||
mounted() {
|
||||
this.$refs.element.appendChild(this.element);
|
||||
},
|
||||
methods: {
|
||||
destroy: function () {
|
||||
if (!this.notDismissable) {
|
||||
if (this.dismissable) {
|
||||
this.dismiss();
|
||||
}
|
||||
},
|
||||
buttonClickHandler: function (method) {
|
||||
method();
|
||||
this.destroy();
|
||||
this.$emit('destroy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ define([], function () {
|
||||
// is inside a layout, or the main layout is selected.
|
||||
return (openmct.editor.isEditing() && selection &&
|
||||
((selection[1] && selection[1].context.item && selection[1].context.item.type === 'layout') ||
|
||||
(selection[0].context.item && selection[0].context.item.type === 'layout')));
|
||||
(selection[0].context.item && selection[0].context.item.type === 'layout')));
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
const DIALOG_FORM = {
|
||||
@ -73,10 +73,13 @@ define([], function () {
|
||||
return openmct.$injector.get('dialogService').getUserInput(form, {});
|
||||
}
|
||||
|
||||
function getPath() {
|
||||
return `configuration.items[${selection[0].context.index}]`;
|
||||
}
|
||||
|
||||
let selectedParent = selection[1] && selection[1].context.item,
|
||||
selectedObject = selection[0].context.item,
|
||||
layoutItem = selection[0].context.layoutItem,
|
||||
layoutItemIndex = selection[0].context.index,
|
||||
toolbar = [];
|
||||
|
||||
if (selectedObject && selectedObject.type === 'layout') {
|
||||
@ -121,7 +124,6 @@ define([], function () {
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
let path = `configuration.items[${layoutItemIndex}]`;
|
||||
let separator = {
|
||||
control: "separator"
|
||||
};
|
||||
@ -140,7 +142,7 @@ define([], function () {
|
||||
label: 'Ok',
|
||||
emphasis: 'true',
|
||||
callback: function () {
|
||||
removeItem(layoutItem, layoutItemIndex);
|
||||
removeItem(layoutItem, selection[0].context.index);
|
||||
prompt.dismiss();
|
||||
}
|
||||
},
|
||||
@ -154,6 +156,96 @@ define([], function () {
|
||||
});
|
||||
}
|
||||
};
|
||||
let stackOrder = {
|
||||
control: "menu",
|
||||
domainObject: selectedParent,
|
||||
icon: "icon-layers",
|
||||
title: "Move the selected object above or below other objects",
|
||||
options: [
|
||||
{
|
||||
name: "Move to Top",
|
||||
value: "top",
|
||||
class: "icon-arrow-double-up"
|
||||
},
|
||||
{
|
||||
name: "Move Up",
|
||||
value: "up",
|
||||
class: "icon-arrow-up"
|
||||
},
|
||||
{
|
||||
name: "Move Down",
|
||||
value: "down",
|
||||
class: "icon-arrow-down"
|
||||
},
|
||||
{
|
||||
name: "Move to Bottom",
|
||||
value: "bottom",
|
||||
class: "icon-arrow-double-down"
|
||||
}
|
||||
],
|
||||
method: function (option) {
|
||||
selection[1].context.orderItem(option.value, selection[0].context.index);
|
||||
}
|
||||
};
|
||||
let useGrid = {
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".useGrid";
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
icon: "icon-grid-snap-to",
|
||||
title: "Grid snapping enabled"
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
icon: "icon-grid-snap-no",
|
||||
title: "Grid snapping disabled"
|
||||
}
|
||||
]
|
||||
};
|
||||
let x = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".x";
|
||||
},
|
||||
label: "X:",
|
||||
title: "X position"
|
||||
},
|
||||
y = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".y";
|
||||
},
|
||||
label: "Y:",
|
||||
title: "Y position",
|
||||
},
|
||||
width = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".width";
|
||||
},
|
||||
label: 'W:',
|
||||
title: 'Resize object width'
|
||||
},
|
||||
height = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".height";
|
||||
},
|
||||
label: 'H:',
|
||||
title: 'Resize object height'
|
||||
};
|
||||
|
||||
if (layoutItem.type === 'subobject-view') {
|
||||
if (toolbar.length > 0) {
|
||||
@ -163,124 +255,113 @@ define([], function () {
|
||||
toolbar.push({
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".hasFrame",
|
||||
property: function () {
|
||||
return getPath() + ".hasFrame";
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Hide frame"
|
||||
icon: 'icon-frame-show',
|
||||
title: "Frame visible"
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-frame-show',
|
||||
title: "Show frame"
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Frame hidden"
|
||||
}
|
||||
]
|
||||
});
|
||||
toolbar.push(separator);
|
||||
toolbar.push(stackOrder);
|
||||
toolbar.push(x);
|
||||
toolbar.push(y);
|
||||
toolbar.push(width);
|
||||
toolbar.push(height);
|
||||
toolbar.push(useGrid);
|
||||
toolbar.push(separator);
|
||||
toolbar.push(remove);
|
||||
} else {
|
||||
const TEXT_SIZE = [9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96];
|
||||
const TEXT_SIZE = [8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96, 128];
|
||||
let fill = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".fill",
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color"
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".fill";
|
||||
},
|
||||
stroke = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".stroke",
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color"
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color"
|
||||
},
|
||||
stroke = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".stroke";
|
||||
},
|
||||
color = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".color",
|
||||
icon: "icon-font",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
preventNone: true
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color"
|
||||
},
|
||||
color = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".color";
|
||||
},
|
||||
size = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".size",
|
||||
title: "Set text size",
|
||||
options: TEXT_SIZE.map(size => {
|
||||
return {
|
||||
value: size + "px"
|
||||
};
|
||||
})
|
||||
icon: "icon-font",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
preventNone: true
|
||||
},
|
||||
size = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".size";
|
||||
},
|
||||
x = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".x",
|
||||
label: "X:",
|
||||
title: "X position"
|
||||
},
|
||||
y = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".y",
|
||||
label: "Y:",
|
||||
title: "Y position",
|
||||
},
|
||||
width = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: path + ".width",
|
||||
label: 'W:',
|
||||
title: 'Resize object width'
|
||||
},
|
||||
height = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: path + ".height",
|
||||
label: 'H:',
|
||||
title: 'Resize object height'
|
||||
};
|
||||
title: "Set text size",
|
||||
options: TEXT_SIZE.map(size => {
|
||||
return {
|
||||
value: size + "px"
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
if (layoutItem.type === 'telemetry-view') {
|
||||
let displayMode = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".displayMode",
|
||||
title: "Set display mode",
|
||||
options: [
|
||||
{
|
||||
name: 'Label + Value',
|
||||
value: 'all'
|
||||
},
|
||||
{
|
||||
name: "Label only",
|
||||
value: "label"
|
||||
},
|
||||
{
|
||||
name: "Value only",
|
||||
value: "value"
|
||||
}
|
||||
]
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".displayMode";
|
||||
},
|
||||
value = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".value",
|
||||
title: "Set value",
|
||||
options: openmct.telemetry.getMetadata(selectedObject).values().map(value => {
|
||||
return {
|
||||
name: value.name,
|
||||
value: value.key
|
||||
}
|
||||
})
|
||||
};
|
||||
title: "Set display mode",
|
||||
options: [
|
||||
{
|
||||
name: 'Label + Value',
|
||||
value: 'all'
|
||||
},
|
||||
{
|
||||
name: "Label only",
|
||||
value: "label"
|
||||
},
|
||||
{
|
||||
name: "Value only",
|
||||
value: "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
value = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".value";
|
||||
},
|
||||
title: "Set value",
|
||||
options: openmct.telemetry.getMetadata(selectedObject).values().map(value => {
|
||||
return {
|
||||
name: value.name,
|
||||
value: value.key
|
||||
}
|
||||
})
|
||||
};
|
||||
toolbar = [
|
||||
displayMode,
|
||||
separator,
|
||||
@ -292,18 +373,22 @@ define([], function () {
|
||||
separator,
|
||||
size,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
} else if (layoutItem.type === 'text-view' ) {
|
||||
} else if (layoutItem.type === 'text-view') {
|
||||
let text = {
|
||||
control: "button",
|
||||
domainObject: selectedParent,
|
||||
property: path,
|
||||
property: function () {
|
||||
return getPath();
|
||||
},
|
||||
icon: "icon-gear",
|
||||
title: "Edit text properties",
|
||||
dialog: DIALOG_FORM['text']
|
||||
@ -311,14 +396,16 @@ define([], function () {
|
||||
toolbar = [
|
||||
fill,
|
||||
stroke,
|
||||
color,
|
||||
separator,
|
||||
color,
|
||||
size,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
text,
|
||||
separator,
|
||||
@ -329,10 +416,12 @@ define([], function () {
|
||||
fill,
|
||||
stroke,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
@ -340,7 +429,9 @@ define([], function () {
|
||||
let url = {
|
||||
control: "button",
|
||||
domainObject: selectedParent,
|
||||
property: path,
|
||||
property: function () {
|
||||
return getPath();
|
||||
},
|
||||
icon: "icon-image",
|
||||
title: "Edit image properties",
|
||||
dialog: DIALOG_FORM['image']
|
||||
@ -348,10 +439,12 @@ define([], function () {
|
||||
toolbar = [
|
||||
stroke,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
url,
|
||||
separator,
|
||||
@ -362,7 +455,9 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".x2",
|
||||
property: function () {
|
||||
return getPath() + ".x2";
|
||||
},
|
||||
label: "X2:",
|
||||
title: "X2 position"
|
||||
},
|
||||
@ -370,17 +465,21 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".y2",
|
||||
property: function () {
|
||||
return getPath() + ".y2";
|
||||
},
|
||||
label: "Y2:",
|
||||
title: "Y2 position",
|
||||
};
|
||||
toolbar = [
|
||||
stroke,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
x2,
|
||||
y2,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
|
@ -25,6 +25,7 @@ define(function () {
|
||||
return {
|
||||
name: "Display Layout",
|
||||
creatable: true,
|
||||
description: 'Assemble other objects and components together into a reusable screen layout. Simply drag in the objects you want, position and size them. Save your design and view or edit it at any time.',
|
||||
cssClass: 'icon-layout',
|
||||
initialize(domainObject) {
|
||||
domainObject.composition = [];
|
||||
@ -32,7 +33,31 @@ define(function () {
|
||||
items: [],
|
||||
layoutGrid: [10, 10],
|
||||
};
|
||||
}
|
||||
},
|
||||
form: [
|
||||
{
|
||||
name: "Horizontal grid (px)",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
property: [
|
||||
"configuration",
|
||||
"layoutGrid",
|
||||
0
|
||||
],
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "Vertical grid (px)",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
property: [
|
||||
"configuration",
|
||||
"layoutGrid",
|
||||
1
|
||||
],
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,8 @@
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 10,
|
||||
height: 5
|
||||
height: 5,
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -25,30 +25,26 @@
|
||||
@dragover="handleDragOver"
|
||||
@click="bypassSelection"
|
||||
@drop="handleDrop">
|
||||
<div class="l-layout__object">
|
||||
<!-- Background grid -->
|
||||
<div class="l-layout__grid-holder c-grid"
|
||||
v-if="!drilledIn">
|
||||
<div class="c-grid__x l-grid l-grid-x"
|
||||
v-if="gridSize[0] >= 3"
|
||||
:style="[{ backgroundSize: gridSize[0] + 'px 100%' }]">
|
||||
</div>
|
||||
<div class="c-grid__y l-grid l-grid-y"
|
||||
v-if="gridSize[1] >= 3"
|
||||
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px' }]"></div>
|
||||
<!-- Background grid -->
|
||||
<div class="l-layout__grid-holder c-grid">
|
||||
<div class="c-grid__x l-grid l-grid-x"
|
||||
v-if="gridSize[0] >= 3"
|
||||
:style="[{ backgroundSize: gridSize[0] + 'px 100%' }]">
|
||||
</div>
|
||||
<component v-for="(item, index) in layoutItems"
|
||||
:is="item.type"
|
||||
:item="item"
|
||||
:key="item.id"
|
||||
:gridSize="gridSize"
|
||||
:initSelect="initSelectIndex === index"
|
||||
:index="index"
|
||||
@drilledIn="updateDrilledIn"
|
||||
@endDrag="endDrag"
|
||||
>
|
||||
</component>
|
||||
<div class="c-grid__y l-grid l-grid-y"
|
||||
v-if="gridSize[1] >= 3"
|
||||
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px' }]"></div>
|
||||
</div>
|
||||
<component v-for="(item, index) in layoutItems"
|
||||
:is="item.type"
|
||||
:item="item"
|
||||
:key="item.id"
|
||||
:gridSize="item.useGrid ? gridSize : [1, 1]"
|
||||
:initSelect="initSelectIndex === index"
|
||||
:index="index"
|
||||
@endDrag="endDrag"
|
||||
>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -59,30 +55,47 @@
|
||||
@include abs();
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
&__grid-holder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__object {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&__frame {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.l-shell__main-container {
|
||||
> .l-layout {
|
||||
[s-selected] {
|
||||
border: $browseSelectedBorder;
|
||||
.is-editing {
|
||||
.l-shell__main-container {
|
||||
&[s-selected],
|
||||
&[s-selected-parent] {
|
||||
// Display grid in main layout holder when editing
|
||||
> .l-layout {
|
||||
background: $editUIGridColorBg;
|
||||
|
||||
> [class*="__grid-holder"] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-layout__frame {
|
||||
&[s-selected],
|
||||
&[s-selected-parent] {
|
||||
// Display grid in nested layouts when editing
|
||||
> * > * > .l-layout {
|
||||
background: $editUIGridColorBg;
|
||||
box-shadow: inset $editUIGridColorFg 0 0 2px 1px;
|
||||
|
||||
> [class*='grid-holder'] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Styles moved to _global.scss;
|
||||
</style>
|
||||
|
||||
|
||||
@ -104,6 +117,12 @@
|
||||
'text-view': TextView,
|
||||
'image-view': ImageView
|
||||
};
|
||||
const ORDERS = {
|
||||
top: Number.POSITIVE_INFINITY,
|
||||
up: 1,
|
||||
down: -1,
|
||||
bottom: Number.NEGATIVE_INFINITY
|
||||
};
|
||||
|
||||
function getItemDefinition(itemType, ...options) {
|
||||
let itemView = ITEM_TYPE_VIEW_MAP[itemType];
|
||||
@ -119,7 +138,6 @@
|
||||
data() {
|
||||
let domainObject = JSON.parse(JSON.stringify(this.domainObject));
|
||||
return {
|
||||
drilledIn: undefined,
|
||||
internalDomainObject: domainObject,
|
||||
initSelectIndex: undefined
|
||||
};
|
||||
@ -144,16 +162,49 @@
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateDrilledIn();
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
}
|
||||
|
||||
let itemIndex = selection[0].context.index;
|
||||
|
||||
if (itemIndex !== undefined) {
|
||||
this.attachSelectionListener(itemIndex);
|
||||
}
|
||||
},
|
||||
updateDrilledIn(drilledInItem) {
|
||||
let identifier = drilledInItem && this.openmct.objects.makeKeyString(drilledInItem.identifier);
|
||||
this.drilledIn = identifier;
|
||||
this.layoutItems.forEach(item => {
|
||||
if (item.type === 'subobject-view') {
|
||||
item.drilledIn = this.openmct.objects.makeKeyString(item.identifier) === identifier;
|
||||
attachSelectionListener(index) {
|
||||
let path = `configuration.items[${index}].useGrid`;
|
||||
this.removeSelectionListener = this.openmct.objects.observe(this.internalDomainObject, path, function (value) {
|
||||
let item = this.layoutItems[index];
|
||||
|
||||
if (value) {
|
||||
item.x = Math.round(item.x / this.gridSize[0]);
|
||||
item.y = Math.round(item.y / this.gridSize[1]);
|
||||
item.width = Math.round(item.width / this.gridSize[0]);
|
||||
item.height = Math.round(item.height / this.gridSize[1]);
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = Math.round(item.x2 / this.gridSize[0]);
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = Math.round(item.y2 / this.gridSize[1]);
|
||||
}
|
||||
} else {
|
||||
item.x = this.gridSize[0] * item.x;
|
||||
item.y = this.gridSize[1] * item.y;
|
||||
item.width = this.gridSize[0] * item.width;
|
||||
item.height = this.gridSize[1] * item.height;
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = this.gridSize[0] * item.x2;
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = this.gridSize[1] * item.y2;
|
||||
}
|
||||
}
|
||||
});
|
||||
item.useGrid = value;
|
||||
this.mutate(`configuration.items[${index}]`, item);
|
||||
}.bind(this));
|
||||
},
|
||||
bypassSelection($event) {
|
||||
if (this.dragInProgress) {
|
||||
@ -177,13 +228,13 @@
|
||||
this.openmct.objects.mutate(this.internalDomainObject, path, value);
|
||||
},
|
||||
handleDrop($event) {
|
||||
if (!$event.dataTransfer.types.includes('domainobject')) {
|
||||
if (!$event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
let domainObject = JSON.parse($event.dataTransfer.getData('domainobject'));
|
||||
let domainObject = JSON.parse($event.dataTransfer.getData('openmct/domain-object-path'))[0];
|
||||
let elementRect = this.$el.getBoundingClientRect();
|
||||
let droppedObjectPosition = [
|
||||
Math.floor(($event.pageX - elementRect.left) / this.gridSize[0]),
|
||||
@ -234,12 +285,17 @@
|
||||
this.initSelectIndex = this.layoutItems.length - 1;
|
||||
},
|
||||
trackItem(item) {
|
||||
if (!item.identifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
||||
|
||||
if (item.type === "telemetry-view") {
|
||||
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
||||
let count = this.telemetryViewMap[keyString] || 0;
|
||||
this.telemetryViewMap[keyString] = ++count;
|
||||
} else if (item.type === "subobject-view") {
|
||||
this.objectViewMap[this.openmct.objects.makeKeyString(item.identifier)] = true;
|
||||
this.objectViewMap[keyString] = true;
|
||||
}
|
||||
},
|
||||
removeItem(item, index) {
|
||||
@ -311,13 +367,28 @@
|
||||
});
|
||||
this.mutate("configuration.items", layoutItems);
|
||||
this.$el.click();
|
||||
},
|
||||
orderItem(position, index) {
|
||||
let delta = ORDERS[position];
|
||||
let newIndex = Math.max(Math.min(index + delta, this.layoutItems.length - 1), 0);
|
||||
let item = this.layoutItems[index];
|
||||
|
||||
if (newIndex !== index) {
|
||||
this.layoutItems.splice(index, 1);
|
||||
this.layoutItems.splice(newIndex, 0, item);
|
||||
this.mutate('configuration.items', this.layoutItems);
|
||||
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
this.attachSelectionListener(newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.unlisten = this.openmct.objects.observe(this.internalDomainObject, '*', function (obj) {
|
||||
this.internalDomainObject = JSON.parse(JSON.stringify(obj));
|
||||
}.bind(this));
|
||||
|
||||
this.openmct.selection.on('change', this.setSelection);
|
||||
this.initializeItems();
|
||||
this.composition = this.openmct.composition.get(this.internalDomainObject);
|
||||
@ -330,7 +401,10 @@
|
||||
this.composition.off('add', this.addChild);
|
||||
this.composition.off('remove', this.removeChild);
|
||||
this.unlisten();
|
||||
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -56,7 +56,8 @@
|
||||
y: 1,
|
||||
width: 10,
|
||||
height: 5,
|
||||
url: element.url
|
||||
url: element.url,
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -25,25 +25,24 @@
|
||||
:class="{
|
||||
'no-frame': !item.hasFrame,
|
||||
'u-inspectable': inspectable,
|
||||
'is-drilled-in': item.drilledIn
|
||||
'is-resizing': isResizing
|
||||
}"
|
||||
:style="style"
|
||||
@dblclick="drill($event)">
|
||||
:style="style">
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<!-- Drag handles -->
|
||||
<div class="c-frame-edit">
|
||||
<div class="c-frame-edit__move"
|
||||
@mousedown="startDrag([1,1], [0,0], $event)"></div>
|
||||
@mousedown="startDrag([1,1], [0,0], $event, 'move')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--nw"
|
||||
@mousedown="startDrag([1,1], [-1,-1], $event)"></div>
|
||||
@mousedown="startDrag([1,1], [-1,-1], $event, 'resize')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--ne"
|
||||
@mousedown="startDrag([0,1], [1,-1], $event)"></div>
|
||||
@mousedown="startDrag([0,1], [1,-1], $event, 'resize')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--sw"
|
||||
@mousedown="startDrag([1,0], [-1,1], $event)"></div>
|
||||
@mousedown="startDrag([1,0], [-1,1], $event, 'resize')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--se"
|
||||
@mousedown="startDrag([0,0], [1,1], $event)"></div>
|
||||
@mousedown="startDrag([0,0], [1,1], $event, 'resize')"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -55,20 +54,167 @@
|
||||
.c-frame {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid transparent;
|
||||
|
||||
/*************************** NO-FRAME */
|
||||
&.no-frame {
|
||||
> [class*="contents"] > [class*="__header"] {
|
||||
display: none;
|
||||
}
|
||||
// Whatever is placed into the slot, make it fill the entirety of the space, obeying padding
|
||||
> *:first-child {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&:not(.no-frame) {
|
||||
background: $colorBodyBg;
|
||||
border: 1px solid $colorInteriorBorder;
|
||||
border: $browseFrameBorder;
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.c-frame-edit {
|
||||
// In Layouts, this is the editing rect and handles
|
||||
// In Fixed Position, this is a wrapper element
|
||||
@include abs();
|
||||
display: none;
|
||||
|
||||
&__move {
|
||||
@include abs();
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&__handle {
|
||||
$d: 6px;
|
||||
$o: floor($d * -0.5);
|
||||
background: $editFrameColorHandleFg;
|
||||
box-shadow: $editFrameColorHandleBg 0 0 0 2px;
|
||||
display: none; // Set to block via s-selected selector
|
||||
position: absolute;
|
||||
width: $d; height: $d;
|
||||
top: auto; right: auto; bottom: auto; left: auto;
|
||||
|
||||
&:before {
|
||||
// Extended hit area
|
||||
@include abs(-10px);
|
||||
content: '';
|
||||
display: block;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $editUIColor;
|
||||
}
|
||||
|
||||
&--nwse {
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
|
||||
&--nw {
|
||||
cursor: nw-resize;
|
||||
left: $o; top: $o;
|
||||
}
|
||||
|
||||
&--ne {
|
||||
cursor: ne-resize;
|
||||
right: $o; top: $o;
|
||||
}
|
||||
|
||||
&--se {
|
||||
cursor: se-resize;
|
||||
right: $o; bottom: $o;
|
||||
}
|
||||
|
||||
&--sw {
|
||||
cursor: sw-resize;
|
||||
left: $o; bottom: $o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-so-view.has-complex-content + .c-frame-edit {
|
||||
// Target frames that hold domain objects that include header elements, as opposed to drawing and alpha objects
|
||||
// Make the __move element a more affordable drag UI element
|
||||
.c-frame-edit__move {
|
||||
@include userSelectNone();
|
||||
background: $editFrameMovebarColorBg;
|
||||
box-shadow: rgba(black, 0.2) 0 1px;
|
||||
bottom: auto;
|
||||
height: 0; // Height is set on hover on s-selected.c-frame
|
||||
opacity: 0.8;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
|
||||
&:before {
|
||||
// Grippy
|
||||
$h: 4px;
|
||||
$tbOffset: ($editFrameMovebarH - $h) / 2;
|
||||
$lrOffset: 25%;
|
||||
@include grippy($editFrameMovebarColorFg);
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: $tbOffset; right: $lrOffset; bottom: $tbOffset; left: $lrOffset;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $editFrameHovMovebarColorBg;
|
||||
&:before { @include grippy($editFrameHovMovebarColorFg); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-editing {
|
||||
.c-frame {
|
||||
$moveBarOutDelay: 500ms;
|
||||
&.no-frame {
|
||||
border: $editFrameBorder; // Base border style for a frame element while editing.
|
||||
}
|
||||
|
||||
&-edit {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
&-edit__move,
|
||||
.c-so-view {
|
||||
transition: $transOut;
|
||||
transition-delay: $moveBarOutDelay;
|
||||
}
|
||||
|
||||
&:not([s-selected]) {
|
||||
&:hover {
|
||||
border: $editFrameBorderHov;
|
||||
}
|
||||
}
|
||||
|
||||
&[s-selected] {
|
||||
// All frames selected while editing
|
||||
border: $editFrameSelectedBorder;
|
||||
box-shadow: $editFrameSelectedShdw;
|
||||
|
||||
> .c-frame-edit {
|
||||
[class*='__handle'] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-layout__frame:not(.is-resizing) {
|
||||
// Show and animate the __move bar for sub-object views with complex content
|
||||
&:hover > .c-so-view.has-complex-content {
|
||||
// Move content down so the __move bar doesn't cover it.
|
||||
padding-top: $editFrameMovebarH;
|
||||
transition: $transIn;
|
||||
|
||||
&.c-so-view--no-frame {
|
||||
// Move content down with a bit more space
|
||||
padding-top: $editFrameMovebarH + $interiorMarginSm;
|
||||
}
|
||||
|
||||
// Show the move bar
|
||||
+ .c-frame-edit .c-frame-edit__move {
|
||||
height: $editFrameMovebarH;
|
||||
transition: $transIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -84,7 +230,8 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragPosition: undefined
|
||||
dragPosition: undefined,
|
||||
isResizing: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -110,24 +257,6 @@
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
drill($event) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
if (!this.openmct.editor.isEditing() || !this.item.identifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.openmct.objects.get(this.item.identifier)
|
||||
.then(domainObject => {
|
||||
if (this.openmct.composition.get(domainObject) === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$emit('drilledIn', this.item);
|
||||
});
|
||||
},
|
||||
updatePosition(event) {
|
||||
let currentPosition = [event.pageX, event.pageY];
|
||||
this.initialPosition = this.initialPosition || currentPosition;
|
||||
@ -135,7 +264,7 @@
|
||||
return value - this.initialPosition[index];
|
||||
}.bind(this));
|
||||
},
|
||||
startDrag(posFactor, dimFactor, event) {
|
||||
startDrag(posFactor, dimFactor, event, type) {
|
||||
document.body.addEventListener('mousemove', this.continueDrag);
|
||||
document.body.addEventListener('mouseup', this.endDrag);
|
||||
|
||||
@ -145,6 +274,7 @@
|
||||
};
|
||||
this.updatePosition(event);
|
||||
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
|
||||
this.isResizing = type === 'resize';
|
||||
event.preventDefault();
|
||||
},
|
||||
continueDrag(event) {
|
||||
@ -162,6 +292,7 @@
|
||||
this.dragPosition = undefined;
|
||||
this.initialPosition = undefined;
|
||||
this.delta = undefined;
|
||||
this.isResizing = undefined;
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,8 @@
|
||||
y: 10,
|
||||
x2: 10,
|
||||
y2: 5,
|
||||
stroke: '#717171'
|
||||
stroke: '#717171',
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -22,12 +22,12 @@
|
||||
<template>
|
||||
<layout-frame :item="item"
|
||||
:grid-size="gridSize"
|
||||
@endDrag="(item, updates) => $emit('endDrag', item, updates)"
|
||||
@drilledIn="item => $emit('drilledIn', item)">
|
||||
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
|
||||
<object-frame v-if="domainObject"
|
||||
:domain-object="domainObject"
|
||||
:object-path="objectPath"
|
||||
:has-frame="item.hasFrame">
|
||||
:has-frame="item.hasFrame"
|
||||
ref="objectFrame">
|
||||
</object-frame>
|
||||
</layout-frame>
|
||||
</template>
|
||||
@ -65,7 +65,8 @@
|
||||
x: position[0],
|
||||
y: position[1],
|
||||
identifier: domainObject.identifier,
|
||||
hasFrame: hasFrameByDefault(domainObject.type)
|
||||
hasFrame: hasFrameByDefault(domainObject.type),
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
@ -98,13 +99,15 @@
|
||||
setObject(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = [this.domainObject].concat(this.openmct.router.path);
|
||||
this.context = {
|
||||
item: domainObject,
|
||||
layoutItem: this.item,
|
||||
index: this.index
|
||||
};
|
||||
this.removeSelectable = this.openmct.selection.selectable(
|
||||
this.$el, this.context, this.initSelect);
|
||||
this.$nextTick(function () {
|
||||
let childContext = this.$refs.objectFrame.getSelectionContext();
|
||||
childContext.item = domainObject;
|
||||
childContext.layoutItem = this.item;
|
||||
childContext.index = this.index;
|
||||
this.context = childContext;
|
||||
this.removeSelectable = this.openmct.selection.selectable(
|
||||
this.$el, this.context, this.initSelect);
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -99,6 +99,7 @@
|
||||
fill: "",
|
||||
color: "",
|
||||
size: "13px",
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -59,7 +59,8 @@
|
||||
y: 1,
|
||||
width: 10,
|
||||
height: 5,
|
||||
text: element.text
|
||||
text: element.text,
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -61,7 +61,8 @@ export default function () {
|
||||
return {
|
||||
item: domainObject,
|
||||
addElement: component && component.$refs.displayLayout.addElement,
|
||||
removeItem: component && component.$refs.displayLayout.removeItem
|
||||
removeItem: component && component.$refs.displayLayout.removeItem,
|
||||
orderItem: component && component.$refs.displayLayout.orderItem
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
|
@ -24,7 +24,7 @@
|
||||
<div class="c-fl-container"
|
||||
:style="[{'flex-basis': sizeString}]"
|
||||
:class="{'is-empty': !frames.length}">
|
||||
<div class="c-fl-container__header icon-grippy-ew"
|
||||
<div class="c-fl-container__header"
|
||||
v-show="isEditing"
|
||||
draggable="true"
|
||||
@dragstart="startContainerDrag">
|
||||
@ -35,7 +35,7 @@
|
||||
class="c-fl-frame__drop-hint"
|
||||
:index="-1"
|
||||
:allow-drop="allowDrop"
|
||||
@object-drop-to="moveOrCreateFrame">
|
||||
@object-drop-to="moveOrCreateNewFrame">
|
||||
</drop-hint>
|
||||
|
||||
<div class="c-fl-container__frames-holder">
|
||||
@ -55,7 +55,7 @@
|
||||
:key="i"
|
||||
:index="i"
|
||||
:allowDrop="allowDrop"
|
||||
@object-drop-to="moveOrCreateFrame">
|
||||
@object-drop-to="moveOrCreateNewFrame">
|
||||
</drop-hint>
|
||||
|
||||
<resize-handle
|
||||
@ -100,7 +100,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
allowDrop(event, index) {
|
||||
if (event.dataTransfer.getData('domainObject')) {
|
||||
if (event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
return true;
|
||||
}
|
||||
let frameId = event.dataTransfer.getData('frameid'),
|
||||
@ -123,15 +123,12 @@ export default {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
moveOrCreateFrame(insertIndex, event) {
|
||||
if (event.dataTransfer.types.includes('domainobject')) {
|
||||
// create frame using domain object
|
||||
let domainObject = JSON.parse(event.dataTransfer.getData('domainObject'));
|
||||
moveOrCreateNewFrame(insertIndex, event) {
|
||||
if (event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
this.$emit(
|
||||
'create-frame',
|
||||
'new-frame',
|
||||
this.index,
|
||||
insertIndex,
|
||||
domainObject.identifier
|
||||
insertIndex
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
@ -21,10 +21,10 @@
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div v-if="isEditing"
|
||||
v-show="isValidTarget">
|
||||
<div v-show="isValidTarget">
|
||||
<div class="c-drop-hint c-drop-hint--always-show"
|
||||
:class="{'is-mouse-over': isMouseOver}"
|
||||
@dragover.prevent
|
||||
@dragenter="dragenter"
|
||||
@dragleave="dragleave"
|
||||
@drop="dropHandler">
|
||||
@ -37,8 +37,6 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
export default {
|
||||
props:{
|
||||
index: Number,
|
||||
@ -47,7 +45,6 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
mixins: [isEditingMixin],
|
||||
data() {
|
||||
return {
|
||||
isMouseOver: false,
|
||||
@ -75,10 +72,12 @@ export default {
|
||||
mounted() {
|
||||
document.addEventListener('dragstart', this.dragstart);
|
||||
document.addEventListener('dragend', this.dragend);
|
||||
document.addEventListener('drop', this.dragend);
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener('dragstart', this.dragstart);
|
||||
document.removeEventListener('dragend', this.dragend);
|
||||
document.removeEventListener('drop', this.dragend);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -22,6 +22,11 @@
|
||||
|
||||
<template>
|
||||
<div class="c-fl">
|
||||
<div
|
||||
id="js-fl-drag-ghost"
|
||||
class="c-fl__drag-ghost">
|
||||
</div>
|
||||
|
||||
<div class="c-fl__empty"
|
||||
v-if="areAllContainersEmpty()">
|
||||
<span class="c-fl__empty-message">This Flexible Layout is currently empty</span>
|
||||
@ -50,7 +55,7 @@
|
||||
:container="container"
|
||||
:rowsLayout="rowsLayout"
|
||||
@move-frame="moveFrame"
|
||||
@create-frame="createFrame"
|
||||
@new-frame="setFrameLocation"
|
||||
@persist="persist">
|
||||
</container-component>
|
||||
|
||||
@ -79,6 +84,22 @@
|
||||
|
||||
<style lang="scss">
|
||||
@import '~styles/sass-base';
|
||||
|
||||
@mixin containerGrippy($headerSize, $dir) {
|
||||
position: absolute;
|
||||
$h: 6px;
|
||||
$minorOffset: ($headerSize - $h) / 2;
|
||||
$majorOffset: 35%;
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
@include grippy($c: $editFrameSelectedMovebarColorFg, $dir: $dir);
|
||||
@if $dir == 'x' {
|
||||
top: $minorOffset; right: $majorOffset; bottom: $minorOffset; left: $majorOffset;
|
||||
} @else {
|
||||
top: $majorOffset; right: $minorOffset; bottom: $majorOffset; left: $minorOffset;
|
||||
}
|
||||
}
|
||||
|
||||
.c-fl {
|
||||
@include abs();
|
||||
@ -100,7 +121,6 @@
|
||||
> * + * { margin-left: 1px; }
|
||||
|
||||
&[class*='--rows'] {
|
||||
//@include test(blue, 0.1);
|
||||
flex-direction: column;
|
||||
> * + * {
|
||||
margin-left: 0;
|
||||
@ -122,13 +142,29 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
&__drag-ghost{
|
||||
background: $colorItemTreeHoverBg;
|
||||
color: $colorItemTreeHoverFg;
|
||||
border-radius: $basicCr;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: $interiorMarginLg $interiorMarginLg * 2;
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
z-index: 2;
|
||||
|
||||
&:before {
|
||||
color: $colorKey;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-fl-container {
|
||||
/***************************************************** CONTAINERS */
|
||||
$headerSize: 16px;
|
||||
|
||||
border: 1px solid transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
@ -138,9 +174,9 @@
|
||||
flex-shrink: 1;
|
||||
|
||||
&__header {
|
||||
// Only displayed when editing
|
||||
background: $editSelectableColor;
|
||||
color: $editSelectableColorFg;
|
||||
// Only displayed when editing, controlled via JS
|
||||
background: $editFrameMovebarColorBg;
|
||||
color: $editFrameMovebarColorFg;
|
||||
cursor: move;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -148,12 +184,8 @@
|
||||
|
||||
&:before {
|
||||
// Drag grippy
|
||||
font-size: 0.8em;
|
||||
@include containerGrippy($headerSize, 'x');
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
transform-origin: center;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,19 +205,27 @@
|
||||
}
|
||||
|
||||
.is-editing & {
|
||||
//background: $editCanvasColorBg;
|
||||
border-color: $editSelectableColor;
|
||||
|
||||
&:hover {
|
||||
border-color: $editSelectableColorHov;
|
||||
.c-fl-container__header {
|
||||
background: $editFrameHovMovebarColorBg;
|
||||
color: $editFrameHovMovebarColorFg;
|
||||
|
||||
&:before {
|
||||
opacity: .75;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[s-selected] {
|
||||
border-color: $editSelectableColorSelected;
|
||||
border: $editFrameSelectedBorder;
|
||||
|
||||
.c-fl-container__header {
|
||||
background: $editSelectableColorSelected;
|
||||
color: $editSelectableColorSelectedFg;
|
||||
background:$editFrameSelectedMovebarColorBg;
|
||||
color: $editFrameSelectedMovebarColorFg;
|
||||
&:before {
|
||||
// Grippy
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,11 +234,6 @@
|
||||
// Frames get styled here because this is particular to their presence in this layout type
|
||||
.c-fl-frame {
|
||||
@include browserPrefix(margin-collapse, collapse);
|
||||
margin: 1px;
|
||||
|
||||
//&__drag-wrapper {
|
||||
// border: 1px solid $colorInteriorBorder; // Now handled by is-selectable
|
||||
//}
|
||||
}
|
||||
|
||||
/****** ROWS LAYOUT */
|
||||
@ -211,8 +246,8 @@
|
||||
overflow: hidden;
|
||||
|
||||
&:before {
|
||||
// Drag grippy
|
||||
transform: rotate(90deg) translate(-50%, 50%);
|
||||
// Grippy
|
||||
@include containerGrippy($headerSize, 'y');
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,8 +270,6 @@
|
||||
$dropHintSize: 15px;
|
||||
|
||||
display: flex;
|
||||
// justify-content: stretch;
|
||||
// align-items: stretch;
|
||||
flex: 1 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden; // Needed to allow frames to collapse when sized down
|
||||
@ -275,7 +308,6 @@
|
||||
pointer-events: none;
|
||||
text-align: center;
|
||||
width: $size;
|
||||
z-index: 2;
|
||||
|
||||
// Changed when layout is different, see below
|
||||
border-top-right-radius: $controlCr;
|
||||
@ -304,37 +336,16 @@
|
||||
|
||||
&:before {
|
||||
// The visible resize line
|
||||
background: $editColor;
|
||||
background: $editUIColor;
|
||||
content: '';
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
min-height: $size; min-width: $size;
|
||||
}
|
||||
|
||||
&__grippy {
|
||||
// Grippy element
|
||||
$d: 4px;
|
||||
$c: black;
|
||||
$a: 0.9;
|
||||
$d: 5px;
|
||||
background: $editColor;
|
||||
color: $editColorBg;
|
||||
border-radius: $smallCr;
|
||||
font-size: 0.8em;
|
||||
height: $d;
|
||||
width: $d * 10;
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
text-align: center;
|
||||
transform-origin: center center;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
padding: $margin $size;
|
||||
&:hover{
|
||||
// padding: $marginHov 0;
|
||||
cursor: row-resize;
|
||||
}
|
||||
}
|
||||
@ -342,20 +353,15 @@
|
||||
&.horizontal {
|
||||
padding: $size $margin;
|
||||
&:hover{
|
||||
// padding: 0 $marginHov;
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
[class*='grippy'] {
|
||||
transform: translate(-50%) rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transition: $transOut;
|
||||
&:before {
|
||||
// The visible resize line
|
||||
background: $editColorHov;
|
||||
background: $editUIColorHov;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -467,7 +473,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject: this.layoutObject
|
||||
domainObject: this.layoutObject,
|
||||
newFrameLocation: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -496,9 +503,27 @@ export default {
|
||||
this.persist();
|
||||
},
|
||||
deleteContainer(containerId) {
|
||||
let container = this.containers.filter(c => c.id === containerId)[0];
|
||||
let containerIndex = this.containers.indexOf(container);
|
||||
let container = this.containers.filter(c => c.id === containerId)[0],
|
||||
containerIndex = this.containers.indexOf(container);
|
||||
|
||||
/*
|
||||
remove associated domainObjects from composition
|
||||
*/
|
||||
container.frames.forEach(f => {
|
||||
this.composition.remove({identifier: f.domainObjectIdentifier});
|
||||
});
|
||||
|
||||
this.containers.splice(containerIndex, 1);
|
||||
|
||||
/*
|
||||
add a container when there are no containers in the FL,
|
||||
to prevent user from not being able to add a frame via
|
||||
drag and drop.
|
||||
*/
|
||||
if (this.containers.length === 0) {
|
||||
this.containers.push(new Container(100));
|
||||
}
|
||||
|
||||
sizeToFill(this.containers);
|
||||
this.persist();
|
||||
},
|
||||
@ -513,12 +538,22 @@ export default {
|
||||
sizeItems(toContainer.frames, frame);
|
||||
this.persist();
|
||||
},
|
||||
createFrame(containerIndex, insertFrameIndex, objectIdentifier) {
|
||||
let frame = new Frame(objectIdentifier);
|
||||
let container = this.containers[containerIndex];
|
||||
container.frames.splice(insertFrameIndex + 1, 0, frame);
|
||||
sizeItems(container.frames, frame);
|
||||
this.persist();
|
||||
setFrameLocation(containerIndex, insertFrameIndex) {
|
||||
this.newFrameLocation = [containerIndex, insertFrameIndex];
|
||||
},
|
||||
addFrame(domainObject) {
|
||||
if (this.newFrameLocation.length) {
|
||||
let containerIndex = this.newFrameLocation[0],
|
||||
frameIndex = this.newFrameLocation[1],
|
||||
frame = new Frame(domainObject.identifier),
|
||||
container = this.containers[containerIndex];
|
||||
|
||||
container.frames.splice(frameIndex + 1, 0, frame);
|
||||
sizeItems(container.frames, frame);
|
||||
|
||||
this.newFrameLocation = [];
|
||||
this.persist(containerIndex);
|
||||
}
|
||||
},
|
||||
deleteFrame(frameId) {
|
||||
let container = this.containers
|
||||
@ -528,6 +563,12 @@ export default {
|
||||
.frames
|
||||
.filter((f => f.id === frameId))[0];
|
||||
let frameIndex = container.frames.indexOf(frame);
|
||||
|
||||
/*
|
||||
remove associated domainObject from composition
|
||||
*/
|
||||
this.composition.remove({identifier: frame.domainObjectIdentifier});
|
||||
|
||||
container.frames.splice(frameIndex, 1);
|
||||
sizeToFill(container.frames);
|
||||
this.persist(containerIndex);
|
||||
@ -600,24 +641,33 @@ export default {
|
||||
} else {
|
||||
this.containers.splice(toIndex, 0, container);
|
||||
}
|
||||
this.persist();
|
||||
},
|
||||
removeChildObject(identifier) {
|
||||
let removeIdentifier = this.openmct.objects.makeKeyString(identifier);
|
||||
|
||||
this.containers.forEach(container => {
|
||||
container.frames = container.frames.filter(frame => {
|
||||
let frameIdentifier = this.openmct.objects.makeKeyString(frame.domainObjectIdentifier);
|
||||
|
||||
return removeIdentifier !== frameIdentifier;
|
||||
});
|
||||
});
|
||||
|
||||
this.persist();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('remove', this.removeChildObject);
|
||||
this.composition.on('add', this.addFrame);
|
||||
|
||||
let context = {
|
||||
item: this.domainObject,
|
||||
addContainer: this.addContainer,
|
||||
deleteContainer: this.deleteContainer,
|
||||
deleteFrame: this.deleteFrame,
|
||||
type: 'flexible-layout'
|
||||
}
|
||||
|
||||
this.unsubscribeSelection = this.openmct.selection.selectable(this.$el, context, true);
|
||||
this.unobserve = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.unsubscribeSelection();
|
||||
this.composition.off('remove', this.removeChildObject);
|
||||
this.composition.off('add', this.addFrame);
|
||||
|
||||
this.unobserve();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
'flex-basis': `${frame.size}%`
|
||||
}">
|
||||
|
||||
<div class="c-frame c-fl-frame__drag-wrapper is-selectable is-moveable"
|
||||
<div class="c-frame c-fl-frame__drag-wrapper is-selectable u-inspectable is-moveable"
|
||||
draggable="true"
|
||||
@dragstart="initDrag"
|
||||
ref="frame">
|
||||
@ -35,7 +35,8 @@
|
||||
v-if="domainObject"
|
||||
:domain-object="domainObject"
|
||||
:object-path="objectPath"
|
||||
:has-frame="hasFrame">
|
||||
:has-frame="hasFrame"
|
||||
ref="objectFrame">
|
||||
</object-frame>
|
||||
|
||||
<div class="c-fl-frame__size-indicator"
|
||||
@ -73,22 +74,33 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
setDomainObject(object) {
|
||||
console.log('setting object!');
|
||||
this.domainObject = object;
|
||||
this.objectPath = [object];
|
||||
this.setSelection();
|
||||
},
|
||||
setSelection() {
|
||||
let context = {
|
||||
item: this.domainObject,
|
||||
addContainer: this.addContainer,
|
||||
type: 'frame',
|
||||
frameId: this.frame.id
|
||||
};
|
||||
|
||||
this.unsubscribeSelection = this.openmct.selection.selectable(this.$refs.frame, context, false);
|
||||
this.$nextTick(function () {
|
||||
let childContext = this.$refs.objectFrame.getSelectionContext();
|
||||
childContext.item = this.domainObject;
|
||||
childContext.type = 'frame';
|
||||
childContext.frameId = this.frame.id;
|
||||
this.unsubscribeSelection = this.openmct.selection.selectable(
|
||||
this.$refs.frame, childContext, false);
|
||||
});
|
||||
},
|
||||
initDrag(event) {
|
||||
let type = this.openmct.types.get(this.domainObject.type),
|
||||
iconClass = type.definition ? type.definition.cssClass : 'icon-object-unknown';
|
||||
|
||||
if (this.dragGhost) {
|
||||
let originalClassName = this.dragGhost.classList[0];
|
||||
this.dragGhost.className = '';
|
||||
this.dragGhost.classList.add(originalClassName, iconClass);
|
||||
|
||||
this.dragGhost.innerHTML = `<span>${this.domainObject.name}</span>`;
|
||||
event.dataTransfer.setDragImage(this.dragGhost, 0, 0);
|
||||
}
|
||||
|
||||
event.dataTransfer.setData('frameid', this.frame.id);
|
||||
event.dataTransfer.setData('containerIndex', this.containerIndex);
|
||||
}
|
||||
@ -99,6 +111,8 @@ export default {
|
||||
this.setDomainObject(object);
|
||||
});
|
||||
}
|
||||
|
||||
this.dragGhost = document.getElementById('js-fl-drag-ghost');
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.unsubscribeSelection) {
|
||||
|
@ -52,9 +52,18 @@ define([
|
||||
layoutObject: domainObject
|
||||
},
|
||||
el: element,
|
||||
template: '<flexible-layout-component></flexible-layout-component>'
|
||||
template: '<flexible-layout-component ref="flexibleLayout"></flexible-layout-component>'
|
||||
});
|
||||
},
|
||||
getSelectionContext: function () {
|
||||
return {
|
||||
item: domainObject,
|
||||
addContainer: component.$refs.flexibleLayout.addContainer,
|
||||
deleteContainer: component.$refs.flexibleLayout.deleteContainer,
|
||||
deleteFrame: component.$refs.flexibleLayout.deleteFrame,
|
||||
type: 'flexible-layout'
|
||||
};
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
@ -44,6 +44,7 @@ define([
|
||||
containers: [new Container.default(50), new Container.default(50)],
|
||||
rowsLayout: false
|
||||
};
|
||||
domainObject.composition = [];
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -53,18 +53,18 @@ function ToolbarProvider(openmct) {
|
||||
toggleContainer = {
|
||||
control: 'toggle-button',
|
||||
key: 'toggle-layout',
|
||||
domainObject: secondary ? secondary.context.item : primary.context.item,
|
||||
domainObject: primary.context.item,
|
||||
property: 'configuration.rowsLayout',
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
value: true,
|
||||
icon: 'icon-columns',
|
||||
title: 'Columns'
|
||||
title: 'Columns layout'
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
value: false,
|
||||
icon: 'icon-rows',
|
||||
title: 'Rows'
|
||||
title: 'Rows layout'
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -120,14 +120,14 @@ function ToolbarProvider(openmct) {
|
||||
property: `configuration.containers[${containerIndex}].frames[${frameIndex}].noFrame`,
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
value: false,
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Hide frame"
|
||||
title: "Frame hidden"
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
value: true,
|
||||
icon: 'icon-frame-show',
|
||||
title: "Show frame"
|
||||
title: "Frame visible"
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -140,6 +140,8 @@ function ToolbarProvider(openmct) {
|
||||
title: 'Add Container'
|
||||
};
|
||||
|
||||
toggleContainer.domainObject = secondary.context.item;
|
||||
|
||||
} else if (primary.context.type === 'container') {
|
||||
|
||||
deleteContainer = {
|
||||
@ -151,7 +153,7 @@ function ToolbarProvider(openmct) {
|
||||
|
||||
let prompt = openmct.overlays.dialog({
|
||||
iconClass: 'alert',
|
||||
message: `This action will permanently delete container ${containerIndex + 1} from this Flexible Layout`,
|
||||
message: 'This action will permanently delete this container from this Flexible Layout',
|
||||
buttons: [
|
||||
{
|
||||
label: 'Ok',
|
||||
@ -202,7 +204,7 @@ function ToolbarProvider(openmct) {
|
||||
addContainer,
|
||||
toggleFrame ? separator: undefined,
|
||||
toggleFrame,
|
||||
deleteFrame || deleteContainer ? separator: undefined,
|
||||
deleteFrame || deleteContainer ? separator : undefined,
|
||||
deleteFrame,
|
||||
deleteContainer
|
||||
];
|
||||
|
@ -4,9 +4,8 @@
|
||||
@click="navigate">
|
||||
<td class="c-list-item__name">
|
||||
<a :href="objectLink" ref="objectLink">
|
||||
<div class="c-list-item__type-icon"
|
||||
:class="item.type.cssClass"></div>
|
||||
{{item.model.name}}
|
||||
<div class="c-list-item__type-icon" :class="item.type.cssClass"></div>
|
||||
<div class="c-list-item__name-value">{{item.model.name}}</div>
|
||||
</a>
|
||||
</td>
|
||||
<td class="c-list-item__type">{{ item.type.name }}</td>
|
||||
@ -20,17 +19,24 @@
|
||||
|
||||
/******************************* LIST ITEM */
|
||||
.c-list-item {
|
||||
&__name {
|
||||
@include ellipsize();
|
||||
&__name a {
|
||||
display: flex;
|
||||
|
||||
> * + * { margin-left: $interiorMarginSm; }
|
||||
}
|
||||
|
||||
&__type-icon {
|
||||
// Have to do it this way instead of using icon-* class, due to need to apply alias to the icon
|
||||
color: $colorKey;
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
margin-right:$interiorMarginSm;
|
||||
}
|
||||
|
||||
&__name-value {
|
||||
@include ellipsize();
|
||||
}
|
||||
|
||||
&.is-alias {
|
||||
// Object is an alias to an original.
|
||||
[class*='__type-icon'] {
|
||||
@ -48,7 +54,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
@ -78,9 +78,12 @@
|
||||
|
||||
td {
|
||||
$p: floor($interiorMargin * 1.5);
|
||||
font-size: 1.1em;
|
||||
@include ellipsize();
|
||||
line-height: 120%; // Needed for icon alignment
|
||||
max-width: 0;
|
||||
padding-top: $p;
|
||||
padding-bottom: $p;
|
||||
width: 25%;
|
||||
|
||||
&:not(.c-list-item__name) {
|
||||
color: $colorItemFgDetails;
|
||||
|
@ -7,18 +7,19 @@
|
||||
<div class="c-ne__embed__info">
|
||||
<div class="c-ne__embed__name">
|
||||
<a class="c-ne__embed__link"
|
||||
v-on:click="navigate(embed.type)"
|
||||
v-bind:class="[embed.cssClass]">{{embed.name}}</a>
|
||||
:href="objectLink"
|
||||
:class="embed.cssClass">{{embed.name}}</a>
|
||||
<a class="c-ne__embed__context-available icon-arrow-down"
|
||||
v-on:click="toggleActionMenu"></a>
|
||||
@click="toggleActionMenu"></a>
|
||||
</div>
|
||||
<div class="hide-menu hidden">
|
||||
<div class="menu-element context-menu-wrapper mobile-disable-select">
|
||||
<div class="menu context-menu">
|
||||
<div class="c-menu">
|
||||
<ul>
|
||||
<li v-for="action in actions"
|
||||
v-bind:class="[action.cssClass]"
|
||||
v-on:click="action.perform(embed, entry)">
|
||||
<li v-for="action in actions"
|
||||
:key="action.name"
|
||||
:class="action.cssClass"
|
||||
@click="action.perform(embed, entry)">
|
||||
{{ action.name }}
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<li class="c-notebook__entry c-ne has-local-controls"
|
||||
v-on:drop="dropOnEntry(entry.id, $event)"
|
||||
v-on:dragover="dragoverOnEntry"
|
||||
>
|
||||
@drop.prevent="dropOnEntry(entry.id, $event)">
|
||||
<div class="c-ne__time-and-content">
|
||||
<div class="c-ne__time">
|
||||
<span>{{formatTime(entry.createdOn, 'YYYY-MM-DD')}}</span>
|
||||
@ -11,18 +9,18 @@
|
||||
<div class="c-ne__text c-input-inline"
|
||||
contenteditable="true"
|
||||
ref="contenteditable"
|
||||
v-on:blur="textBlur($event, entry.id)"
|
||||
v-on:focus="textFocus($event, entry.id)"
|
||||
v-bind:key="entry.id"
|
||||
@blur="textBlur($event, entry.id)"
|
||||
@focus="textFocus($event, entry.id)"
|
||||
v-html="entry.text">
|
||||
</div>
|
||||
<div class="c-ne__embeds">
|
||||
<notebook-embed
|
||||
v-for="(embed, index) in entry.embeds"
|
||||
:key="index"
|
||||
v-for="embed in entry.embeds"
|
||||
:key="embed.id"
|
||||
:embed="embed"
|
||||
:entry="entry"
|
||||
></notebook-embed>
|
||||
:objectPath="embed.objectPath"
|
||||
:entry="entry">
|
||||
</notebook-embed>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -30,6 +28,7 @@
|
||||
<div class="c-ne__local-controls--hidden">
|
||||
<button class="c-click-icon c-click-icon--major icon-trash"
|
||||
title="Delete this entry"
|
||||
v-on:click="deleteEntry"></button>
|
||||
@click="deleteEntry">
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
@ -5,30 +5,25 @@
|
||||
@input="search"
|
||||
@clear="search">
|
||||
</search>
|
||||
<div class="c-notebook__controls">
|
||||
<div class="select c-notebook__controls__time">
|
||||
<select v-model="showTime">
|
||||
<option value="0" selected="selected">Show all</option>
|
||||
<option value="1">Last hour</option>
|
||||
<option value="8">Last 8 hours</option>
|
||||
<option value="24">Last 24 hours</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="select c-notebook__controls__sort">
|
||||
<select v-model="sortEntries">
|
||||
<option value="newest" :selected="sortEntries === 'newest'">Newest first</option>
|
||||
<option value="oldest" :selected="sortEntries === 'oldest'">Oldest first</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="c-notebook__controls ">
|
||||
<select class="c-notebook__controls__time" v-model="showTime">
|
||||
<option value="0" selected="selected">Show all</option>
|
||||
<option value="1">Last hour</option>
|
||||
<option value="8">Last 8 hours</option>
|
||||
<option value="24">Last 24 hours</option>
|
||||
</select>
|
||||
<select class="c-notebook__controls__time" v-model="sortEntries">
|
||||
<option value="newest" :selected="sortEntries === 'newest'">Newest first</option>
|
||||
<option value="oldest" :selected="sortEntries === 'oldest'">Oldest first</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-notebook__drag-area icon-plus"
|
||||
@click="newEntry($event)"
|
||||
@drop="newEntry($event)"
|
||||
id="newEntry">
|
||||
@drop="newEntry($event)">
|
||||
<span class="c-notebook__drag-area__label">To start a new entry, click here or drag and drop any object</span>
|
||||
</div>
|
||||
<div class="c-notebook__entries" ng-mouseover="handleActive()">
|
||||
<div class="c-notebook__entries">
|
||||
<ul>
|
||||
<notebook-entry
|
||||
v-for="(entry,index) in filteredAndSortedEntries"
|
||||
|
@ -34,28 +34,17 @@ function (
|
||||
Vue,
|
||||
Painterro
|
||||
) {
|
||||
function EmbedController (openmct, domainObject) {
|
||||
function EmbedController(openmct, domainObject) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectService = openmct.$injector.get('objectService');
|
||||
this.navigationService = openmct.$injector.get('navigationService');
|
||||
this.popupService = openmct.$injector.get('popupService');
|
||||
this.agentService = openmct.$injector.get('agentService');
|
||||
this.dialogService = openmct.$injector.get('dialogService');
|
||||
|
||||
|
||||
this.navigate = this.navigate.bind(this);
|
||||
this.exposedData = this.exposedData.bind(this);
|
||||
this.exposedMethods = this.exposedMethods.bind(this);
|
||||
this.toggleActionMenu = this.toggleActionMenu.bind(this);
|
||||
}
|
||||
|
||||
EmbedController.prototype.navigate = function (embedType) {
|
||||
this.objectService.getObjects([embedType]).then(function (objects) {
|
||||
this.navigationService.setNavigation(objects[embedType]);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
EmbedController.prototype.openSnapshot = function (domainObject, entry, embed) {
|
||||
|
||||
function annotateSnapshot(openmct) {
|
||||
@ -63,20 +52,22 @@ function (
|
||||
|
||||
var save = false,
|
||||
painterroInstance = {},
|
||||
annotateOverlay = new Vue({
|
||||
annotateVue = new Vue({
|
||||
template: '<div id="snap-annotation"></div>'
|
||||
}),
|
||||
self = this;
|
||||
|
||||
openmct.overlays.overlay({
|
||||
element: annotateOverlay.$mount().$el,
|
||||
let annotateOverlay = openmct.overlays.overlay({
|
||||
element: annotateVue.$mount().$el,
|
||||
size: 'large',
|
||||
dismissable: false,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Cancel',
|
||||
callback: function () {
|
||||
save = false;
|
||||
painterroInstance.save();
|
||||
annotateOverlay.dismiss();
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -84,11 +75,12 @@ function (
|
||||
callback: function () {
|
||||
save = true;
|
||||
painterroInstance.save();
|
||||
annotateOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
],
|
||||
onDestroy: function () {
|
||||
annotateOverlay.$destroy(true);
|
||||
annotateVue.$destroy(true);
|
||||
}
|
||||
});
|
||||
|
||||
@ -162,14 +154,11 @@ function (
|
||||
}
|
||||
});
|
||||
|
||||
function onDestroyCallback() {
|
||||
snapshot.$destroy(true);
|
||||
}
|
||||
|
||||
var snapshotOverlay = this.openmct.overlays.overlay({
|
||||
element: snapshot.$mount().$el,
|
||||
onDestroy: onDestroyCallback,
|
||||
onDestroy: () => {snapshot.$destroy(true)},
|
||||
size: 'large',
|
||||
dismissable: true,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Done',
|
||||
@ -199,23 +188,20 @@ function (
|
||||
return foundId;
|
||||
};
|
||||
|
||||
EmbedController.prototype.actionToMenuDecorator = function (action) {
|
||||
return {
|
||||
name: action.getMetadata().name,
|
||||
cssClass: action.getMetadata().cssClass,
|
||||
perform: action.perform
|
||||
};
|
||||
};
|
||||
|
||||
EmbedController.prototype.populateActionMenu = function (objectService, actionService) {
|
||||
EmbedController.prototype.populateActionMenu = function (openmct, actions) {
|
||||
return function () {
|
||||
var self = this;
|
||||
|
||||
objectService.getObjects([self.embed.type]).then(function (resp) {
|
||||
var domainObject = resp[self.embed.type],
|
||||
previewAction = actionService.getActions({key: 'mct-preview-action', domainObject: domainObject})[0];
|
||||
|
||||
self.actions.push(self.actionToMenuDecorator(previewAction));
|
||||
openmct.objects.get(self.embed.type).then(function (domainObject) {
|
||||
actions.forEach((action) => {
|
||||
self.actions.push({
|
||||
cssClass: action.cssClass,
|
||||
name: action.name,
|
||||
perform: () => {
|
||||
action.invoke([domainObject].concat(openmct.router.path));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
@ -268,13 +254,14 @@ function (
|
||||
// Remove the context menu
|
||||
function dismiss() {
|
||||
container.find('.hide-menu').append(menu);
|
||||
body.off(initiatingEvent, dismiss);
|
||||
menu.off(initiatingEvent, menuClickHandler);
|
||||
body.off(initiatingEvent, menuClickHandler);
|
||||
dismissExistingMenu = undefined;
|
||||
}
|
||||
|
||||
function menuClickHandler(e) {
|
||||
e.stopPropagation();
|
||||
window.setTimeout(() => {
|
||||
dismiss();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Dismiss any menu which was already showing
|
||||
@ -290,11 +277,7 @@ function (
|
||||
marginY: -50
|
||||
});
|
||||
|
||||
// Stop propagation so that clicks or touches on the menu do not close the menu
|
||||
menu.on(initiatingEvent, menuClickHandler);
|
||||
|
||||
body.on(initiatingEvent, dismiss);
|
||||
|
||||
body.on(initiatingEvent, menuClickHandler);
|
||||
};
|
||||
|
||||
EmbedController.prototype.exposedData = function () {
|
||||
@ -308,11 +291,9 @@ function (
|
||||
var self = this;
|
||||
|
||||
return {
|
||||
navigate: self.navigate,
|
||||
openSnapshot: self.openSnapshot,
|
||||
formatTime: self.formatTime,
|
||||
toggleActionMenu: self.toggleActionMenu,
|
||||
actionToMenuDecorator: self.actionToMenuDecorator,
|
||||
findInArray: self.findInArray
|
||||
};
|
||||
};
|
||||
|
@ -30,8 +30,6 @@ function (
|
||||
function EntryController (openmct, domainObject) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.dndService = this.openmct.$injector.get('dndService');
|
||||
this.dialogService = this.openmct.$injector.get('dialogService');
|
||||
|
||||
this.currentEntryValue = '';
|
||||
|
||||
@ -106,37 +104,35 @@ function (
|
||||
};
|
||||
|
||||
EntryController.prototype.dropOnEntry = function (entryid, event) {
|
||||
|
||||
var data = event.dataTransfer.getData('domainObject');
|
||||
var data = event.dataTransfer.getData('openmct/domain-object-path');
|
||||
|
||||
if (data) {
|
||||
var selectedObject = JSON.parse(data),
|
||||
selectedObjectId = selectedObject.identifier.key,
|
||||
cssClass = this.openmct.types.get(selectedObject.type),
|
||||
var objectPath = JSON.parse(data),
|
||||
domainObject = objectPath[0],
|
||||
domainObjectKey = domainObject.identifier.key,
|
||||
domainObjectType = this.openmct.types.get(domainObject.type),
|
||||
cssClass = domainObjectType && domainObjectType.definition ?
|
||||
domainObjectType.definition.cssClass : 'icon-object-unknown',
|
||||
entryPos = this.entryPosById(entryid),
|
||||
currentEntryEmbeds = this.domainObject.entries[entryPos].embeds,
|
||||
newEmbed = {
|
||||
type: selectedObjectId,
|
||||
id: '' + Date.now(),
|
||||
domainObject: domainObject,
|
||||
objectPath: objectPath,
|
||||
type: domainObjectKey,
|
||||
cssClass: cssClass,
|
||||
name: selectedObject.name,
|
||||
name: domainObject.name,
|
||||
snapshot: ''
|
||||
};
|
||||
|
||||
currentEntryEmbeds.push(newEmbed);
|
||||
this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].embeds', currentEntryEmbeds);
|
||||
}
|
||||
};
|
||||
|
||||
EntryController.prototype.dragoverOnEntry = function () {
|
||||
|
||||
};
|
||||
|
||||
EntryController.prototype.exposedData = function () {
|
||||
return {
|
||||
openmct: this.openmct,
|
||||
domainObject: this.domainObject,
|
||||
dialogService: this.dialogService,
|
||||
currentEntryValue: this.currentEntryValue
|
||||
};
|
||||
};
|
||||
@ -148,8 +144,7 @@ function (
|
||||
textBlur: this.textBlur,
|
||||
formatTime: this.formatTime,
|
||||
deleteEntry: this.deleteEntry,
|
||||
dropOnEntry: this.dropOnEntry,
|
||||
dragoverOnEntry: this.dragoverOnEntry
|
||||
dropOnEntry: this.dropOnEntry
|
||||
};
|
||||
};
|
||||
return EntryController;
|
||||
|
@ -27,7 +27,9 @@ define([
|
||||
'../../res/templates/notebook.html',
|
||||
'../../res/templates/entry.html',
|
||||
'../../res/templates/embed.html',
|
||||
'../../../../ui/components/search.vue'
|
||||
'../../../../ui/components/search.vue',
|
||||
'../../../../ui/preview/PreviewAction',
|
||||
'../../../../ui/mixins/object-link'
|
||||
],
|
||||
function (
|
||||
Vue,
|
||||
@ -36,15 +38,16 @@ function (
|
||||
NotebookTemplate,
|
||||
EntryTemplate,
|
||||
EmbedTemplate,
|
||||
search
|
||||
search,
|
||||
PreviewAction,
|
||||
objectLinkMixin
|
||||
) {
|
||||
|
||||
function NotebookController(openmct, domainObject) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.entrySearch = '';
|
||||
this.objectService = openmct.$injector.get('objectService');
|
||||
this.actionService = openmct.$injector.get('actionService');
|
||||
this.previewAction = new PreviewAction.default(openmct);
|
||||
|
||||
this.show = this.show.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
@ -61,11 +64,12 @@ function (
|
||||
|
||||
var notebookEmbed = {
|
||||
inject:['openmct', 'domainObject'],
|
||||
mixins:[objectLinkMixin.default],
|
||||
props:['embed', 'entry'],
|
||||
template: EmbedTemplate,
|
||||
data: embedController.exposedData,
|
||||
methods: embedController.exposedMethods(),
|
||||
beforeMount: embedController.populateActionMenu(self.objectService, self.actionService)
|
||||
beforeMount: embedController.populateActionMenu(self.openmct, [self.previewAction])
|
||||
};
|
||||
|
||||
var entryComponent = {
|
||||
@ -120,8 +124,8 @@ function (
|
||||
var date = Date.now(),
|
||||
embed;
|
||||
|
||||
if (event.dataTransfer && event.dataTransfer.getData('domainObject')) {
|
||||
var selectedObject = JSON.parse(event.dataTransfer.getData('domainObject')),
|
||||
if (event.dataTransfer && event.dataTransfer.getData('openmct/domain-object-path')) {
|
||||
var selectedObject = JSON.parse(event.dataTransfer.getData('openmct/domain-object-path'))[0],
|
||||
selectedObjectId = selectedObject.identifier.key,
|
||||
cssClass = this.openmct.types.get(selectedObject.type);
|
||||
|
||||
|
@ -41,28 +41,24 @@
|
||||
<div class="grid-cell label"
|
||||
title="The field to be plotted as a value for this series.">Value</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.yKey">
|
||||
<option ng-repeat="option in yKeyOptions"
|
||||
value="{{option.value}}"
|
||||
ng-selected="option.value == form.yKey">
|
||||
{{option.name}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.yKey">
|
||||
<option ng-repeat="option in yKeyOptions"
|
||||
value="{{option.value}}"
|
||||
ng-selected="option.value == form.yKey">
|
||||
{{option.name}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
<div class="grid-cell label"
|
||||
title="The line rendering style for this series.">Line Style</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.interpolate">
|
||||
<option value="none">None</option>
|
||||
<option value="linear">Linear interpolate</option>
|
||||
<option value="stepAfter">Step after</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.interpolate">
|
||||
<option value="none">None</option>
|
||||
<option value="linear">Linear interpolate</option>
|
||||
<option value="stepAfter">Step after</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
@ -160,15 +156,13 @@
|
||||
<div class="grid-cell label"
|
||||
title="The position of the legend relative to the plot display area.">Position</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.position">
|
||||
<option value="hidden">Hidden</option>
|
||||
<option value="top">Top</option>
|
||||
<option value="right">Right</option>
|
||||
<option value="bottom">Bottom</option>
|
||||
<option value="left">Left</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.position">
|
||||
<option value="hidden">Hidden</option>
|
||||
<option value="top">Top</option>
|
||||
<option value="right">Right</option>
|
||||
<option value="bottom">Bottom</option>
|
||||
<option value="left">Left</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
@ -180,15 +174,13 @@
|
||||
<div class="grid-cell label"
|
||||
title="What to display in the legend when it's collapsed.">When collapsed show</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.valueToShowWhenCollapsed">
|
||||
<option value="none">nothing</option>
|
||||
<option value="nearestTimestamp">nearest timestamp</option>
|
||||
<option value="nearestValue">nearest Value</option>
|
||||
<option value="min">minimum value</option>
|
||||
<option value="max">maximum value</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.valueToShowWhenCollapsed">
|
||||
<option value="none">Nothing</option>
|
||||
<option value="nearestTimestamp">Nearest timestamp</option>
|
||||
<option value="nearestValue">Nearest value</option>
|
||||
<option value="min">Minimum value</option>
|
||||
<option value="max">Maximum value</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
|
@ -30,7 +30,7 @@ define(
|
||||
],
|
||||
function (
|
||||
html2canvas,
|
||||
saveAs
|
||||
{ saveAs }
|
||||
) {
|
||||
|
||||
/**
|
||||
|
@ -39,9 +39,7 @@ define([
|
||||
'./folderView/plugin',
|
||||
'./flexibleLayout/plugin',
|
||||
'./tabs/plugin',
|
||||
'../../platform/features/fixed/plugin',
|
||||
'./LADTable/plugin',
|
||||
'./preview/plugin'
|
||||
'./LADTable/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@ -61,9 +59,7 @@ define([
|
||||
FolderView,
|
||||
FlexibleLayout,
|
||||
Tabs,
|
||||
FixedView,
|
||||
LADTable,
|
||||
PreviewPlugin
|
||||
LADTable
|
||||
) {
|
||||
var bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
@ -176,10 +172,8 @@ define([
|
||||
plugins.DisplayLayout = DisplayLayoutPlugin.default;
|
||||
plugins.FolderView = FolderView;
|
||||
plugins.Tabs = Tabs;
|
||||
plugins.FixedView = FixedView;
|
||||
plugins.FlexibleLayout = FlexibleLayout;
|
||||
plugins.LADTable = LADTable;
|
||||
plugins.Preview = PreviewPlugin.default;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
@ -15,25 +15,25 @@
|
||||
v-for="(tab,index) in tabsList"
|
||||
:key="index"
|
||||
:class="[
|
||||
{'is-current': tab=== currentTab},
|
||||
{'is-current': isCurrent(tab)},
|
||||
tab.type.definition.cssClass
|
||||
]"
|
||||
@click="showTab(tab)">
|
||||
<span class="c-button__label">{{tab.model.name}}</span>
|
||||
<span class="c-button__label">{{tab.domainObject.name}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="c-tabs-view__object-holder"
|
||||
v-for="(object, index) in tabsList"
|
||||
v-for="(tab, index) in tabsList"
|
||||
:key="index"
|
||||
:class="{'invisible': object !== currentTab}">
|
||||
:class="{'invisible': !isCurrent(tab)}">
|
||||
<div class="c-tabs-view__object-name l-browse-bar__object-name--w"
|
||||
:class="currentTab.type.definition.cssClass">
|
||||
<div class="l-browse-bar__object-name">
|
||||
{{currentTab.model.name}}
|
||||
{{currentTab.domainObject.name}}
|
||||
</div>
|
||||
</div>
|
||||
<object-view class="c-tabs-view__object"
|
||||
:object="object.model">
|
||||
:object="tab.domainObject">
|
||||
</object-view>
|
||||
</div>
|
||||
</div>
|
||||
@ -87,6 +87,7 @@
|
||||
|
||||
<script>
|
||||
import ObjectView from '../../../ui/components/ObjectView.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
var unknownObjectType = {
|
||||
definition: {
|
||||
@ -100,9 +101,71 @@ export default {
|
||||
components: {
|
||||
ObjectView
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
currentTab: {},
|
||||
tabsList: [],
|
||||
setCurrentTab: true,
|
||||
isDragging: false,
|
||||
allowDrop: false
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
showTab(tab) {
|
||||
this.currentTab = tab;
|
||||
},
|
||||
addItem(domainObject) {
|
||||
let type = this.openmct.types.get(domainObject.type) || unknownObjectType,
|
||||
tabItem = {
|
||||
domainObject,
|
||||
type: type
|
||||
};
|
||||
|
||||
this.tabsList.push(tabItem);
|
||||
|
||||
if (this.setCurrentTab) {
|
||||
this.currentTab = tabItem;
|
||||
this.setCurrentTab = false;
|
||||
}
|
||||
},
|
||||
removeItem(identifier) {
|
||||
let pos = this.tabsList.findIndex(tab =>
|
||||
tab.domainObject.identifier.namespace === identifier.namespace && tab.domainObject.identifier.key === identifier.key
|
||||
),
|
||||
tabToBeRemoved = this.tabsList[pos];
|
||||
|
||||
this.tabsList.splice(pos, 1);
|
||||
|
||||
if (this.isCurrent(tabToBeRemoved)) {
|
||||
this.showTab(this.tabsList[this.tabsList.length - 1]);
|
||||
}
|
||||
},
|
||||
onDrop(e) {
|
||||
this.setCurrentTab = true;
|
||||
},
|
||||
dragstart (e) {
|
||||
if (e.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
this.isDragging = true;
|
||||
}
|
||||
},
|
||||
dragend(e) {
|
||||
this.isDragging = false;
|
||||
this.allowDrop = false;
|
||||
},
|
||||
dragenter() {
|
||||
this.allowDrop = true;
|
||||
},
|
||||
dragleave() {
|
||||
this.allowDrop = false;
|
||||
},
|
||||
isCurrent(tab) {
|
||||
return _.isEqual(this.currentTab, tab)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.composition) {
|
||||
this.composition.on('add', this.addItem, this);
|
||||
this.composition.on('add', this.addItem);
|
||||
this.composition.on('remove', this.removeItem);
|
||||
this.composition.load();
|
||||
}
|
||||
|
||||
@ -116,54 +179,9 @@ export default {
|
||||
dropHint.addEventListener('dragleave', this.dragleave);
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
currentTab: {},
|
||||
tabsList: [],
|
||||
setCurrentTab: true,
|
||||
isDragging: false,
|
||||
allowDrop: false
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
showTab (tab) {
|
||||
this.currentTab = tab;
|
||||
},
|
||||
addItem (model) {
|
||||
let type = this.openmct.types.get(model.type) || unknownObjectType,
|
||||
tabItem = {
|
||||
model,
|
||||
type: type
|
||||
};
|
||||
|
||||
this.tabsList.push(tabItem);
|
||||
|
||||
if (this.setCurrentTab) {
|
||||
this.currentTab = tabItem;
|
||||
this.setCurrentTab = false;
|
||||
}
|
||||
},
|
||||
onDrop (e) {
|
||||
this.setCurrentTab = true;
|
||||
},
|
||||
dragstart (e) {
|
||||
if (e.dataTransfer.getData('domainObject')) {
|
||||
this.isDragging = true;
|
||||
}
|
||||
},
|
||||
dragend (e) {
|
||||
this.isDragging = false;
|
||||
this.allowDrop = false;
|
||||
},
|
||||
dragenter () {
|
||||
this.allowDrop = true;
|
||||
},
|
||||
dragleave() {
|
||||
this.allowDrop = false;
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.composition.off('add', this.addItem, this);
|
||||
this.composition.off('add', this.addItem);
|
||||
this.composition.off('remove', this.removeItem);
|
||||
|
||||
document.removeEventListener('dragstart', this.dragstart);
|
||||
document.removeEventListener('dragend', this.dragend);
|
||||
|
@ -79,8 +79,8 @@ define([
|
||||
|
||||
loadComposition() {
|
||||
this.tableComposition = this.openmct.composition.get(this.domainObject);
|
||||
if (this.tableComposition !== undefined){
|
||||
this.tableComposition.load().then((composition)=>{
|
||||
if (this.tableComposition !== undefined) {
|
||||
this.tableComposition.load().then((composition) => {
|
||||
composition = composition.filter(this.isTelemetryObject);
|
||||
|
||||
this.configuration.addColumnsForAllObjects(composition);
|
||||
@ -122,7 +122,6 @@ define([
|
||||
|
||||
let telemetryRows = telemetryData.map(datum => new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
||||
this.boundedRows.add(telemetryRows);
|
||||
console.log('Loaded %i rows', telemetryRows.length);
|
||||
this.decrementOutstandingRequests();
|
||||
});
|
||||
}
|
||||
@ -131,7 +130,7 @@ define([
|
||||
* @private
|
||||
*/
|
||||
incrementOutstandingRequests() {
|
||||
if (this.outstandingRequests === 0){
|
||||
if (this.outstandingRequests === 0) {
|
||||
this.emit('outstanding-requests', true);
|
||||
}
|
||||
this.outstandingRequests++;
|
||||
@ -143,7 +142,7 @@ define([
|
||||
decrementOutstandingRequests() {
|
||||
this.outstandingRequests--;
|
||||
|
||||
if (this.outstandingRequests === 0){
|
||||
if (this.outstandingRequests === 0) {
|
||||
this.emit('outstanding-requests', false);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ define([
|
||||
objectMutated(object) {
|
||||
//Synchronize domain object reference. Duplicate object otherwise change detection becomes impossible.
|
||||
this.domainObject = object;
|
||||
//Was it the configuration that changed?
|
||||
if (!_.eq(object.configuration, this.oldConfiguration)) {
|
||||
//Make copy of configuration, otherwise change detection is impossible if shared instance is being modified.
|
||||
this.oldConfiguration = JSON.parse(JSON.stringify(this.getConfiguration()));
|
||||
@ -91,16 +92,19 @@ define([
|
||||
let columnsToRemove = this.columns[objectKeyString];
|
||||
|
||||
delete this.columns[objectKeyString];
|
||||
|
||||
let configuration = this.domainObject.configuration;
|
||||
let configurationChanged = false;
|
||||
columnsToRemove.forEach((column) => {
|
||||
//There may be more than one column with the same key (eg. time system columns)
|
||||
if (!this.hasColumnWithKey(column.getKey())) {
|
||||
let configuration = this.domainObject.configuration;
|
||||
delete configuration.hiddenColumns[column.getKey()];
|
||||
// If there are no more columns with this key, delete any configuration, and trigger
|
||||
// a column refresh.
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration', configuration);
|
||||
configurationChanged = true;
|
||||
}
|
||||
});
|
||||
if (configurationChanged) {
|
||||
this.updateConfiguration(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
hasColumnWithKey(columnKey) {
|
||||
|
@ -34,7 +34,7 @@
|
||||
<div class="c-telemetry-table__headers-w js-table__headers-w" ref="headersTable" :style="{ 'max-width': widthWithScroll}">
|
||||
<table class="c-table__headers c-telemetry-table__headers">
|
||||
<thead>
|
||||
<tr>
|
||||
<tr class="c-telemetry-table__headers__name">
|
||||
<table-column-header
|
||||
v-for="(title, key, headerIndex) in headers"
|
||||
:key="key"
|
||||
@ -50,7 +50,7 @@
|
||||
:sortOptions="sortOptions"
|
||||
>{{title}}</table-column-header>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="c-telemetry-table__headers__filter">
|
||||
<table-column-header
|
||||
v-for="(title, key, headerIndex) in headers"
|
||||
:key="key"
|
||||
@ -110,8 +110,8 @@
|
||||
.c-telemetry-table__drop-target {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
background-color: $editColor;
|
||||
box-shadow: rgba($editColor, 0.5) 0 0 10px;
|
||||
background-color: $editUIColor;
|
||||
box-shadow: rgba($editUIColor, 0.5) 0 0 10px;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
@ -214,6 +214,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
/******************************* EDITING */
|
||||
.is-editing {
|
||||
.c-telemetry-table__headers__name {
|
||||
th[draggable],
|
||||
th[draggable] > * {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
th[draggable]:hover {
|
||||
$b: $editFrameHovMovebarColorBg;
|
||||
background: $b;
|
||||
> * { background: $b; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************* LEGACY */
|
||||
.s-status-taking-snapshot,
|
||||
.overlay.snapshot {
|
||||
|
@ -22,9 +22,8 @@
|
||||
<template>
|
||||
<div class="c-conductor"
|
||||
:class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']">
|
||||
<form class="u-contents" ref="conductorForm"
|
||||
@submit="isFixed ? setBoundsFromView($event) : setOffsetsFromView($event)">
|
||||
|
||||
<form class="u-contents" ref="conductorForm" @submit.prevent="updateTimeFromConductor">
|
||||
<button class="c-input--submit" type="submit" ref="submitButton"></button>
|
||||
<ConductorModeIcon class="c-conductor__mode-icon"></ConductorModeIcon>
|
||||
|
||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__start-fixed"
|
||||
@ -35,7 +34,7 @@
|
||||
type="text" autocorrect="off" spellcheck="false"
|
||||
ref="startDate"
|
||||
v-model="formattedBounds.start"
|
||||
@change="validateBounds('start', $event.target); setBoundsFromView()" />
|
||||
@change="validateAllBounds(); submitForm()" />
|
||||
<date-picker
|
||||
:default-date-time="formattedBounds.start"
|
||||
:formatter="timeFormatter"
|
||||
@ -48,9 +47,10 @@
|
||||
<div class="c-direction-indicator icon-minus"></div>
|
||||
<input class="c-input--hrs-min-sec"
|
||||
type="text" autocorrect="off"
|
||||
ref="startOffset"
|
||||
spellcheck="false"
|
||||
v-model="offsets.start"
|
||||
@change="validateOffsets($event); setOffsetsFromView()">
|
||||
@change="validateAllOffsets(); submitForm()">
|
||||
</div>
|
||||
|
||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__end-fixed">
|
||||
@ -63,7 +63,7 @@
|
||||
v-model="formattedBounds.end"
|
||||
:disabled="!isFixed"
|
||||
ref="endDate"
|
||||
@change="validateBounds('end', $event.target); setBoundsFromView()">
|
||||
@change="validateAllBounds(); submitForm()">
|
||||
<date-picker
|
||||
class="c-ctrl-wrapper--menus-left"
|
||||
:default-date-time="formattedBounds.end"
|
||||
@ -80,8 +80,9 @@
|
||||
type="text"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
ref="endOffset"
|
||||
v-model="offsets.end"
|
||||
@change="validateOffsets($event); setOffsetsFromView()">
|
||||
@change="validateAllOffsets(); submitForm()">
|
||||
</div>
|
||||
|
||||
<conductor-axis
|
||||
@ -101,6 +102,14 @@
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
.c-input--submit {
|
||||
// Can't use display: none because some browsers will pretend the input doesn't exist, and enter won't work
|
||||
visibility: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*********************************************** CONDUCTOR LAYOUT */
|
||||
.c-conductor {
|
||||
display: grid;
|
||||
@ -357,6 +366,7 @@ export default {
|
||||
},
|
||||
setViewFromClock(clock) {
|
||||
this.isFixed = clock === undefined;
|
||||
this.clearAllValidation();
|
||||
},
|
||||
setViewFromBounds(bounds) {
|
||||
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
|
||||
@ -368,45 +378,87 @@ export default {
|
||||
this.offsets.start = this.durationFormatter.format(Math.abs(offsets.start));
|
||||
this.offsets.end = this.durationFormatter.format(Math.abs(offsets.end));
|
||||
},
|
||||
validateBounds(startOrEnd, input) {
|
||||
let validationResult = true;
|
||||
|
||||
if (!this.timeFormatter.validate(input.value)){
|
||||
validationResult = 'Invalid date value';
|
||||
updateTimeFromConductor() {
|
||||
if (this.isFixed) {
|
||||
this.setBoundsFromView();
|
||||
} else {
|
||||
let boundsValues = {
|
||||
start: this.timeFormatter.parse(this.formattedBounds.start),
|
||||
end: this.timeFormatter.parse(this.formattedBounds.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
this.setOffsetsFromView();
|
||||
}
|
||||
},
|
||||
validateOffsets(event) {
|
||||
let input = event.target;
|
||||
let validationResult = true;
|
||||
|
||||
if (!this.durationFormatter.validate(input.value)) {
|
||||
validationResult = 'Invalid offset value';
|
||||
} else {
|
||||
let offsetValues = {
|
||||
start: 0 - this.durationFormatter.parse(this.offsets.start),
|
||||
end: this.durationFormatter.parse(this.offsets.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
} else {
|
||||
clearAllValidation() {
|
||||
[this.$refs.startDate, this.$refs.endDate, this.$refs.startOffset, this.$refs.endOffset].forEach((input) => {
|
||||
input.setCustomValidity('');
|
||||
}
|
||||
input.title = '';
|
||||
});
|
||||
},
|
||||
validateAllBounds() {
|
||||
return [this.$refs.startDate, this.$refs.endDate].every((input) => {
|
||||
let validationResult = true;
|
||||
let formattedDate;
|
||||
|
||||
if (input === this.$refs.startDate) {
|
||||
formattedDate = this.formattedBounds.start;
|
||||
} else {
|
||||
formattedDate = this.formattedBounds.end;
|
||||
}
|
||||
|
||||
if (!this.timeFormatter.validate(formattedDate)){
|
||||
validationResult = 'Invalid date';
|
||||
} else {
|
||||
let boundsValues = {
|
||||
start: this.timeFormatter.parse(this.formattedBounds.start),
|
||||
end: this.timeFormatter.parse(this.formattedBounds.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
validateAllOffsets(event) {
|
||||
return [this.$refs.startOffset, this.$refs.endOffset].every((input) => {
|
||||
let validationResult = true;
|
||||
let formattedOffset;
|
||||
|
||||
if (input === this.$refs.startOffset) {
|
||||
formattedOffset = this.offsets.start;
|
||||
} else {
|
||||
formattedOffset = this.offsets.end;
|
||||
}
|
||||
|
||||
if (!this.durationFormatter.validate(formattedOffset)) {
|
||||
validationResult = 'Offsets must be in the format hh:mm:ss and less than 24 hours in duration';
|
||||
} else {
|
||||
let offsetValues = {
|
||||
start: 0 - this.durationFormatter.parse(this.offsets.start),
|
||||
end: this.durationFormatter.parse(this.offsets.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
submitForm() {
|
||||
// Allow Vue model to catch up to user input.
|
||||
// Submitting form will cause validation messages to display (but only if triggered by button click)
|
||||
this.$nextTick(() => this.$refs.submitButton.click());
|
||||
},
|
||||
getFormatter(key) {
|
||||
return this.openmct.telemetry.getValueFormatter({
|
||||
@ -415,13 +467,13 @@ export default {
|
||||
},
|
||||
startDateSelected(date){
|
||||
this.formattedBounds.start = this.timeFormatter.format(date);
|
||||
this.validateBounds('start', this.$refs.startDate);
|
||||
this.setBoundsFromView();
|
||||
this.validateAllBounds();
|
||||
this.submitForm();
|
||||
},
|
||||
endDateSelected(date){
|
||||
this.formattedBounds.end = this.timeFormatter.format(date);
|
||||
this.validateBounds('end', this.$refs.endDate);
|
||||
this.setBoundsFromView();
|
||||
this.validateAllBounds();
|
||||
this.submitForm();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
@ -22,11 +22,11 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up">
|
||||
<button class="c-button--menu c-mode-button"
|
||||
@click="toggleMenu($event)">
|
||||
@click.prevent="toggle">
|
||||
<span class="c-button__label">{{selectedMode.name}}</span>
|
||||
</button>
|
||||
<div class="c-menu c-super-menu c-conductor__mode-menu"
|
||||
v-if="showMenu">
|
||||
v-if="open">
|
||||
<div class="c-super-menu__menu">
|
||||
<ul>
|
||||
<li v-for="mode in modes"
|
||||
@ -69,8 +69,11 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import toggleMixin from '../../ui/mixins/toggle-mixin';
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'configuration'],
|
||||
mixins: [toggleMixin],
|
||||
data: function () {
|
||||
let activeClock = this.openmct.time.clock();
|
||||
if (activeClock !== undefined) {
|
||||
@ -81,8 +84,7 @@ export default {
|
||||
selectedMode: this.getModeOptionForClock(activeClock),
|
||||
selectedTimeSystem: JSON.parse(JSON.stringify(this.openmct.time.timeSystem())),
|
||||
modes: [],
|
||||
hoveredMode: {},
|
||||
showMenu: false
|
||||
hoveredMode: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -177,17 +179,7 @@ export default {
|
||||
|
||||
setViewFromClock(clock) {
|
||||
this.selectedMode = this.getModeOptionForClock(clock);
|
||||
},
|
||||
|
||||
toggleMenu(event) {
|
||||
this.showMenu = !this.showMenu;
|
||||
|
||||
if (this.showMenu) {
|
||||
document.addEventListener('click', this.toggleMenu, true);
|
||||
} else {
|
||||
document.removeEventListener('click', this.toggleMenu, true);
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.loadClocksFromConfiguration();
|
||||
|
@ -24,10 +24,10 @@
|
||||
v-if="selectedTimeSystem.name">
|
||||
<button class="c-button--menu c-time-system-button"
|
||||
:class="selectedTimeSystem.cssClass"
|
||||
@click="toggleMenu($event)">
|
||||
@click.prevent="toggle">
|
||||
<span class="c-button__label">{{selectedTimeSystem.name}}</span>
|
||||
</button>
|
||||
<div class="c-menu" v-if="showMenu">
|
||||
<div class="c-menu" v-if="open">
|
||||
<ul>
|
||||
<li @click="setTimeSystemFromView(timeSystem)"
|
||||
v-for="timeSystem in timeSystems"
|
||||
@ -41,15 +41,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import toggleMixin from '../../ui/mixins/toggle-mixin';
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'configuration'],
|
||||
mixins: [toggleMixin],
|
||||
data: function () {
|
||||
let activeClock = this.openmct.time.clock();
|
||||
|
||||
return {
|
||||
selectedTimeSystem: JSON.parse(JSON.stringify(this.openmct.time.timeSystem())),
|
||||
timeSystems: this.getValidTimesystemsForClock(activeClock),
|
||||
showMenu: false
|
||||
timeSystems: this.getValidTimesystemsForClock(activeClock)
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -94,16 +96,6 @@ export default {
|
||||
return this.configuration.menuOptions.filter(configMatches)[0];
|
||||
},
|
||||
|
||||
toggleMenu(event) {
|
||||
this.showMenu = !this.showMenu;
|
||||
|
||||
if (this.showMenu) {
|
||||
document.addEventListener('click', this.toggleMenu, true);
|
||||
} else {
|
||||
document.removeEventListener('click', this.toggleMenu, true);
|
||||
}
|
||||
},
|
||||
|
||||
setViewFromTimeSystem(timeSystem) {
|
||||
this.selectedTimeSystem = timeSystem;
|
||||
},
|
||||
|
@ -22,12 +22,12 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up c-datetime-picker__wrapper" ref="calendarHolder">
|
||||
<a class="c-click-icon icon-calendar"
|
||||
@click="togglePicker()"></a>
|
||||
@click="toggle"></a>
|
||||
<div class="c-menu c-menu--mobile-modal c-datetime-picker"
|
||||
v-if="showPicker">
|
||||
v-if="open">
|
||||
<div class="c-datetime-picker__close-button">
|
||||
<button class="c-click-icon icon-x-in-circle"
|
||||
@click="togglePicker()"></button>
|
||||
@click="toggle"></button>
|
||||
</div>
|
||||
<div class="c-datetime-picker__pager c-pager l-month-year-pager">
|
||||
<div class="c-pager__prev c-click-icon icon-arrow-left"
|
||||
@ -160,6 +160,7 @@
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import toggleMixin from '../../ui/mixins/toggle-mixin';
|
||||
|
||||
const TIME_NAMES = {
|
||||
'hours': "Hour",
|
||||
@ -181,13 +182,13 @@ const TIME_OPTIONS = (function makeRanges() {
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
mixins: [toggleMixin],
|
||||
props: {
|
||||
defaultDateTime: String,
|
||||
formatter: Object
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
showPicker: false,
|
||||
picker: {
|
||||
year: undefined,
|
||||
month: undefined,
|
||||
@ -285,7 +286,6 @@ export default {
|
||||
this.date.year = cell.year;
|
||||
this.date.day = cell.day;
|
||||
this.updateFromView();
|
||||
this.showPicker = false;
|
||||
},
|
||||
|
||||
dateEquals(d1, d2) {
|
||||
@ -315,23 +315,6 @@ export default {
|
||||
optionsFor(key) {
|
||||
return TIME_OPTIONS[key];
|
||||
},
|
||||
|
||||
hidePicker(event) {
|
||||
let path = event.composedPath();
|
||||
if (path.indexOf(this.$refs.calendarHolder) === -1) {
|
||||
this.showPicker = false;
|
||||
}
|
||||
},
|
||||
|
||||
togglePicker() {
|
||||
this.showPicker = !this.showPicker;
|
||||
|
||||
if (this.showPicker) {
|
||||
document.addEventListener('click', this.hidePicker, {
|
||||
capture: true
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.updateFromModel(this.defaultDateTime);
|
||||
|
@ -47,6 +47,14 @@ $bodyFont: $heroFont;
|
||||
@return linear-gradient(lighten($c, 5%), $c);
|
||||
}
|
||||
|
||||
@function pullForward($val, $amt) {
|
||||
@return lighten($val, $amt);
|
||||
}
|
||||
|
||||
@function pushBack($val, $amt) {
|
||||
@return darken($val, $amt);
|
||||
}
|
||||
|
||||
// Constants
|
||||
$fontBaseSize: 12px;
|
||||
$smallCr: 2px;
|
||||
@ -55,7 +63,7 @@ $basicCr: 4px;
|
||||
|
||||
// Base colors
|
||||
$colorBodyBg: #393939;
|
||||
$colorBodyFg: #aaa;
|
||||
$colorBodyFg: #aaaaaa;
|
||||
$colorBodyFgEm: #fff;
|
||||
$colorGenBg: #222;
|
||||
$colorHeadBg: #262626;
|
||||
@ -65,10 +73,11 @@ $colorStatusBarFg: $colorBodyFg;
|
||||
$colorStatusBarFgHov: #aaa;
|
||||
$colorKey: #0099cc;
|
||||
$colorKeyFg: #fff;
|
||||
$colorKeyHov: #00c0f6;
|
||||
$colorKeyHov: #26d8ff;
|
||||
$colorKeyFilter: invert(36%) sepia(76%) saturate(2514%) hue-rotate(170deg) brightness(99%) contrast(101%);
|
||||
$colorKeyFilterHov: invert(63%) sepia(88%) saturate(3029%) hue-rotate(154deg) brightness(101%) contrast(100%);
|
||||
$colorKeySelectedBg: $colorKey;
|
||||
$uiColor: #00b2ff; // Resize bars, splitter bars, etc.
|
||||
$colorInteriorBorder: rgba($colorBodyFg, 0.2);
|
||||
$colorA: #ccc;
|
||||
$colorAHov: #fff;
|
||||
@ -94,51 +103,52 @@ $colorPausedFg: #fff;
|
||||
$colorOk: #33cc33;
|
||||
|
||||
// Base variations
|
||||
$colorBodyBgSubtle: lighten($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: darken($colorKey, 50%);
|
||||
$colorKeySubtle: darken($colorKey, 10%);
|
||||
$colorBodyBgSubtle: pullForward($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: pushBack($colorKey, 50%);
|
||||
$colorKeySubtle: pushBack($colorKey, 10%);
|
||||
|
||||
// Time Colors
|
||||
$colorTime: #618cff;
|
||||
$colorTimeBg: $colorTime;
|
||||
$colorTimeFg: lighten($colorTimeBg, 30%);
|
||||
$colorTimeHov: lighten($colorTime, 10%);
|
||||
$colorTimeSubtle: darken($colorTime, 20%);
|
||||
$colorTimeFg: pullForward($colorTimeBg, 30%);
|
||||
$colorTimeHov: pullForward($colorTime, 10%);
|
||||
$colorTimeSubtle: pushBack($colorTime, 20%);
|
||||
$colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
|
||||
$colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
|
||||
|
||||
/************************************************** EDITING */
|
||||
// Base Colors
|
||||
$dlSpread: 20%;
|
||||
$editColor: #00c7c3;
|
||||
$editColorAlt: #9971ff;
|
||||
$editColorBgBase: darken($editColor, $dlSpread);
|
||||
$editColorBg: rgba($editColorBgBase, 0.2);
|
||||
$editColorFg: lighten($editColor, $dlSpread);
|
||||
$editColorHov: lighten($editColor, 20%);
|
||||
// Canvas
|
||||
$editCanvasColorBg: $editColorBg; //#002524;
|
||||
$editCanvasColorGrid: rgba($editColorBgBase, 0.4); //lighten($editCanvasColorBg, 3%);
|
||||
// Selectable
|
||||
$editSelectableColor: #006563;
|
||||
$editSelectableColorFg: lighten($editSelectableColor, 20%);
|
||||
$editSelectableColorHov: lighten($editSelectableColor, 10%);
|
||||
// Selectable selected
|
||||
$editSelectableColorSelected: $editSelectableColorHov;
|
||||
$editSelectableColorSelectedFg: lighten($editSelectableColorSelected, 30%);
|
||||
$editSelectableColorFg: darken($editSelectableColor, 40%);
|
||||
$editSelectableBorder: 1px dotted $editSelectableColor;
|
||||
$editSelectableBorderHov: 1px dotted $editColorAlt;
|
||||
$editSelectableBorderSelected: 1px solid $editColor;
|
||||
$editSelectableShdwSelected: rgba($editColor, 0.75) 0 0 0 1px;
|
||||
$editMoveableSelectedShdw: rgba($editColor, 0.5) 0 0 10px;
|
||||
$editBorderDrilledIn: 1px dashed $editColorAlt;
|
||||
$colorGridLines: rgba($editColor, 0.2);
|
||||
|
||||
/************************************************** BROWSING */
|
||||
$browseSelectableBorderHov: 1px dotted rgba($colorBodyFg, 0.2);
|
||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.2) 0 0 3px;
|
||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.6);
|
||||
$browseFrameColor: pullForward($colorBodyBg, 10%);
|
||||
$browseFrameBorder: 1px solid $browseFrameColor; // Frames in Disp and Flex Layouts when frame is showing
|
||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.3) 0 0 3px;
|
||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
|
||||
|
||||
/************************************************** EDITING */
|
||||
$editUIColor: $uiColor; // Base color
|
||||
$editUIColorHov: pullForward(saturate($uiColor, 10%), 20%); // Hover color when $editUIColor is applied as a base color
|
||||
$editUIBaseColor: #344b8d; // Base color, toolbar bg
|
||||
$editUIBaseColorHov: pullForward($editUIBaseColor, 20%);
|
||||
$editUIBaseColorFg: #ffffff; // Toolbar button icon colors, etc.
|
||||
$editUIAreaBaseColor: pullForward(saturate($editUIBaseColor, 30%), 20%);
|
||||
$editUIAreaShdw: $editUIAreaBaseColor 0 0 0 2px; // Edit area s-selected-parent
|
||||
$editUIAreaShdwSelected: $editUIAreaBaseColor 0 0 0 3px; // Edit area s-selected
|
||||
$editUIGridColorBg: rgba($editUIBaseColor, 0.2); // Background of layout editing area
|
||||
$editUIGridColorFg: rgba(#000, 0.1); // Grid lines in layout editing area
|
||||
$editFrameColor: $browseFrameColor; // Solid or dotted border applied to non-selected frames in a layout; move-bar on frame hover
|
||||
$editFrameBorder: 1px dotted $editFrameColor;
|
||||
$editFrameColorHov: $editUIColor; // Solid border hover on frames; hover should not be applied to selected objects
|
||||
$editFrameBorderHov: 1px solid $editFrameColorHov; // Hover on selectable frames
|
||||
$editFrameColorSelected: #ccc; // Border of selected frames
|
||||
$editFrameColorHandleBg: $colorBodyBg; // Resize handle 'offset' color to make handle standout
|
||||
$editFrameColorHandleFg: $editFrameColorSelected; // Resize handle main color
|
||||
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 10px 1px;
|
||||
$editFrameSelectedBorder: 1px dashed $editFrameColorSelected; // Selected frame element
|
||||
$editFrameMovebarColorBg: $editFrameColor; // Movebar bg color
|
||||
$editFrameMovebarColorFg: pullForward($editFrameMovebarColorBg, 20%); // Grippy lines, container size text
|
||||
$editFrameHovMovebarColorBg: pullForward($editFrameMovebarColorBg, 10%); // Hover style
|
||||
$editFrameHovMovebarColorFg: pullForward($editFrameMovebarColorFg, 10%);
|
||||
$editFrameSelectedMovebarColorBg: pullForward($editFrameMovebarColorBg, 15%); // Selected style
|
||||
$editFrameSelectedMovebarColorFg: pullForward($editFrameMovebarColorFg, 15%);
|
||||
$editFrameMovebarH: 10px; // Height of move bar in layout frame
|
||||
|
||||
// Icons
|
||||
$colorIconAlias: #4af6f3;
|
||||
@ -148,16 +158,16 @@ $colorIconAliasForKeyFilter: #aaa;
|
||||
$colorTabsHolderBg: rgba(black, 0.2);
|
||||
|
||||
// Buttons and Controls
|
||||
$colorBtnBg: lighten($colorBodyBg, 10%);
|
||||
$colorBtnBgHov: lighten($colorBtnBg, 10%);
|
||||
$colorBtnFg: lighten($colorBodyFg, 10%);
|
||||
$colorBtnReverseFg: lighten($colorBtnFg, 10%);
|
||||
$colorBtnReverseBg: lighten($colorBtnBg, 10%);
|
||||
$colorBtnBg: pullForward($colorBodyBg, 10%);
|
||||
$colorBtnBgHov: pullForward($colorBtnBg, 10%);
|
||||
$colorBtnFg: pullForward($colorBodyFg, 10%);
|
||||
$colorBtnReverseFg: pullForward($colorBtnFg, 10%);
|
||||
$colorBtnReverseBg: pullForward($colorBtnBg, 10%);
|
||||
$colorBtnFgHov: $colorBtnFg;
|
||||
$colorBtnMajorBg: $colorKey;
|
||||
$colorBtnMajorBgHov: $colorKeyHov;
|
||||
$colorBtnMajorFg: $colorKeyFg;
|
||||
$colorBtnMajorFgHov: darken($colorBtnMajorFg, 10%);
|
||||
$colorBtnMajorFgHov: pushBack($colorBtnMajorFg, 10%);
|
||||
$colorBtnCautionBg: #f16f6f;
|
||||
$colorBtnCautionBgHov: #f1504e;
|
||||
$colorBtnCautionFg: $colorBtnFg;
|
||||
@ -165,20 +175,20 @@ $colorClickIcon: $colorKey;
|
||||
$colorClickIconBgHov: rgba($colorKey, 0.6);
|
||||
$colorClickIconFgHov: $colorKeyHov;
|
||||
$colorDropHint: $colorKey;
|
||||
$colorDropHintBg: darken($colorDropHint, 10%);
|
||||
$colorDropHintBg: pushBack($colorDropHint, 10%);
|
||||
$colorDropHintBgHov: $colorDropHint;
|
||||
$colorDropHintFg: lighten($colorDropHint, 40%);
|
||||
$colorDropHintFg: pullForward($colorDropHint, 40%);
|
||||
$colorDisclosureCtrl: rgba($colorBodyFg, 0.5);
|
||||
$colorDisclosureCtrlHov: rgba($colorBodyFg, 0.7);
|
||||
|
||||
// Menus
|
||||
$colorMenuBg: lighten($colorBodyBg, 15%);
|
||||
$colorMenuFg: lighten($colorBodyFg, 30%);
|
||||
$colorMenuIc: lighten($colorKey, 15%);
|
||||
$colorMenuBg: pullForward($colorBodyBg, 15%);
|
||||
$colorMenuFg: pullForward($colorBodyFg, 30%);
|
||||
$colorMenuIc: pullForward($colorKey, 15%);
|
||||
$colorMenuHovBg: $colorMenuIc;
|
||||
$colorMenuHovFg: lighten($colorMenuFg, 10%);
|
||||
$colorMenuHovFg: pullForward($colorMenuFg, 10%);
|
||||
$colorMenuHovIc: $colorMenuHovFg;
|
||||
$colorMenuElementHilite: lighten($colorMenuBg, 10%);
|
||||
$colorMenuElementHilite: pullForward($colorMenuBg, 10%);
|
||||
$shdwMenu: rgba(black, 0.5) 0 1px 5px;
|
||||
$shdwMenuText: none;
|
||||
$menuItemPad: $interiorMargin, floor($interiorMargin * 1.25);
|
||||
@ -200,21 +210,21 @@ $colorFormLines: rgba(#000, 0.1);
|
||||
$colorFormSectionHeader: rgba(#000, 0.05);
|
||||
$colorInputBg: rgba(black, 0.2);
|
||||
$colorInputFg: $colorBodyFg;
|
||||
$colorInputPlaceholder: darken($colorBodyFg, 20%);
|
||||
$colorFormText: darken($colorBodyFg, 10%);
|
||||
$colorInputIcon: darken($colorBodyFg, 25%);
|
||||
$colorFieldHint: lighten($colorBodyFg, 40%);
|
||||
$colorInputPlaceholder: pushBack($colorBodyFg, 20%);
|
||||
$colorFormText: pushBack($colorBodyFg, 10%);
|
||||
$colorInputIcon: pushBack($colorBodyFg, 25%);
|
||||
$colorFieldHint: pullForward($colorBodyFg, 40%);
|
||||
$shdwInput: inset rgba(black, 0.4) 0 0 1px;
|
||||
$shdwInputHov: inset rgba(black, 0.7) 0 0 2px;
|
||||
$shdwInputFoc: inset rgba(black, 0.8) 0 0.25px 3px;
|
||||
|
||||
// Inspector
|
||||
$colorInspectorBg: lighten($colorBodyBg, 5%);
|
||||
$colorInspectorBg: pullForward($colorBodyBg, 5%);
|
||||
$colorInspectorFg: $colorBodyFg;
|
||||
$colorInspectorPropName: darken($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: lighten($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: lighten($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: lighten($colorInspectorBg, 40%);
|
||||
$colorInspectorPropName: pushBack($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: pullForward($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Overlay
|
||||
$overlayColorBg: $colorMenuBg;
|
||||
@ -229,8 +239,8 @@ $colorIndicatorOn: $colorOk;
|
||||
$colorIndicatorOff: #777777;
|
||||
|
||||
// Staleness
|
||||
$colorTelemFresh: lighten($colorBodyFg, 20%);
|
||||
$colorTelemStale: darken($colorBodyFg, 20%);
|
||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
$styleTelemStale: italic;
|
||||
|
||||
// Limits
|
||||
@ -256,22 +266,22 @@ $colorInfoBubbleFg: #666;
|
||||
|
||||
// Items
|
||||
$colorItemBg: buttonBg($colorBtnBg);
|
||||
$colorItemBgHov: buttonBg(lighten($colorBtnBg, 5%));
|
||||
$colorItemBgHov: buttonBg(pullForward($colorBtnBg, 5%));
|
||||
$colorListItemBg: transparent;
|
||||
$colorListItemBgHov: rgba($colorKey, 0.1);
|
||||
$colorItemFg: $colorBtnFg;
|
||||
$colorItemFgDetails: darken($colorItemFg, 20%);
|
||||
$colorItemFgDetails: pushBack($colorItemFg, 20%);
|
||||
$shdwItemText: none;
|
||||
|
||||
// Tabular
|
||||
$colorTabBorder: lighten($colorBodyBg, 10%);
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: lighten($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: lighten($colorBodyBg, 10%);
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
$colorTabHeaderFg: $colorBodyFg;
|
||||
$colorTabHeaderBorder: $colorBodyBg;
|
||||
$colorTabGroupHeaderBg: lighten($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: darken($colorTabHeaderFg, 10%);
|
||||
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: pushBack($colorTabHeaderFg, 10%);
|
||||
|
||||
// Plot
|
||||
$colorPlotBg: rgba(black, 0.05);
|
||||
@ -280,22 +290,22 @@ $colorPlotHash: black;
|
||||
$opacityPlotHash: 0.2;
|
||||
$stylePlotHash: dashed;
|
||||
$colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: darken($colorPlotFg, 20%);
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
$legendHoverValueBg: rgba($colorBodyFg, 0.2);
|
||||
|
||||
// Tree
|
||||
$colorTreeBg: transparent;
|
||||
$colorItemTreeHoverBg: lighten($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: lighten($colorBodyFg, 20%);
|
||||
$colorItemTreeHoverBg: pullForward($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: pullForward($colorBodyFg, 20%);
|
||||
$colorItemTreeIcon: $colorKey; // Used
|
||||
$colorItemTreeIconHover: $colorItemTreeIcon; // Used
|
||||
$colorItemTreeFg: $colorBodyFg;
|
||||
$colorItemTreeSelectedBg: darken($colorKey, 15%);
|
||||
$colorItemTreeSelectedBg: pushBack($colorKey, 15%);
|
||||
$colorItemTreeSelectedFg: $colorItemTreeHoverFg;
|
||||
$colorItemTreeSelectedIcon: $colorItemTreeSelectedFg;
|
||||
$colorItemTreeEditingBg: darken($editColor, 20%);
|
||||
$colorItemTreeEditingFg: $editColorFg;
|
||||
$colorItemTreeEditingIcon: $editColorFg;
|
||||
$colorItemTreeEditingBg: pushBack($editUIColor, 20%);
|
||||
$colorItemTreeEditingFg: $editUIColor;
|
||||
$colorItemTreeEditingIcon: $editUIColor;
|
||||
$colorItemTreeVC: $colorDisclosureCtrl;
|
||||
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
||||
$shdwItemTreeIcon: none;
|
||||
@ -307,18 +317,18 @@ $colorThumbHoverBg: $colorItemTreeHoverBg;
|
||||
$scrollbarTrackSize: 7px;
|
||||
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
|
||||
$scrollbarTrackColorBg: rgba(#000, 0.2);
|
||||
$scrollbarThumbColor: darken($colorBodyBg, 50%);
|
||||
$scrollbarThumbColor: pushBack($colorBodyBg, 50%);
|
||||
$scrollbarThumbColorHov: $colorKey;
|
||||
$scrollbarThumbColorMenu: lighten($colorMenuBg, 10%);
|
||||
$scrollbarThumbColorMenuHov: lighten($scrollbarThumbColorMenu, 2%);
|
||||
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%);
|
||||
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
|
||||
|
||||
// Splitter
|
||||
$splitterHandleD: 2px;
|
||||
$splitterHandleHitMargin: 4px;
|
||||
$colorSplitterBaseBg: $colorBodyBg;
|
||||
$colorSplitterBg: lighten($colorSplitterBaseBg, 10%);
|
||||
$colorSplitterBg: pullForward($colorBodyBg, 10%);
|
||||
$colorSplitterFg: $colorBodyBg;
|
||||
$colorSplitterHover: $colorKey;
|
||||
$colorSplitterHover: $uiColor;
|
||||
$colorSplitterActive: $colorKey;
|
||||
$splitterBtnD: (16px, 35px); // height, width
|
||||
$splitterBtnColorBg: $colorBtnBg;
|
||||
@ -330,7 +340,7 @@ $splitterCollapsedBtnColorBgHov: $colorKey;
|
||||
$splitterCollapsedBtnColorFgHov: $colorKeyFg;
|
||||
|
||||
// Mobile
|
||||
$colorMobilePaneLeft: darken($colorBodyBg, 2%);
|
||||
$colorMobilePaneLeft: pushBack($colorBodyBg, 2%);
|
||||
$colorMobilePaneLeftTreeItemBg: rgba($colorBodyFg, 0.1);
|
||||
$colorMobilePaneLeftTreeItemFg: $colorItemTreeFg;
|
||||
$colorMobileSelectListTreeItemBg: rgba(#000, 0.05);
|
||||
@ -367,21 +377,10 @@ $createBtnTextTransform: uppercase;
|
||||
}
|
||||
|
||||
@mixin themedButton($c: $colorBtnBg) {
|
||||
background: linear-gradient(lighten($c, 5%), $c);
|
||||
background: linear-gradient(pullForward($c, 5%), $c);
|
||||
box-shadow: rgba(black, 0.5) 0 0.5px 2px;
|
||||
}
|
||||
|
||||
/**************************************************** NOT USED, LEAVE FOR NOW */
|
||||
// Slider controls, not in use
|
||||
/*
|
||||
$sliderColorBase: $colorKey;
|
||||
$sliderColorRangeHolder: rgba(black, 0.07);
|
||||
$sliderColorRange: rgba($sliderColorBase, 0.2);
|
||||
$sliderColorRangeHov: rgba($sliderColorBase, 0.4);
|
||||
$sliderColorKnob: darken($sliderColorBase, 20%);
|
||||
$sliderColorKnobHov: rgba($sliderColorBase, 0.7);
|
||||
$sliderColorRangeValHovBg: $sliderColorRange;
|
||||
$sliderColorRangeValHovFg: $colorBodyFg;
|
||||
$sliderKnobW: 15px;
|
||||
$sliderKnobR: 2px;
|
||||
*/
|
||||
@mixin themedSelect($bg: $colorBtnBg, $fg: $colorBtnFg) {
|
||||
@include cSelect(linear-gradient(lighten($bg, 5%), $bg), $fg, lighten($bg, 20%), rgba(black, 0.5) 0 0.5px 3px);
|
||||
}
|
||||
|
@ -51,6 +51,14 @@ $bodyFont: 'Chakra Petch', sans-serif;
|
||||
@return linear-gradient(lighten($c, 5%), $c);
|
||||
}
|
||||
|
||||
@function pullForward($val, $amt) {
|
||||
@return lighten($val, $amt);
|
||||
}
|
||||
|
||||
@function pushBack($val, $amt) {
|
||||
@return darken($val, $amt);
|
||||
}
|
||||
|
||||
// Constants
|
||||
$fontBaseSize: 12px;
|
||||
$smallCr: 2px;
|
||||
@ -69,10 +77,11 @@ $colorStatusBarFg: $colorBodyFg;
|
||||
$colorStatusBarFgHov: #aaa;
|
||||
$colorKey: #0099cc;
|
||||
$colorKeyFg: #fff;
|
||||
$colorKeyHov: #00c0f6;
|
||||
$colorKeyHov: #26d8ff;
|
||||
$colorKeyFilter: invert(36%) sepia(76%) saturate(2514%) hue-rotate(170deg) brightness(99%) contrast(101%);
|
||||
$colorKeyFilterHov: invert(63%) sepia(88%) saturate(3029%) hue-rotate(154deg) brightness(101%) contrast(100%);
|
||||
$colorKeySelectedBg: $colorKey;
|
||||
$uiColor: #00b2ff; // Resize bars, splitter bars, etc.
|
||||
$colorInteriorBorder: rgba($colorBodyFg, 0.2);
|
||||
$colorA: #ccc;
|
||||
$colorAHov: #fff;
|
||||
@ -98,51 +107,52 @@ $colorPausedFg: #fff;
|
||||
$colorOk: #33cc33;
|
||||
|
||||
// Base variations
|
||||
$colorBodyBgSubtle: lighten($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: darken($colorKey, 50%);
|
||||
$colorKeySubtle: darken($colorKey, 10%);
|
||||
$colorBodyBgSubtle: pullForward($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: pushBack($colorKey, 50%);
|
||||
$colorKeySubtle: pushBack($colorKey, 10%);
|
||||
|
||||
// Time Colors
|
||||
$colorTime: #618cff;
|
||||
$colorTimeBg: $colorTime;
|
||||
$colorTimeFg: lighten($colorTimeBg, 30%);
|
||||
$colorTimeHov: lighten($colorTime, 10%);
|
||||
$colorTimeSubtle: darken($colorTime, 20%);
|
||||
$colorTimeFg: pullForward($colorTimeBg, 30%);
|
||||
$colorTimeHov: pullForward($colorTime, 10%);
|
||||
$colorTimeSubtle: pushBack($colorTime, 20%);
|
||||
$colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
|
||||
$colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
|
||||
|
||||
/************************************************** EDITING */
|
||||
// Base Colors
|
||||
$dlSpread: 20%;
|
||||
$editColor: #00c7c3;
|
||||
$editColorAlt: #9971ff;
|
||||
$editColorBgBase: darken($editColor, $dlSpread);
|
||||
$editColorBg: rgba($editColorBgBase, 0.2);
|
||||
$editColorFg: lighten($editColor, $dlSpread);
|
||||
$editColorHov: lighten($editColor, 20%);
|
||||
// Canvas
|
||||
$editCanvasColorBg: $editColorBg; //#002524;
|
||||
$editCanvasColorGrid: rgba($editColorBgBase, 0.4); //lighten($editCanvasColorBg, 3%);
|
||||
// Selectable
|
||||
$editSelectableColor: #006563;
|
||||
$editSelectableColorFg: lighten($editSelectableColor, 20%);
|
||||
$editSelectableColorHov: lighten($editSelectableColor, 10%);
|
||||
// Selectable selected
|
||||
$editSelectableColorSelected: $editSelectableColorHov;
|
||||
$editSelectableColorSelectedFg: lighten($editSelectableColorSelected, 30%);
|
||||
$editSelectableColorFg: darken($editSelectableColor, 40%);
|
||||
$editSelectableBorder: 1px dotted $editSelectableColor;
|
||||
$editSelectableBorderHov: 1px dotted $editColorAlt;
|
||||
$editSelectableBorderSelected: 1px solid $editColor;
|
||||
$editSelectableShdwSelected: rgba($editColor, 0.75) 0 0 0 1px;
|
||||
$editMoveableSelectedShdw: rgba($editColor, 0.5) 0 0 10px;
|
||||
$editBorderDrilledIn: 1px dashed $editColorAlt;
|
||||
$colorGridLines: rgba($editColor, 0.2);
|
||||
|
||||
/************************************************** BROWSING */
|
||||
$browseSelectableBorderHov: 1px dotted rgba($colorBodyFg, 0.2);
|
||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.2) 0 0 3px;
|
||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.6);
|
||||
$browseFrameColor: pullForward($colorBodyBg, 10%);
|
||||
$browseFrameBorder: 1px solid $browseFrameColor; // Frames in Disp and Flex Layouts when frame is showing
|
||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.3) 0 0 3px;
|
||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
|
||||
|
||||
/************************************************** EDITING */
|
||||
$editUIColor: $uiColor; // Base color
|
||||
$editUIColorHov: pullForward(saturate($uiColor, 10%), 20%); // Hover color when $editUIColor is applied as a base color
|
||||
$editUIBaseColor: #344b8d; // Base color, toolbar bg
|
||||
$editUIBaseColorHov: pullForward($editUIBaseColor, 20%);
|
||||
$editUIBaseColorFg: #ffffff; // Toolbar button icon colors, etc.
|
||||
$editUIAreaBaseColor: pullForward(saturate($editUIBaseColor, 30%), 20%);
|
||||
$editUIAreaShdw: $editUIAreaBaseColor 0 0 0 2px; // Edit area s-selected-parent
|
||||
$editUIAreaShdwSelected: $editUIAreaBaseColor 0 0 0 3px; // Edit area s-selected
|
||||
$editUIGridColorBg: rgba($editUIBaseColor, 0.2); // Background of layout editing area
|
||||
$editUIGridColorFg: rgba(#000, 0.1); // Grid lines in layout editing area
|
||||
$editFrameColor: $browseFrameColor; // Solid or dotted border applied to non-selected frames in a layout; move-bar on frame hover
|
||||
$editFrameBorder: 1px dotted $editFrameColor;
|
||||
$editFrameColorHov: $editUIColor; // Solid border hover on frames; hover should not be applied to selected objects
|
||||
$editFrameBorderHov: 1px solid $editFrameColorHov; // Hover on selectable frames
|
||||
$editFrameColorSelected: #ccc; // Border of selected frames
|
||||
$editFrameColorHandleBg: $colorBodyBg; // Resize handle 'offset' color to make handle standout
|
||||
$editFrameColorHandleFg: $editFrameColorSelected; // Resize handle main color
|
||||
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 10px 1px;
|
||||
$editFrameSelectedBorder: 1px dashed $editFrameColorSelected; // Selected frame element
|
||||
$editFrameMovebarColorBg: $editFrameColor; // Movebar bg color
|
||||
$editFrameMovebarColorFg: pullForward($editFrameMovebarColorBg, 20%); // Grippy lines, container size text
|
||||
$editFrameHovMovebarColorBg: pullForward($editFrameMovebarColorBg, 10%); // Hover style
|
||||
$editFrameHovMovebarColorFg: pullForward($editFrameMovebarColorFg, 10%);
|
||||
$editFrameSelectedMovebarColorBg: pullForward($editFrameMovebarColorBg, 15%); // Selected style
|
||||
$editFrameSelectedMovebarColorFg: pullForward($editFrameMovebarColorFg, 15%);
|
||||
$editFrameMovebarH: 10px; // Height of move bar in layout frame
|
||||
|
||||
// Icons
|
||||
$colorIconAlias: #4af6f3;
|
||||
@ -152,16 +162,16 @@ $colorIconAliasForKeyFilter: #aaa;
|
||||
$colorTabsHolderBg: rgba(black, 0.2);
|
||||
|
||||
// Buttons and Controls
|
||||
$colorBtnBg: lighten($colorBodyBg, 10%);
|
||||
$colorBtnBgHov: lighten($colorBtnBg, 10%);
|
||||
$colorBtnFg: lighten($colorBodyFg, 10%);
|
||||
$colorBtnReverseFg: lighten($colorBtnFg, 10%);
|
||||
$colorBtnReverseBg: lighten($colorBtnBg, 10%);
|
||||
$colorBtnBg: pullForward($colorBodyBg, 10%);
|
||||
$colorBtnBgHov: pullForward($colorBtnBg, 10%);
|
||||
$colorBtnFg: pullForward($colorBodyFg, 10%);
|
||||
$colorBtnReverseFg: pullForward($colorBtnFg, 10%);
|
||||
$colorBtnReverseBg: pullForward($colorBtnBg, 10%);
|
||||
$colorBtnFgHov: $colorBtnFg;
|
||||
$colorBtnMajorBg: $colorKey;
|
||||
$colorBtnMajorBgHov: $colorKeyHov;
|
||||
$colorBtnMajorFg: $colorKeyFg;
|
||||
$colorBtnMajorFgHov: darken($colorBtnMajorFg, 10%);
|
||||
$colorBtnMajorFgHov: pushBack($colorBtnMajorFg, 10%);
|
||||
$colorBtnCautionBg: #f16f6f;
|
||||
$colorBtnCautionBgHov: #f1504e;
|
||||
$colorBtnCautionFg: $colorBtnFg;
|
||||
@ -169,20 +179,20 @@ $colorClickIcon: $colorKey;
|
||||
$colorClickIconBgHov: rgba($colorKey, 0.6);
|
||||
$colorClickIconFgHov: $colorKeyHov;
|
||||
$colorDropHint: $colorKey;
|
||||
$colorDropHintBg: darken($colorDropHint, 10%);
|
||||
$colorDropHintBg: pushBack($colorDropHint, 10%);
|
||||
$colorDropHintBgHov: $colorDropHint;
|
||||
$colorDropHintFg: lighten($colorDropHint, 40%);
|
||||
$colorDropHintFg: pullForward($colorDropHint, 40%);
|
||||
$colorDisclosureCtrl: rgba($colorBodyFg, 0.5);
|
||||
$colorDisclosureCtrlHov: rgba($colorBodyFg, 0.7);
|
||||
|
||||
// Menus
|
||||
$colorMenuBg: lighten($colorBodyBg, 15%);
|
||||
$colorMenuFg: lighten($colorBodyFg, 30%);
|
||||
$colorMenuIc: lighten($colorKey, 15%);
|
||||
$colorMenuBg: pullForward($colorBodyBg, 15%);
|
||||
$colorMenuFg: pullForward($colorBodyFg, 30%);
|
||||
$colorMenuIc: pullForward($colorKey, 15%);
|
||||
$colorMenuHovBg: $colorMenuIc;
|
||||
$colorMenuHovFg: lighten($colorMenuFg, 10%);
|
||||
$colorMenuHovFg: pullForward($colorMenuFg, 10%);
|
||||
$colorMenuHovIc: $colorMenuHovFg;
|
||||
$colorMenuElementHilite: lighten($colorMenuBg, 10%);
|
||||
$colorMenuElementHilite: pullForward($colorMenuBg, 10%);
|
||||
$shdwMenu: rgba(black, 0.5) 0 1px 5px;
|
||||
$shdwMenuText: none;
|
||||
$menuItemPad: $interiorMargin, floor($interiorMargin * 1.25);
|
||||
@ -204,21 +214,21 @@ $colorFormLines: rgba(#000, 0.1);
|
||||
$colorFormSectionHeader: rgba(#000, 0.05);
|
||||
$colorInputBg: rgba(black, 0.2);
|
||||
$colorInputFg: $colorBodyFg;
|
||||
$colorInputPlaceholder: darken($colorBodyFg, 20%);
|
||||
$colorFormText: darken($colorBodyFg, 10%);
|
||||
$colorInputIcon: darken($colorBodyFg, 25%);
|
||||
$colorFieldHint: lighten($colorBodyFg, 40%);
|
||||
$colorInputPlaceholder: pushBack($colorBodyFg, 20%);
|
||||
$colorFormText: pushBack($colorBodyFg, 10%);
|
||||
$colorInputIcon: pushBack($colorBodyFg, 25%);
|
||||
$colorFieldHint: pullForward($colorBodyFg, 40%);
|
||||
$shdwInput: inset rgba(black, 0.4) 0 0 1px;
|
||||
$shdwInputHov: inset rgba(black, 0.7) 0 0 2px;
|
||||
$shdwInputFoc: inset rgba(black, 0.8) 0 0.25px 3px;
|
||||
|
||||
// Inspector
|
||||
$colorInspectorBg: lighten($colorBodyBg, 5%);
|
||||
$colorInspectorBg: pullForward($colorBodyBg, 5%);
|
||||
$colorInspectorFg: $colorBodyFg;
|
||||
$colorInspectorPropName: darken($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: lighten($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: lighten($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: lighten($colorInspectorBg, 40%);
|
||||
$colorInspectorPropName: pushBack($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: pullForward($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Overlay
|
||||
$overlayColorBg: $colorMenuBg;
|
||||
@ -233,8 +243,8 @@ $colorIndicatorOn: $colorOk;
|
||||
$colorIndicatorOff: #777777;
|
||||
|
||||
// Staleness
|
||||
$colorTelemFresh: lighten($colorBodyFg, 20%);
|
||||
$colorTelemStale: darken($colorBodyFg, 20%);
|
||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
$styleTelemStale: italic;
|
||||
|
||||
// Limits
|
||||
@ -260,22 +270,22 @@ $colorInfoBubbleFg: #666;
|
||||
|
||||
// Items
|
||||
$colorItemBg: buttonBg($colorBtnBg);
|
||||
$colorItemBgHov: buttonBg(lighten($colorBtnBg, 5%));
|
||||
$colorItemBgHov: buttonBg(pullForward($colorBtnBg, 5%));
|
||||
$colorListItemBg: transparent;
|
||||
$colorListItemBgHov: rgba($colorKey, 0.1);
|
||||
$colorItemFg: $colorBtnFg;
|
||||
$colorItemFgDetails: darken($colorItemFg, 20%);
|
||||
$colorItemFgDetails: pushBack($colorItemFg, 20%);
|
||||
$shdwItemText: none;
|
||||
|
||||
// Tabular
|
||||
$colorTabBorder: lighten($colorBodyBg, 10%);
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: lighten($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: lighten($colorBodyBg, 10%);
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
$colorTabHeaderFg: $colorBodyFg;
|
||||
$colorTabHeaderBorder: $colorBodyBg;
|
||||
$colorTabGroupHeaderBg: lighten($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: darken($colorTabHeaderFg, 10%);
|
||||
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: pushBack($colorTabHeaderFg, 10%);
|
||||
|
||||
// Plot
|
||||
$colorPlotBg: rgba(black, 0.05);
|
||||
@ -284,22 +294,22 @@ $colorPlotHash: black;
|
||||
$opacityPlotHash: 0.2;
|
||||
$stylePlotHash: dashed;
|
||||
$colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: darken($colorPlotFg, 20%);
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
$legendHoverValueBg: rgba($colorBodyFg, 0.2);
|
||||
|
||||
// Tree
|
||||
$colorTreeBg: transparent;
|
||||
$colorItemTreeHoverBg: lighten($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: lighten($colorBodyFg, 20%);
|
||||
$colorItemTreeHoverBg: pullForward($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: pullForward($colorBodyFg, 20%);
|
||||
$colorItemTreeIcon: $colorKey; // Used
|
||||
$colorItemTreeIconHover: $colorItemTreeIcon; // Used
|
||||
$colorItemTreeFg: $colorBodyFg;
|
||||
$colorItemTreeSelectedBg: darken($colorKey, 15%);
|
||||
$colorItemTreeSelectedBg: pushBack($colorKey, 15%);
|
||||
$colorItemTreeSelectedFg: $colorItemTreeHoverFg;
|
||||
$colorItemTreeSelectedIcon: $colorItemTreeSelectedFg;
|
||||
$colorItemTreeEditingBg: darken($editColor, 20%);
|
||||
$colorItemTreeEditingFg: $editColorFg;
|
||||
$colorItemTreeEditingIcon: $editColorFg;
|
||||
$colorItemTreeEditingBg: pushBack($editUIColor, 20%);
|
||||
$colorItemTreeEditingFg: $editUIColor;
|
||||
$colorItemTreeEditingIcon: $editUIColor;
|
||||
$colorItemTreeVC: $colorDisclosureCtrl;
|
||||
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
||||
$shdwItemTreeIcon: none;
|
||||
@ -311,18 +321,18 @@ $colorThumbHoverBg: $colorItemTreeHoverBg;
|
||||
$scrollbarTrackSize: 7px;
|
||||
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
|
||||
$scrollbarTrackColorBg: rgba(#000, 0.2);
|
||||
$scrollbarThumbColor: darken($colorBodyBg, 50%);
|
||||
$scrollbarThumbColor: pushBack($colorBodyBg, 50%);
|
||||
$scrollbarThumbColorHov: $colorKey;
|
||||
$scrollbarThumbColorMenu: lighten($colorMenuBg, 10%);
|
||||
$scrollbarThumbColorMenuHov: lighten($scrollbarThumbColorMenu, 2%);
|
||||
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%);
|
||||
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
|
||||
|
||||
// Splitter
|
||||
$splitterHandleD: 2px;
|
||||
$splitterHandleHitMargin: 4px;
|
||||
$colorSplitterBaseBg: $colorBodyBg;
|
||||
$colorSplitterBg: lighten($colorSplitterBaseBg, 10%);
|
||||
$colorSplitterBg: pullForward($colorBodyBg, 10%);
|
||||
$colorSplitterFg: $colorBodyBg;
|
||||
$colorSplitterHover: $colorKey;
|
||||
$colorSplitterHover: $uiColor;
|
||||
$colorSplitterActive: $colorKey;
|
||||
$splitterBtnD: (16px, 35px); // height, width
|
||||
$splitterBtnColorBg: $colorBtnBg;
|
||||
@ -334,7 +344,7 @@ $splitterCollapsedBtnColorBgHov: $colorKey;
|
||||
$splitterCollapsedBtnColorFgHov: $colorKeyFg;
|
||||
|
||||
// Mobile
|
||||
$colorMobilePaneLeft: darken($colorBodyBg, 2%);
|
||||
$colorMobilePaneLeft: pushBack($colorBodyBg, 2%);
|
||||
$colorMobilePaneLeftTreeItemBg: rgba($colorBodyFg, 0.1);
|
||||
$colorMobilePaneLeftTreeItemFg: $colorItemTreeFg;
|
||||
$colorMobileSelectListTreeItemBg: rgba(#000, 0.05);
|
||||
@ -371,10 +381,14 @@ $createBtnTextTransform: uppercase;
|
||||
}
|
||||
|
||||
@mixin themedButton($c: $colorBtnBg) {
|
||||
background: linear-gradient(lighten($c, 5%), $c);
|
||||
background: linear-gradient(pullForward($c, 5%), $c);
|
||||
box-shadow: rgba(black, 0.5) 0 0.5px 2px;
|
||||
}
|
||||
|
||||
@mixin themedSelect($bg: $colorBtnBg, $fg: $colorBtnFg) {
|
||||
@include cSelect(linear-gradient(lighten($bg, 5%), $bg), $fg, lighten($bg, 20%), rgba(black, 0.5) 0 0.5px 3px);
|
||||
}
|
||||
|
||||
/**************************************************** OVERRIDES */
|
||||
.c-frame {
|
||||
&:not(.no-frame) {
|
||||
|
@ -47,6 +47,14 @@ $bodyFont: $heroFont;
|
||||
@return $c;
|
||||
}
|
||||
|
||||
@function pullForward($val, $amt) {
|
||||
@return darken($val, $amt);
|
||||
}
|
||||
|
||||
@function pushBack($val, $amt) {
|
||||
@return lighten($val, $amt);
|
||||
}
|
||||
|
||||
// Constants
|
||||
$fontBaseSize: 12px;
|
||||
$smallCr: 2px;
|
||||
@ -69,6 +77,7 @@ $colorKeyHov: #00c0f6;
|
||||
$colorKeyFilter: invert(37%) sepia(100%) saturate(686%) hue-rotate(157deg) brightness(102%) contrast(102%);
|
||||
$colorKeyFilterHov: invert(69%) sepia(87%) saturate(3243%) hue-rotate(151deg) brightness(97%) contrast(102%);
|
||||
$colorKeySelectedBg: $colorKey;
|
||||
$uiColor: #289fec; // Resize bars, splitter bars, etc.
|
||||
$colorInteriorBorder: rgba($colorBodyFg, 0.2);
|
||||
$colorA: #999;
|
||||
$colorAHov: $colorKey;
|
||||
@ -94,51 +103,52 @@ $colorPausedFg: #fff;
|
||||
$colorOk: #33cc33;
|
||||
|
||||
// Base variations
|
||||
$colorBodyBgSubtle: darken($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: lighten($colorKey, 50%);
|
||||
$colorKeySubtle: lighten($colorKey, 50%);
|
||||
$colorBodyBgSubtle: pullForward($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: pushBack($colorKey, 50%);
|
||||
$colorKeySubtle: pushBack($colorKey, 10%);
|
||||
|
||||
// Time Colors
|
||||
$colorTime: #618cff;
|
||||
$colorTimeBg: $colorTime;
|
||||
$colorTimeFg: $colorBodyBg;
|
||||
$colorTimeHov: lighten($colorTime, 5%);
|
||||
$colorTimeSubtle: lighten($colorTime, 20%);
|
||||
$colorTimeHov: pushBack($colorTime, 5%);
|
||||
$colorTimeSubtle: pushBack($colorTime, 20%);
|
||||
$colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
|
||||
$colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
|
||||
|
||||
/************************************************** EDITING */
|
||||
// Base Colors
|
||||
$dlSpread: 20%;
|
||||
$editColor: #00c7c3;
|
||||
$editColorAlt: #9971ff;
|
||||
$editColorBgBase: darken($editColor, $dlSpread);
|
||||
$editColorBg: darken($editColor, $dlSpread);
|
||||
$editColorFg: lighten($editColor, $dlSpread);
|
||||
$editColorHov: lighten($editColor, 20%);
|
||||
// Canvas
|
||||
$editCanvasColorBg: #e6ffff;
|
||||
$editCanvasColorGrid: darken($editCanvasColorBg, 10%);
|
||||
// Selectable
|
||||
$editSelectableColor: #acdad6;
|
||||
$editSelectableColorFg: darken($editSelectableColor, 20%);
|
||||
$editSelectableColorHov: darken($editSelectableColor, 10%);
|
||||
// Selectable selected
|
||||
$editSelectableColorSelected: $editColor;
|
||||
$editSelectableColorSelectedFg: lighten($editSelectableColorSelected, 50%);
|
||||
$editSelectableColorFg: darken($editSelectableColor, 40%);
|
||||
$editSelectableBorder: 1px dotted $editSelectableColor;
|
||||
$editSelectableBorderHov: 1px dotted $editColorAlt;
|
||||
$editSelectableBorderSelected: 1px solid $editColor;
|
||||
$editSelectableShdwSelected: rgba($editColor, 0.75) 0 0 0 1px;
|
||||
$editMoveableSelectedShdw: rgba($editColor, 0.5) 0 0 10px;
|
||||
$editBorderDrilledIn: 1px dashed $editColorAlt;
|
||||
$colorGridLines: rgba($editColor, 0.2);
|
||||
|
||||
/************************************************** BROWSING */
|
||||
$browseSelectableBorderHov: 1px dotted rgba($colorBodyFg, 0.2);
|
||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.2) 0 0 3px;
|
||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.6);
|
||||
$browseFrameColor: pullForward($colorBodyBg, 10%);
|
||||
$browseFrameBorder: 1px solid $browseFrameColor; // Frames in Disp and Flex Layouts when frame is showing
|
||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.3) 0 0 3px;
|
||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
|
||||
|
||||
/************************************************** EDITING */
|
||||
$editUIColor: $uiColor; // Base color
|
||||
$editUIColorHov: pullForward(saturate($uiColor, 10%), 20%); // Hover color when $editUIColor is applied as a base color
|
||||
$editUIBaseColor: #cae1ff; // Base color, toolbar bg
|
||||
$editUIBaseColorHov: pushBack($editUIBaseColor, 20%);
|
||||
$editUIBaseColorFg: #4c4c4c; // Toolbar button icon colors, etc.
|
||||
$editUIAreaBaseColor: pullForward(saturate($editUIBaseColor, 30%), 20%);
|
||||
$editUIAreaShdw: $editUIAreaBaseColor 0 0 0 2px; // Edit area s-selected-parent
|
||||
$editUIAreaShdwSelected: $editUIAreaBaseColor 0 0 0 3px; // Edit area s-selected
|
||||
$editUIGridColorBg: rgba($editUIBaseColor, 0.2); // Background of layout editing area
|
||||
$editUIGridColorFg: rgba($editUIBaseColor, 0.3); // Grid lines in layout editing area
|
||||
$editFrameColor: $browseFrameColor; // Solid or dotted border applied to non-selected frames in a layout; move-bar on frame hover
|
||||
$editFrameBorder: 1px dotted $editFrameColor;
|
||||
$editFrameColorHov: $editUIColor; // Solid border hover on frames; hover should not be applied to selected objects
|
||||
$editFrameBorderHov: 1px solid $editFrameColorHov; // Hover on selectable frames
|
||||
$editFrameColorSelected: #333; // Border of selected frames
|
||||
$editFrameColorHandleBg: $colorBodyBg; // Resize handle 'offset' color to make handle standout
|
||||
$editFrameColorHandleFg: $editFrameColorSelected; // Resize handle main color
|
||||
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 10px 1px;
|
||||
$editFrameSelectedBorder: 1px dashed $editFrameColorSelected; // Selected frame element
|
||||
$editFrameMovebarColorBg: $editFrameColor; // Movebar bg color
|
||||
$editFrameMovebarColorFg: pullForward($editFrameMovebarColorBg, 20%); // Grippy lines, container size text
|
||||
$editFrameHovMovebarColorBg: pullForward($editFrameMovebarColorBg, 10%); // Hover style
|
||||
$editFrameHovMovebarColorFg: pullForward($editFrameMovebarColorFg, 10%);
|
||||
$editFrameSelectedMovebarColorBg: pullForward($editFrameMovebarColorBg, 15%); // Selected style
|
||||
$editFrameSelectedMovebarColorFg: pullForward($editFrameMovebarColorFg, 15%);
|
||||
$editFrameMovebarH: 10px; // Height of move bar in layout frame
|
||||
|
||||
// Icons
|
||||
$colorIconAlias: #4af6f3;
|
||||
@ -149,7 +159,7 @@ $colorTabsHolderBg: rgba($colorBodyFg, 0.2);
|
||||
|
||||
// Buttons and Controls
|
||||
$colorBtnBg: #aaa;
|
||||
$colorBtnBgHov: darken($colorBtnBg, 10%);
|
||||
$colorBtnBgHov: pullForward($colorBtnBg, 10%);
|
||||
$colorBtnFg: #fff;
|
||||
$colorBtnReverseFg: $colorBodyBg;
|
||||
$colorBtnReverseBg: $colorBodyFg;
|
||||
@ -157,7 +167,7 @@ $colorBtnFgHov: $colorBtnFg;
|
||||
$colorBtnMajorBg: $colorKey;
|
||||
$colorBtnMajorBgHov: $colorKeyHov;
|
||||
$colorBtnMajorFg: $colorKeyFg;
|
||||
$colorBtnMajorFgHov: lighten($colorBtnMajorFg, 10%);
|
||||
$colorBtnMajorFgHov: pushBack($colorBtnMajorFg, 10%);
|
||||
$colorBtnCautionBg: #f16f6f;
|
||||
$colorBtnCautionBgHov: #f1504e;
|
||||
$colorBtnCautionFg: $colorBtnFg;
|
||||
@ -165,15 +175,15 @@ $colorClickIcon: $colorKey;
|
||||
$colorClickIconBgHov: rgba($colorKey, 0.2);
|
||||
$colorClickIconFgHov: $colorKeyHov;
|
||||
$colorDropHint: $colorKey;
|
||||
$colorDropHintBg: lighten($colorDropHint, 30%);
|
||||
$colorDropHintBgHov: lighten($colorDropHint, 40%);
|
||||
$colorDropHintFg: lighten($colorDropHint, 0);
|
||||
$colorDropHintBg: pushBack($colorDropHint, 10%);
|
||||
$colorDropHintBgHov: pushBack($colorDropHint, 40%);
|
||||
$colorDropHintFg: pushBack($colorDropHint, 0);
|
||||
$colorDisclosureCtrl: rgba($colorBodyFg, 0.5);
|
||||
$colorDisclosureCtrlHov: rgba($colorBodyFg, 0.7);
|
||||
|
||||
// Menus
|
||||
$colorMenuBg: lighten($colorBodyBg, 10%);
|
||||
$colorMenuFg: darken($colorMenuBg, 70%);
|
||||
$colorMenuBg: pushBack($colorBodyBg, 10%);
|
||||
$colorMenuFg: pullForward($colorMenuBg, 70%);
|
||||
$colorMenuIc: $colorKey;
|
||||
$colorMenuHovBg: $colorMenuIc;
|
||||
$colorMenuHovFg: $colorMenuBg;
|
||||
@ -200,27 +210,27 @@ $colorFormLines: rgba(#000, 0.1);
|
||||
$colorFormSectionHeader: rgba(#000, 0.05);
|
||||
$colorInputBg: $colorGenBg;
|
||||
$colorInputFg: $colorBodyFg;
|
||||
$colorInputPlaceholder: lighten($colorBodyFg, 20%);
|
||||
$colorFormText: lighten($colorBodyFg, 10%);
|
||||
$colorInputIcon: lighten($colorBodyFg, 25%);
|
||||
$colorFieldHint: darken($colorBodyFg, 40%);
|
||||
$colorInputPlaceholder: pushBack($colorBodyFg, 20%);
|
||||
$colorFormText: pushBack($colorBodyFg, 10%);
|
||||
$colorInputIcon: pushBack($colorBodyFg, 25%);
|
||||
$colorFieldHint: pullForward($colorBodyFg, 40%);
|
||||
$shdwInput: inset rgba(black, 0.7) 0 0 1px;
|
||||
$shdwInputHov: inset rgba(black, 0.7) 0 0 2px;
|
||||
$shdwInputFoc: inset rgba(black, 0.8) 0 0.25px 3px;
|
||||
|
||||
// Inspector
|
||||
$colorInspectorBg: darken($colorBodyBg, 5%);
|
||||
$colorInspectorBg: pullForward($colorBodyBg, 5%);
|
||||
$colorInspectorFg: $colorBodyFg;
|
||||
$colorInspectorPropName: lighten($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: darken($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: darken($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: darken($colorInspectorBg, 40%);
|
||||
$colorInspectorPropName: pushBack($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: pullForward($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Overlay
|
||||
$overlayColorBg: $colorMenuBg;
|
||||
$overlayColorFg: $colorMenuFg;
|
||||
$overlayCr: $interiorMarginLg;
|
||||
$overlayBrightnessAdjust: brightness(1);
|
||||
$overlayBrightnessAdjust: brightness(1.3);
|
||||
|
||||
// Indicator colors
|
||||
$colorIndicatorAvailable: $colorKey;
|
||||
@ -229,8 +239,8 @@ $colorIndicatorOn: $colorOk;
|
||||
$colorIndicatorOff: #666;
|
||||
|
||||
// Staleness
|
||||
$colorTelemFresh: darken($colorBodyFg, 20%);
|
||||
$colorTelemStale: lighten($colorBodyFg, 20%);
|
||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
$styleTelemStale: italic;
|
||||
|
||||
// Limits
|
||||
@ -255,23 +265,23 @@ $colorInfoBubbleBg: $colorMenuBg;
|
||||
$colorInfoBubbleFg: #666;
|
||||
|
||||
// Items
|
||||
$colorItemBg: lighten($colorBtnBg, 20%);
|
||||
$colorItemBgHov: lighten($colorItemBg, 5%);
|
||||
$colorItemBg: pushBack($colorBtnBg, 20%);
|
||||
$colorItemBgHov: pushBack($colorItemBg, 5%);
|
||||
$colorListItemBg: transparent;
|
||||
$colorListItemBgHov: rgba($colorKey, 0.1);
|
||||
$colorItemFg: $colorBodyFg;
|
||||
$colorItemFgDetails: lighten($colorItemFg, 15%);
|
||||
$colorItemFgDetails: pushBack($colorItemFg, 15%);
|
||||
$shdwItemText: none;
|
||||
|
||||
// Tabular
|
||||
$colorTabBorder: darken($colorBodyBg, 10%);
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: darken($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: darken($colorBodyBg, 10%);
|
||||
$colorTabHeaderFg: darken($colorBodyFg, 20%);
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
$colorTabHeaderFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBorder: $colorBodyBg;
|
||||
$colorTabGroupHeaderBg: darken($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: darken($colorTabGroupHeaderBg, 40%);
|
||||
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: pullForward($colorTabGroupHeaderBg, 40%);
|
||||
|
||||
// Plot
|
||||
$colorPlotBg: rgba(black, 0.05);
|
||||
@ -280,22 +290,22 @@ $colorPlotHash: black;
|
||||
$opacityPlotHash: 0.2;
|
||||
$stylePlotHash: dashed;
|
||||
$colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: lighten($colorPlotFg, 20%);
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
$legendHoverValueBg: rgba($colorBodyFg, 0.2);
|
||||
|
||||
// Tree
|
||||
$colorTreeBg: transparent;
|
||||
$colorItemTreeHoverBg: darken($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: darken($colorBodyFg, 10%);
|
||||
$colorItemTreeHoverBg: pullForward($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: pullForward($colorBodyFg, 10%);
|
||||
$colorItemTreeIcon: $colorKey; // Used
|
||||
$colorItemTreeIconHover: $colorItemTreeIcon; // Used
|
||||
$colorItemTreeFg: $colorBodyFg;
|
||||
$colorItemTreeSelectedBg: lighten($colorKey, 15%);
|
||||
$colorItemTreeSelectedBg: pushBack($colorKey, 15%);
|
||||
$colorItemTreeSelectedFg: $colorBodyBg;
|
||||
$colorItemTreeSelectedIcon: $colorItemTreeSelectedFg;
|
||||
$colorItemTreeEditingBg: $editColor;
|
||||
$colorItemTreeEditingFg: $editColorFg;
|
||||
$colorItemTreeEditingIcon: $editColorFg;
|
||||
$colorItemTreeEditingBg: pushBack($editUIColor, 20%);
|
||||
$colorItemTreeEditingFg: $editUIColor;
|
||||
$colorItemTreeEditingIcon: $editUIColor;
|
||||
$colorItemTreeVC: $colorDisclosureCtrl;
|
||||
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
||||
$shdwItemTreeIcon: none;
|
||||
@ -307,16 +317,16 @@ $colorThumbHoverBg: $colorItemTreeHoverBg;
|
||||
$scrollbarTrackSize: 7px;
|
||||
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
|
||||
$scrollbarTrackColorBg: rgba(#000, 0.2);
|
||||
$scrollbarThumbColor: darken($colorBodyBg, 50%);
|
||||
$scrollbarThumbColor: pullForward($colorBodyBg, 50%);
|
||||
$scrollbarThumbColorHov: $colorKey;
|
||||
$scrollbarThumbColorMenu: darken($colorMenuBg, 10%);
|
||||
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%);
|
||||
$scrollbarThumbColorMenuHov: darken($scrollbarThumbColorMenu, 2%);
|
||||
|
||||
// Splitter
|
||||
$splitterHandleD: 2px;
|
||||
$splitterHandleHitMargin: 4px;
|
||||
$colorSplitterBaseBg: $colorBodyBg;
|
||||
$colorSplitterBg: darken($colorSplitterBaseBg, 20%);
|
||||
$colorSplitterBg: pullForward($colorSplitterBaseBg, 20%);
|
||||
$colorSplitterFg: $colorBodyBg;
|
||||
$colorSplitterHover: $colorKey;
|
||||
$colorSplitterActive: $colorKey;
|
||||
@ -330,7 +340,7 @@ $splitterCollapsedBtnColorBgHov: $colorKey;
|
||||
$splitterCollapsedBtnColorFgHov: $colorKeyFg;
|
||||
|
||||
// Mobile
|
||||
$colorMobilePaneLeft: darken($colorBodyBg, 2%);
|
||||
$colorMobilePaneLeft: pullForward($colorBodyBg, 2%);
|
||||
$colorMobilePaneLeftTreeItemBg: rgba($colorBodyFg, 0.1);
|
||||
$colorMobilePaneLeftTreeItemFg: $colorItemTreeFg;
|
||||
$colorMobileSelectListTreeItemBg: rgba(#000, 0.05);
|
||||
@ -370,16 +380,6 @@ $createBtnTextTransform: uppercase;
|
||||
background: $c;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************** NOT USED, LEAVE FOR NOW */
|
||||
|
||||
// Content status
|
||||
/*
|
||||
$colorAlert: #ff3c00;
|
||||
$colorWarningHi: #990000;
|
||||
$colorWarningLo: #ff9900;
|
||||
$colorDiagnostic: #a4b442;
|
||||
$colorCommand: #3693bd;
|
||||
$colorInfo: #2294a2;
|
||||
$colorOk: #33cc33;
|
||||
*/
|
||||
@mixin themedSelect($bg: $colorBtnBg, $fg: $colorBtnFg) {
|
||||
@include cSelect($bg, $fg, lighten($bg, 20%), none);
|
||||
}
|
||||
|
@ -228,6 +228,17 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
}
|
||||
}
|
||||
|
||||
// SELECTS
|
||||
select {
|
||||
@include appearanceNone();
|
||||
@include themedSelect();
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
background-position: right .4em top 80%, 0 0;
|
||||
border: none;
|
||||
border-radius: $controlCr;
|
||||
padding: 1px 20px 1px $interiorMargin;
|
||||
}
|
||||
|
||||
/******************************************************** HYPERLINKS AND HYPERLINK BUTTONS */
|
||||
.c-hyperlink {
|
||||
&--link {
|
||||
@ -411,7 +422,7 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
}
|
||||
|
||||
@mixin cToolbarSeparator() {
|
||||
$m: $interiorMargin;
|
||||
$m: 1px;
|
||||
$b: 1px;
|
||||
display: block;
|
||||
width: $m + $b; // Allow for border
|
||||
@ -421,21 +432,35 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
|
||||
.c-toolbar {
|
||||
$p: $interiorMargin;
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
background: $editUIBaseColor;
|
||||
border-radius: $basicCr;
|
||||
height: $p + 24px; // Need to standardize the height
|
||||
padding-top: $p;
|
||||
padding: $p;
|
||||
|
||||
> * + * {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
&__separator {
|
||||
@include cToolbarSeparator();
|
||||
}
|
||||
|
||||
.c-click-icon,
|
||||
.c-labeled-input {
|
||||
color: $editUIBaseColorFg;
|
||||
}
|
||||
|
||||
.c-click-icon {
|
||||
@include cControl();
|
||||
$pLR: $interiorMargin - 1;
|
||||
$pTB: 2px;
|
||||
color: $colorBodyFg;
|
||||
padding: $pTB $pLR;
|
||||
|
||||
&:hover {
|
||||
background: $editUIBaseColorHov !important;
|
||||
color: $editUIBaseColorFg !important;
|
||||
}
|
||||
|
||||
&--swatched {
|
||||
padding-bottom: floor($pTB / 2);
|
||||
width: 2em; // Standardize the width
|
||||
|
@ -191,8 +191,8 @@ body.desktop .has-local-controls {
|
||||
.c-grid {
|
||||
pointer-events: none;
|
||||
|
||||
&__x { @include bgTicks($editCanvasColorGrid, 'x'); }
|
||||
&__y { @include bgTicks($editCanvasColorGrid, 'y'); }
|
||||
&__x { @include bgTicks($editUIGridColorFg, 'x'); }
|
||||
&__y { @include bgTicks($editUIGridColorFg, 'y'); }
|
||||
}
|
||||
|
||||
/*************************** SELECTION */
|
||||
@ -200,32 +200,14 @@ body.desktop .has-local-controls {
|
||||
&:hover {
|
||||
box-shadow: $browseSelectableShdwHov;
|
||||
}
|
||||
|
||||
&[s-selected] {
|
||||
border: $browseSelectedBorder;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************** EDITING */
|
||||
.is-editing {
|
||||
*:not(.is-drilled-in).c-frame {
|
||||
border: $editSelectableBorder;
|
||||
|
||||
&:not([s-selected]) {
|
||||
&:hover {
|
||||
border: $editSelectableBorderHov;
|
||||
}
|
||||
}
|
||||
|
||||
&[s-selected] {
|
||||
box-shadow: $editSelectableShdwSelected;
|
||||
|
||||
> .c-frame-edit {
|
||||
display: block; // Show the editing rect and handles
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*.is-drilled-in {
|
||||
border: $editBorderDrilledIn;
|
||||
}
|
||||
|
||||
.is-moveable {
|
||||
cursor: move;
|
||||
}
|
||||
@ -234,116 +216,8 @@ body.desktop .has-local-controls {
|
||||
// Applied in markup to objects that provide links. Disable while editing.
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.c-frame-edit {
|
||||
// In Layouts, this is the editing rect and handles
|
||||
// In Fixed Position, this is a wrapper element
|
||||
$z: 10;
|
||||
|
||||
@include abs();
|
||||
display: none;
|
||||
|
||||
&__move {
|
||||
@include abs();
|
||||
box-shadow: $editMoveableSelectedShdw;
|
||||
cursor: move;
|
||||
z-index: $z;
|
||||
}
|
||||
|
||||
&__handle {
|
||||
$d: 8px;
|
||||
$o: floor($d * -0.5);
|
||||
background: rgba($editColor, 0.3);
|
||||
border: 1px solid $editColor;
|
||||
position: absolute;
|
||||
width: $d; height: $d;
|
||||
top: auto; right: auto; bottom: auto; left: auto;
|
||||
z-index: $z + 1;
|
||||
|
||||
&:before {
|
||||
// Extended hit area
|
||||
$m: -5px;
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: $m; right: $m; bottom: $m; left: $m;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $editColor;
|
||||
}
|
||||
|
||||
&--nwse {
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
|
||||
&--nw {
|
||||
cursor: nw-resize;
|
||||
left: $o; top: $o;
|
||||
}
|
||||
|
||||
&--ne {
|
||||
cursor: ne-resize;
|
||||
right: $o; top: $o;
|
||||
}
|
||||
|
||||
&--se {
|
||||
cursor: se-resize;
|
||||
right: $o; bottom: $o;
|
||||
}
|
||||
|
||||
&--sw {
|
||||
cursor: sw-resize;
|
||||
left: $o; bottom: $o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move this into DisplayLayout and Fixed Position vue files respectively
|
||||
.l-shell__main-container > .l-layout,
|
||||
.l-shell__main-container > .c-object-view .l-fixed-position {
|
||||
// Target the top-most layout container and color its background
|
||||
background: $editCanvasColorBg;
|
||||
}
|
||||
|
||||
.l-shell__main-container {
|
||||
box-shadow: $colorBodyBg 0 0 0 1px, rgba($editColor, 0.7) 0 0 0 2px;
|
||||
&[s-selected] {
|
||||
// Provide a clearer selection context articulation
|
||||
box-shadow: $colorBodyBg 0 0 0 1px, $editColor 0 0 0px 3px;
|
||||
}
|
||||
}
|
||||
|
||||
// Layouts
|
||||
[s-selected],
|
||||
[s-selected-parent] {
|
||||
.l-layout {
|
||||
// Show the layout grid for the top-most child of the current selection,
|
||||
// and hide the grid for deeper nested levels.
|
||||
[class*="__grid-holder"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.l-layout [class*="__grid-holder"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed position
|
||||
.l-fixed-position {
|
||||
&__grid-holder {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c-frame-edit {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************** LEGACY */
|
||||
|
||||
mct-container {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user