mirror of
https://github.com/nasa/openmct.git
synced 2025-02-21 09:52:04 +00:00
Vue toolbar (#2191)
* Add a toolbar provider for display layout. * Move toolbar provider to the plugin * basic toolbar generation * componentize different toolbar control types Break toolbar control types down into different parts and provide a test toolbar generator in index.html that utilizes all the controls. * Get the 'Show frame' checkbox working in the toolbar * - Remove extra listener. - Display toolbar only when editing. * Modify the Selection API to set s-selected and s-selected-parent attributes instead of adding to the css class names. * Move the logic for allowing the toolbar in the edit mode to the provider. * Use toggle-button component to toggle frame * Delete old files * Remove MCTToolbar * Modify the toggle button component to return the computed value * Remove reload=true * Revert to the original setting * use value from props * Always update toolbars on edit status change * restore fixed position bundle * bring back reload when hmr unavailable
This commit is contained in:
parent
64b9d4c24a
commit
d48cc2deee
2
app.js
2
app.js
@ -46,7 +46,7 @@ webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) });
|
||||
|
||||
webpackConfig.entry.openmct = [
|
||||
'webpack-hot-middleware/client',
|
||||
'webpack-hot-middleware/client?reload=true',
|
||||
webpackConfig.entry.openmct
|
||||
];
|
||||
|
||||
|
198
index.html
198
index.html
@ -79,5 +79,203 @@
|
||||
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
|
||||
openmct.time.timeSystem('utc');
|
||||
openmct.start();
|
||||
|
||||
// openmct.toolbars.addProvider({
|
||||
// name: "Testing Toolbar",
|
||||
// key: "testing",
|
||||
// description: "a mock toolbar that exercises all controls",
|
||||
// forSelection: function (selection) {
|
||||
// return true; // always applies.
|
||||
// },
|
||||
// toolbar: function (selection) {
|
||||
// return [
|
||||
// {
|
||||
// control: 'menu',
|
||||
// icon: 'icon-plus',
|
||||
// label: 'Add',
|
||||
// options: [
|
||||
// { name: 'Box', class: 'icon-box', title: 'Add Box' },
|
||||
// { name: 'Line', class: 'icon-line-horz', title: 'Add Line' },
|
||||
// { name: 'Text', class: 'icon-font', title: 'Add Text' },
|
||||
// { name: 'Image', class: 'icon-image', title: 'Add Image' }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'color-picker',
|
||||
// icon: 'icon-paint-bucket',
|
||||
// value: '#33ff00',
|
||||
// },
|
||||
// {
|
||||
// control: 'color-picker',
|
||||
// icon: 'icon-pencil',
|
||||
// value: '#ffffff',
|
||||
// },
|
||||
// {
|
||||
// control: 'color-picker',
|
||||
// icon: 'icon-font',
|
||||
// value: '#333333',
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'select-menu',
|
||||
// value: 11,
|
||||
// options: [
|
||||
// { value: 9, name: '9 px' },
|
||||
// { value: 10, name: '10 px' },
|
||||
// { value: 11, name: '11 px' },
|
||||
// { value: 12, name: '12 px' },
|
||||
// { value: 13, name: '13 px' },
|
||||
// { value: 14, name: '14 px' },
|
||||
// { value: 16, name: '16 px' },
|
||||
// { value: 18, name: '18 px' },
|
||||
// { value: 20, name: '20 px' },
|
||||
// { value: 24, name: '24 px' },
|
||||
// { value: 28, name: '28 px' },
|
||||
// { value: 32, name: '32 px' },
|
||||
// { value: 40, name: '40 px' },
|
||||
// { value: 48, name: '48 px' },
|
||||
// { value: 56, name: '56 px' },
|
||||
// { value: 64, name: '64 px' },
|
||||
// { value: 72, name: '72 px' },
|
||||
// { value: 80, name: '80 px' },
|
||||
// { value: 88, name: '88 px' },
|
||||
// { value: 96, name: '96 px' },
|
||||
// { value: 128, name: '128 px' },
|
||||
// { value: 160, name: '160 px' }
|
||||
// ]
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'menu',
|
||||
// icon: 'icon-layers',
|
||||
// options: [
|
||||
// { name: 'Move to top', class: 'icon-arrow-double-up', title: 'Move to top' },
|
||||
// { name: 'Move up', class: 'icon-arrow-up', title: 'Move up' },
|
||||
// { name: 'Move down', class: 'icon-arrow-down', title: 'Move down' },
|
||||
// { name: 'Move to bottom', class: 'icon-arrow-double-down', title: 'Move to bottom' }
|
||||
// ]
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'button',
|
||||
// icon: 'icon-gear'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'X',
|
||||
// value: 1,
|
||||
// title: 'X position'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'Y',
|
||||
// value: 2,
|
||||
// title: 'Y position'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'W',
|
||||
// value: 3,
|
||||
// title: 'Width'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'H',
|
||||
// value: 4,
|
||||
// title: 'Height'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'button',
|
||||
// icon: 'icon-trash',
|
||||
// label: 'delete',
|
||||
// modifier: 'caution'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'checkbox',
|
||||
// name: 'this is a checkbox',
|
||||
// },
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'toggle-button',
|
||||
// title: 'Toggle Frame',
|
||||
// property: 'hideFrame',
|
||||
// value: false,
|
||||
// options: [
|
||||
// {
|
||||
// value: true,
|
||||
// icon: 'icon-frame-hide'
|
||||
// },
|
||||
// {
|
||||
// value: false,
|
||||
// icon: 'icon-frame-show'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// control: 'toggle-button',
|
||||
// title: 'Snap to grid',
|
||||
// property: 'snapToGrid',
|
||||
// value: true,
|
||||
// options: [
|
||||
// {
|
||||
// value: true,
|
||||
// icon: 'icon-grid-snap-to'
|
||||
// },
|
||||
// {
|
||||
// value: false,
|
||||
// icon: 'icon-grid-snap-no'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// control: 'toggle-button',
|
||||
// title: 'Toggle label',
|
||||
// property: 'showLabel',
|
||||
// value: true,
|
||||
// options: [
|
||||
// {
|
||||
// value: true,
|
||||
// icon: 'icon-two-parts-both'
|
||||
// },
|
||||
// {
|
||||
// value: false,
|
||||
// icon: 'icon-two-parts-one-only'
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ];
|
||||
// }
|
||||
// });
|
||||
|
||||
</script>
|
||||
</html>
|
||||
|
@ -1,254 +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/api/objects/object-utils',
|
||||
'lodash'
|
||||
],
|
||||
function (
|
||||
objectUtils,
|
||||
_
|
||||
) {
|
||||
|
||||
/**
|
||||
* Provides initial structure and state (as suitable for provision
|
||||
* to the `mct-toolbar` directive) for a view's toolbar, based on
|
||||
* that view's declaration of what belongs in its toolbar and on
|
||||
* the current selection.
|
||||
*
|
||||
* @param $scope the Angular scope
|
||||
* @param {Object} openmct the openmct object
|
||||
* @param structure the toolbar structure
|
||||
* @memberof platform/commonUI/edit
|
||||
* @constructor
|
||||
*/
|
||||
function EditToolbar($scope, openmct, structure) {
|
||||
this.toolbarStructure = [];
|
||||
this.properties = [];
|
||||
this.toolbarState = [];
|
||||
this.openmct = openmct;
|
||||
this.domainObjectsById = {};
|
||||
this.unobserveObjects = [];
|
||||
this.stateTracker = [];
|
||||
|
||||
$scope.$watchCollection(this.getState.bind(this), this.handleStateChanges.bind(this));
|
||||
$scope.$on("$destroy", this.destroy.bind(this));
|
||||
|
||||
this.updateToolbar(structure);
|
||||
this.registerListeners(structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the toolbar with a new structure.
|
||||
*
|
||||
* @param {Array} structure the toolbar structure
|
||||
*/
|
||||
EditToolbar.prototype.updateToolbar = function (structure) {
|
||||
var self = this;
|
||||
|
||||
function addKey(item) {
|
||||
self.stateTracker.push({
|
||||
id: objectUtils.makeKeyString(item.domainObject.identifier),
|
||||
domainObject: item.domainObject,
|
||||
property: item.property
|
||||
});
|
||||
self.properties.push(item.property);
|
||||
|
||||
return self.properties.length - 1; // Return index of property
|
||||
}
|
||||
|
||||
function convertItem(item) {
|
||||
var converted = Object.create(item || {});
|
||||
|
||||
if (item.property) {
|
||||
converted.key = addKey(item);
|
||||
}
|
||||
|
||||
if (item.method) {
|
||||
converted.click = function (value) {
|
||||
item.method(value);
|
||||
};
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
// Get initial value for a given property
|
||||
function initializeState(property) {
|
||||
var result;
|
||||
structure.forEach(function (item) {
|
||||
if (item.property === property) {
|
||||
result = _.get(item.domainObject, item.property);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Tracks the domain object and property for every element in the state array
|
||||
this.stateTracker = [];
|
||||
this.toolbarStructure = structure.map(convertItem);
|
||||
this.toolbarState = this.properties.map(initializeState);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the structure of the toolbar, as appropriate to
|
||||
* pass to `mct-toolbar`.
|
||||
*
|
||||
* @returns {Array} the toolbar structure
|
||||
*/
|
||||
EditToolbar.prototype.getStructure = function () {
|
||||
return this.toolbarStructure;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the current state of the toolbar, as appropriate
|
||||
* to two-way bind to the state handled by `mct-toolbar`.
|
||||
*
|
||||
* @returns {Array} state of the toolbar
|
||||
*/
|
||||
EditToolbar.prototype.getState = function () {
|
||||
return this.toolbarState;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mutates the domain object's property with a new value.
|
||||
*
|
||||
* @param {Object} dominObject the domain object
|
||||
* @param {string} property the domain object's property to update
|
||||
* @param value the property's new value
|
||||
*/
|
||||
EditToolbar.prototype.updateDomainObject = function (domainObject, property, value) {
|
||||
this.openmct.objects.mutate(domainObject, property, value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates state with the new value.
|
||||
*
|
||||
* @param {number} index the index of the corresponding
|
||||
* element in the state array
|
||||
* @param value the new value to update the state array with
|
||||
*/
|
||||
EditToolbar.prototype.updateState = function (index, value) {
|
||||
this.toolbarState[index] = value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register listeners for domain objects to watch for updates.
|
||||
*
|
||||
* @param {Array} the toolbar structure
|
||||
*/
|
||||
EditToolbar.prototype.registerListeners = function (structure) {
|
||||
var self = this;
|
||||
|
||||
function observeObject(domainObject, id) {
|
||||
var unobserveObject = self.openmct.objects.observe(domainObject, '*', function (newObject) {
|
||||
self.domainObjectsById[id].newObject = JSON.parse(JSON.stringify(newObject));
|
||||
self.scheduleStateUpdate();
|
||||
});
|
||||
self.unobserveObjects.push(unobserveObject);
|
||||
}
|
||||
|
||||
structure.forEach(function (item) {
|
||||
var domainObject = item.domainObject;
|
||||
var id = objectUtils.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (!self.domainObjectsById[id]) {
|
||||
self.domainObjectsById[id] = {
|
||||
domainObject: domainObject,
|
||||
properties: []
|
||||
};
|
||||
observeObject(domainObject, id);
|
||||
}
|
||||
|
||||
self.domainObjectsById[id].properties.push(item.property);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Delays updating the state.
|
||||
*/
|
||||
EditToolbar.prototype.scheduleStateUpdate = function () {
|
||||
if (this.stateUpdateScheduled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.stateUpdateScheduled = true;
|
||||
setTimeout(this.updateStateAfterMutation.bind(this));
|
||||
};
|
||||
|
||||
EditToolbar.prototype.updateStateAfterMutation = function () {
|
||||
this.stateTracker.forEach(function (state, index) {
|
||||
if (!this.domainObjectsById[state.id].newObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
var domainObject = this.domainObjectsById[state.id].domainObject;
|
||||
var newObject = this.domainObjectsById[state.id].newObject;
|
||||
var currentValue = _.get(domainObject, state.property);
|
||||
var newValue = _.get(newObject, state.property);
|
||||
|
||||
state.domainObject = newObject;
|
||||
|
||||
if (currentValue !== newValue) {
|
||||
this.updateState(index, newValue);
|
||||
}
|
||||
}, this);
|
||||
|
||||
Object.values(this.domainObjectsById).forEach(function (tracker) {
|
||||
if (tracker.newObject) {
|
||||
tracker.domainObject = tracker.newObject;
|
||||
}
|
||||
delete tracker.newObject;
|
||||
});
|
||||
this.stateUpdateScheduled = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the listeners.
|
||||
*/
|
||||
EditToolbar.prototype.deregisterListeners = function () {
|
||||
this.unobserveObjects.forEach(function (unobserveObject) {
|
||||
unobserveObject();
|
||||
});
|
||||
this.unobserveObjects = [];
|
||||
};
|
||||
|
||||
EditToolbar.prototype.handleStateChanges = function (state) {
|
||||
(state || []).map(function (newValue, index) {
|
||||
var domainObject = this.stateTracker[index].domainObject;
|
||||
var property = this.stateTracker[index].property;
|
||||
var currentValue = _.get(domainObject, property);
|
||||
|
||||
if (currentValue !== newValue) {
|
||||
this.updateDomainObject(domainObject, property, newValue);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
EditToolbar.prototype.destroy = function () {
|
||||
this.deregisterListeners();
|
||||
};
|
||||
|
||||
return EditToolbar;
|
||||
}
|
||||
);
|
@ -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(
|
||||
['../../src/representers/EditToolbar'],
|
||||
function (EditToolbar) {
|
||||
|
||||
describe("An Edit mode toolbar", function () {
|
||||
var mockOpenMCT,
|
||||
mockScope,
|
||||
mockObjects,
|
||||
mockDomainObject,
|
||||
testStructure,
|
||||
toolbar;
|
||||
|
||||
beforeEach(function () {
|
||||
mockOpenMCT = jasmine.createSpy('openmct', ['objects']);
|
||||
mockObjects = jasmine.createSpyObj('objects', ['observe']);
|
||||
mockObjects.observe.and.returnValue();
|
||||
mockOpenMCT.objects = mockObjects;
|
||||
mockScope = jasmine.createSpyObj("$scope", [
|
||||
"$watchCollection",
|
||||
"$on"
|
||||
]);
|
||||
mockScope.$watchCollection.and.returnValue();
|
||||
mockDomainObject = jasmine.createSpyObj("domainObject", [
|
||||
'identifier'
|
||||
]);
|
||||
|
||||
testStructure = [
|
||||
{ name: "A", property: "a", domainObject: mockDomainObject },
|
||||
{ name: "B", property: "b", domainObject: mockDomainObject },
|
||||
{ name: "C", property: "c", domainObject: mockDomainObject },
|
||||
{ name: "X", property: "x", domainObject: mockDomainObject },
|
||||
{ name: "Y", property: "y", domainObject: mockDomainObject },
|
||||
{ name: "Z", property: "z", domainObject: mockDomainObject },
|
||||
{ name: "M", method: "m", domainObject: mockDomainObject }
|
||||
];
|
||||
|
||||
toolbar = new EditToolbar(mockScope, mockOpenMCT, testStructure);
|
||||
});
|
||||
|
||||
it("adds click functions when a method is specified", function () {
|
||||
var structure = toolbar.getStructure();
|
||||
expect(structure[6].click).toBeDefined();
|
||||
});
|
||||
|
||||
it("adds key for controls that define a property", function () {
|
||||
var structure = toolbar.getStructure();
|
||||
expect(structure[0].key).toEqual(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -21,10 +21,24 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
"../layout/res/templates/fixed.html",
|
||||
'legacyRegistry'
|
||||
"./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
|
||||
) {
|
||||
|
||||
@ -39,10 +53,46 @@ define([
|
||||
"cssClass": "icon-box-with-dashed-lines",
|
||||
"type": "telemetry.fixed",
|
||||
"template": fixedTemplate,
|
||||
"uses": [],
|
||||
"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",
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@ -1,356 +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/LayoutController",
|
||||
"./src/FixedController",
|
||||
"./src/LayoutCompositionPolicy",
|
||||
'./src/MCTTriggerModal',
|
||||
"./res/templates/layout.html",
|
||||
"./res/templates/fixed.html",
|
||||
"./res/templates/frame.html",
|
||||
"./res/templates/elements/telemetry.html",
|
||||
"./res/templates/elements/box.html",
|
||||
"./res/templates/elements/line.html",
|
||||
"./res/templates/elements/text.html",
|
||||
"./res/templates/elements/image.html",
|
||||
'legacyRegistry'
|
||||
], function (
|
||||
LayoutController,
|
||||
FixedController,
|
||||
LayoutCompositionPolicy,
|
||||
MCTTriggerModal,
|
||||
layoutTemplate,
|
||||
fixedTemplate,
|
||||
frameTemplate,
|
||||
telemetryTemplate,
|
||||
boxTemplate,
|
||||
lineTemplate,
|
||||
textTemplate,
|
||||
imageTemplate,
|
||||
legacyRegistry
|
||||
) {
|
||||
|
||||
legacyRegistry.register("platform/features/layout", {
|
||||
"name": "Layout components.",
|
||||
"description": "Plug in adding Layout capabilities.",
|
||||
"extensions": {
|
||||
"views": [
|
||||
{
|
||||
"key": "layout",
|
||||
"name": "Display Layout",
|
||||
"cssClass": "icon-layout",
|
||||
"type": "layout",
|
||||
"template": layoutTemplate,
|
||||
"editable": true,
|
||||
"uses": []
|
||||
},
|
||||
{
|
||||
"key": "fixed",
|
||||
"name": "Fixed Position",
|
||||
"cssClass": "icon-box-with-dashed-lines",
|
||||
"type": "telemetry.panel",
|
||||
"template": fixedTemplate,
|
||||
"uses": [
|
||||
"composition"
|
||||
],
|
||||
"toolbar": {
|
||||
"sections": [
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"method": "add",
|
||||
"cssClass": "icon-plus",
|
||||
"control": "menu-button",
|
||||
"text": "Add",
|
||||
"title": "Add",
|
||||
"description": "Add new items",
|
||||
"options": [
|
||||
{
|
||||
"name": "Box",
|
||||
"cssClass": "icon-box",
|
||||
"key": "fixed.box"
|
||||
},
|
||||
{
|
||||
"name": "Line",
|
||||
"cssClass": "icon-line-horz",
|
||||
"key": "fixed.line"
|
||||
},
|
||||
{
|
||||
"name": "Text",
|
||||
"cssClass": "icon-T",
|
||||
"key": "fixed.text"
|
||||
},
|
||||
{
|
||||
"name": "Image",
|
||||
"cssClass": "icon-image",
|
||||
"key": "fixed.image"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"method": "order",
|
||||
"cssClass": "icon-layers",
|
||||
"control": "menu-button",
|
||||
"title": "Layering",
|
||||
"description": "Move the selected object above or below other objects",
|
||||
"options": [
|
||||
{
|
||||
"name": "Move to Top",
|
||||
"cssClass": "icon-arrow-double-up",
|
||||
"key": "top"
|
||||
},
|
||||
{
|
||||
"name": "Move Up",
|
||||
"cssClass": "icon-arrow-up",
|
||||
"key": "up"
|
||||
},
|
||||
{
|
||||
"name": "Move Down",
|
||||
"cssClass": "icon-arrow-down",
|
||||
"key": "down"
|
||||
},
|
||||
{
|
||||
"name": "Move to Bottom",
|
||||
"cssClass": "icon-arrow-double-down",
|
||||
"key": "bottom"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"property": "fill",
|
||||
"cssClass": "icon-paint-bucket",
|
||||
"title": "Fill color",
|
||||
"description": "Set fill color",
|
||||
"control": "color"
|
||||
},
|
||||
{
|
||||
"property": "stroke",
|
||||
"cssClass": "icon-line-horz",
|
||||
"title": "Border color",
|
||||
"description": "Set border color",
|
||||
"control": "color"
|
||||
},
|
||||
{
|
||||
"property": "color",
|
||||
"cssClass": "icon-T",
|
||||
"title": "Text color",
|
||||
"description": "Set text color",
|
||||
"mandatory": true,
|
||||
"control": "color"
|
||||
},
|
||||
{
|
||||
"property": "url",
|
||||
"cssClass": "icon-image",
|
||||
"control": "dialog-button",
|
||||
"title": "Image Properties",
|
||||
"description": "Edit image properties",
|
||||
"dialog": {
|
||||
"control": "textfield",
|
||||
"name": "Image URL",
|
||||
"cssClass": "l-input-lg",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "text",
|
||||
"cssClass": "icon-gear",
|
||||
"control": "dialog-button",
|
||||
"title": "Text Properties",
|
||||
"description": "Edit text properties",
|
||||
"dialog": {
|
||||
"control": "textfield",
|
||||
"name": "Text",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "showTitle",
|
||||
"cssClass": "icon-two-parts-both",
|
||||
"control": "button",
|
||||
"title": "Show title",
|
||||
"description": "Show telemetry element title"
|
||||
},
|
||||
{
|
||||
"method": "hideTitle",
|
||||
"cssClass": "icon-two-parts-one-only",
|
||||
"control": "button",
|
||||
"title": "Hide title",
|
||||
"description": "Hide telemetry element title"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"method": "remove",
|
||||
"control": "button",
|
||||
"cssClass": "icon-trash",
|
||||
"title": "Delete",
|
||||
"description": "Delete the selected item"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"representations": [
|
||||
{
|
||||
"key": "frame",
|
||||
"template": frameTemplate
|
||||
}
|
||||
],
|
||||
"directives": [
|
||||
{
|
||||
"key": "mctTriggerModal",
|
||||
"implementation": MCTTriggerModal,
|
||||
"depends": [
|
||||
"$document"
|
||||
]
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "LayoutController",
|
||||
"implementation": LayoutController,
|
||||
"depends": [
|
||||
"$scope",
|
||||
"$element",
|
||||
"openmct"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "FixedController",
|
||||
"implementation": FixedController,
|
||||
"depends": [
|
||||
"$scope",
|
||||
"$q",
|
||||
"dialogService",
|
||||
"openmct",
|
||||
"$element"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
],
|
||||
"policies": [
|
||||
{
|
||||
"category": "composition",
|
||||
"implementation": LayoutCompositionPolicy
|
||||
}
|
||||
],
|
||||
"toolbars": [
|
||||
{
|
||||
name: "Display Layout Toolbar",
|
||||
key: "layout",
|
||||
description: "A toolbar for objects inside a display layout.",
|
||||
forSelection: function (selection) {
|
||||
// Apply the layout toolbar if the selected object is inside a layout.
|
||||
return (selection && selection[1] && selection[1].context.item.type === 'layout');
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
return [
|
||||
{
|
||||
control: "checkbox",
|
||||
name: "Show frame",
|
||||
domainObject: selection[1].context.item,
|
||||
property: "configuration.layout.panels[" + selection[0].context.oldItem.id + "].hasFrame"
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"key": "layout",
|
||||
"name": "Display Layout",
|
||||
"cssClass": "icon-layout",
|
||||
"description": "Assemble other objects and components together into a reusable screen layout. Working in a simple canvas workspace, simply drag in the objects you want, position and size them. Save your design and view or edit it at any time.",
|
||||
"priority": 900,
|
||||
"features": "creation",
|
||||
"model": {
|
||||
"composition": [],
|
||||
configuration: {
|
||||
layout: {
|
||||
panels: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "Layout Grid",
|
||||
"control": "composite",
|
||||
"pattern": "^(\\d*[1-9]\\d*)?$",
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"key": "layoutGrid",
|
||||
"conversion": "number[]"
|
||||
},
|
||||
{
|
||||
"name": "Advanced",
|
||||
"control": "textfield",
|
||||
"key": "layoutAdvancedCss",
|
||||
"cssClass": "l-input-lg"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
@ -22,7 +22,6 @@
|
||||
|
||||
define([
|
||||
"./src/MCTForm",
|
||||
"./src/MCTToolbar",
|
||||
"./src/MCTControl",
|
||||
"./src/MCTFileInput",
|
||||
"./src/FileInputService",
|
||||
@ -48,7 +47,6 @@ define([
|
||||
'legacyRegistry'
|
||||
], function (
|
||||
MCTForm,
|
||||
MCTToolbar,
|
||||
MCTControl,
|
||||
MCTFileInput,
|
||||
FileInputService,
|
||||
@ -83,10 +81,6 @@ define([
|
||||
"key": "mctForm",
|
||||
"implementation": MCTForm
|
||||
},
|
||||
{
|
||||
"key": "mctToolbar",
|
||||
"implementation": MCTToolbar
|
||||
},
|
||||
{
|
||||
"key": "mctControl",
|
||||
"implementation": MCTControl,
|
||||
|
@ -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.
|
||||
-->
|
||||
<form novalidate>
|
||||
<div class="tool-bar btn-bar contents abs">
|
||||
<span ng-repeat="item in structure">
|
||||
<span ng-if="item.control === 'divider'" class="l-control-group">
|
||||
</span>
|
||||
<ng-form ng-class="{ 'input-labeled': item.name }"
|
||||
ng-hide="item.hidden"
|
||||
ng-if="item.control !== 'divider'"
|
||||
class="inline"
|
||||
title="{{item.description}}"
|
||||
name="mctFormInner">
|
||||
|
||||
<label ng-if="item.name">
|
||||
{{item.name}}:
|
||||
</label>
|
||||
<mct-control key="item.control"
|
||||
ng-class="{ disabled: item.disabled }"
|
||||
ng-model="ngModel"
|
||||
ng-required="item.required"
|
||||
ng-pattern="getRegExp(item.pattern)"
|
||||
options="item.options"
|
||||
structure="item"
|
||||
field="item.key">
|
||||
</mct-control>
|
||||
</ng-form>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
@ -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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Module defining MCTForm. Created by vwoeltje on 11/10/14.
|
||||
*/
|
||||
define(
|
||||
[
|
||||
"./MCTForm",
|
||||
"../res/templates/toolbar.html",
|
||||
"./controllers/ToolbarController"
|
||||
],
|
||||
function (
|
||||
MCTForm,
|
||||
toolbarTemplate,
|
||||
ToolbarController
|
||||
) {
|
||||
|
||||
/**
|
||||
* The mct-toolbar directive allows generation of displayable
|
||||
* forms based on a declarative description of the form's
|
||||
* structure.
|
||||
*
|
||||
* This directive accepts three attributes:
|
||||
*
|
||||
* * `ng-model`: The model for the form; where user input
|
||||
* will be stored.
|
||||
* * `structure`: The declarative structure of the toolbar.
|
||||
* Describes what controls should be shown and where
|
||||
* their values should be read/written in the model.
|
||||
* * `name`: The name under which to expose the form's
|
||||
* dirty/valid state. This is similar to ng-form's use
|
||||
* of name, except this will be made available in the
|
||||
* parent scope.
|
||||
*
|
||||
* @memberof platform/forms
|
||||
* @constructor
|
||||
*/
|
||||
function MCTToolbar() {
|
||||
// Use Directive Definition Object from mct-form,
|
||||
// but use the toolbar's template and controller instead.
|
||||
var ddo = new MCTForm();
|
||||
ddo.template = toolbarTemplate;
|
||||
ddo.controller = ['$scope', 'openmct', ToolbarController];
|
||||
return ddo;
|
||||
}
|
||||
|
||||
return MCTToolbar;
|
||||
}
|
||||
);
|
@ -1,84 +0,0 @@
|
||||
define(
|
||||
[
|
||||
'../../../commonUI/edit/src/representers/EditToolbar'
|
||||
],
|
||||
function (EditToolbar) {
|
||||
|
||||
// Default ng-pattern; any non whitespace
|
||||
var NON_WHITESPACE = /\S/;
|
||||
|
||||
/**
|
||||
* Controller for mct-toolbar directive.
|
||||
*
|
||||
* @memberof platform/forms
|
||||
* @constructor
|
||||
*/
|
||||
function ToolbarController($scope, openmct) {
|
||||
var regexps = [];
|
||||
|
||||
// ng-pattern seems to want a RegExp, and not a
|
||||
// string (despite what documentation says) but
|
||||
// we want toolbar structure to be JSON-expressible,
|
||||
// so we make RegExp's from strings as-needed
|
||||
function getRegExp(pattern) {
|
||||
// If undefined, don't apply a pattern
|
||||
if (!pattern) {
|
||||
return NON_WHITESPACE;
|
||||
}
|
||||
|
||||
// Just echo if it's already a regexp
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
// Otherwise, assume a string
|
||||
// Cache for easy lookup later (so we don't
|
||||
// creat a new RegExp every digest cycle)
|
||||
if (!regexps[pattern]) {
|
||||
regexps[pattern] = new RegExp(pattern);
|
||||
}
|
||||
|
||||
return regexps[pattern];
|
||||
}
|
||||
|
||||
this.openmct = openmct;
|
||||
this.$scope = $scope;
|
||||
$scope.editToolbar = {};
|
||||
$scope.getRegExp = getRegExp;
|
||||
|
||||
$scope.$on("$destroy", this.destroy.bind(this));
|
||||
openmct.selection.on('change', this.handleSelection.bind(this));
|
||||
}
|
||||
|
||||
ToolbarController.prototype.handleSelection = function (selection) {
|
||||
var domainObject = selection[0].context.oldItem;
|
||||
var element = selection[0].context.elementProxy;
|
||||
|
||||
if ((domainObject && domainObject === this.selectedObject) || (element && element === this.selectedObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedObject = domainObject || element;
|
||||
|
||||
if (this.editToolbar) {
|
||||
this.editToolbar.destroy();
|
||||
}
|
||||
|
||||
var structure = this.openmct.toolbars.get(selection) || [];
|
||||
this.editToolbar = new EditToolbar(this.$scope, this.openmct, structure);
|
||||
this.$scope.$parent.editToolbar = this.editToolbar;
|
||||
this.$scope.$parent.editToolbar.structure = this.editToolbar.getStructure();
|
||||
this.$scope.$parent.editToolbar.state = this.editToolbar.getState();
|
||||
|
||||
setTimeout(function () {
|
||||
this.$scope.$apply();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ToolbarController.prototype.destroy = function () {
|
||||
this.openmct.selection.off("change", this.handleSelection);
|
||||
};
|
||||
|
||||
return ToolbarController;
|
||||
}
|
||||
);
|
@ -1,112 +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/MCTToolbar"],
|
||||
function (MCTToolbar) {
|
||||
|
||||
describe("The mct-toolbar directive", function () {
|
||||
var mockScope,
|
||||
mockOpenMCT,
|
||||
mockSelection,
|
||||
mctToolbar;
|
||||
|
||||
function installController() {
|
||||
var Controller = mctToolbar.controller[2];
|
||||
return new Controller(mockScope, mockOpenMCT);
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj("$scope", [
|
||||
"$watch",
|
||||
"$on"
|
||||
]);
|
||||
mockScope.$parent = {};
|
||||
mockSelection = jasmine.createSpyObj("selection", [
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
mockOpenMCT = {
|
||||
selection: mockSelection
|
||||
};
|
||||
mctToolbar = new MCTToolbar();
|
||||
});
|
||||
|
||||
it("is restricted to elements", function () {
|
||||
expect(mctToolbar.restrict).toEqual("E");
|
||||
});
|
||||
|
||||
it("listens for selection change event", function () {
|
||||
installController();
|
||||
|
||||
expect(mockOpenMCT.selection.on).toHaveBeenCalledWith(
|
||||
"change",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it("allows strings to be converted to RegExps", function () {
|
||||
// This is needed to support ng-pattern in the template
|
||||
installController();
|
||||
|
||||
// Should have added getRegExp to the scope,
|
||||
// to convert strings to regular expressions
|
||||
expect(mockScope.getRegExp("^\\d+$")).toEqual(/^\d+$/);
|
||||
});
|
||||
|
||||
it("returns the same regexp instance for the same string", function () {
|
||||
// Don't want new instances each digest cycle, for performance
|
||||
var strRegExp = "^[a-z]\\d+$",
|
||||
regExp;
|
||||
|
||||
// Add getRegExp to scope
|
||||
installController();
|
||||
regExp = mockScope.getRegExp(strRegExp);
|
||||
|
||||
// Same object instance each time...
|
||||
expect(mockScope.getRegExp(strRegExp)).toBe(regExp);
|
||||
expect(mockScope.getRegExp(strRegExp)).toBe(regExp);
|
||||
});
|
||||
|
||||
it("passes RegExp objects through untouched", function () {
|
||||
// Permit using forms to simply provide their own RegExp object
|
||||
var regExp = /^\d+[a-d]$/;
|
||||
|
||||
// Add getRegExp to scope
|
||||
installController();
|
||||
|
||||
// Should have added getRegExp to the scope,
|
||||
// to convert strings to regular expressions
|
||||
expect(mockScope.getRegExp(regExp)).toBe(regExp);
|
||||
});
|
||||
|
||||
it("passes a non-whitespace regexp when no pattern is defined", function () {
|
||||
// If no pattern is supplied, ng-pattern should match anything
|
||||
installController();
|
||||
expect(mockScope.getRegExp()).toEqual(/\S/);
|
||||
expect(mockScope.getRegExp(undefined)).toEqual(/\S/);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -91,8 +91,8 @@
|
||||
background: rgba($editColor, 0.1);
|
||||
}
|
||||
|
||||
.s-selected,
|
||||
.s-selected-parent {
|
||||
[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.
|
||||
@ -128,7 +128,6 @@
|
||||
frames: [],
|
||||
frameStyles: [],
|
||||
rawPositions: {},
|
||||
initSelect: true,
|
||||
drilledIn: undefined
|
||||
}
|
||||
},
|
||||
@ -141,6 +140,7 @@
|
||||
this.newDomainObject = this.domainObject;
|
||||
this.gridSize = this.newDomainObject.layoutGrid || DEFAULT_GRID_SIZE;
|
||||
this.composition = this.openmct.composition.get(this.newDomainObject);
|
||||
this.Listeners = [];
|
||||
let panels = (((this.newDomainObject.configuration || {}).layout || {}).panels || {});
|
||||
|
||||
if (this.composition !== undefined) {
|
||||
@ -237,8 +237,32 @@
|
||||
return;
|
||||
}
|
||||
|
||||
let domainObject = selection[0].context.item;
|
||||
if (domainObject && domainObject === this.selectedObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedObject = domainObject;
|
||||
this.removeListeners();
|
||||
|
||||
if (selection[1]) {
|
||||
this.attachSelectionListeners();
|
||||
}
|
||||
|
||||
this.updateDrilledInState();
|
||||
},
|
||||
attachSelectionListeners() {
|
||||
let id = this.openmct.objects.makeKeyString(this.selectedObject.identifier);
|
||||
let path = "configuration.layout.panels[" + id + "]";
|
||||
this.listeners.push(this.openmct.objects.observe(this.newDomainObject, path + ".hasFrame", function (newValue) {
|
||||
this.frameItems.forEach(function (item) {
|
||||
if (item.id === id) {
|
||||
item.hasFrame = newValue;
|
||||
}
|
||||
});
|
||||
this.frames[id] = newValue;
|
||||
}.bind(this)));
|
||||
},
|
||||
updateDrilledInState(id) {
|
||||
this.drilledIn = id;
|
||||
this.frameItems.forEach(function (item) {
|
||||
@ -282,6 +306,7 @@
|
||||
},
|
||||
handleDrop($event) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
|
||||
let child = JSON.parse($event.dataTransfer.getData('domainObject'));
|
||||
let duplicates = [];
|
||||
@ -311,6 +336,14 @@
|
||||
},
|
||||
handleDragOver($event){
|
||||
$event.preventDefault();
|
||||
},
|
||||
removeListeners() {
|
||||
if (this.listeners) {
|
||||
this.listeners.forEach(function (l) {
|
||||
l();
|
||||
})
|
||||
}
|
||||
this.listeners = [];
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -321,6 +354,7 @@
|
||||
this.composition.off('remove', this.onRemoveComposition);
|
||||
this.openmct.off('change', this.selection);
|
||||
this.unlisten();
|
||||
this.removeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.s-selected, // LEGACY
|
||||
&[s-selected], // LEGACY
|
||||
&.is-selected {
|
||||
border: $browseBorderSelected;
|
||||
}
|
||||
@ -155,7 +155,7 @@
|
||||
border: $editBorderSelectableHov;
|
||||
}
|
||||
|
||||
&.s-selected,
|
||||
&[s-selected],
|
||||
&.is-selected {
|
||||
border: $editBorderSelected;
|
||||
|
||||
|
@ -63,5 +63,40 @@ export default function () {
|
||||
}
|
||||
});
|
||||
openmct.types.addType('layout', DisplayLayoutType());
|
||||
openmct.toolbars.addProvider({
|
||||
name: "Display Layout Toolbar",
|
||||
key: "layout",
|
||||
description: "A toolbar for objects inside a display layout.",
|
||||
forSelection: function (selection) {
|
||||
// Apply the layout toolbar if the selected object is inside a layout,
|
||||
// and in edit mode.
|
||||
return (selection &&
|
||||
selection[1] &&
|
||||
selection[1].context.item.type === 'layout' &&
|
||||
openmct.editor.isEditing());
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
let id = openmct.objects.makeKeyString(selection[0].context.item.identifier);
|
||||
return [
|
||||
{
|
||||
control: "toggle-button",
|
||||
domainObject: selection[1].context.item,
|
||||
property: "configuration.layout.panels[" + id + "].hasFrame",
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Hide frame"
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-frame-show',
|
||||
title: "Show frame"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,19 +55,19 @@ define(['EventEmitter'], function (EventEmitter) {
|
||||
}
|
||||
|
||||
if (this.selected[0] && this.selected[0].element) {
|
||||
this.selected[0].element.classList.remove('s-selected');
|
||||
this.selected[0].element.removeAttribute('s-selected');
|
||||
}
|
||||
|
||||
if (this.selected[1] && this.selected[1].element) {
|
||||
this.selected[1].element.classList.remove('s-selected-parent');
|
||||
this.selected[1].element.removeAttribute('s-selected-parent');
|
||||
}
|
||||
|
||||
if (selectable[0] && selectable[0].element) {
|
||||
selectable[0].element.classList.add('s-selected');
|
||||
selectable[0].element.setAttribute('s-selected', "");
|
||||
}
|
||||
|
||||
if (selectable[1] && selectable[1].element) {
|
||||
selectable[1].element.classList.add('s-selected-parent');
|
||||
selectable[1].element.setAttribute('s-selected-parent', "");
|
||||
}
|
||||
|
||||
this.selected = selectable;
|
||||
|
@ -50,7 +50,12 @@ button {
|
||||
.c-click-icon {
|
||||
@include cClickIcon();
|
||||
|
||||
.c-click-icon__label {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
|
||||
&--menu {
|
||||
|
||||
&:after {
|
||||
content: $glyph-icon-arrow-down;
|
||||
font-family: symbolsfont;
|
||||
|
@ -85,15 +85,15 @@
|
||||
}
|
||||
|
||||
// Display grid when selected or selection parent.
|
||||
.s-selected .l-grid-holder,
|
||||
.s-selected-parent .l-grid-holder {
|
||||
[s-selected] .l-grid-holder,
|
||||
[s-selected-parent] .l-grid-holder {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Display in nested frames...
|
||||
.t-frame-outer {
|
||||
// ...when drilled in or selection parent...
|
||||
&.s-drilled-in, &.s-selected-parent {
|
||||
&.s-drilled-in, &[s-selected-parent] {
|
||||
.l-grid-holder {
|
||||
display: block;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ body.desktop {
|
||||
border-style: dashed !important;
|
||||
}
|
||||
}
|
||||
.s-selected {
|
||||
[s-selected] {
|
||||
> .s-hover-border,
|
||||
&.s-hover-border {
|
||||
// Styles for a selected object. Also used by legacy Fixed Position/Panel objects.
|
||||
@ -71,8 +71,8 @@ body.desktop {
|
||||
}
|
||||
}
|
||||
|
||||
.s-selected > .s-hover-border,
|
||||
.s-selected.s-hover-border {
|
||||
[s-selected] > .s-hover-border,
|
||||
[s-selected].s-hover-border {
|
||||
border-color: $colorSelectableSelectedPrimary !important;
|
||||
//z-index: 1; // Bring selected item from beneath others. BUT, this breaks editing in Fixed Position.
|
||||
}
|
||||
|
@ -1,168 +0,0 @@
|
||||
<template>
|
||||
<div class="c-custom-checkbox">
|
||||
<input type="checkbox"
|
||||
:id="id"
|
||||
:name="name"
|
||||
:value="value"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@change="onChange"
|
||||
:checked="state">
|
||||
<label :for="id">
|
||||
<div class="c-custom-checkbox__box"></div>
|
||||
<div class="c-custom-checkbox__label-text">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
.c-custom-checkbox {
|
||||
$d: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
label {
|
||||
@include userSelectNone();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__box {
|
||||
@include nice-input();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: $d;
|
||||
width: $d;
|
||||
height: $d;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
|
||||
input {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
|
||||
&:checked + label > .c-custom-checkbox__box {
|
||||
background: $colorKey;
|
||||
&:before {
|
||||
color: $colorKeyFg;
|
||||
content: $glyph-icon-check;
|
||||
font-family: symbolsfont;
|
||||
font-size: 0.6em;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:disabled) + label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:disabled + label {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
/*
|
||||
Custom checkbox control. Use just like a checkbox in HTML, except label string is passed within tag.
|
||||
Supports value, true-value, false-value, checked and disabled attributes.
|
||||
Example usage:
|
||||
<checkbox checked>Enable markers</checkbox>
|
||||
*/
|
||||
export default {
|
||||
model: {
|
||||
prop: 'modelValue',
|
||||
event: 'input'
|
||||
},
|
||||
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return 'checkbox-id-' + this._uid;
|
||||
},
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
value: {
|
||||
default: null,
|
||||
},
|
||||
modelValue: {
|
||||
default: undefined,
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
model: {}
|
||||
},
|
||||
|
||||
computed: {
|
||||
state() {
|
||||
if (this.modelValue === undefined) {
|
||||
return this.checked;
|
||||
}
|
||||
|
||||
if (Array.isArray(this.modelValue)) {
|
||||
return this.modelValue.indexOf(this.value) > -1;
|
||||
}
|
||||
|
||||
return !!this.modelValue;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange() {
|
||||
this.toggle();
|
||||
},
|
||||
|
||||
toggle() {
|
||||
let value;
|
||||
|
||||
if (Array.isArray(this.modelValue)) {
|
||||
value = this.modelValue.slice(0);
|
||||
|
||||
if (this.state) {
|
||||
value.splice(value.indexOf(this.value), 1);
|
||||
} else {
|
||||
value.push(this.value);
|
||||
}
|
||||
} else {
|
||||
value = !this.state;
|
||||
}
|
||||
|
||||
this.$emit('input', value);
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
checked(newValue) {
|
||||
if (newValue !== this.state) {
|
||||
this.toggle();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.checked && !this.state) {
|
||||
this.toggle();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -1,51 +0,0 @@
|
||||
<template>
|
||||
<div class="c-labeled-input"
|
||||
:title="title">
|
||||
<div class="c-labeled-input__label">{{ label }}</div>
|
||||
<input type="number"
|
||||
v-bind="$attrs"
|
||||
v-bind:value="value"
|
||||
v-on="inputListeners"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* Emits input and clear events */
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: String,
|
||||
label: String,
|
||||
title: String
|
||||
},
|
||||
computed: {
|
||||
inputListeners: function () {
|
||||
let vm = this;
|
||||
return Object.assign({},
|
||||
this.$listeners,
|
||||
{
|
||||
input: function (event) {
|
||||
vm.$emit('input', event.target.value);
|
||||
},
|
||||
change: function (event) {
|
||||
vm.$emit('change', event.target.value);
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
// active: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearInput() {
|
||||
// Clear the user's input and set 'active' to false
|
||||
this.value = '';
|
||||
this.$emit('clear','');
|
||||
this.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,176 +0,0 @@
|
||||
<template>
|
||||
<div class="c-togglebutton">
|
||||
<input type="checkbox"
|
||||
:id="id"
|
||||
:name="name"
|
||||
:value="value"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@change="onChange"
|
||||
:checked="state">
|
||||
<label :for="id">
|
||||
<div class="c-togglebutton__on"
|
||||
:class="innerClassOn"></div>
|
||||
<div class="c-togglebutton__off"
|
||||
:class="innerClassOff"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
.c-togglebutton {
|
||||
$d: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.c-togglebutton__on {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
|
||||
&:checked + label {
|
||||
.c-togglebutton__on {
|
||||
display: block;
|
||||
}
|
||||
.c-togglebutton__off {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:disabled) + label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:disabled + label {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
/*
|
||||
Toggle button control, based on checkboxCustom. Use just like a checkbox in HTML.
|
||||
Requires inner-class-on and -off attributes to be passed.
|
||||
Supports checked and disabled attributes.
|
||||
Example usage:
|
||||
<toggle-button checked
|
||||
class="c-click-icon"
|
||||
inner-class-on="icon-grid-snap-to"
|
||||
inner-class-off="icon-grid-snap-no"></toggle-button>
|
||||
*/
|
||||
export default {
|
||||
model: {
|
||||
prop: 'modelValue',
|
||||
event: 'input'
|
||||
},
|
||||
|
||||
props: {
|
||||
innerClassOn: {
|
||||
type: String,
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
innerClassOff: {
|
||||
type: String,
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return 'checkbox-id-' + this._uid;
|
||||
},
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
value: {
|
||||
default: null,
|
||||
},
|
||||
modelValue: {
|
||||
default: undefined,
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
model: {}
|
||||
},
|
||||
|
||||
computed: {
|
||||
state() {
|
||||
if (this.modelValue === undefined) {
|
||||
return this.checked;
|
||||
}
|
||||
|
||||
if (Array.isArray(this.modelValue)) {
|
||||
return this.modelValue.indexOf(this.value) > -1;
|
||||
}
|
||||
return !!this.modelValue;
|
||||
},
|
||||
stateClass() {
|
||||
return this.onClass;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange() {
|
||||
this.toggle();
|
||||
},
|
||||
|
||||
toggle() {
|
||||
let value;
|
||||
|
||||
if (Array.isArray(this.modelValue)) {
|
||||
value = this.modelValue.slice(0);
|
||||
|
||||
if (this.state) {
|
||||
value.splice(value.indexOf(this.value), 1);
|
||||
} else {
|
||||
value.push(this.value);
|
||||
}
|
||||
} else {
|
||||
value = !this.state;
|
||||
}
|
||||
|
||||
this.$emit('input', value);
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
checked(newValue) {
|
||||
if (newValue !== this.state) {
|
||||
this.toggle();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.checked && !this.state) {
|
||||
this.toggle();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
@ -246,7 +246,7 @@
|
||||
import pane from '../controls/pane.vue';
|
||||
import BrowseBar from './BrowseBar.vue';
|
||||
import StatusBar from './status-bar/StatusBar.vue';
|
||||
import Toolbar from './Toolbar.vue';
|
||||
import Toolbar from '../toolbar/Toolbar.vue';
|
||||
|
||||
var enterFullScreen = () => {
|
||||
var docElm = document.documentElement;
|
||||
|
@ -1,291 +0,0 @@
|
||||
<template>
|
||||
<div class="c-toolbar">
|
||||
<!-- VERSION MANUALLY RESTORED FROM VUE-LAYOUT -->
|
||||
<div class="c-button-set">
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-button--menu js-add-button icon-plus"
|
||||
@click="toggleMenus">
|
||||
<div class="c-button__label">Add</div>
|
||||
</div>
|
||||
<div class="c-menu" v-if="showMenus">
|
||||
<ul>
|
||||
<li v-for="item in addMenuItems"
|
||||
:class="item.class"
|
||||
:title="item.title">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected">
|
||||
<div class="c-ctrl-wrapper"
|
||||
v-if="toolsItemSelected">
|
||||
<div class="c-click-icon c-click-icon--menu js-layers icon-layers"
|
||||
@click="toggleMenus"></div>
|
||||
<div class="c-menu" v-if="showMenus">
|
||||
<ul>
|
||||
<li v-for="item in layersMenuItems"
|
||||
:class="item.class"
|
||||
:title="item.title">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="c-ctrl-wrapper"
|
||||
v-if="toolsColorFill">
|
||||
<div class="c-click-icon c-click-icon--swatched js-color-fill icon-paint-bucket"
|
||||
@click="toggleMenus">
|
||||
<div class="c-swatch" style="background: #33ff00;"></div>
|
||||
</div>
|
||||
<div class="c-menu c-palette c-palette--color"
|
||||
v-if="showMenus">
|
||||
<div class="c-palette__item-none"
|
||||
vif="this.palette.itemNone === true">
|
||||
<div class="c-palette__item"
|
||||
@click="this.setColor('no-color')"></div>
|
||||
No fill
|
||||
</div>
|
||||
<div class="c-palette__items">
|
||||
<div class="c-palette__item"
|
||||
v-for="color in colorPalette"
|
||||
:style="{ background: color.value }"
|
||||
@click="this.setColor(color.value)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="c-ctrl-wrapper"
|
||||
v-if="toolsColorStroke">
|
||||
<div class="c-click-icon c-click-icon--swatched js-color-stroke icon-pencil">
|
||||
<div class="c-toolbar-button__swatch" style="background: #ffffff;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="c-ctrl-wrapper"
|
||||
v-if="toolsColorText">
|
||||
<div class="c-click-icon c-click-icon--swatched js-color-text icon-font">
|
||||
<div class="c-toolbar-button__swatch" style="background: #333333;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected && toolsFontSize">
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon c-click-icon--menu js-font-size"
|
||||
@click="toggleMenus">
|
||||
<div class="c-button__label">11 px</div>
|
||||
</div>
|
||||
<div class="c-menu" v-if="showMenus">
|
||||
<ul>
|
||||
<li v-for="item in fontSizeMenuItems">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected && toolsEditProperties">
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon js-image icon-gear"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected">
|
||||
<labeledNumberInput label="X" value=1 title="X position"></labeledNumberInput>
|
||||
<labeledNumberInput label="Y" value=2 title="Y position"></labeledNumberInput>
|
||||
<labeledNumberInput label="W" value=3 title="Width"></labeledNumberInput>
|
||||
<labeledNumberInput label="H" value=4 title="Height"></labeledNumberInput>
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected">
|
||||
<div class="c-click-icon c-click-icon--caution icon-trash"></div>
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected">
|
||||
<checkbox checked title="This is a checkbox">Checkbox</checkbox>
|
||||
</div>
|
||||
|
||||
<div class="c-button-set"
|
||||
v-if="toolsItemSelected">
|
||||
<toggle-button title="Toggle frame" checked
|
||||
class="c-click-icon"
|
||||
inner-class-on="icon-frame-show"
|
||||
inner-class-off="icon-frame-hide"></toggle-button>
|
||||
<toggle-button title="Snap to grid" checked
|
||||
class="c-click-icon"
|
||||
inner-class-on="icon-grid-snap-to"
|
||||
inner-class-off="icon-grid-snap-no"></toggle-button>
|
||||
<toggle-button title="Show label and value" checked
|
||||
class="c-click-icon"
|
||||
inner-class-on="icon-two-parts-both"
|
||||
inner-class-off="icon-two-parts-one-only"></toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import labeledNumberInput from '../controls/labeledNumberInput.vue';
|
||||
import checkbox from '../controls/checkboxCustom.vue';
|
||||
import toggleButton from '../controls/toggleButton.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
labeledNumberInput,
|
||||
checkbox,
|
||||
toggleButton
|
||||
},
|
||||
methods: {
|
||||
toggleMenus: function () {
|
||||
this.showMenus = !this.showMenus;
|
||||
}
|
||||
},
|
||||
props: {
|
||||
toolsItemSelected: { type: Boolean, default: true },
|
||||
toolsColorFill: { type: Boolean, default: true },
|
||||
toolsColorStroke: { type: Boolean, default: true },
|
||||
toolsColorText: { type: Boolean, default: true },
|
||||
toolsFontSize: { type: Boolean, default: true },
|
||||
toolsEditProperties: { type: Boolean, default: true },
|
||||
toolSetBox: ['toolsColorFill', 'toolsColorStroke'],
|
||||
toolSetLine: ['toolsColorStroke'],
|
||||
toolSetText: ['toolsColorFill', 'toolsColorStroke', 'toolsColorText', 'toolsFontSize', 'toolsEditProperties'],
|
||||
toolSetImage: ['toolsColorStroke', 'toolsEditProperties'],
|
||||
toolSetTelemetry: ['toolsColorFill', 'toolsColorStroke', 'toolsColorText', 'toolsFontSize', 'toolsLabelValue']
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
showMenus: false,
|
||||
addMenuItems: [
|
||||
{ name: 'Box', class: 'icon-box', title: 'Add Box' },
|
||||
{ name: 'Line', class: 'icon-line-horz', title: 'Add Line' },
|
||||
{ name: 'Text', class: 'icon-font', title: 'Add Text' },
|
||||
{ name: 'Image', class: 'icon-image', title: 'Add Image' }
|
||||
],
|
||||
layersMenuItems: [
|
||||
{ name: 'Move to top', class: 'icon-arrow-double-up', title: 'Move to top' },
|
||||
{ name: 'Move up', class: 'icon-arrow-up', title: 'Move up' },
|
||||
{ name: 'Move down', class: 'icon-arrow-down', title: 'Move down' },
|
||||
{ name: 'Move to bottom', class: 'icon-arrow-double-down', title: 'Move to bottom' }
|
||||
],
|
||||
fontSizeMenuItems: [
|
||||
{ value: '9', name: '9 px' },
|
||||
{ value: '10', name: '10 px' },
|
||||
{ value: '11', name: '11 px' },
|
||||
{ value: '12', name: '12 px' },
|
||||
{ value: '13', name: '13 px' },
|
||||
{ value: '14', name: '14 px' },
|
||||
{ value: '16', name: '16 px' },
|
||||
{ value: '18', name: '18 px' },
|
||||
{ value: '20', name: '20 px' },
|
||||
{ value: '24', name: '24 px' },
|
||||
{ value: '28', name: '28 px' },
|
||||
{ value: '32', name: '32 px' },
|
||||
{ value: '40', name: '40 px' },
|
||||
{ value: '48', name: '48 px' },
|
||||
{ value: '56', name: '56 px' },
|
||||
{ value: '64', name: '64 px' },
|
||||
{ value: '72', name: '72 px' },
|
||||
{ value: '80', name: '80 px' },
|
||||
{ value: '88', name: '88 px' },
|
||||
{ value: '96', name: '96 px' },
|
||||
{ value: '128', name: '128 px' },
|
||||
{ value: '160', name: '160 px' }
|
||||
],
|
||||
colorPalette: [
|
||||
{ value: '#000000' },
|
||||
{ value: '#434343' },
|
||||
{ value: '#666666' },
|
||||
{ value: '#999999' },
|
||||
{ value: '#b7b7b7' },
|
||||
{ value: '#cccccc' },
|
||||
{ value: '#d9d9d9' },
|
||||
{ value: '#efefef' },
|
||||
{ value: '#f3f3f3' },
|
||||
{ value: '#ffffff' },
|
||||
{ value: '#980000' },
|
||||
{ value: '#ff0000' },
|
||||
{ value: '#ff9900' },
|
||||
{ value: '#ffff00' },
|
||||
{ value: '#00ff00' },
|
||||
{ value: '#00ffff' },
|
||||
{ value: '#4a86e8' },
|
||||
{ value: '#0000ff' },
|
||||
{ value: '#9900ff' },
|
||||
{ value: '#ff00ff' },
|
||||
{ value: '#e6b8af' },
|
||||
{ value: '#f4cccc' },
|
||||
{ value: '#fce5cd' },
|
||||
{ value: '#fff2cc' },
|
||||
{ value: '#d9ead3' },
|
||||
{ value: '#d0e0e3' },
|
||||
{ value: '#c9daf8' },
|
||||
{ value: '#cfe2f3' },
|
||||
{ value: '#d9d2e9' },
|
||||
{ value: '#ead1dc' },
|
||||
{ value: '#dd7e6b' },
|
||||
{ value: '#dd7e6b' },
|
||||
{ value: '#f9cb9c' },
|
||||
{ value: '#ffe599' },
|
||||
{ value: '#b6d7a8' },
|
||||
{ value: '#a2c4c9' },
|
||||
{ value: '#a4c2f4' },
|
||||
{ value: '#9fc5e8' },
|
||||
{ value: '#b4a7d6' },
|
||||
{ value: '#d5a6bd' },
|
||||
{ value: '#cc4125' },
|
||||
{ value: '#e06666' },
|
||||
{ value: '#f6b26b' },
|
||||
{ value: '#ffd966' },
|
||||
{ value: '#93c47d' },
|
||||
{ value: '#76a5af' },
|
||||
{ value: '#6d9eeb' },
|
||||
{ value: '#6fa8dc' },
|
||||
{ value: '#8e7cc3' },
|
||||
{ value: '#c27ba0' },
|
||||
{ value: '#a61c00' },
|
||||
{ value: '#cc0000' },
|
||||
{ value: '#e69138' },
|
||||
{ value: '#f1c232' },
|
||||
{ value: '#6aa84f' },
|
||||
{ value: '#45818e' },
|
||||
{ value: '#3c78d8' },
|
||||
{ value: '#3d85c6' },
|
||||
{ value: '#674ea7' },
|
||||
{ value: '#a64d79' },
|
||||
{ value: '#85200c' },
|
||||
{ value: '#990000' },
|
||||
{ value: '#b45f06' },
|
||||
{ value: '#bf9000' },
|
||||
{ value: '#38761d' },
|
||||
{ value: '#134f5c' },
|
||||
{ value: '#1155cc' },
|
||||
{ value: '#0b5394' },
|
||||
{ value: '#351c75' },
|
||||
{ value: '#741b47' },
|
||||
{ value: '#5b0f00' },
|
||||
{ value: '#660000' },
|
||||
{ value: '#783f04' },
|
||||
{ value: '#7f6000' },
|
||||
{ value: '#274e13' },
|
||||
{ value: '#0c343d' },
|
||||
{ value: '#1c4587' },
|
||||
{ value: '#073763' },
|
||||
{ value: '#20124d' },
|
||||
{ value: '#4c1130' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
109
src/ui/components/toolbar/Toolbar.vue
Normal file
109
src/ui/components/toolbar/Toolbar.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div class="c-toolbar">
|
||||
<component v-for="item in structure"
|
||||
:is="item.control"
|
||||
:options="item"
|
||||
@change="updateObjectValue"></component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import toolbarButton from './components/toolbar-button.vue';
|
||||
import toolbarColorPicker from './components/toolbar-color-picker.vue';
|
||||
import toolbarCheckbox from './components/toolbar-checkbox.vue';
|
||||
import toolbarInput from './components/toolbar-input.vue';
|
||||
import toolbarMenu from './components/toolbar-menu.vue';
|
||||
import toolbarSelectMenu from './components/toolbar-select-menu.vue';
|
||||
import toolbarSeparator from './components/toolbar-separator.vue';
|
||||
import toolbarToggleButton from './components/toolbar-toggle-button.vue';
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'lodash'],
|
||||
components: {
|
||||
toolbarButton,
|
||||
toolbarColorPicker,
|
||||
toolbarCheckbox,
|
||||
toolbarInput,
|
||||
toolbarMenu,
|
||||
toolbarSelectMenu,
|
||||
toolbarSeparator,
|
||||
toolbarToggleButton
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
structure: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSelection(selection) {
|
||||
if (!selection[0]) {
|
||||
this.structure = [];
|
||||
this.selectedObject = undefined;
|
||||
this.removeListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
let domainObject = selection[0].context.item;
|
||||
|
||||
this.selectedObject = domainObject;
|
||||
this.removeListeners();
|
||||
|
||||
let structure = this.openmct.toolbars.get(selection) || [];
|
||||
this.structure = structure.map(function (item) {
|
||||
let toolbarItem = {...item};
|
||||
toolbarItem.control = "toolbar-" + toolbarItem.control;
|
||||
toolbarItem.value = _.get(toolbarItem.domainObject, item.property);
|
||||
this.registerListener(toolbarItem.domainObject);
|
||||
return toolbarItem;
|
||||
}.bind(this));
|
||||
},
|
||||
registerListener(domainObject) {
|
||||
let unobserveObject = this.openmct.objects.observe(domainObject, '*', function(newObject) {
|
||||
let newObjectId = this.openmct.objects.makeKeyString(newObject.identifier);
|
||||
this.structure = this.structure.map((item) => {
|
||||
let toolbarItem = {...item};
|
||||
let domainObjectId = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
|
||||
if (domainObjectId === newObjectId) {
|
||||
toolbarItem.domainObject = JSON.parse(JSON.stringify(newObject));
|
||||
}
|
||||
return toolbarItem;
|
||||
});
|
||||
}.bind(this));
|
||||
this.unObserveObjects.push(unobserveObject);
|
||||
},
|
||||
removeListeners() {
|
||||
if (this.unObserveObjects) {
|
||||
this.unObserveObjects.forEach((unObserveObject) => {
|
||||
unObserveObject();
|
||||
});
|
||||
}
|
||||
this.unObserveObjects = [];
|
||||
},
|
||||
updateObjectValue(value, item) {
|
||||
let changedId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
|
||||
this.structure = this.structure.map((s) => {
|
||||
let toolbarItem = {...s};
|
||||
if (changedId === this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier)) {
|
||||
toolbarItem.value = value;
|
||||
}
|
||||
return toolbarItem;
|
||||
});
|
||||
this.openmct.objects.mutate(item.domainObject, item.property, value);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.openmct.selection.on('change', this.handleSelection);
|
||||
this.handleSelection(this.openmct.selection.get());
|
||||
|
||||
// Toolbars may change when edit mode is enabled/disabled, so listen
|
||||
// for edit mode changes and update toolbars if necessary.
|
||||
this.openmct.editor.on('isEditing', (isEditing) => {
|
||||
this.handleSelection(this.openmct.selection.get());
|
||||
});
|
||||
},
|
||||
detroyed() {
|
||||
this.openmct.selection.off('change', this.handleSelection);
|
||||
this.removeListeners();
|
||||
}
|
||||
}
|
||||
</script>
|
22
src/ui/components/toolbar/components/toggle-mixin.js
Normal file
22
src/ui/components/toolbar/components/toggle-mixin.js
Normal file
@ -0,0 +1,22 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
open: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle(event) {
|
||||
if (this.open) {
|
||||
document.removeEventListener('click', this.toggle);
|
||||
this.open = false;
|
||||
} else {
|
||||
document.addEventListener('click', this.toggle);
|
||||
event.stopPropagation();
|
||||
this.open = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener('click', this.toggle);
|
||||
},
|
||||
}
|
29
src/ui/components/toolbar/components/toolbar-button.vue
Normal file
29
src/ui/components/toolbar/components/toolbar-button.vue
Normal file
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon"
|
||||
:class="{
|
||||
[options.icon]: true,
|
||||
'c-click-icon--caution': options.modifier === 'caution'
|
||||
}"
|
||||
@click="onClick">
|
||||
<div class="c-click-icon__label"
|
||||
v-if="options.label">
|
||||
{{ options.label }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
options: Object
|
||||
},
|
||||
methods: {
|
||||
onClick(event) {
|
||||
this.$emit('click', this.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
89
src/ui/components/toolbar/components/toolbar-checkbox.vue
Normal file
89
src/ui/components/toolbar/components/toolbar-checkbox.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="c-custom-checkbox">
|
||||
<input type="checkbox"
|
||||
:id="uid"
|
||||
:name="options.name"
|
||||
:checked="options.value"
|
||||
:disabled="options.disabled"
|
||||
@change="onChange">
|
||||
|
||||
<label :for="uid">
|
||||
<div class="c-custom-checkbox__box"></div>
|
||||
<div class="c-custom-checkbox__label-text">
|
||||
{{options.name}}
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
.c-custom-checkbox {
|
||||
$d: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
label {
|
||||
@include userSelectNone();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__box {
|
||||
@include nice-input();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: $d;
|
||||
width: $d;
|
||||
height: $d;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
|
||||
input {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
|
||||
&:checked + label > .c-custom-checkbox__box {
|
||||
background: $colorKey;
|
||||
&:before {
|
||||
color: $colorKeyFg;
|
||||
content: $glyph-icon-check;
|
||||
font-family: symbolsfont;
|
||||
font-size: 0.6em;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:disabled) + label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:disabled + label {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
let uniqueId = 100;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
options: Object
|
||||
},
|
||||
data() {
|
||||
uniqueId++;
|
||||
return {
|
||||
uid: `mct-checkbox-id-${uniqueId}`
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onChange(event) {
|
||||
this.$emit('change', event.target.checked, {...this.options});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
132
src/ui/components/toolbar/components/toolbar-color-picker.vue
Normal file
132
src/ui/components/toolbar/components/toolbar-color-picker.vue
Normal file
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon c-click-icon--swatched"
|
||||
:class="options.icon"
|
||||
@click="toggle">
|
||||
<div class="c-swatch" :style="{
|
||||
background: options.value
|
||||
}"></div>
|
||||
</div>
|
||||
<div class="c-menu c-palette c-palette--color"
|
||||
v-if="open">
|
||||
<div class="c-palette__item-none"
|
||||
v-if="!this.options.preventNone"
|
||||
@click="select({value: 'transparent'})">
|
||||
<div class="c-palette__item"></div>
|
||||
No fill
|
||||
</div>
|
||||
<div class="c-palette__items">
|
||||
<div class="c-palette__item"
|
||||
v-for="color in colorPalette"
|
||||
:style="{ background: color.value }"
|
||||
@click="select(color)"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import toggleMixin from './toggle-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [toggleMixin],
|
||||
props: {
|
||||
options: Object
|
||||
},
|
||||
methods: {
|
||||
select(color) {
|
||||
if (color.value !== this.options.value) {
|
||||
this.$emit('change', color, this.options);
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
colorPalette: [
|
||||
{ value: '#000000' },
|
||||
{ value: '#434343' },
|
||||
{ value: '#666666' },
|
||||
{ value: '#999999' },
|
||||
{ value: '#b7b7b7' },
|
||||
{ value: '#cccccc' },
|
||||
{ value: '#d9d9d9' },
|
||||
{ value: '#efefef' },
|
||||
{ value: '#f3f3f3' },
|
||||
{ value: '#ffffff' },
|
||||
{ value: '#980000' },
|
||||
{ value: '#ff0000' },
|
||||
{ value: '#ff9900' },
|
||||
{ value: '#ffff00' },
|
||||
{ value: '#00ff00' },
|
||||
{ value: '#00ffff' },
|
||||
{ value: '#4a86e8' },
|
||||
{ value: '#0000ff' },
|
||||
{ value: '#9900ff' },
|
||||
{ value: '#ff00ff' },
|
||||
{ value: '#e6b8af' },
|
||||
{ value: '#f4cccc' },
|
||||
{ value: '#fce5cd' },
|
||||
{ value: '#fff2cc' },
|
||||
{ value: '#d9ead3' },
|
||||
{ value: '#d0e0e3' },
|
||||
{ value: '#c9daf8' },
|
||||
{ value: '#cfe2f3' },
|
||||
{ value: '#d9d2e9' },
|
||||
{ value: '#ead1dc' },
|
||||
{ value: '#dd7e6b' },
|
||||
{ value: '#dd7e6b' },
|
||||
{ value: '#f9cb9c' },
|
||||
{ value: '#ffe599' },
|
||||
{ value: '#b6d7a8' },
|
||||
{ value: '#a2c4c9' },
|
||||
{ value: '#a4c2f4' },
|
||||
{ value: '#9fc5e8' },
|
||||
{ value: '#b4a7d6' },
|
||||
{ value: '#d5a6bd' },
|
||||
{ value: '#cc4125' },
|
||||
{ value: '#e06666' },
|
||||
{ value: '#f6b26b' },
|
||||
{ value: '#ffd966' },
|
||||
{ value: '#93c47d' },
|
||||
{ value: '#76a5af' },
|
||||
{ value: '#6d9eeb' },
|
||||
{ value: '#6fa8dc' },
|
||||
{ value: '#8e7cc3' },
|
||||
{ value: '#c27ba0' },
|
||||
{ value: '#a61c00' },
|
||||
{ value: '#cc0000' },
|
||||
{ value: '#e69138' },
|
||||
{ value: '#f1c232' },
|
||||
{ value: '#6aa84f' },
|
||||
{ value: '#45818e' },
|
||||
{ value: '#3c78d8' },
|
||||
{ value: '#3d85c6' },
|
||||
{ value: '#674ea7' },
|
||||
{ value: '#a64d79' },
|
||||
{ value: '#85200c' },
|
||||
{ value: '#990000' },
|
||||
{ value: '#b45f06' },
|
||||
{ value: '#bf9000' },
|
||||
{ value: '#38761d' },
|
||||
{ value: '#134f5c' },
|
||||
{ value: '#1155cc' },
|
||||
{ value: '#0b5394' },
|
||||
{ value: '#351c75' },
|
||||
{ value: '#741b47' },
|
||||
{ value: '#5b0f00' },
|
||||
{ value: '#660000' },
|
||||
{ value: '#783f04' },
|
||||
{ value: '#7f6000' },
|
||||
{ value: '#274e13' },
|
||||
{ value: '#0c343d' },
|
||||
{ value: '#1c4587' },
|
||||
{ value: '#073763' },
|
||||
{ value: '#20124d' },
|
||||
{ value: '#4c1130' }
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
40
src/ui/components/toolbar/components/toolbar-input.vue
Normal file
40
src/ui/components/toolbar/components/toolbar-input.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="c-labeled-input"
|
||||
:title="options.title">
|
||||
<label :for="uid">
|
||||
<div class="c-labeled-input__label">{{ options.label }}</div>
|
||||
</label>
|
||||
<input :id="uid"
|
||||
:type="options.type"
|
||||
:value="options.value"
|
||||
v-bind="options.attrs"
|
||||
@change="onChange"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
let inputUniqueId = 100;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
options: {
|
||||
type: Object,
|
||||
validator(value) {
|
||||
return ['number', 'text'].indexOf(value.type) !== -1;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
inputUniqueId++;
|
||||
return {
|
||||
uid: `mct-input-id-${inputUniqueId}`
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onChange(event) {
|
||||
this.$emit('change', event.target.value, this.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
38
src/ui/components/toolbar/components/toolbar-menu.vue
Normal file
38
src/ui/components/toolbar/components/toolbar-menu.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon c-click-icon--menu"
|
||||
:class="options.icon"
|
||||
@click="toggle">
|
||||
<div class="c-click-icon__label"
|
||||
v-if="options.label">
|
||||
{{ options.label }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-menu" v-if="open">
|
||||
<ul>
|
||||
<li v-for="option in options.options"
|
||||
:class="option.class"
|
||||
:title="option.title">
|
||||
{{ option.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import toggle from './toggle-mixin';
|
||||
export default {
|
||||
mixins: [toggle],
|
||||
props: {
|
||||
options: {
|
||||
type: Object,
|
||||
validator(value) {
|
||||
// must pass valid options array.
|
||||
return Array.isArray(value.options) &&
|
||||
value.options.every((o) => o.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
55
src/ui/components/toolbar/components/toolbar-select-menu.vue
Normal file
55
src/ui/components/toolbar/components/toolbar-select-menu.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon c-click-icon--menu"
|
||||
:class="options.icon"
|
||||
@click="toggle">
|
||||
<div class="c-button__label">{{ selectedName }}</div>
|
||||
</div>
|
||||
<div class="c-menu" v-if="open">
|
||||
<ul>
|
||||
<li v-for="option in options.options"
|
||||
:key="option.value"
|
||||
@click="select(option)">
|
||||
{{ option.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import toggleMixin from './toggle-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [toggleMixin],
|
||||
props: {
|
||||
options: {
|
||||
type: Object,
|
||||
validator(value) {
|
||||
// must pass valid options array.
|
||||
return Array.isArray(value.options) &&
|
||||
value.options.every((o) => o.value && o.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
select(option) {
|
||||
if (this.options.value === option.value) {
|
||||
return;
|
||||
}
|
||||
this.$emit('change', option.value, this.options);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
},
|
||||
computed: {
|
||||
selectedName() {
|
||||
let selectedOption = this.options.options.filter((o) => o.value === this.options.value)[0];
|
||||
if (selectedOption) {
|
||||
return selectedOption.name
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
13
src/ui/components/toolbar/components/toolbar-separator.vue
Normal file
13
src/ui/components/toolbar/components/toolbar-separator.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="c-button-set"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
options: Object
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div class="c-click-icon"
|
||||
:title="nextValue.title"
|
||||
:class="nextValue.icon"
|
||||
@click="cycle">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
options: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
nextValue() {
|
||||
let currentValue = this.options.options.filter((v) => this.options.value === v.value)[0];
|
||||
let nextIndex = this.options.options.indexOf(currentValue) + 1;
|
||||
if (nextIndex >= this.options.options.length) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
return this.options.options[nextIndex];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cycle() {
|
||||
this.$emit('change', this.nextValue.value, this.options);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user