Compare commits
	
		
			20 Commits
		
	
	
		
			V4.4.1-RC1
			...
			dialog-ser
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 5f6ff074cd | ||
|   | 2cbcf7d004 | ||
|   | 543bc0a4b3 | ||
|   | c9f5fcb730 | ||
|   | a47dfe2584 | ||
|   | 6cb05bc74a | ||
|   | d5e48b2b1f | ||
|   | f7914ab36d | ||
|   | 279815a6c3 | ||
|   | ce32e6190b | ||
|   | a4993a6e8e | ||
|   | 023068d03e | ||
|   | 34b296f553 | ||
|   | 36d2fc659d | ||
|   | 9062901c06 | ||
|   | be5da7fa72 | ||
|   | 5e3acc4363 | ||
|   | 196f49fca6 | ||
|   | f9cb753fce | ||
|   | 9bc1630cb4 | 
							
								
								
									
										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 | ||||
| ]; | ||||
|  | ||||
|   | ||||
| @@ -26,12 +26,16 @@ define([ | ||||
|     "./src/NotificationLaunchController", | ||||
|     "./src/DialogLaunchIndicator", | ||||
|     "./src/NotificationLaunchIndicator", | ||||
|     "./res/dialog-launch.html", | ||||
|     "./res/notification-launch.html", | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     DialogLaunchController, | ||||
|     NotificationLaunchController, | ||||
|     DialogLaunchIndicator, | ||||
|     NotificationLaunchIndicator, | ||||
|     DialogLaunch, | ||||
|     NotificationLaunch, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|     "use strict"; | ||||
| @@ -41,11 +45,11 @@ define([ | ||||
|             "templates": [ | ||||
|                 { | ||||
|                     "key": "dialogLaunchTemplate", | ||||
|                     "templateUrl": "dialog-launch.html" | ||||
|                     "template": DialogLaunch | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "notificationLaunchTemplate", | ||||
|                     "templateUrl": "notification-launch.html" | ||||
|                     "template": NotificationLaunch | ||||
|                 } | ||||
|             ], | ||||
|             "controllers": [ | ||||
|   | ||||
| @@ -51,76 +51,26 @@ define( | ||||
|                 return actionTexts[Math.floor(Math.random()*3)]; | ||||
|             } | ||||
|  | ||||
|             function getExampleActions() { | ||||
|                 var actions = [ | ||||
|                     { | ||||
|                         label: "Try Again", | ||||
|                         callback: function () { | ||||
|                             $log.debug("Try Again pressed"); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         label: "Remove", | ||||
|                         callback: function () { | ||||
|                             $log.debug("Remove pressed"); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         label: "Cancel", | ||||
|                         callback: function () { | ||||
|                             $log.debug("Cancel pressed"); | ||||
|                         } | ||||
|                     } | ||||
|                 ]; | ||||
|  | ||||
|                 // Randomly remove some actions off the top; leave at least one | ||||
|                 actions.splice(0,Math.floor(Math.random() * actions.length)); | ||||
|  | ||||
|                 return actions; | ||||
|             } | ||||
|  | ||||
|             function getExampleSeverity() { | ||||
|                 var severities = [ | ||||
|                     "info", | ||||
|                     "alert", | ||||
|                     "error" | ||||
|                 ]; | ||||
|                 return severities[Math.floor(Math.random() * severities.length)]; | ||||
|             } | ||||
|  | ||||
|             /** | ||||
|              * Launch a new notification with a severity level of 'Error'. | ||||
|              */ | ||||
|             $scope.newError = function(){ | ||||
|  | ||||
|             $scope.newError = function () { | ||||
|                 notificationService.notify({ | ||||
|                     title: "Example error notification " + messageCounter++, | ||||
|                     hint: "An error has occurred", | ||||
|                     severity: "error", | ||||
|                     primaryOption: { | ||||
|                         label: 'Retry', | ||||
|                         callback: function() { | ||||
|                             $log.info('Retry clicked'); | ||||
|                         } | ||||
|                     }, | ||||
|                     options: getExampleActions()}); | ||||
|                     severity: "error" | ||||
|                 }); | ||||
|             }; | ||||
|             /** | ||||
|              * Launch a new notification with a severity of 'Alert'. | ||||
|              */ | ||||
|             $scope.newAlert = function(){ | ||||
|  | ||||
|             $scope.newAlert = function () { | ||||
|                 notificationService.notify({ | ||||
|                     title: "Alert notification " + (messageCounter++), | ||||
|                     hint: "This is an alert message", | ||||
|                     severity: "alert", | ||||
|                     primaryOption: { | ||||
|                         label: 'Retry', | ||||
|                         callback: function() { | ||||
|                             $log.info('Retry clicked'); | ||||
|                         } | ||||
|                     }, | ||||
|                     options: getExampleActions()}); | ||||
|                     autoDismiss: true | ||||
|                 }); | ||||
|             }; | ||||
|  | ||||
|  | ||||
| @@ -128,39 +78,38 @@ define( | ||||
|              * Launch a new notification with a progress bar that is updated | ||||
|              * periodically, tracking an ongoing process. | ||||
|              */ | ||||
|             $scope.newProgress = function(){ | ||||
|  | ||||
|             $scope.newProgress = function () { | ||||
|                 var notificationModel = { | ||||
|                     title: "Progress notification example", | ||||
|                     severity: "info", | ||||
|                     progress: 0, | ||||
|                     actionText: getExampleActionText(), | ||||
|                     unknownProgress: false | ||||
|                     actionText: getExampleActionText() | ||||
|                 }; | ||||
|  | ||||
|                 /** | ||||
|                  * Simulate an ongoing process and update the progress bar. | ||||
|                  * @param notification | ||||
|                  */ | ||||
|                 function incrementProgress(notificationModel) { | ||||
|                 function incrementProgress() { | ||||
|                     notificationModel.progress = Math.min(100, Math.floor(notificationModel.progress + Math.random() * 30)); | ||||
|                     notificationModel.progressText = ["Estimated time" + | ||||
|                     " remaining:" + | ||||
|                     " about ", 60 - Math.floor((notificationModel.progress / 100) * 60), " seconds"].join(" "); | ||||
|                     if (notificationModel.progress < 100) { | ||||
|                         $timeout(function(){incrementProgress(notificationModel);}, 1000); | ||||
|                         $timeout(function () { | ||||
|                             incrementProgress(notificationModel); | ||||
|                         }, 1000); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 notificationService.notify(notificationModel); | ||||
|                 incrementProgress(notificationModel); | ||||
|                 incrementProgress(); | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Launch a new notification with severity level of INFO. | ||||
|              */ | ||||
|             $scope.newInfo = function(){ | ||||
|  | ||||
|             $scope.newInfo = function () { | ||||
|                 notificationService.info({ | ||||
|                     title: "Example Info notification " + messageCounter++ | ||||
|                 }); | ||||
|   | ||||
							
								
								
									
										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); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
|  | ||||
|  | ||||
| @@ -60,7 +60,7 @@ define( | ||||
|                     }; | ||||
|                     //If the notification is dismissed by the user, close | ||||
|                     // the dialog. | ||||
|                     notification.onDismiss(function () { | ||||
|                     notification.on('dismiss', function () { | ||||
|                         dialog.dismiss(); | ||||
|                     }); | ||||
|  | ||||
|   | ||||
| @@ -23,33 +23,17 @@ | ||||
| define([ | ||||
|     "./src/NotificationIndicatorController", | ||||
|     "./src/NotificationIndicator", | ||||
|     "./src/NotificationService", | ||||
|     "./res/notification-indicator.html", | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     NotificationIndicatorController, | ||||
|     NotificationIndicator, | ||||
|     NotificationService, | ||||
|     notificationIndicatorTemplate, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|  | ||||
|     legacyRegistry.register("platform/commonUI/notification", { | ||||
|         "extensions": { | ||||
|             "constants": [ | ||||
|                 { | ||||
|                     "key": "DEFAULT_AUTO_DISMISS", | ||||
|                     "value": 3000 | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "FORCE_AUTO_DISMISS", | ||||
|                     "value": 1000 | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "MINIMIZE_TIMEOUT", | ||||
|                     "value": 300 | ||||
|                 } | ||||
|             ], | ||||
|             "templates": [ | ||||
|                 { | ||||
|                     "key": "notificationIndicatorTemplate", | ||||
| @@ -76,12 +60,11 @@ define([ | ||||
|             "services": [ | ||||
|                 { | ||||
|                     "key": "notificationService", | ||||
|                     "implementation": NotificationService, | ||||
|                     "implementation": function (openmct) { | ||||
|                         return openmct.notifications; | ||||
|                     }, | ||||
|                     "depends": [ | ||||
|                         "$timeout", | ||||
|                         "topic", | ||||
|                         "DEFAULT_AUTO_DISMISS", | ||||
|                         "MINIMIZE_TIMEOUT" | ||||
|                         "openmct" | ||||
|                     ] | ||||
|                 } | ||||
|             ] | ||||
|   | ||||
| @@ -1,437 +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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * This bundle implements the notification service, which can be used to | ||||
|  * show banner notifications to the user. Banner notifications | ||||
|  * are used to inform users of events in a non-intrusive way. As | ||||
|  * much as possible, notifications share a model with blocking | ||||
|  * dialogs so that the same information can be provided in a dialog | ||||
|  * and then minimized to a banner notification if needed. | ||||
|  * | ||||
|  * @namespace platform/commonUI/notification | ||||
|  */ | ||||
| define( | ||||
|     ['moment'], | ||||
|     function (moment) { | ||||
|  | ||||
|         /** | ||||
|          * A representation of a user action. Options are provided to | ||||
|          * dialogs and notifications and are shown as buttons. | ||||
|          * | ||||
|          * @typedef {object} NotificationOption | ||||
|          * @property {string} label the label to appear on the button for | ||||
|          * this action | ||||
|          * @property {function} callback a callback function to be invoked | ||||
|          * when the button is clicked | ||||
|         */ | ||||
|  | ||||
|         /** | ||||
|          * A representation of a banner notification. Banner notifications | ||||
|          * are used to inform users of events in a non-intrusive way. As | ||||
|          * much as possible, notifications share a model with blocking | ||||
|          * dialogs so that the same information can be provided in a dialog | ||||
|          * and then minimized to a banner notification if needed, or vice-versa. | ||||
|          * | ||||
|          * @typedef {object} NotificationModel | ||||
|          * @property {string} title The title of the message | ||||
|          * @property {string} severity The importance of the message (one of | ||||
|          * 'info', 'alert', or 'error' where info < alert <error) | ||||
|          * @property {number} [progress] The completion status of a task | ||||
|          * represented numerically | ||||
|          * @property {boolean} [unknownProgress] a boolean indicating that the | ||||
|          * progress of the underlying task is unknown. This will result in a | ||||
|          * visually distinct progress bar. | ||||
|          * @property {boolean} [autoDismiss] If truthy, dialog will | ||||
|          * be automatically minimized or dismissed (depending on severity). | ||||
|          * Additionally, if the provided value is a number, it will be used | ||||
|          * as the delay period before being dismissed. | ||||
|          * @property {boolean} [dismissable=true] If true, notification will | ||||
|          * include an option to dismiss it completely. | ||||
|          * @property {NotificationOption} [primaryOption] the default user | ||||
|          * response to | ||||
|          * this message. Will be represented as a button with the provided | ||||
|          * label and action. May be used by banner notifications to display | ||||
|          * only the most important option to users. | ||||
|          * @property {NotificationOption[]} [options] any additional | ||||
|          * actions the user can take. Will be represented as additional buttons | ||||
|          * that may or may not be available from a banner. | ||||
|          * @see DialogModel | ||||
|          */ | ||||
|  | ||||
|         /** | ||||
|          * A wrapper object that is returned as a handle to a newly created | ||||
|          * notification. Wraps the notifications model and decorates with | ||||
|          * functions to dismiss or minimize the notification. | ||||
|          * | ||||
|          * @typedef {object} Notification | ||||
|          * @property {function} dismiss This method is added to the object | ||||
|          * returned by {@link NotificationService#notify} and can be used to | ||||
|          * dismiss this notification. Dismissing a notification will remove | ||||
|          * it completely and it will not appear in the notification indicator | ||||
|          * @property {function} minimize This method is added to the object | ||||
|          * returned by {@link NotificationService#notify} and can be used to | ||||
|          * minimize this notification. Minimizing a notification will send | ||||
|          * it to the notification indicator | ||||
|          * @property {function} dismissOrMinimize This method is added to the | ||||
|          * object returned by {@link NotificationService#notify}. It will | ||||
|          * hide the notification by either dismissing or minimizing it, | ||||
|          * depending on severity. Typically this is the method that should | ||||
|          * be used for dismissing a notification. If more control is | ||||
|          * required, then the minimize or dismiss functions can be called | ||||
|          * individually. | ||||
|          * @property {function} onDismiss Allows listening for on dismiss | ||||
|          * events. This allows cleanup etc. when the notification is dismissed. | ||||
|          */ | ||||
|  | ||||
|         /** | ||||
|          * The notification service is responsible for informing the user of | ||||
|          * events via the use of banner notifications. | ||||
|          * @memberof platform/commonUI/notification | ||||
|          * @constructor | ||||
|          * @param $timeout the Angular $timeout service | ||||
|          * @param defaultAutoDismissTimeout The period of time that an | ||||
|          * auto-dismissed message will be displayed for. | ||||
|          * @param minimizeAnimationTimeout When notifications are minimized, a brief | ||||
|          * animation is shown. This animation requires some time to execute, | ||||
|          * so a timeout is required before the notification is hidden | ||||
|          */ | ||||
|         function NotificationService($timeout, topic, defaultAutoDismissTimeout, minimizeAnimationTimeout) { | ||||
|             this.notifications = []; | ||||
|             this.$timeout = $timeout; | ||||
|             this.highest = { severity: "info" }; | ||||
|             this.AUTO_DISMISS_TIMEOUT = defaultAutoDismissTimeout; | ||||
|             this.MINIMIZE_ANIMATION_TIMEOUT = minimizeAnimationTimeout; | ||||
|             this.topic = topic; | ||||
|  | ||||
|             /* | ||||
|              * A context in which to hold the active notification and a | ||||
|              * handle to its timeout. | ||||
|              */ | ||||
|             this.active = {}; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Minimize a notification. The notification will still be available | ||||
|          * from the notification list. Typically notifications with a | ||||
|          * severity of 'info' should not be minimized, but rather | ||||
|          * dismissed. If you're not sure which is appropriate, | ||||
|          * use {@link Notification#dismissOrMinimize} | ||||
|          * | ||||
|          * @private | ||||
|          */ | ||||
|         NotificationService.prototype.minimize = function (service, notification) { | ||||
|             //Check this is a known notification | ||||
|             var index = service.notifications.indexOf(notification); | ||||
|  | ||||
|             if (service.active.timeout) { | ||||
|                 /* | ||||
|                  Method can be called manually (clicking dismiss) or | ||||
|                  automatically from an auto-timeout. this.active.timeout | ||||
|                  acts as a semaphore to prevent race conditions. Cancel any | ||||
|                  timeout in progress (for the case where a manual dismiss | ||||
|                  has shortcut an active auto-dismiss), and clear the | ||||
|                  semaphore. | ||||
|                  */ | ||||
|                 service.$timeout.cancel(service.active.timeout); | ||||
|                 delete service.active.timeout; | ||||
|             } | ||||
|  | ||||
|             if (index >= 0) { | ||||
|                 notification.model.minimized = true; | ||||
|                 //Add a brief timeout before showing the next notification | ||||
|                 // in order to allow the minimize animation to run through. | ||||
|                 service.$timeout(function () { | ||||
|                     service.setActiveNotification(service.selectNextNotification()); | ||||
|                 }, service.MINIMIZE_ANIMATION_TIMEOUT); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Completely removes a notification. This will dismiss it from the | ||||
|          * message banner and remove it from the list of notifications. | ||||
|          * Typically only notifications with a severity of info should be | ||||
|          * dismissed. If you're not sure whether to dismiss or minimize a | ||||
|          * notification, use {@link Notification#dismissOrMinimize}. | ||||
|          * dismiss | ||||
|          * | ||||
|          * @private | ||||
|          */ | ||||
|         NotificationService.prototype.dismiss = function (service, notification) { | ||||
|             //Check this is a known notification | ||||
|             var index = service.notifications.indexOf(notification); | ||||
|  | ||||
|             if (service.active.timeout) { | ||||
|                 /* Method can be called manually (clicking dismiss) or | ||||
|                  * automatically from an auto-timeout. this.active.timeout | ||||
|                  * acts as a semaphore to prevent race conditions. Cancel any | ||||
|                  * timeout in progress (for the case where a manual dismiss | ||||
|                  * has shortcut an active auto-dismiss), and clear the | ||||
|                  * semaphore. | ||||
|                  */ | ||||
|  | ||||
|                 service.$timeout.cancel(service.active.timeout); | ||||
|                 delete service.active.timeout; | ||||
|             } | ||||
|  | ||||
|             if (index >= 0) { | ||||
|                 service.notifications.splice(index, 1); | ||||
|             } | ||||
|             service.setActiveNotification(service.selectNextNotification()); | ||||
|  | ||||
|             this.setHighestSeverity(); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Depending on the severity of the notification will selectively | ||||
|          * dismiss or minimize where appropriate. | ||||
|          * | ||||
|          * @private | ||||
|          */ | ||||
|         NotificationService.prototype.dismissOrMinimize = function (notification) { | ||||
|             var model = notification.model; | ||||
|             if (model.severity === "info") { | ||||
|                 if (model.autoDismiss === false) { | ||||
|                     notification.minimize(); | ||||
|                 } else { | ||||
|                     notification.dismiss(); | ||||
|                 } | ||||
|             } else { | ||||
|                 notification.minimize(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Returns the notification that is currently visible in the banner area | ||||
|          * @returns {Notification} | ||||
|          */ | ||||
|         NotificationService.prototype.getActiveNotification = function () { | ||||
|             return this.active.notification; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * A convenience method for info notifications. Notifications | ||||
|          * created via this method will be auto-dismissed after a default | ||||
|          * wait period unless explicitly forbidden by the caller through | ||||
|          * the {autoDismiss} property on the {NotificationModel}, in which | ||||
|          * case the notification will be minimized after the wait. | ||||
|          * @param {NotificationModel | string} message either a string for | ||||
|          * the title of the notification message, or a {@link NotificationModel} | ||||
|          * defining the options notification to display | ||||
|          * @returns {Notification} the provided notification decorated with | ||||
|          * functions to dismiss or minimize | ||||
|          */ | ||||
|         NotificationService.prototype.info = function (message) { | ||||
|             var notificationModel = typeof message === "string" ? {title: message} : message; | ||||
|             notificationModel.severity = "info"; | ||||
|             return this.notify(notificationModel); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * A convenience method for alert notifications. Notifications | ||||
|          * created via this method will will have severity of "alert" enforced | ||||
|          * @param {NotificationModel | string} message either a string for | ||||
|          * the title of the alert message with default options, or a | ||||
|          * {@link NotificationModel} defining the options notification to | ||||
|          * display | ||||
|          * @returns {Notification} the provided notification decorated with | ||||
|          * functions to dismiss or minimize | ||||
|          */ | ||||
|         NotificationService.prototype.alert = function (message) { | ||||
|             var notificationModel = typeof message === "string" ? {title: message} : message; | ||||
|             notificationModel.severity = "alert"; | ||||
|             return this.notify(notificationModel); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * A convenience method for error notifications. Notifications | ||||
|          * created via this method will will have severity of "error" enforced | ||||
|          * @param {NotificationModel | string} message either a string for | ||||
|          * the title of the error message with default options, or a | ||||
|          * {@link NotificationModel} defining the options notification to | ||||
|          * display | ||||
|          * @returns {Notification} the provided notification decorated with | ||||
|          * functions to dismiss or minimize | ||||
|          */ | ||||
|         NotificationService.prototype.error = function (message) { | ||||
|             var notificationModel = typeof message === "string" ? {title: message} : message; | ||||
|             notificationModel.severity = "error"; | ||||
|             return this.notify(notificationModel); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * @private | ||||
|          */ | ||||
|         NotificationService.prototype.setHighestSeverity = function () { | ||||
|             var severity = { | ||||
|                 "info": 1, | ||||
|                 "alert": 2, | ||||
|                 "error": 3 | ||||
|             }; | ||||
|             this.highest.severity = this.notifications.reduce(function (previous, notification) { | ||||
|                 if (severity[notification.model.severity] > severity[previous]) { | ||||
|                     return notification.model.severity; | ||||
|                 } else { | ||||
|                     return previous; | ||||
|                 } | ||||
|             }, "info"); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Notifies the user of an event. If there is a banner notification | ||||
|          * already active, then it will be dismissed or minimized automatically, | ||||
|          * and the provided notification displayed in its place. | ||||
|          * | ||||
|          * @param {NotificationModel} notificationModel The notification to | ||||
|          * display | ||||
|          * @returns {Notification} the provided notification decorated with | ||||
|          * functions to {@link Notification#dismiss} or {@link Notification#minimize} | ||||
|          */ | ||||
|         NotificationService.prototype.notify = function (notificationModel) { | ||||
|             var self = this, | ||||
|                 notification, | ||||
|                 activeNotification = self.active.notification, | ||||
|                 topic = this.topic(); | ||||
|  | ||||
|             notificationModel.severity = notificationModel.severity || "info"; | ||||
|             notificationModel.timestamp = moment.utc().format('YYYY-MM-DD hh:mm:ss.ms'); | ||||
|  | ||||
|             notification = { | ||||
|                 model: notificationModel, | ||||
|  | ||||
|                 minimize: function () { | ||||
|                     self.minimize(self, notification); | ||||
|                 }, | ||||
|  | ||||
|                 dismiss: function () { | ||||
|                     self.dismiss(self, notification); | ||||
|                     topic.notify(); | ||||
|                 }, | ||||
|  | ||||
|                 dismissOrMinimize: function () { | ||||
|                     self.dismissOrMinimize(notification); | ||||
|                 }, | ||||
|  | ||||
|                 onDismiss: function (callback) { | ||||
|                     topic.listen(callback); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             //Notifications support a 'dismissable' attribute. This is a | ||||
|             // convenience to support adding a 'dismiss' option to the | ||||
|             // notification for the common case of dismissing a | ||||
|             // notification. Could also be done manually by specifying an | ||||
|             // option on the model | ||||
|             if (notificationModel.dismissable !== false) { | ||||
|                 notificationModel.options = notificationModel.options || []; | ||||
|                 notificationModel.options.unshift({ | ||||
|                     label: "Dismiss", | ||||
|                     callback: function () { | ||||
|                         notification.dismiss(); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             this.notifications.push(notification); | ||||
|  | ||||
|             this.setHighestSeverity(); | ||||
|  | ||||
|             /* | ||||
|             Check if there is already an active (ie. visible) notification | ||||
|              */ | ||||
|             if (!this.active.notification) { | ||||
|                 this.setActiveNotification(notification); | ||||
|  | ||||
|             } else if (!this.active.timeout) { | ||||
|                 /* | ||||
|                  If there is already an active notification, time it out. If it's | ||||
|                  already got a timeout in progress (either because it has had | ||||
|                  timeout forced because of a queue of messages, or it had an | ||||
|                  autodismiss specified), leave it to run. Otherwise force a | ||||
|                   timeout. | ||||
|  | ||||
|                  This notification has been added to queue and will be | ||||
|                   serviced as soon as possible. | ||||
|                  */ | ||||
|                 this.active.timeout = this.$timeout(function () { | ||||
|                     activeNotification.dismissOrMinimize(); | ||||
|                 }, this.AUTO_DISMISS_TIMEOUT); | ||||
|             } | ||||
|  | ||||
|             return notification; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Used internally by the NotificationService | ||||
|          * @private | ||||
|          */ | ||||
|         NotificationService.prototype.setActiveNotification = function (notification) { | ||||
|             var shouldAutoDismiss; | ||||
|             this.active.notification = notification; | ||||
|  | ||||
|             if (!notification) { | ||||
|                 delete this.active.timeout; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (notification.model.severity === "info") { | ||||
|                 shouldAutoDismiss = true; | ||||
|             } else { | ||||
|                 shouldAutoDismiss = notification.model.autoDismiss; | ||||
|             } | ||||
|  | ||||
|             if (shouldAutoDismiss || this.selectNextNotification()) { | ||||
|                 this.active.timeout = this.$timeout(function () { | ||||
|                     notification.dismissOrMinimize(); | ||||
|                 }, this.AUTO_DISMISS_TIMEOUT); | ||||
|             } else { | ||||
|                 delete this.active.timeout; | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Used internally by the NotificationService | ||||
|          * | ||||
|          * @private | ||||
|          */ | ||||
|         NotificationService.prototype.selectNextNotification = function () { | ||||
|             var notification, | ||||
|                 i = 0; | ||||
|  | ||||
|             /* | ||||
|             Loop through the notifications queue and find the first one that | ||||
|             has not already been minimized (manually or otherwise). | ||||
|              */ | ||||
|             for (; i < this.notifications.length; i++) { | ||||
|                 notification = this.notifications[i]; | ||||
|  | ||||
|                 if (!notification.model.minimized && | ||||
|                     notification !== this.active.notification) { | ||||
|  | ||||
|                     return notification; | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         return NotificationService; | ||||
|     } | ||||
| ); | ||||
| @@ -1,275 +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. | ||||
|  *****************************************************************************/ | ||||
| /*global describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ['../src/NotificationService'], | ||||
|     function (NotificationService) { | ||||
|  | ||||
|         describe("The notification service ", function () { | ||||
|             var notificationService, | ||||
|                 mockTimeout, | ||||
|                 mockAutoDismiss, | ||||
|                 mockMinimizeTimeout, | ||||
|                 mockTopicFunction, | ||||
|                 mockTopicObject, | ||||
|                 infoModel, | ||||
|                 alertModel, | ||||
|                 errorModel; | ||||
|  | ||||
|             function elapseTimeout() { | ||||
|                 mockTimeout.calls.mostRecent().args[0](); | ||||
|             } | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockTimeout = jasmine.createSpy("$timeout"); | ||||
|                 mockTopicFunction = jasmine.createSpy("topic"); | ||||
|                 mockTopicObject = jasmine.createSpyObj("topicObject", ["listen", "notify"]); | ||||
|                 mockTopicFunction.and.returnValue(mockTopicObject); | ||||
|  | ||||
|                 mockAutoDismiss = mockMinimizeTimeout = 1000; | ||||
|                 notificationService = new NotificationService(mockTimeout, mockTopicFunction, mockAutoDismiss, mockMinimizeTimeout); | ||||
|  | ||||
|                 infoModel = { | ||||
|                     title: "Mock Info Notification", | ||||
|                     severity: "info" | ||||
|                 }; | ||||
|  | ||||
|                 alertModel = { | ||||
|                     title: "Mock Alert Notification", | ||||
|                     severity: "alert" | ||||
|                 }; | ||||
|  | ||||
|                 errorModel = { | ||||
|                     title: "Mock Error Notification", | ||||
|                     severity: "error" | ||||
|                 }; | ||||
|             }); | ||||
|  | ||||
|             it("notifies listeners on dismissal of notification", function () { | ||||
|                 var dismissListener = jasmine.createSpy("ondismiss"); | ||||
|                 var notification = notificationService.notify(infoModel); | ||||
|                 notification.onDismiss(dismissListener); | ||||
|                 expect(mockTopicObject.listen).toHaveBeenCalled(); | ||||
|                 notification.dismiss(); | ||||
|                 expect(mockTopicObject.notify).toHaveBeenCalled(); | ||||
|                 mockTopicObject.listen.calls.mostRecent().args[0](); | ||||
|                 expect(dismissListener).toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("dismisses a notification when the notification's dismiss method is used", function () { | ||||
|                 var notification = notificationService.info(infoModel); | ||||
|                 notification.dismiss(); | ||||
|                 expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                 expect(notificationService.notifications.length).toEqual(0); | ||||
|             }); | ||||
|  | ||||
|             it("minimizes a notification when the notification's minimize method is used", function () { | ||||
|                 var notification = notificationService.info(infoModel); | ||||
|                 notification.minimize(); | ||||
|                 elapseTimeout(); // needed for the minimize animation timeout | ||||
|                 expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                 expect(notificationService.notifications.length).toEqual(1); | ||||
|                 expect(notificationService.notifications[0]).toEqual(notification); | ||||
|             }); | ||||
|  | ||||
|             describe("when receiving info notifications", function () { | ||||
|                 it("minimizes info notifications if the caller disables auto-dismiss", function () { | ||||
|                     infoModel.autoDismiss = false; | ||||
|                     var notification = notificationService.info(infoModel); | ||||
|                     elapseTimeout(); | ||||
|                     // 2nd elapse for the minimize animation timeout | ||||
|                     elapseTimeout(); | ||||
|                     expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|  | ||||
|                 it("dismisses info notifications if the caller ignores auto-dismiss", function () { | ||||
|                     notificationService.info(infoModel); | ||||
|                     elapseTimeout(); | ||||
|                     expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                     expect(notificationService.notifications.length).toEqual(0); | ||||
|                 }); | ||||
|  | ||||
|                 it("dismisses info notifications if the caller requests auto-dismiss", function () { | ||||
|                     infoModel.autoDismiss = true; | ||||
|                     notificationService.info(infoModel); | ||||
|                     elapseTimeout(); | ||||
|                     expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                     expect(notificationService.notifications.length).toEqual(0); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             describe("when receiving alert notifications", function () { | ||||
|                 it("minimizes alert notifications if the caller enables auto-dismiss", function () { | ||||
|                     alertModel.autoDismiss = true; | ||||
|                     var notification = notificationService.alert(alertModel); | ||||
|                     elapseTimeout(); | ||||
|                     elapseTimeout(); | ||||
|                     expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|  | ||||
|                 it("keeps alert notifications active if the caller disables auto-dismiss", function () { | ||||
|                     mockTimeout.and.callFake(function (callback, time) { | ||||
|                         callback(); | ||||
|                     }); | ||||
|                     alertModel.autoDismiss = false; | ||||
|                     var notification = notificationService.alert(alertModel); | ||||
|                     expect(notificationService.getActiveNotification()).toEqual(notification); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|  | ||||
|                 it("keeps alert notifications active if the caller ignores auto-dismiss", function () { | ||||
|                     mockTimeout.and.callFake(function (callback, time) { | ||||
|                         callback(); | ||||
|                     }); | ||||
|                     var notification = notificationService.alert(alertModel); | ||||
|                     expect(notificationService.getActiveNotification()).toEqual(notification); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             describe("when receiving error notifications", function () { | ||||
|                 it("minimizes error notifications if the caller enables auto-dismiss", function () { | ||||
|                     errorModel.autoDismiss = true; | ||||
|                     var notification = notificationService.error(errorModel); | ||||
|                     elapseTimeout(); | ||||
|                     elapseTimeout(); | ||||
|                     expect(notificationService.getActiveNotification()).toBeUndefined(); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|  | ||||
|                 it("keeps error notifications active if the caller disables auto-dismiss", function () { | ||||
|                     mockTimeout.and.callFake(function (callback, time) { | ||||
|                         callback(); | ||||
|                     }); | ||||
|                     errorModel.autoDismiss = false; | ||||
|                     var notification = notificationService.error(errorModel); | ||||
|                     expect(notificationService.getActiveNotification()).toEqual(notification); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|  | ||||
|                 it("keeps error notifications active if the caller ignores auto-dismiss", function () { | ||||
|                     mockTimeout.and.callFake(function (callback, time) { | ||||
|                         callback(); | ||||
|                     }); | ||||
|                     var notification = notificationService.error(errorModel); | ||||
|                     expect(notificationService.getActiveNotification()).toEqual(notification); | ||||
|                     expect(notificationService.notifications.length).toEqual(1); | ||||
|                     expect(notificationService.notifications[0]).toEqual(notification); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             describe("when called with multiple notifications", function () { | ||||
|                 it("auto-dismisses the previously active notification, making the new notification active", function () { | ||||
|                     var activeNotification; | ||||
|                     infoModel.autoDismiss = false; | ||||
|                     //First pre-load with a info message | ||||
|                     notificationService.notify(infoModel); | ||||
|                     activeNotification = notificationService.getActiveNotification(); | ||||
|                     //Initially expect the active notification to be info | ||||
|                     expect(activeNotification.model).toBe(infoModel); | ||||
|                     //Then notify of an error | ||||
|                     notificationService.notify(errorModel); | ||||
|                     //But it should be auto-dismissed and replaced with the | ||||
|                     // error notification | ||||
|                     elapseTimeout(); | ||||
|                     //Two timeouts, one is to force minimization after | ||||
|                     // displaying the message for a minimum period, the | ||||
|                     // second is to allow minimization animation to take place. | ||||
|                     elapseTimeout(); | ||||
|                     activeNotification = notificationService.getActiveNotification(); | ||||
|                     expect(activeNotification.model).toBe(errorModel); | ||||
|                 }); | ||||
|  | ||||
|                 it("auto-minimizes an active error notification", function () { | ||||
|                     var activeNotification; | ||||
|                     //First pre-load with an error message | ||||
|                     notificationService.notify(errorModel); | ||||
|                     //Then notify of info | ||||
|                     notificationService.notify(infoModel); | ||||
|                     expect(notificationService.notifications.length).toEqual(2); | ||||
|                     //Mock the auto-minimize | ||||
|                     elapseTimeout(); | ||||
|                     //Two timeouts, one is to force minimization after | ||||
|                     // displaying the message for a minimum period, the | ||||
|                     // second is to allow minimization animation to take place. | ||||
|                     elapseTimeout(); | ||||
|                     //Previous error message should be minimized, not | ||||
|                     // dismissed | ||||
|                     expect(notificationService.notifications.length).toEqual(2); | ||||
|                     activeNotification = notificationService.getActiveNotification(); | ||||
|                     expect(activeNotification.model).toBe(infoModel); | ||||
|                     expect(errorModel.minimized).toEqual(true); | ||||
|                 }); | ||||
|  | ||||
|                 it("auto-minimizes errors when a number of them arrive in short succession", function () { | ||||
|                     var activeNotification, | ||||
|                         error2 = { | ||||
|                             title: "Second Mock Error Notification", | ||||
|                             severity: "error" | ||||
|                         }, | ||||
|                         error3 = { | ||||
|                             title: "Third Mock Error Notification", | ||||
|                             severity: "error" | ||||
|                         }; | ||||
|  | ||||
|                     //First pre-load with a info message | ||||
|                     notificationService.notify(errorModel); | ||||
|                     //Then notify of a third error | ||||
|                     notificationService.notify(error2); | ||||
|                     notificationService.notify(error3); | ||||
|                     expect(notificationService.notifications.length).toEqual(3); | ||||
|                     //Mock the auto-minimize | ||||
|                     elapseTimeout(); | ||||
|                     //Two timeouts, one is to force minimization after | ||||
|                     // displaying the message for a minimum period, the | ||||
|                     // second is to allow minimization animation to take place. | ||||
|                     elapseTimeout(); | ||||
|                     //Previous error message should be minimized, not | ||||
|                     // dismissed | ||||
|                     expect(notificationService.notifications.length).toEqual(3); | ||||
|                     activeNotification = notificationService.getActiveNotification(); | ||||
|                     expect(activeNotification.model).toBe(error2); | ||||
|                     expect(errorModel.minimized).toEqual(true); | ||||
|  | ||||
|                     //Mock the second auto-minimize | ||||
|                     elapseTimeout(); | ||||
|                     //Two timeouts, one is to force minimization after | ||||
|                     // displaying the message for a minimum period, the | ||||
|                     // second is to allow minimization animation to take place. | ||||
|                     elapseTimeout(); | ||||
|                     activeNotification = notificationService.getActiveNotification(); | ||||
|                     expect(activeNotification.model).toBe(error3); | ||||
|                     expect(error2.minimized).toEqual(true); | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -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/); | ||||
|             }); | ||||
|  | ||||
|  | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -223,6 +223,8 @@ define([ | ||||
|          */ | ||||
|         this.indicators = new api.IndicatorAPI(this); | ||||
|  | ||||
|         this.notifications = new api.NotificationAPI(); | ||||
|  | ||||
|         this.Dialog = api.Dialog; | ||||
|  | ||||
|         this.editor = new api.EditorAPI.default(this); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ define([ | ||||
|     './ui/GestureAPI', | ||||
|     './telemetry/TelemetryAPI', | ||||
|     './indicators/IndicatorAPI', | ||||
|     './notifications/NotificationAPI', | ||||
|     './Editor' | ||||
|  | ||||
| ], function ( | ||||
| @@ -40,6 +41,7 @@ define([ | ||||
|     GestureAPI, | ||||
|     TelemetryAPI, | ||||
|     IndicatorAPI, | ||||
|     NotificationAPI, | ||||
|     EditorAPI | ||||
| ) { | ||||
|     return { | ||||
| @@ -51,6 +53,7 @@ define([ | ||||
|         GestureAPI: GestureAPI, | ||||
|         TelemetryAPI: TelemetryAPI, | ||||
|         IndicatorAPI: IndicatorAPI, | ||||
|         NotificationAPI: NotificationAPI.default, | ||||
|         EditorAPI: EditorAPI | ||||
|     }; | ||||
| }); | ||||
|   | ||||
| @@ -28,7 +28,7 @@ define([ | ||||
| ) { | ||||
|     function IndicatorAPI(openmct) { | ||||
|         this.openmct = openmct; | ||||
|         this.indicatorElements = []; | ||||
|         this.indicatorObjects = []; | ||||
|     } | ||||
|  | ||||
|     IndicatorAPI.prototype.simpleIndicator = function () { | ||||
| @@ -55,12 +55,7 @@ define([ | ||||
|      * | ||||
|      */ | ||||
|     IndicatorAPI.prototype.add = function (indicator) { | ||||
|         // So that we can consistently position indicator elements, | ||||
|         // guarantee that they are wrapped in an element we control | ||||
|         var wrapperNode = document.createElement('div'); | ||||
|         wrapperNode.className = 'h-indicator'; | ||||
|         wrapperNode.appendChild(indicator.element); | ||||
|         this.indicatorElements.push(wrapperNode); | ||||
|         this.indicatorObjects.push(indicator); | ||||
|     }; | ||||
|  | ||||
|     return IndicatorAPI; | ||||
|   | ||||
							
								
								
									
										48
									
								
								src/api/notifications/MCTNotification.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/api/notifications/MCTNotification.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| import EventEmitter from 'EventEmitter'; | ||||
| export default class MCTNotification extends EventEmitter { | ||||
|  | ||||
|     constructor(notificationModel, notificationAPI) { | ||||
|         super(); | ||||
|         this.notifications = notificationAPI; | ||||
|         this.model = notificationModel; | ||||
|         this.initializeModel(); | ||||
|     } | ||||
|  | ||||
|     minimize() { | ||||
|         this.notifications.minimize(this); | ||||
|     } | ||||
|  | ||||
|     dismiss() { | ||||
|         this.notifications.dismiss(this) | ||||
|     } | ||||
|  | ||||
|     dismissOrMinimize() { | ||||
|         this.notifications.dismissOrMinimize(this); | ||||
|     } | ||||
|  | ||||
|     initializeModel() { | ||||
|         this.model.minimized = this.model.minimized || false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										353
									
								
								src/api/notifications/NotificationApi.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								src/api/notifications/NotificationApi.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,353 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * This bundle implements the notification service, which can be used to | ||||
|  * show banner notifications to the user. Banner notifications | ||||
|  * are used to inform users of events in a non-intrusive way. As | ||||
|  * much as possible, notifications share a model with blocking | ||||
|  * dialogs so that the same information can be provided in a dialog | ||||
|  * and then minimized to a banner notification if needed. | ||||
|  * | ||||
|  * @namespace platform/api/notifications | ||||
|  */ | ||||
| import moment from 'moment'; | ||||
| import EventEmitter from 'EventEmitter'; | ||||
| import MCTNotification from './MCTNotification.js'; | ||||
|  | ||||
| /** | ||||
|  * A representation of a banner notification. Banner notifications | ||||
|  * are used to inform users of events in a non-intrusive way. As | ||||
|  * much as possible, notifications share a model with blocking | ||||
|  * dialogs so that the same information can be provided in a dialog | ||||
|  * and then minimized to a banner notification if needed, or vice-versa. | ||||
|  * | ||||
|  * @typedef {object} NotificationModel | ||||
|  * @property {string} title The title of the message | ||||
|  * @property {string} severity The importance of the message (one of | ||||
|  * 'info', 'alert', or 'error' where info < alert <error) | ||||
|  * @property {number} [progress] The completion status of a task | ||||
|  * represented numerically | ||||
|  * @property {boolean} [unknownProgress] a boolean indicating that the | ||||
|  * progress of the underlying task is unknown. This will result in a | ||||
|  * visually distinct progress bar. | ||||
|  * @property {boolean} [autoDismiss] If truthy, dialog will | ||||
|  * be automatically minimized or dismissed (depending on severity). | ||||
|  * Additionally, if the provided value is a number, it will be used | ||||
|  * as the delay period before being dismissed. | ||||
|  * @property {boolean} [dismissable=true] If true, notification will | ||||
|  * include an option to dismiss it completely. | ||||
|  * @see DialogModel | ||||
|  */ | ||||
|  | ||||
| const DEFAULT_AUTO_DISMISS_TIMEOUT = 3000; | ||||
| const MINIMIZE_ANIMATION_TIMEOUT = 300; | ||||
|  | ||||
| /** | ||||
|  * The notification service is responsible for informing the user of | ||||
|  * events via the use of banner notifications. | ||||
|  * @memberof platform/commonUI/notification | ||||
|  * @constructor | ||||
|  * @param defaultAutoDismissTimeout The period of time that an | ||||
|  * auto-dismissed message will be displayed for. | ||||
|  * @param minimizeAnimationTimeout When notifications are minimized, a brief | ||||
|  * animation is shown. This animation requires some time to execute, | ||||
|  * so a timeout is required before the notification is hidden | ||||
|  */ | ||||
| export default class NotificationAPI extends EventEmitter { | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.notifications = []; | ||||
|         this.highest = { severity: "info" }; | ||||
|  | ||||
|         /* | ||||
|         * A context in which to hold the active notification and a | ||||
|         * handle to its timeout. | ||||
|         */ | ||||
|         this.activeNotification = undefined; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Minimize a notification. The notification will still be available | ||||
|      * from the notification list. Typically notifications with a | ||||
|      * severity of 'info' should not be minimized, but rather | ||||
|      * dismissed. If you're not sure which is appropriate, | ||||
|      * use {@link Notification#dismissOrMinimize} | ||||
|      * | ||||
|      * @private | ||||
|      */ | ||||
|     minimize(notification) { | ||||
|         //Check this is a known notification | ||||
|         let index = this.notifications.indexOf(notification); | ||||
|  | ||||
|         if (this.activeTimeout) { | ||||
|             /* | ||||
|                 Method can be called manually (clicking dismiss) or | ||||
|                 automatically from an auto-timeout. this.activeTimeout | ||||
|                 acts as a semaphore to prevent race conditions. Cancel any | ||||
|                 timeout in progress (for the case where a manual dismiss | ||||
|                 has shortcut an active auto-dismiss), and clear the | ||||
|                 semaphore. | ||||
|                 */ | ||||
|             clearTimeout(this.activeTimeout); | ||||
|             delete this.activeTimeout; | ||||
|         } | ||||
|  | ||||
|         if (index >= 0) { | ||||
|             notification.model.minimized = true; | ||||
|             //Add a brief timeout before showing the next notification | ||||
|             // in order to allow the minimize animation to run through. | ||||
|             setTimeout(() => { | ||||
|                 notification.emit('destroy'); | ||||
|                 this.setActiveNotification(this.selectNextNotification()); | ||||
|             }, MINIMIZE_ANIMATION_TIMEOUT); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Completely removes a notification. This will dismiss it from the | ||||
|      * message banner and remove it from the list of notifications. | ||||
|      * Typically only notifications with a severity of info should be | ||||
|      * dismissed. If you're not sure whether to dismiss or minimize a | ||||
|      * notification, use {@link Notification#dismissOrMinimize}. | ||||
|      * dismiss | ||||
|      * | ||||
|      * @private | ||||
|      */ | ||||
|     dismiss(notification) { | ||||
|         //Check this is a known notification | ||||
|         let index = this.notifications.indexOf(notification); | ||||
|  | ||||
|         if (this.activeTimeout) { | ||||
|             /* Method can be called manually (clicking dismiss) or | ||||
|                 * automatically from an auto-timeout. this.activeTimeout | ||||
|                 * acts as a semaphore to prevent race conditions. Cancel any | ||||
|                 * timeout in progress (for the case where a manual dismiss | ||||
|                 * has shortcut an active auto-dismiss), and clear the | ||||
|                 * semaphore. | ||||
|                 */ | ||||
|  | ||||
|             clearTimeout(this.activeTimeout); | ||||
|             delete this.activeTimeout; | ||||
|         } | ||||
|  | ||||
|         if (index >= 0) { | ||||
|             this.notifications.splice(index, 1); | ||||
|         } | ||||
|         this.setActiveNotification(this.selectNextNotification()); | ||||
|         this.setHighestSeverity(); | ||||
|         notification.emit('destroy'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Depending on the severity of the notification will selectively | ||||
|      * dismiss or minimize where appropriate. | ||||
|      * | ||||
|      * @private | ||||
|      */ | ||||
|     dismissOrMinimize(notification) { | ||||
|         let model = notification.model; | ||||
|         if (model.severity === "info") { | ||||
|             if (model.autoDismiss === false) { | ||||
|                 this.minimize(notification); | ||||
|             } else { | ||||
|                 this.dismiss(notification); | ||||
|             } | ||||
|         } else { | ||||
|             this.minimize(notification); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the notification that is currently visible in the banner area | ||||
|      * @returns {Notification} | ||||
|      */ | ||||
|     getActiveNotification() { | ||||
|         return this.activeNotification; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * A convenience method for info notifications. Notifications | ||||
|      * created via this method will be auto-destroy after a default | ||||
|      * wait period unless explicitly forbidden by the caller through | ||||
|      * the {autoDismiss} property on the {NotificationModel}, in which | ||||
|      * case the notification will be minimized after the wait. | ||||
|      * @param {NotificationModel | string} message either a string for | ||||
|      * the title of the notification message, or a {@link NotificationModel} | ||||
|      * defining the options notification to display | ||||
|      * @returns {Notification} the provided notification decorated with | ||||
|      * functions to dismiss or minimize | ||||
|      */ | ||||
|     info(message) { | ||||
|         let notificationModel = typeof message === "string" ? {title: message} : message; | ||||
|         notificationModel.severity = "info"; | ||||
|         return this.notify(notificationModel); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * A convenience method for alert notifications. Notifications | ||||
|      * created via this method will will have severity of "alert" enforced | ||||
|      * @param {NotificationModel | string} message either a string for | ||||
|      * the title of the alert message with default options, or a | ||||
|      * {@link NotificationModel} defining the options notification to | ||||
|      * display | ||||
|      * @returns {Notification} the provided notification decorated with | ||||
|      * functions to dismiss or minimize | ||||
|      */ | ||||
|     alert(message) { | ||||
|         let notificationModel = typeof message === "string" ? {title: message} : message; | ||||
|         notificationModel.severity = "alert"; | ||||
|         return this.notify(notificationModel); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * A convenience method for error notifications. Notifications | ||||
|      * created via this method will will have severity of "error" enforced | ||||
|      * @param {NotificationModel | string} message either a string for | ||||
|      * the title of the error message with default options, or a | ||||
|      * {@link NotificationModel} defining the options of the notification to | ||||
|      * display | ||||
|      * @returns {Notification} the provided notification decorated with | ||||
|      * functions to dismiss or minimize | ||||
|      */ | ||||
|     error(message) { | ||||
|         let notificationModel = typeof message === "string" ? {title: message} : message; | ||||
|         notificationModel.severity = "error"; | ||||
|         return this.notify(notificationModel); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     setHighestSeverity() { | ||||
|         let severity = { | ||||
|             "info": 1, | ||||
|             "alert": 2, | ||||
|             "error": 3 | ||||
|         }; | ||||
|         this.highest.severity = this.notifications.reduce((previous, notification) => { | ||||
|             if (severity[notification.model.severity] > severity[previous]) { | ||||
|                 return notification.model.severity; | ||||
|             } else { | ||||
|                 return previous; | ||||
|             } | ||||
|         }, "info"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Notifies the user of an event. If there is a banner notification | ||||
|      * already active, then it will be dismissed or minimized automatically, | ||||
|      * and the provided notification displayed in its place. | ||||
|      * | ||||
|      * @param {NotificationModel} notificationModel The notification to | ||||
|      * display | ||||
|      * @returns {Notification} the provided notification decorated with | ||||
|      * functions to {@link Notification#dismiss} or {@link Notification#minimize} | ||||
|      */ | ||||
|     notify(notificationModel) { | ||||
|         let notification; | ||||
|         let activeNotification = this.activeNotification; | ||||
|  | ||||
|         notificationModel.severity = notificationModel.severity || "info"; | ||||
|         notificationModel.timestamp = moment.utc().format('YYYY-MM-DD hh:mm:ss.ms'); | ||||
|  | ||||
|         notification = new MCTNotification(notificationModel, this); | ||||
|  | ||||
|         this.notifications.push(notification); | ||||
|         this.setHighestSeverity(); | ||||
|  | ||||
|         /* | ||||
|         Check if there is already an active (ie. visible) notification | ||||
|             */ | ||||
|         if (!this.activeNotification) { | ||||
|             this.setActiveNotification(notification); | ||||
|         } else if (!this.activeTimeout) { | ||||
|             /* | ||||
|                 If there is already an active notification, time it out. If it's | ||||
|                 already got a timeout in progress (either because it has had | ||||
|                 timeout forced because of a queue of messages, or it had an | ||||
|                 autodismiss specified), leave it to run. Otherwise force a | ||||
|                 timeout. | ||||
|  | ||||
|                 This notification has been added to queue and will be | ||||
|                 serviced as soon as possible. | ||||
|                 */ | ||||
|             this.activeTimeout = setTimeout(() => { | ||||
|                 this.dismissOrMinimize(activeNotification); | ||||
|             }, DEFAULT_AUTO_DISMISS_TIMEOUT); | ||||
|         } | ||||
|          | ||||
|         return notification; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Used internally by the NotificationService | ||||
|      * @private | ||||
|      */ | ||||
|     setActiveNotification(notification) { | ||||
|         let shouldAutoDismiss; | ||||
|         this.activeNotification = notification; | ||||
|  | ||||
|         if (!notification) { | ||||
|             delete this.activeTimeout; | ||||
|             return; | ||||
|         } | ||||
|         this.emit('notification', notification); | ||||
|  | ||||
|         if (notification.model.severity === "info") { | ||||
|             shouldAutoDismiss = true; | ||||
|         } else { | ||||
|             shouldAutoDismiss = notification.model.autoDismiss; | ||||
|         } | ||||
|  | ||||
|         if (shouldAutoDismiss || this.selectNextNotification()) { | ||||
|             this.activeTimeout = setTimeout(() => { | ||||
|                 this.dismissOrMinimize(notification); | ||||
|             }, DEFAULT_AUTO_DISMISS_TIMEOUT); | ||||
|         } else { | ||||
|             delete this.activeTimeout; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Used internally by the NotificationService | ||||
|      * | ||||
|      * @private | ||||
|      */ | ||||
|     selectNextNotification() { | ||||
|         let notification; | ||||
|         let i = 0; | ||||
|  | ||||
|         /* | ||||
|         Loop through the notifications queue and find the first one that | ||||
|         has not already been minimized (manually or otherwise). | ||||
|             */ | ||||
|         for (; i < this.notifications.length; i++) { | ||||
|             notification = this.notifications[i]; | ||||
|  | ||||
|             if (!notification.model.minimized && | ||||
|                 notification !== this.activeNotification) { | ||||
|                 return notification; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -79,7 +79,6 @@ | ||||
|     } | ||||
|  | ||||
|     .c-grid { | ||||
|         z-index: -1; | ||||
|         pointer-events: none; | ||||
|  | ||||
|         &__x  { @include bgTicks($colorGridLines, 'x'); } | ||||
| @@ -92,13 +91,18 @@ | ||||
|             background: rgba($editColor, 0.1); | ||||
|         } | ||||
|  | ||||
|         .c-frame, | ||||
|         .l-layout { | ||||
|             &.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. | ||||
|                 [class*="__grid-holder"] { | ||||
|                     display: block; | ||||
|                 } | ||||
|  | ||||
|                 .l-layout [class*="__grid-holder"] { | ||||
|                     display: none; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -124,7 +128,6 @@ | ||||
|                 frames: [], | ||||
|                 frameStyles: [], | ||||
|                 rawPositions: {}, | ||||
|                 initSelect: true, | ||||
|                 drilledIn: undefined | ||||
|             } | ||||
|         },           | ||||
| @@ -137,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) { | ||||
| @@ -233,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) { | ||||
| @@ -278,6 +306,7 @@ | ||||
|             }, | ||||
|             handleDrop($event) { | ||||
|                 $event.preventDefault(); | ||||
|                 $event.stopPropagation(); | ||||
|  | ||||
|                 let child = JSON.parse($event.dataTransfer.getData('domainObject')); | ||||
|                 let duplicates = []; | ||||
| @@ -307,24 +336,25 @@ | ||||
|             }, | ||||
|             handleDragOver($event){ | ||||
|                 $event.preventDefault(); | ||||
|             }, | ||||
|             removeListeners() { | ||||
|                 if (this.listeners) { | ||||
|                     this.listeners.forEach(function (l) { | ||||
|                         l(); | ||||
|                     }) | ||||
|                 } | ||||
|                 this.listeners = []; | ||||
|             } | ||||
|         }, | ||||
|         mounted() { | ||||
|             this.removeSelectable = this.openmct.selection.selectable( | ||||
|                 this.$el, | ||||
|                 { | ||||
|                     item: this.newDomainObject | ||||
|                 }, | ||||
|                 this.initSelect | ||||
|             ); | ||||
|             this.openmct.selection.on('change', this.setSelection); | ||||
|         }, | ||||
|         destroyed: function () { | ||||
|             this.composition.off('add', this.onAddComposition); | ||||
|             this.composition.off('remove', this.onRemoveComposition); | ||||
|             this.openmct.off('change', this.selection); | ||||
|             this.removeSelectable(); | ||||
|             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" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 ]; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -14,9 +14,9 @@ | ||||
|                      :title="item.model.name">{{item.model.name}}</div> | ||||
|                 <div class="c-grid-item__metadata" | ||||
|                      :title="item.type.name"> | ||||
|                     <span>{{item.type.name}}</span> | ||||
|                     <span v-if="item.model.composition !== undefined"> | ||||
|                         - {{item.model.composition.length}} item<span v-if="item.model.composition.length !== 1">s</span> | ||||
|                     <span class="c-grid-item__metadata__type">{{item.type.name}}</span> | ||||
|                     <span class="c-grid-item__metadata__item-count" v-if="item.model.composition !== undefined"> | ||||
|                         {{item.model.composition.length}} item<span v-if="item.model.composition.length !== 1">s</span> | ||||
|                     </span> | ||||
|                 </div> | ||||
|             </div> | ||||
| @@ -45,8 +45,8 @@ | ||||
|         body.desktop & { | ||||
|             flex-flow: row wrap; | ||||
|             &__item { | ||||
|                 height: $ueBrowseGridItemLg; | ||||
|                 width: $ueBrowseGridItemLg; | ||||
|                 height: $gridItemDesk; | ||||
|                 width: $gridItemDesk; | ||||
|                 margin: 0 $interiorMargin $interiorMargin 0; | ||||
|             } | ||||
|         } | ||||
| @@ -62,8 +62,8 @@ | ||||
|  | ||||
|         &__type-icon { | ||||
|             filter: $colorKeyFilter; | ||||
|             flex: 0 0 32px; | ||||
|             font-size: 2em; // Drives the size of the alias indicator when present | ||||
|             flex: 0 0 $gridItemMobile; | ||||
|             font-size: floor($gridItemMobile / 2); | ||||
|             margin-right: $interiorMarginLg; | ||||
|         } | ||||
|  | ||||
| @@ -84,13 +84,22 @@ | ||||
|         &__name { | ||||
|             @include ellipsize(); | ||||
|             color: $colorItemFg; | ||||
|             font-size: 1.3em; | ||||
|             font-size: 1.2em; | ||||
|             font-weight: 400; | ||||
|             margin-bottom: $interiorMarginSm; | ||||
|         } | ||||
|  | ||||
|         &__metadata { | ||||
|             color: $colorItemFgDetails; | ||||
|             font-size: 0.9em; | ||||
|  | ||||
|             body.mobile & { | ||||
|                 [class*='__item-count'] { | ||||
|                     &:before { | ||||
|                         content: ' - '; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         &__controls { | ||||
| @@ -136,8 +145,8 @@ | ||||
|  | ||||
|             &__type-icon { | ||||
|                 flex: 1 1 auto; | ||||
|                 font-size: 6em; // Drives the size of the alias indicator when present | ||||
|                 margin: $interiorMargin 22.5%; | ||||
|                 font-size: floor($gridItemDesk / 3); | ||||
|                 margin: $interiorMargin 22.5% $interiorMargin * 3 22.5%; | ||||
|                 order: 2; | ||||
|                 transform: scale(0.9); | ||||
|                 transform-origin: center; | ||||
| @@ -149,6 +158,20 @@ | ||||
|                 justify-content: flex-end; | ||||
|                 order: 3; | ||||
|             } | ||||
|  | ||||
|             &__metadata { | ||||
|                 display: flex; | ||||
|  | ||||
|                 &__type { | ||||
|                     flex: 1 1 auto; | ||||
|                     @include ellipsize(); | ||||
|                 } | ||||
|  | ||||
|                 &__item-count { | ||||
|                     opacity: 0.7; | ||||
|                     flex: 0 0 auto; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </style> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <div class="c-ne__embed"> | ||||
|     <div class="c-ne__embed__snap-thumb" | ||||
|         v-if="embed.snapshot" | ||||
|         v-on:click="openSnapshot"> | ||||
|         v-on:click="openSnapshot(domainObject, entry, embed)"> | ||||
|         <img v-bind:src="embed.snapshot.src"> | ||||
|     </div> | ||||
|     <div class="c-ne__embed__info"> | ||||
|   | ||||
| @@ -8,8 +8,7 @@ | ||||
|             <span>{{formatTime(entry.createdOn, 'HH:mm:ss')}}</span> | ||||
|         </div> | ||||
|         <div class="c-ne__content"> | ||||
|             <!-- TODO: fix styling for c-input-inline when SCSS is merged and remove s-input-inline class here --> | ||||
|             <div class="c-ne__text c-input-inline s-input-inline" | ||||
|             <div class="c-ne__text c-input-inline" | ||||
|                  contenteditable="true" | ||||
|                  ref="contenteditable" | ||||
|                  v-on:blur="textBlur($event, entry.id)" | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
|         <div class="flex-elem holder flex-can-shrink s-snapshot-datetime"> | ||||
|             SNAPSHOT {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}} | ||||
|         </div> | ||||
|         <a class="s-button icon-pencil" title="Annotate"> | ||||
|         <a class="s-button icon-pencil" title="Annotate" @click="annotateSnapshot"> | ||||
|             <span class="title-label">Annotate</span> | ||||
|         </a> | ||||
|     </div> | ||||
| @@ -23,7 +23,7 @@ | ||||
|     <div class="abs object-holder t-image-holder s-image-holder"> | ||||
|         <div  | ||||
|             class="image-main s-image-main" | ||||
|             v-bind:style="{ backgroundImage: 'url(' + embed.snapshot.src + ')' }"> | ||||
|             :style="{ backgroundImage: 'url(' + embed.snapshot.src + ')' }"> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| @@ -23,16 +23,16 @@ | ||||
| define([ | ||||
|     'moment', | ||||
|     'zepto', | ||||
|     '../utils/SnapshotOverlay', | ||||
|     '../../res/templates/snapshotTemplate.html', | ||||
|     'vue' | ||||
|     'vue', | ||||
|     'painterro' | ||||
| ], | ||||
| function ( | ||||
|     Moment, | ||||
|     $, | ||||
|     SnapshotOverlay, | ||||
|     SnapshotTemplate, | ||||
|     Vue | ||||
|     Vue, | ||||
|     Painterro | ||||
| ) { | ||||
|     function EmbedController (openmct, domainObject) { | ||||
|         this.openmct = openmct; | ||||
| @@ -52,11 +52,102 @@ function ( | ||||
|  | ||||
|     EmbedController.prototype.navigate = function (embedType) { | ||||
|         this.objectService.getObjects([embedType]).then(function (objects) { | ||||
|             this.navigationService.setNavigation(objects[embedType]);    | ||||
|             this.navigationService.setNavigation(objects[embedType]); | ||||
|         }.bind(this)); | ||||
|     }; | ||||
|  | ||||
|     EmbedController.prototype.openSnapshot = function () { | ||||
|     EmbedController.prototype.openSnapshot = function (domainObject, entry, embed) { | ||||
|  | ||||
|         function annotateSnapshot(openmct) { | ||||
|             return function () { | ||||
|  | ||||
|                 var save = false, | ||||
|                     painterroInstance = {}, | ||||
|                     annotateOverlay = new Vue({ | ||||
|                         template: '<div id="snap-annotation"></div>' | ||||
|                     }), | ||||
|                     self = this; | ||||
|  | ||||
|                 var options = { | ||||
|                     cssClass: 'l-large-view', | ||||
|                     onDestroy: function () { | ||||
|                         annotateOverlay.$destroy(true); | ||||
|                     }, | ||||
|                     buttons: [ | ||||
|                         { | ||||
|                             label: 'Cancel', | ||||
|                             callback: function () { | ||||
|                                 save = false; | ||||
|                                 painterroInstance.save(); | ||||
|                             } | ||||
|                         }, | ||||
|                         { | ||||
|                             label: 'Save', | ||||
|                             callback: function () { | ||||
|                                 save = true; | ||||
|                                 painterroInstance.save(); | ||||
|                             } | ||||
|                         } | ||||
|                     ] | ||||
|                 }; | ||||
|  | ||||
|                 openmct.OverlayService.show(annotateOverlay.$mount().$el, options); | ||||
|  | ||||
|                 painterroInstance = Painterro({ | ||||
|                     id: 'snap-annotation', | ||||
|                     activeColor: '#ff0000', | ||||
|                     activeColorAlpha: 1.0, | ||||
|                     activeFillColor: '#fff', | ||||
|                     activeFillColorAlpha: 0.0, | ||||
|                     backgroundFillColor: '#000', | ||||
|                     backgroundFillColorAlpha: 0.0, | ||||
|                     defaultFontSize: 16, | ||||
|                     defaultLineWidth: 2, | ||||
|                     defaultTool: 'ellipse', | ||||
|                     hiddenTools: ['save', 'open', 'close', 'eraser', 'pixelize', 'rotate', 'settings', 'resize'], | ||||
|                     translation: { | ||||
|                         name: 'en', | ||||
|                         strings: { | ||||
|                             lineColor: 'Line', | ||||
|                             fillColor: 'Fill', | ||||
|                             lineWidth: 'Size', | ||||
|                             textColor: 'Color', | ||||
|                             fontSize: 'Size', | ||||
|                             fontStyle: 'Style' | ||||
|                         } | ||||
|                     }, | ||||
|                     saveHandler: function (image, done) { | ||||
|                         if (save) { | ||||
|                             var entryPos = self.findInArray(domainObject.entries, entry.id), | ||||
|                                 embedPos = self.findInArray(entry.embeds, embed.id); | ||||
|  | ||||
|                             if (entryPos !== -1 && embedPos !== -1) { | ||||
|                                 var url = image.asBlob(), | ||||
|                                     reader = new window.FileReader(); | ||||
|  | ||||
|                                 reader.readAsDataURL(url); | ||||
|                                 reader.onloadend = function () { | ||||
|                                     var snapshot = reader.result, | ||||
|                                         snapshotObject = { | ||||
|                                             src: snapshot, | ||||
|                                             type: url.type, | ||||
|                                             size: url.size, | ||||
|                                             modified: Date.now() | ||||
|                                         }, | ||||
|                                         dirString = 'entries[' + entryPos + '].embeds[' + embedPos + '].snapshot'; | ||||
|  | ||||
|                                     openmct.objects.mutate(domainObject, dirString, snapshotObject); | ||||
|                                 }; | ||||
|                             } | ||||
|                         } else { | ||||
|                             console.log('You cancelled the annotation!!!'); | ||||
|                         } | ||||
|                         done(true); | ||||
|                     } | ||||
|                 }).show(embed.snapshot.src); | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         var self = this, | ||||
|             snapshot = new Vue({ | ||||
|                 template: SnapshotTemplate, | ||||
| @@ -66,15 +157,22 @@ function ( | ||||
|                     }; | ||||
|                 }, | ||||
|                 methods: { | ||||
|                     formatTime: self.formatTime | ||||
|                     formatTime: self.formatTime, | ||||
|                     annotateSnapshot: annotateSnapshot(self.openmct), | ||||
|                     findInArray: self.findInArray | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|         function onDestroyCallback() { | ||||
|             snapshot.$destroy(true); | ||||
|         } | ||||
|         var options = { | ||||
|             onDestroy: onDestroyCallback, | ||||
|             cssClass: 'l-large-view' | ||||
|         }; | ||||
|  | ||||
|         this.openmct.OverlayService.show(snapshot.$mount().$el, {onDestroy: onDestroyCallback, cssClass: 'l-large-view'}); | ||||
|  | ||||
|         this.openmct.OverlayService.show(snapshot.$mount().$el, options); | ||||
|     }; | ||||
|  | ||||
|     EmbedController.prototype.formatTime = function (unixTime, timeFormat) { | ||||
| @@ -125,23 +223,20 @@ function ( | ||||
|                 var entryPosition = self.findInArray(self.domainObject.entries, entry.id), | ||||
|                     embedPosition = self.findInArray(entry.embeds, embed.id); | ||||
|  | ||||
|                 var warningDialog = self.dialogService.showBlockingMessage({ | ||||
|                 self.openmct.OverlayService.showBlockingMessage({ | ||||
|                     severity: "error", | ||||
|                     title: "This action will permanently delete this embed. Do you wish to continue?", | ||||
|                     options: [{ | ||||
|                         label: "OK", | ||||
|                     actionText: 'This Action will permanently delete this embed. Do you wish to continue?', | ||||
|                     buttons: [{ | ||||
|                         label: "No", | ||||
|                         callback: function () {} | ||||
|                     }, | ||||
|                     { | ||||
|                         label: "Yes", | ||||
|                         callback: function () { | ||||
|                             entry.embeds.splice(embedPosition, 1); | ||||
|                             var dirString = 'entries[' + entryPosition + '].embeds'; | ||||
|  | ||||
|                             self.openmct.objects.mutate(self.domainObject, dirString, entry.embeds); | ||||
|  | ||||
|                             warningDialog.dismiss(); | ||||
|                         } | ||||
|                     },{ | ||||
|                         label: "Cancel", | ||||
|                         callback: function () { | ||||
|                             warningDialog.dismiss(); | ||||
|                         } | ||||
|                     }] | ||||
|                 }); | ||||
| @@ -207,7 +302,8 @@ function ( | ||||
|             openSnapshot: self.openSnapshot, | ||||
|             formatTime: self.formatTime, | ||||
|             toggleActionMenu: self.toggleActionMenu, | ||||
|             actionToMenuDecorator: self.actionToMenuDecorator | ||||
|             actionToMenuDecorator: self.actionToMenuDecorator, | ||||
|             findInArray: self.findInArray | ||||
|         }; | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -81,23 +81,23 @@ function ( | ||||
|  | ||||
|         if (entryPos !== -1) { | ||||
|  | ||||
|             var errorDialog = this.dialogService.showBlockingMessage({ | ||||
|                 severity: "error", | ||||
|                 title: "This action will permanently delete this Notebook entry. Do you wish to continue?", | ||||
|                 options: [{ | ||||
|                     label: "OK", | ||||
|                     callback: function () { | ||||
|                         domainObject.entries.splice(entryPos, 1); | ||||
|                         openmct.objects.mutate(domainObject, 'entries', domainObject.entries); | ||||
|  | ||||
|                         errorDialog.dismiss(); | ||||
|             this.openmct.OverlayService.showBlockingMessage({ | ||||
|                 severity: "alert", | ||||
|                 actionText: "This action will permanently delete this Notebook entry. Do you wish to continue?", | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         label: "Ok", | ||||
|                         emphasis: true, | ||||
|                         callback: function () { | ||||
|                             domainObject.entries.splice(entryPos, 1); | ||||
|                             openmct.objects.mutate(domainObject, 'entries', domainObject.entries); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         label: "Cancel", | ||||
|                         callback: function () {} | ||||
|                     } | ||||
|                 },{ | ||||
|                     label: "Cancel", | ||||
|                     callback: function () { | ||||
|                         errorDialog.dismiss(); | ||||
|                     } | ||||
|                 }] | ||||
|                 ] | ||||
|             }); | ||||
|         } | ||||
|     }; | ||||
|   | ||||
| @@ -60,7 +60,7 @@ function ( | ||||
|         this.container = container; | ||||
|  | ||||
|         var notebookEmbed = { | ||||
|             inject:['openmct'], | ||||
|             inject:['openmct', 'domainObject'], | ||||
|             props:['embed', 'entry'], | ||||
|             template: EmbedTemplate, | ||||
|             data: embedController.exposedData, | ||||
| @@ -81,7 +81,7 @@ function ( | ||||
|  | ||||
|         var notebookVue = Vue.extend({ | ||||
|             template: NotebookTemplate, | ||||
|             provide: {openmct: self.openmct}, | ||||
|             provide: {openmct: self.openmct, domainObject: self.domainObject}, | ||||
|             components: { | ||||
|                 'notebook-entry': entryComponent, | ||||
|                 'search': search.default | ||||
|   | ||||
| @@ -21,71 +21,67 @@ | ||||
|  *****************************************************************************/ | ||||
| <template> | ||||
|     <div class="c-conductor" | ||||
|          :class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode', panning ? 'status-panning' : '']"> | ||||
|          :class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']"> | ||||
|         <form class="u-contents" ref="conductorForm" | ||||
|               @submit="isFixed ? setBoundsFromView($event) : setOffsetsFromView($event)"> | ||||
|  | ||||
|             <ConductorModeIcon class="c-conductor__mode-icon"></ConductorModeIcon> | ||||
|  | ||||
|             <div class="c-conductor__start-input"> | ||||
|                 <!-- Start input and controls --> | ||||
|                 <div class="c-ctrl-wrapper c-conductor-input c-conductor__start__fixed" | ||||
|                      v-if="isFixed"> | ||||
|                     <!-- Fixed input --> | ||||
|                     <div class="c-conductor__start__fixed__label">Start</div> | ||||
|                     <input class="c-input--datetime" | ||||
|                            type="text" autocorrect="off" spellcheck="false" | ||||
|                            ref="startDate" | ||||
|                            v-model="formattedBounds.start" | ||||
|                            @change="validateBounds('start', $event.target); setBoundsFromView()" /> | ||||
|                     <date-picker | ||||
|                             :default-date-time="formattedBounds.start" | ||||
|                             :formatter="timeFormatter" | ||||
|                             @date-selected="startDateSelected"></date-picker> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="c-ctrl-wrapper c-conductor-input c-conductor__start__delta" | ||||
|                      v-if="!isFixed"> | ||||
|                     <!-- RT input --> | ||||
|                     <div class="c-direction-indicator icon-minus"></div> | ||||
|                     <input class="c-input--hrs-min-sec" | ||||
|                            type="text" autocorrect="off" | ||||
|                            spellcheck="false" | ||||
|                            v-model="offsets.start" | ||||
|                            @change="validateOffsets($event); setOffsetsFromView()"> | ||||
|                 </div> | ||||
|             <div class="c-ctrl-wrapper c-conductor-input c-conductor__start-fixed" | ||||
|                  v-if="isFixed"> | ||||
|                 <!-- Fixed start --> | ||||
|                 <div class="c-conductor__start-fixed__label">Start</div> | ||||
|                 <input class="c-input--datetime" | ||||
|                        type="text" autocorrect="off" spellcheck="false" | ||||
|                        ref="startDate" | ||||
|                        v-model="formattedBounds.start" | ||||
|                        @change="validateBounds('start', $event.target); setBoundsFromView()" /> | ||||
|                 <date-picker | ||||
|                         :default-date-time="formattedBounds.start" | ||||
|                         :formatter="timeFormatter" | ||||
|                         @date-selected="startDateSelected"></date-picker> | ||||
|             </div> | ||||
|  | ||||
|             <div class="c-conductor__end-input"> | ||||
|                 <!-- End input and controls --> | ||||
|                 <div class="c-ctrl-wrapper c-conductor-input c-conductor__end__fixed" | ||||
|                      v-if="isFixed"> | ||||
|                     <!-- Fixed input --> | ||||
|                     <div class="c-conductor__end__fixed__label">End</div> | ||||
|                     <input class="c-input--datetime" | ||||
|                            type="text" autocorrect="off" spellcheck="false" | ||||
|                            v-model="formattedBounds.end" | ||||
|                            :disabled="!isFixed" | ||||
|                            ref="endDate" | ||||
|                            @change="validateBounds('end', $event.target); setBoundsFromView()"> | ||||
|                     <date-picker | ||||
|                             class="c-ctrl-wrapper--menus-left" | ||||
|                             :default-date-time="formattedBounds.end" | ||||
|                             :formatter="timeFormatter" | ||||
|                             @date-selected="endDateSelected"></date-picker> | ||||
|                 </div> | ||||
|             <div class="c-ctrl-wrapper c-conductor-input c-conductor__start-delta" | ||||
|                  v-if="!isFixed"> | ||||
|                 <!-- RT start --> | ||||
|                 <div class="c-direction-indicator icon-minus"></div> | ||||
|                 <input class="c-input--hrs-min-sec" | ||||
|                        type="text" autocorrect="off" | ||||
|                        spellcheck="false" | ||||
|                        v-model="offsets.start" | ||||
|                        @change="validateOffsets($event); setOffsetsFromView()"> | ||||
|             </div> | ||||
|  | ||||
|                 <div class="c-ctrl-wrapper c-conductor-input c-conductor__end__delta" | ||||
|                      v-if="!isFixed"> | ||||
|                     <!-- RT input --> | ||||
|                     <div class="c-direction-indicator icon-plus"></div> | ||||
|                     <input class="c-input--hrs-min-sec" | ||||
|                            type="text" | ||||
|                            autocorrect="off" | ||||
|                            spellcheck="false" | ||||
|                            v-model="offsets.end" | ||||
|                            @change="validateOffsets($event); setOffsetsFromView()"> | ||||
|             <div class="c-ctrl-wrapper c-conductor-input c-conductor__end-fixed"> | ||||
|                 <!-- Fixed end and RT 'last update' display --> | ||||
|                 <div class="c-conductor__end-fixed__label"> | ||||
|                     {{ isFixed ? 'End' : 'Updated' }} | ||||
|                 </div> | ||||
|                 <input class="c-input--datetime" | ||||
|                        type="text" autocorrect="off" spellcheck="false" | ||||
|                        v-model="formattedBounds.end" | ||||
|                        :disabled="!isFixed" | ||||
|                        ref="endDate" | ||||
|                        @change="validateBounds('end', $event.target); setBoundsFromView()"> | ||||
|                 <date-picker | ||||
|                         class="c-ctrl-wrapper--menus-left" | ||||
|                         :default-date-time="formattedBounds.end" | ||||
|                         :formatter="timeFormatter" | ||||
|                         @date-selected="endDateSelected" | ||||
|                         v-if="isFixed"></date-picker> | ||||
|             </div> | ||||
|  | ||||
|             <div class="c-ctrl-wrapper c-conductor-input c-conductor__end-delta" | ||||
|                  v-if="!isFixed"> | ||||
|                 <!-- RT end --> | ||||
|                 <div class="c-direction-indicator icon-plus"></div> | ||||
|                 <input class="c-input--hrs-min-sec" | ||||
|                        type="text" | ||||
|                        autocorrect="off" | ||||
|                        spellcheck="false" | ||||
|                        v-model="offsets.end" | ||||
|                        @change="validateOffsets($event); setOffsetsFromView()"> | ||||
|             </div> | ||||
|  | ||||
|             <conductor-axis | ||||
| @@ -112,65 +108,28 @@ | ||||
|         grid-row-gap: $interiorMargin; | ||||
|         align-items: center; | ||||
|  | ||||
|  | ||||
|         // Default: fixed mode, desktop | ||||
|         grid-template-rows: 1fr 1fr; | ||||
|         grid-template-columns: 20px auto 1fr auto; | ||||
|         grid-template-areas: | ||||
|                 "tc-mode-icon tc-start tc-ticks tc-end" | ||||
|                 "tc-controls tc-controls tc-controls tc-controls"; | ||||
|  | ||||
|         .c-conductor__end-input { | ||||
|             justify-content: flex-end; | ||||
|         } | ||||
|  | ||||
|         body.phone.portrait & { | ||||
|             &.is-fixed-mode { | ||||
|                 grid-row-gap: $interiorMargin; | ||||
|                 grid-template-rows: auto auto auto; | ||||
|                 grid-template-columns: 20px auto; | ||||
|                 grid-template-areas: | ||||
|                         "tc-mode-icon tc-start" | ||||
|                         "tc-mode-icon tc-end" | ||||
|                         "tc-mode-icon tc-controls"; | ||||
|  | ||||
|                 .c-conductor { | ||||
|                     &__mode-icon { | ||||
|                         grid-row: 1; | ||||
|                     } | ||||
|  | ||||
|                     &__ticks, | ||||
|                     &__zoom { | ||||
|                         display: none; | ||||
|                     } | ||||
|  | ||||
|                     &-input [class*='__label'] { | ||||
|                         // Start and end are in separate columns; make the labels line up | ||||
|                         width: 40px; | ||||
|                     } | ||||
|  | ||||
|                     &__end-input { | ||||
|                         justify-content: flex-start; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         &__mode-icon { | ||||
|             grid-area: tc-mode-icon; | ||||
|         } | ||||
|  | ||||
|         &__start-input, | ||||
|         &__end-input { | ||||
|         &__start-fixed, | ||||
|         &__start-delta { | ||||
|             grid-area: tc-start; | ||||
|             display: flex; | ||||
|         } | ||||
|  | ||||
|         &__start-input { | ||||
|             grid-area: tc-start; | ||||
|         } | ||||
|  | ||||
|         &__end-input { | ||||
|         &__end-fixed, | ||||
|         &__end-delta { | ||||
|             grid-area: tc-end; | ||||
|             display: flex; | ||||
|             justify-content: flex-end; | ||||
|         } | ||||
|  | ||||
|         &__ticks { | ||||
| @@ -186,12 +145,68 @@ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [class*='__delta'] { | ||||
|         [class*='-delta'] { | ||||
|             &:before { | ||||
|                 content: $glyph-icon-clock; | ||||
|                 font-family: symbolsfont; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         &.is-realtime-mode { | ||||
|             grid-template-columns: 20px auto 1fr auto auto; | ||||
|             grid-template-areas: | ||||
|                     "tc-mode-icon tc-start tc-ticks tc-updated tc-end" | ||||
|                     "tc-controls tc-controls tc-controls tc-controls tc-controls"; | ||||
|  | ||||
|             .c-conductor__end-fixed { | ||||
|                 grid-area: tc-updated; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         body.phone.portrait & { | ||||
|             grid-row-gap: $interiorMargin; | ||||
|             grid-template-rows: auto auto auto; | ||||
|             grid-template-columns: 20px auto auto; | ||||
|  | ||||
|             &__mode-icon { | ||||
|                 grid-row: 1; | ||||
|             } | ||||
|  | ||||
|             &__ticks, | ||||
|             &__zoom { | ||||
|                 display: none; | ||||
|             } | ||||
|  | ||||
|             &.is-fixed-mode { | ||||
|                 [class*='__start-fixed'], | ||||
|                 [class*='__end-fixed'] { | ||||
|                     [class*='__label'] { | ||||
|                         // Start and end are in separate columns; make the labels line up | ||||
|                         width: 30px; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 [class*='__end-input'] { | ||||
|                     justify-content: flex-start; | ||||
|                 } | ||||
|  | ||||
|                 grid-template-areas: | ||||
|                         "tc-mode-icon tc-start tc-start" | ||||
|                         "tc-mode-icon tc-end tc-end" | ||||
|                         "tc-mode-icon tc-controls tc-controls"; | ||||
|             } | ||||
|  | ||||
|             &.is-realtime-mode { | ||||
|                 grid-template-areas: | ||||
|                         "tc-mode-icon tc-start tc-updated" | ||||
|                         "tc-mode-icon tc-end tc-end" | ||||
|                         "tc-mode-icon tc-controls tc-controls"; | ||||
|  | ||||
|                 .c-conductor__end-fixed { | ||||
|                     justify-content: flex-end; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .c-conductor-input { | ||||
| @@ -215,16 +230,39 @@ | ||||
|         } | ||||
|  | ||||
|         input:invalid { | ||||
|             background: rgba($colorFormInvalid, 0.3); | ||||
|             background: rgba($colorFormInvalid, 0.5); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .is-realtime-mode { | ||||
|         button { | ||||
|             @include themedButton($colorTimeBg); | ||||
|             color: $colorTimeFg; | ||||
|  | ||||
|             &:hover { | ||||
|                 background: $colorTimeHov !important; | ||||
|                 color: $colorTimeFg !important; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         .c-conductor-input { | ||||
|             &:before { | ||||
|                 color: $colorTime; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         .c-conductor__end-fixed { | ||||
|             // Displays last RT udpate | ||||
|             color: $colorTime; | ||||
|  | ||||
|             input { | ||||
|                 // Remove input look | ||||
|                 background: none; | ||||
|                 box-shadow: none; | ||||
|                 color: $colorTime; | ||||
|                 pointer-events: none; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </style> | ||||
|  | ||||
| @@ -396,5 +434,3 @@ export default { | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -37,6 +37,7 @@ | ||||
|         @include bgTicks($c: rgba($colorBodyFg, 0.4)); | ||||
|         background-position: 0 50%; | ||||
|         background-size: 5px 2px; | ||||
|         border-radius: $controlCr; | ||||
|         height: $h; | ||||
|  | ||||
|         svg { | ||||
| @@ -76,34 +77,37 @@ | ||||
|         body.desktop .is-fixed-mode & { | ||||
|             @include cursorGrab(); | ||||
|             background-size: 3px 30%; | ||||
|             border-radius: $controlCr; | ||||
|             background-color: $colorBodyBgSubtle; | ||||
|             box-shadow: inset rgba(black, 0.2) 0 1px 1px; | ||||
|             box-shadow: inset rgba(black, 0.4) 0 1px 1px; | ||||
|             transition: $transOut; | ||||
|  | ||||
|             svg text { | ||||
|                 fill: $colorBodyFg; | ||||
|                 stroke: $colorBodyBgSubtle; | ||||
|                 transition: $transOut; | ||||
|             } | ||||
|  | ||||
|             &:hover, | ||||
|             &:active { | ||||
|                 $c: $colorKeySubtle; | ||||
|                 background-color: $c; | ||||
|                 transition: $transIn; | ||||
|                 svg text { | ||||
|                     stroke: $c; | ||||
|                     transition: $transIn; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         .is-realtime-mode & { | ||||
|             $c: 1px solid rgba($colorTime, 0.7); | ||||
|             border-left: $c; | ||||
|             border-right: $c; | ||||
|             svg text { | ||||
|                 fill: $colorTime; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| @@ -199,11 +203,10 @@ export default { | ||||
|                     let bounds = this.openmct.time.bounds(); | ||||
|                     let deltaTime = bounds.end - bounds.start; | ||||
|                     let newStart = bounds.start - percX * deltaTime; | ||||
|                     this.bounds = { | ||||
|                     this.$emit('panAxis',{ | ||||
|                         start: newStart, | ||||
|                         end: newStart + deltaTime | ||||
|                     }; | ||||
|                     this.$emit('panAxis', this.bounds); | ||||
|                     }); | ||||
|                     this.dragging = false; | ||||
|                 }) | ||||
|             } else { | ||||
|   | ||||
| @@ -21,10 +21,10 @@ | ||||
|  *****************************************************************************/ | ||||
| <template> | ||||
|     <div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up"> | ||||
|         <div class="c-button--menu c-mode-button" | ||||
|         <button class="c-button--menu c-mode-button" | ||||
|              @click="toggleMenu($event)"> | ||||
|             <span class="c-button__label">{{selectedMode.name}}</span> | ||||
|         </div> | ||||
|         </button> | ||||
|         <div class="c-menu c-super-menu c-conductor__mode-menu" | ||||
|              v-if="showMenu"> | ||||
|             <div class="c-super-menu__menu"> | ||||
| @@ -66,16 +66,6 @@ | ||||
|             min-width: 200px; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .is-realtime-mode { | ||||
|         .c-mode-button { | ||||
|             background: $colorTimeBg; | ||||
|  | ||||
|             &:hover { | ||||
|                 background: $colorTimeHov; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
|   | ||||
| @@ -22,11 +22,11 @@ | ||||
| <template> | ||||
|     <div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up" | ||||
|          v-if="selectedTimeSystem.name"> | ||||
|         <div class="c-button--menu c-time-system-button" | ||||
|         <button class="c-button--menu c-time-system-button" | ||||
|             :class="selectedTimeSystem.cssClass" | ||||
|              @click="toggleMenu($event)"> | ||||
|             <span class="c-button__label">{{selectedTimeSystem.name}}</span> | ||||
|         </div> | ||||
|         </button> | ||||
|         <div class="c-menu" v-if="showMenu"> | ||||
|             <ul> | ||||
|                 <li @click="setTimeSystemFromView(timeSystem)" | ||||
| @@ -40,20 +40,6 @@ | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <style lang="scss"> | ||||
|     @import "~styles/sass-base"; | ||||
|  | ||||
|     .is-realtime-mode { | ||||
|         .c-time-system-button { | ||||
|             background: $colorTimeBg; | ||||
|  | ||||
|             &:hover { | ||||
|                 background: $colorTimeHov; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|     inject: ['openmct', 'configuration'], | ||||
|   | ||||
| @@ -108,7 +108,7 @@ | ||||
|         grid-gap: 1px; | ||||
|         height: 100%; | ||||
|  | ||||
|         $mutedOpacity: 0.7; | ||||
|         $mutedOpacity: 0.5; | ||||
|  | ||||
|         ul { | ||||
|             display: contents; | ||||
| @@ -127,7 +127,7 @@ | ||||
|             padding: $interiorMargin; | ||||
|  | ||||
|             &.is-in-month { | ||||
|                 background: rgba($colorBodyFg, 0.1); | ||||
|                 background: $colorMenuElementHilite; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
							
								
								
									
										336
									
								
								src/styles-new/_constants-espresso.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										336
									
								
								src/styles-new/_constants-espresso.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,336 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /************************************************** ESPRESSO THEME CONSTANTS */ | ||||
|  | ||||
| @import "constants"; | ||||
|  | ||||
| // Functions | ||||
| @function buttonBg($c: $colorBtnBg) { | ||||
|     @return linear-gradient(lighten($c, 5%), $c); | ||||
| } | ||||
|  | ||||
| // Constants | ||||
| $fontBaseSize: 12px; | ||||
| $smallCr: 2px; | ||||
| $controlCr: 3px; | ||||
| $basicCr: 4px; | ||||
|  | ||||
| // Base colors | ||||
| $colorBodyBg: #393939; | ||||
| $colorBodyFg: #aaa; | ||||
| $colorGenBg: #222; | ||||
| $colorHeadBg: #262626; | ||||
| $colorHeadFg: $colorBodyFg; | ||||
| $colorStatusBarBg: $colorHeadBg; | ||||
| $colorStatusBarFg: $colorBodyFg; | ||||
| $colorStatusBarFgHov: #aaa; | ||||
| $colorKey: #0099cc; | ||||
| $colorKeyFg: #fff; | ||||
| $colorKeyHov: #00c0f6; | ||||
| $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; | ||||
| $colorInteriorBorder: rgba($colorBodyFg, 0.2); | ||||
| $colorA: #ccc; | ||||
| $colorAHov: #fff; | ||||
|  | ||||
| // Layout | ||||
| $shellMainPad: 4px 0; | ||||
| $shellPanePad: $interiorMargin, 7px; | ||||
|  | ||||
| // Status colors, mainly used for messaging and item ancillary symbols | ||||
| $colorStatusFg: #999; | ||||
| $colorStatusDefault: #ccc; | ||||
| $colorStatusInfo: #60ba7b; | ||||
| $colorStatusInfoFilter: invert(58%) sepia(44%) saturate(405%) hue-rotate(85deg) brightness(102%) contrast(92%); | ||||
| $colorStatusAlert: #ffb66c; | ||||
| $colorStatusAlertFilter: invert(78%) sepia(26%) saturate(1160%) hue-rotate(324deg) brightness(107%) contrast(101%); | ||||
| $colorStatusError: #da0004; | ||||
| $colorStatusErrorFilter: invert(10%) sepia(96%) saturate(4360%) hue-rotate(351deg) brightness(111%) contrast(115%); | ||||
| $colorStatusBtnBg: #666; // Where is this used? | ||||
|  | ||||
| // States | ||||
| $colorPausedBg: #ff9900; | ||||
| $colorPausedFg: #fff; | ||||
| $colorOk: #33cc33; | ||||
|  | ||||
| // Base variations | ||||
| $colorBodyBgSubtle: lighten($colorBodyBg, 5%); | ||||
| $colorBodyBgSubtleHov: darken($colorKey, 50%); | ||||
| $colorKeySubtle: darken($colorKey, 10%); | ||||
|  | ||||
| // Time Colors | ||||
| $colorTime: #618cff; | ||||
| $colorTimeBg: $colorTime; | ||||
| $colorTimeFg: lighten($colorTimeBg, 30%); | ||||
| $colorTimeHov: lighten($colorTime, 10%); | ||||
| $colorTimeSubtle: darken($colorTime, 20%); | ||||
| $colorTOI: $colorBodyFg; // was $timeControllerToiLineColor | ||||
| $colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov | ||||
|  | ||||
| // Edit Colors | ||||
| $editColor: #00c7c3; | ||||
| $editColorFg: $colorBodyFg; | ||||
| $browseBorderSelectableHov: 1px dotted rgba($colorBodyFg, 0.2); | ||||
| $browseShdwSelectableHov: rgba($colorBodyFg, 0.2) 0 0 3px; | ||||
| $browseBorderSelected: 1px solid rgba($colorBodyFg, 0.6); | ||||
| $editBorderSelectable: 1px dotted rgba($editColor, 1); | ||||
| $editBorderSelectableHov: 1px dashed rgba($editColor, 1); | ||||
| $editBorderSelected: 1px solid $editColor; | ||||
| $editBorderDrilledIn: 1px dashed #ff4d9a; | ||||
| $colorGridLines: rgba($editColor, 0.2); | ||||
|  | ||||
| // Icons | ||||
| $colorIconAlias: #4af6f3; | ||||
| $colorIconAliasForKeyFilter: #aaa; | ||||
|  | ||||
| // Alerts, dialogs and notifications | ||||
| $colorProgressBarOuter: rgba(#000, 0.1); | ||||
| $colorProgressBarAmt: #0a0; | ||||
|  | ||||
| // Buttons and Controls | ||||
| $colorBtnBg: lighten($colorBodyBg, 10%); // ! | ||||
| $colorBtnBgHov: lighten($colorBtnBg, 10%); // ! | ||||
| $colorBtnFg: lighten($colorBodyFg, 10%); // ! | ||||
| $colorBtnFgHov: $colorBtnFg; | ||||
| $colorBtnMajorBg: $colorKey; | ||||
| $colorBtnMajorBgHov: $colorKeyHov; | ||||
| $colorBtnMajorFg: $colorKeyFg; | ||||
| $colorBtnMajorFgHov: darken($colorBtnMajorFg, 10%); | ||||
| $colorBtnCautionBg: #f16f6f; | ||||
| $colorBtnCautionBgHov: #f1504e; | ||||
| $colorBtnCautionFg: $colorBtnFg; | ||||
| $colorClickIcon: $colorKey; | ||||
| $colorClickIconBgHov: rgba($colorKey, 0.6); | ||||
| $colorClickIconFgHov: $colorKeyHov; | ||||
|  | ||||
| // Menus | ||||
| $colorMenuBg: lighten($colorBodyBg, 20%); | ||||
| $colorMenuFg: lighten($colorBodyFg, 30%); | ||||
| $colorMenuIc: lighten($colorKey, 15%); | ||||
| $colorMenuHovBg: $colorMenuIc; | ||||
| $colorMenuHovFg: lighten($colorMenuFg, 10%); | ||||
| $colorMenuHovIc: $colorMenuHovFg; | ||||
| $colorMenuElementHilite: lighten($colorMenuBg, 10%); | ||||
| $shdwMenu: rgba(black, 0.5) 0 1px 5px; | ||||
| $shdwMenuText: none; | ||||
| $menuItemPad: $interiorMargin, floor($interiorMargin * 1.25); | ||||
|  | ||||
| // Palettes and Swatches | ||||
| $paletteItemBorderOuterColorSelected: black; | ||||
| $paletteItemBorderInnerColorSelected: white; | ||||
| $paletteItemBorderInnerColor: rgba($paletteItemBorderOuterColorSelected, 0.3); | ||||
|  | ||||
| // Form colors | ||||
| $colorCheck: $colorKey; | ||||
| $colorFormRequired: $colorKey; | ||||
| $colorFormValid: $colorOk; | ||||
| $colorFormError: #990000; | ||||
| $colorFormInvalid: #ff2200; | ||||
| $colorFormFieldErrorBg: $colorFormError; | ||||
| $colorFormFieldErrorFg: rgba(#fff, 0.6); | ||||
| $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%); | ||||
| $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%); | ||||
| $colorInspectorFg: $colorBodyFg; | ||||
| $colorInspectorPropName: darken($colorBodyFg, 20%); | ||||
| $colorInspectorPropVal: lighten($colorInspectorFg, 15%); | ||||
| $colorInspectorSectionHeaderBg: lighten($colorInspectorBg, 5%); | ||||
| $colorInspectorSectionHeaderFg: lighten($colorInspectorBg, 40%); | ||||
|  | ||||
| // Overlay | ||||
| $overlayColorBg: $colorMenuBg; | ||||
| $overlayColorFg: $colorMenuFg; | ||||
| $overlayButtonColorBg: lighten($overlayColorBg, 20%); | ||||
| $overlayButtonColorFg: #fff; | ||||
| $overlayCr: $interiorMarginLg; | ||||
|  | ||||
| // Indicator colors | ||||
| $colorIndicatorAvailable: $colorKey; | ||||
| $colorIndicatorDisabled: #444; | ||||
| $colorIndicatorOn: $colorOk; | ||||
| $colorIndicatorOff: #666; | ||||
|  | ||||
| // Limits and staleness colors// | ||||
| $colorTelemFresh: lighten($colorBodyFg, 20%); | ||||
| $colorTelemStale: darken($colorBodyFg, 20%); | ||||
| $styleTelemStale: italic; | ||||
| $colorLimitYellowBg: rgba(#ffaa00, 0.3); | ||||
| $colorLimitYellowIc: #ffaa00; | ||||
| $colorLimitRedBg: rgba(red, 0.3); | ||||
| $colorLimitRedIc: red; | ||||
|  | ||||
| // Bubble colors | ||||
| $colorInfoBubbleBg: $colorMenuBg; | ||||
| $colorInfoBubbleFg: #666; | ||||
|  | ||||
| // Items | ||||
| $colorItemBg: buttonBg($colorBtnBg); | ||||
| $colorItemBgHov: buttonBg(lighten($colorBtnBg, 5%)); | ||||
| $colorListItemBg: transparent; | ||||
| $colorListItemBgHov: rgba($colorKey, 0.1); | ||||
| $colorItemFg: $colorBtnFg; | ||||
| $colorItemFgDetails: darken($colorItemFg, 20%); | ||||
| $shdwItemText: none; | ||||
|  | ||||
| // Tabular | ||||
| $colorTabBorder: lighten($colorBodyBg, 10%); | ||||
| $colorTabBodyBg: $colorBodyBg; | ||||
| $colorTabBodyFg: lighten($colorBodyFg, 20%); | ||||
| $colorTabHeaderBg: lighten($colorBodyBg, 10%); | ||||
| $colorTabHeaderFg: lighten($colorBodyFg, 20%); | ||||
| $colorTabHeaderBorder: $colorBodyBg; | ||||
|  | ||||
| // Plot | ||||
| $colorPlotBg: rgba(black, 0.05); | ||||
| $colorPlotFg: $colorBodyFg; | ||||
| $colorPlotHash: black; | ||||
| $opacityPlotHash: 0.2; | ||||
| $stylePlotHash: dashed; | ||||
| $colorPlotAreaBorder: $colorInteriorBorder; | ||||
| $colorPlotLabelFg: darken($colorPlotFg, 20%); | ||||
| $legendCollapsedNameMaxW: 50%; | ||||
| $legendHoverValueBg: rgba($colorBodyFg, 0.2); | ||||
|  | ||||
| // Tree | ||||
| $colorTreeBg: transparent; | ||||
| $colorItemTreeHoverBg: lighten($colorBodyBg, 10%); | ||||
| $colorItemTreeHoverFg: lighten($colorBodyFg, 10%); | ||||
| $colorItemTreeIcon: $colorKey; // Used | ||||
| $colorItemTreeIconHover: $colorItemTreeIcon; // Used | ||||
| $colorItemTreeFg: $colorBodyFg; | ||||
| $colorItemTreeSelectedBg: darken($colorKey, 15%); | ||||
| $colorItemTreeSelectedFg: $colorBodyBg; | ||||
| $colorItemTreeEditingBg: $editColor; | ||||
| $colorItemTreeEditingFg: $editColorFg; | ||||
| $colorItemTreeVC: $colorBodyFg; | ||||
| $colorItemTreeVCHover: $colorKey; | ||||
| $shdwItemTreeIcon: none; | ||||
|  | ||||
| // Images | ||||
| $colorThumbHoverBg: $colorItemTreeHoverBg; | ||||
|  | ||||
| // Scrollbar | ||||
| $scrollbarTrackSize: 7px; | ||||
| $scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px; | ||||
| $scrollbarTrackColorBg: rgba(#000, 0.2); | ||||
| $scrollbarThumbColor: darken($colorBodyBg, 50%); | ||||
| $scrollbarThumbColorHov: $colorKey; | ||||
| $scrollbarThumbColorMenu: lighten($colorMenuBg, 10%); | ||||
| $scrollbarThumbColorMenuHov: lighten($scrollbarThumbColorMenu, 2%); | ||||
|  | ||||
| // Splitter | ||||
| $splitterHandleD: 2px; | ||||
| $splitterHandleHitMargin: 4px; | ||||
| $colorSplitterBaseBg: $colorBodyBg; | ||||
| $colorSplitterBg: lighten($colorSplitterBaseBg, 10%); | ||||
| $colorSplitterFg: $colorBodyBg; | ||||
| $colorSplitterHover: $colorKey; | ||||
| $colorSplitterActive: $colorKey; | ||||
| $splitterBtnD: (16px, 35px); // height, width | ||||
| $splitterBtnColorBg: $colorBtnBg; | ||||
| $splitterBtnColorFg: #999; | ||||
| $splitterBtnLabelColorFg: #666; | ||||
| $splitterCollapsedBtnColorBg: #222; | ||||
| $splitterCollapsedBtnColorFg: #666; | ||||
| $splitterCollapsedBtnColorBgHov: $colorKey; | ||||
| $splitterCollapsedBtnColorFgHov: $colorKeyFg; | ||||
|  | ||||
| // Mobile | ||||
| $colorMobilePaneLeft: darken($colorBodyBg, 2%); | ||||
| $colorMobilePaneLeftTreeItemBg: rgba($colorBodyFg, 0.1); | ||||
| $colorMobilePaneLeftTreeItemFg: $colorItemTreeFg; | ||||
| $colorMobileSelectListTreeItemBg: rgba(#000, 0.05); | ||||
|  | ||||
| // About Screen | ||||
| $colorAboutLink: $colorKeySubtle; | ||||
|  | ||||
| // Loading | ||||
| $colorLoadingFg: #776ba2; | ||||
| $colorLoadingBg: rgba($colorLoadingFg, 0.1); | ||||
|  | ||||
| // Transitions | ||||
| $transIn: all 50ms ease-in-out; | ||||
| $transOut: all 250ms ease-in-out; | ||||
| $transInBounce: all 200ms cubic-bezier(.47,.01,.25,1.5); | ||||
| $transInBounceBig: all 300ms cubic-bezier(.2,1.6,.6,3); | ||||
|  | ||||
| // Discrete items, like Notebook entries, Widget rules | ||||
| $createBtnTextTransform: uppercase; | ||||
|  | ||||
| @mixin discreteItem() { | ||||
|     background: rgba($colorBodyFg,0.1); | ||||
|     border: none; | ||||
|     border-radius: $controlCr; | ||||
|  | ||||
|     .c-input-inline:hover { | ||||
|         background: $colorBodyBg; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin discreteItemInnerElem() { | ||||
|     border: 1px solid rgba(#fff, 0.1); | ||||
|     border-radius: $controlCr; | ||||
| } | ||||
|  | ||||
| @mixin themedButton($c: $colorBtnBg) { | ||||
|     background: linear-gradient(lighten($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; | ||||
| */ | ||||
|  | ||||
| // Content status | ||||
| /* | ||||
| $colorAlert: #ff3c00; | ||||
| $colorWarningHi: #990000; | ||||
| $colorWarningLo: #ff9900; | ||||
| $colorDiagnostic: #a4b442; | ||||
| $colorCommand: #3693bd; | ||||
| $colorInfo: #2294a2; | ||||
| $colorOk: #33cc33; | ||||
| */ | ||||
| @@ -20,115 +20,77 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /****************************************************** SNOW THEME CONSTANTS */ | ||||
|  | ||||
| @import "constants"; | ||||
|  | ||||
| // Functions | ||||
| @function pullForward($c: $colorBodyBg, $p: 20%) { | ||||
|     // For dark interfaces, lighter things come forward - opposite for light interfaces | ||||
|     @return darken($c, $p); | ||||
| @function buttonBg($c: $colorBtnBg) { | ||||
|     @return $c; | ||||
| } | ||||
|  | ||||
| @function pushBack($c: $colorBodyBg, $p: 20%) { | ||||
|     // For dark interfaces, darker things move back - opposite for light interfaces | ||||
|     @return lighten($c, $p); | ||||
| } | ||||
|  | ||||
| // Global | ||||
| // Constants | ||||
| $fontBaseSize: 12px; | ||||
| $smallCr: 2px; | ||||
| $controlCr: 3px; | ||||
| $basicCr: 4px; | ||||
|  | ||||
| // Base colors | ||||
| $colorBodyBg: #fcfcfc; | ||||
| $colorBodyFg: #666; | ||||
| $colorGenBg: #fff; | ||||
| $colorHeadBg: #eee; | ||||
| $colorHeadFg: $colorBodyFg; | ||||
| $colorStatusBarBg: #000; | ||||
| $colorStatusBarFg: #999; | ||||
| $colorStatusBarFgHov: #aaa; | ||||
| $colorKey: #0099cc; | ||||
| $colorKeyFilter: brightness(0.9) sepia(1) hue-rotate(145deg) saturate(6); | ||||
| $colorKeyFilterHov: brightness(1) sepia(1) hue-rotate(145deg) saturate(7); | ||||
| $colorKeySelectedBg: $colorKey; | ||||
| $colorKeyFg: #fff; | ||||
| $colorKeyHov: #00c0f6; | ||||
| $colorEditAreaBg: #eafaff; // Deprecated, use $editColor instead | ||||
| $colorEditAreaFg: #4bb1c7; // Deprecated, use $editColor instead | ||||
| $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; | ||||
| $colorInteriorBorder: rgba($colorBodyFg, 0.2); | ||||
| $colorA: #999; | ||||
| $colorAHov: $colorKey; | ||||
| $contrastRatioPercent: 40%; | ||||
| $hoverRatioPercent: 10%; | ||||
| $basicCr: 4px; | ||||
| $controlCr: 3px; | ||||
| $smallCr: 2px; | ||||
| $overlayCr: 11px; | ||||
| $shdwTextSubtle: rgba(black, 0.2) 0 1px 2px; | ||||
|  | ||||
| // Variations | ||||
| $colorBodyBgSubtle: pullForward($colorBodyBg, 5%); | ||||
| $colorBodyBgSubtleHov: pushBack($colorKey, 50%); | ||||
| $colorKeySubtle: pushBack($colorKey, 50%); | ||||
| // Layout | ||||
| $shellMainPad: 4px 0; | ||||
| $shellPanePad: $interiorMargin, 7px; | ||||
|  | ||||
| // Status colors, mainly used for messaging and item ancillary symbols | ||||
| $colorStatusFg: #999; | ||||
| $colorStatusDefault: #ccc; | ||||
| $colorStatusInfo: #60ba7b; | ||||
| $colorStatusInfoFilter: invert(64%) sepia(42%) saturate(416%) hue-rotate(85deg) brightness(93%) contrast(93%); | ||||
| $colorStatusAlert: #ffb66c; | ||||
| $colorStatusAlertFilter: invert(89%) sepia(26%) saturate(5035%) hue-rotate(316deg) brightness(114%) contrast(107%); | ||||
| $colorStatusError: #da0004; | ||||
| $colorStatusErrorFilter: invert(8%) sepia(96%) saturate(4511%) hue-rotate(352deg) brightness(136%) contrast(114%); | ||||
| $colorStatusBtnBg: #666; // Where is this used? | ||||
|  | ||||
| // States | ||||
| $colorPausedBg: #ff9900; | ||||
| $colorPausedFg: #fff; | ||||
| $colorOk: #33cc33; | ||||
|  | ||||
| // Base variations | ||||
| $colorBodyBgSubtle: darken($colorBodyBg, 5%); | ||||
| $colorBodyBgSubtleHov: lighten($colorKey, 50%); | ||||
| $colorKeySubtle: lighten($colorKey, 50%); | ||||
|  | ||||
| // Time Colors | ||||
| $colorTime: #618cff; | ||||
| $colorTimeBg: $colorTime; | ||||
| $colorTimeFg: $colorBodyBg; | ||||
| $colorTimeHov: pushBack($colorTime, 5%); | ||||
| $colorTimeSubtle: pushBack($colorTime, 20%); | ||||
|  | ||||
| // Buttons and Controls | ||||
| $btnPad: $interiorMargin, $interiorMargin * 1.25; | ||||
| $colorBtnBg: #aaaaaa; | ||||
| $colorBtnBgHov: pullForward($colorBtnBg, $hoverRatioPercent); | ||||
| $colorBtnFg: #fff; | ||||
| $colorBtnFgHov: $colorBtnFg; | ||||
| $colorBtnIcon: #eee; | ||||
| $colorBtnIconHov: $colorBtnFgHov; | ||||
| $colorBtnMajorBg: $colorKey; | ||||
| $colorBtnMajorBgHov: $colorKeyHov; | ||||
| $colorBtnMajorFg: $colorKeyFg; | ||||
| $colorBtnMajorFgHov: pushBack($colorBtnMajorFg, $hoverRatioPercent); | ||||
| $colorBtnCautionBg: #f16f6f; | ||||
| $colorBtnCautionBgHov: #f1504e; | ||||
| $colorBtnCautionFg: $colorBtnFg; | ||||
| $colorClickIcon: $colorKey; | ||||
| $colorClickIconHov: $colorKeyHov; | ||||
| $colorToggleIcon: rgba($colorClickIcon, 0.5); | ||||
| $colorToggleIconActive: $colorKey; | ||||
| $colorToggleIconHov: rgba($colorToggleIconActive, 0.5); | ||||
| $colorInvokeMenu: #000; | ||||
| $contrastInvokeMenuPercent: 40%; | ||||
| $shdwBtns: none; | ||||
| $shdwBtnsOverlay: none; | ||||
| $sliderColorBase: $colorKey; | ||||
| $sliderColorRangeHolder: rgba(black, 0.07); | ||||
| $sliderColorRange: rgba($sliderColorBase, 0.2); | ||||
| $sliderColorRangeHov: rgba($sliderColorBase, 0.4); | ||||
| $sliderColorKnob: pushBack($sliderColorBase, 20%); | ||||
| $sliderColorKnobHov: rgba($sliderColorBase, 0.7); | ||||
| $sliderColorRangeValHovBg: $sliderColorRange; | ||||
| $sliderColorRangeValHovFg: $colorBodyFg; | ||||
| $sliderKnobW: 15px; | ||||
| $sliderKnobR: 2px; | ||||
| $timeControllerToiLineColor: $colorBodyFg; | ||||
| $timeControllerToiLineColorHov: $colorTime; | ||||
| $colorTransLucBg: #666; // Used as a visual blocking element over variable backgrounds, like imagery | ||||
| $createBtnTextTransform: uppercase; | ||||
|  | ||||
| // Foundation Colors | ||||
| $colorAlt1: #776ba2; | ||||
| $colorAlert: #ff3c00; | ||||
| $colorWarningHi: #990000; | ||||
| $colorWarningLo: #ff9900; | ||||
| $colorDiagnostic: #a4b442; | ||||
| $colorCommand: #3693bd; | ||||
| $colorInfo: #2294a2; | ||||
| $colorOk: #33cc33; | ||||
| $colorIconAlias: #4af6f3; | ||||
| $colorIconAliasForKeyFilter: #aaa; | ||||
| $colorPausedBg: #ff9900; | ||||
| $colorPausedFg: #fff; | ||||
| $colorCreateBtn: $colorKey; | ||||
| $colorInvokeMenu: #fff; | ||||
| $colorObjHdrTxt: $colorBodyFg; | ||||
| $colorObjHdrIc: lighten($colorObjHdrTxt, 30%); | ||||
| $colorTick: rgba(black, 0.2); | ||||
| $colorTimeHov: lighten($colorTime, 5%); | ||||
| $colorTimeSubtle: lighten($colorTime, 20%); | ||||
| $colorTOI: $colorBodyFg; // was $timeControllerToiLineColor | ||||
| $colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov | ||||
|  | ||||
| // Edit Colors | ||||
| $editColor: #00c7c3; | ||||
| $editColorFg: $colorBodyFg; | ||||
| $browseBorderSelectableHov: 1px dotted rgba($colorBodyFg, 0.2); | ||||
| $browseShdwSelectableHov: rgba($colorBodyFg, 0.2) 0 0 3px; | ||||
| $browseBorderSelected: 1px solid rgba($colorBodyFg, 0.6); | ||||
| @@ -138,18 +100,41 @@ $editBorderSelected: 1px solid $editColor; | ||||
| $editBorderDrilledIn: 1px dashed #ff4d9a; | ||||
| $colorGridLines: rgba($editColor, 0.2); | ||||
|  | ||||
| // Icons | ||||
| $colorIconAlias: #4af6f3; | ||||
| $colorIconAliasForKeyFilter: #aaa; | ||||
|  | ||||
| // Alerts, dialogs and notifications | ||||
| $colorProgressBarOuter: rgba(#000, 0.1); | ||||
| $colorProgressBarAmt: #0a0; | ||||
|  | ||||
| // Buttons and Controls | ||||
| $colorBtnBg: #aaaaaa; | ||||
| $colorBtnBgHov: darken($colorBtnBg, 10%); | ||||
| $colorBtnFg: #fff; | ||||
| $colorBtnFgHov: $colorBtnFg; | ||||
| $colorBtnMajorBg: $colorKey; | ||||
| $colorBtnMajorBgHov: $colorKeyHov; | ||||
| $colorBtnMajorFg: $colorKeyFg; | ||||
| $colorBtnMajorFgHov: lighten($colorBtnMajorFg, 10%); | ||||
| $colorBtnCautionBg: #f16f6f; | ||||
| $colorBtnCautionBgHov: #f1504e; | ||||
| $colorBtnCautionFg: $colorBtnFg; | ||||
| $colorClickIcon: $colorKey; | ||||
| $colorClickIconBgHov: rgba($colorKey, 0.2); | ||||
| $colorClickIconFgHov: $colorKeyHov; | ||||
|  | ||||
| // Menus | ||||
| $colorMenuBg: pushBack($colorBodyBg, 10%); | ||||
| $colorMenuFg: pullForward($colorMenuBg, 70%); | ||||
| $colorMenuBg: lighten($colorBodyBg, 10%); | ||||
| $colorMenuFg: darken($colorMenuBg, 70%); | ||||
| $colorMenuIc: $colorKey; | ||||
| $colorMenuHovBg: $colorMenuIc; //pullForward($colorMenuBg, $hoverRatioPercent); | ||||
| $colorMenuHovBg: $colorMenuIc; | ||||
| $colorMenuHovFg: $colorMenuBg; | ||||
| $colorMenuHovIc: $colorMenuBg; | ||||
| $colorMenuElementHilite: darken($colorMenuBg, 10%); | ||||
| $shdwMenu: rgba(black, 0.5) 0 1px 5px; | ||||
| $shdwMenuText: none; | ||||
| $colorCreateMenuLgIcon: $colorKey; | ||||
| $colorCreateMenuText: $colorBodyFg; | ||||
| $menuItemPad: ($interiorMargin, nth($btnPad, 2)); | ||||
| $menuItemPad: $interiorMargin, floor($interiorMargin * 1.25); | ||||
|  | ||||
| // Palettes and Swatches | ||||
| $paletteItemBorderOuterColorSelected: black; | ||||
| @@ -160,7 +145,7 @@ $paletteItemBorderInnerColor: rgba($paletteItemBorderOuterColorSelected, 0.3); | ||||
| $colorCheck: $colorKey; | ||||
| $colorFormRequired: $colorKey; | ||||
| $colorFormValid: $colorOk; | ||||
| $colorFormError: $colorWarningHi; | ||||
| $colorFormError: #990000; | ||||
| $colorFormInvalid: #ff2200; | ||||
| $colorFormFieldErrorBg: $colorFormError; | ||||
| $colorFormFieldErrorFg: rgba(#fff, 0.6); | ||||
| @@ -168,35 +153,28 @@ $colorFormLines: rgba(#000, 0.1); | ||||
| $colorFormSectionHeader: rgba(#000, 0.05); | ||||
| $colorInputBg: $colorGenBg; | ||||
| $colorInputFg: $colorBodyFg; | ||||
| $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 1px; | ||||
| $shdwInputFoc: inset rgba(black, 0.7) 0 0 3px; | ||||
| $colorInputPlaceholder: lighten($colorBodyFg, 20%); | ||||
| $colorFormText: lighten($colorBodyFg, 10%); | ||||
| $colorInputIcon: lighten($colorBodyFg, 25%); | ||||
| $colorFieldHint: darken($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: pullForward($colorBodyBg, 5%); | ||||
| $colorInspectorBg: darken($colorBodyBg, 5%); | ||||
| $colorInspectorFg: $colorBodyFg; | ||||
| $colorInspectorPropName: pushBack($colorBodyFg, 20%); | ||||
| $colorInspectorPropVal: pullForward($colorInspectorFg, 15%); | ||||
| $colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%); | ||||
| $colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%); | ||||
| $colorInspectorPropName: lighten($colorBodyFg, 20%); | ||||
| $colorInspectorPropVal: darken($colorInspectorFg, 15%); | ||||
| $colorInspectorSectionHeaderBg: darken($colorInspectorBg, 5%); | ||||
| $colorInspectorSectionHeaderFg: darken($colorInspectorBg, 40%); | ||||
|  | ||||
| // Status colors, mainly used for messaging and item ancillary symbols | ||||
| $colorStatusFg: #999; | ||||
| $colorStatusDefault: #ccc; | ||||
| $colorStatusInfo: #60ba7b; | ||||
| $colorStatusAlert: #ffb66c; | ||||
| $colorStatusError: #da0004; | ||||
| $colorStatusBtnBg: #666; | ||||
| $colorProgressBarOuter: rgba(#000, 0.1); | ||||
| $colorProgressBarAmt: #0a0; | ||||
| $progressBarHOverlay: 15px; | ||||
| $progressBarStripeW: 20px; | ||||
| $shdwStatusIc: rgba(white, 0.8) 0 0px 5px; | ||||
| $animPausedPulseDur: 1s; | ||||
| // Overlay | ||||
| $overlayColorBg: $colorMenuBg; | ||||
| $overlayColorFg: $colorMenuFg; | ||||
| $overlayButtonColorBg: $colorBtnBg; | ||||
| $overlayButtonColorFg: $colorBtnFg; | ||||
| $overlayCr: $interiorMarginLg; | ||||
|  | ||||
| // Indicator colors | ||||
| $colorIndicatorAvailable: $colorKey; | ||||
| @@ -204,13 +182,9 @@ $colorIndicatorDisabled: #444; | ||||
| $colorIndicatorOn: $colorOk; | ||||
| $colorIndicatorOff: #666; | ||||
|  | ||||
| // Selects | ||||
| $colorSelectBg: $colorBtnBg; | ||||
| $colorSelectFg: $colorBtnFg; | ||||
|  | ||||
| // Limits and staleness colors// | ||||
| $colorTelemFresh: pullForward($colorBodyFg, 20%); | ||||
| $colorTelemStale: pushBack($colorBodyFg, 20%); | ||||
| $colorTelemFresh: darken($colorBodyFg, 20%); | ||||
| $colorTelemStale: lighten($colorBodyFg, 20%); | ||||
| $styleTelemStale: italic; | ||||
| $colorLimitYellowBg: rgba(#ffaa00, 0.3); | ||||
| $colorLimitYellowIc: #ffaa00; | ||||
| @@ -220,37 +194,22 @@ $colorLimitRedIc: red; | ||||
| // Bubble colors | ||||
| $colorInfoBubbleBg: $colorMenuBg; | ||||
| $colorInfoBubbleFg: #666; | ||||
| $colorThumbsBubbleFg: pullForward($colorBodyFg, 10%); | ||||
| $colorThumbsBubbleBg: pullForward($colorBodyBg, 10%); | ||||
|  | ||||
| // Overlay | ||||
| $colorOvrBlocker: rgba(black, 0.7); // Used | ||||
| $colorOvrBg: $colorBodyBg; // Used | ||||
| $colorOvrFg: $colorBodyFg; // Used | ||||
| $colorOvrBtnBg: pullForward($colorOvrBg, 40%); | ||||
| $colorOvrBtnFg: #fff; | ||||
| $colorFieldHintOverlay: pullForward($colorOvrBg, 40%); | ||||
| $durLargeViewExpand: 250ms; | ||||
|  | ||||
| // Items | ||||
| $colorItemBg: #ddd; | ||||
| $colorItemBgHov: rgba($colorKey, 0.1); //pushBack($colorItemBg, $hoverRatioPercent * 0.4); | ||||
| $colorItemBg: lighten($colorBtnBg, 20%); | ||||
| $colorItemBgHov: lighten($colorItemBg, 5%); | ||||
| $colorListItemBg: transparent; | ||||
| $colorListItemBgHov: rgba($colorKey, 0.1); | ||||
| $colorItemFg: $colorBodyFg; | ||||
| $colorItemFgDetails: pushBack($colorItemFg, 15%); | ||||
| $colorItemIc: $colorKey; | ||||
| $colorItemSubIcons: $colorItemFgDetails; | ||||
| $colorItemOpenIcon: $colorItemFgDetails; | ||||
| $colorItemFgDetails: lighten($colorItemFg, 15%); | ||||
| $shdwItemText: none; | ||||
| $colorItemBgSelected: $colorKey; | ||||
|  | ||||
| // Tabular | ||||
| $colorTabBorder: pullForward($colorBodyBg, 10%); | ||||
| $colorTabBorder: darken($colorBodyBg, 10%); | ||||
| $colorTabBodyBg: $colorBodyBg; | ||||
| $colorTabBodyFg: pullForward($colorBodyFg, 20%); | ||||
| $colorTabHeaderBg: pullForward($colorBodyBg, 10%); | ||||
| $colorTabHeaderFg: pullForward($colorBodyFg, 20%); | ||||
| $colorTabBodyFg: darken($colorBodyFg, 20%); | ||||
| $colorTabHeaderBg: darken($colorBodyBg, 10%); | ||||
| $colorTabHeaderFg: darken($colorBodyFg, 20%); | ||||
| $colorTabHeaderBorder: $colorBodyBg; | ||||
|  | ||||
| // Plot | ||||
| @@ -260,24 +219,23 @@ $colorPlotHash: black; | ||||
| $opacityPlotHash: 0.2; | ||||
| $stylePlotHash: dashed; | ||||
| $colorPlotAreaBorder: $colorInteriorBorder; | ||||
| $colorPlotLabelFg: pushBack($colorPlotFg, 20%); | ||||
| $colorPlotLabelFg: lighten($colorPlotFg, 20%); | ||||
| $legendCollapsedNameMaxW: 50%; | ||||
| $legendHoverValueBg: rgba($colorBodyFg, 0.2); | ||||
|  | ||||
| // Tree | ||||
| $colorTreeBg: #f0f0f0; // Used | ||||
| $colorItemTreeHoverBg: pullForward($colorBodyBg, $hoverRatioPercent); | ||||
| $colorItemTreeHoverFg: pullForward($colorBodyFg, $hoverRatioPercent); | ||||
| $colorTreeBg: transparent; | ||||
| $colorItemTreeHoverBg: darken($colorBodyBg, 10%); | ||||
| $colorItemTreeHoverFg: darken($colorBodyFg, 10%); | ||||
| $colorItemTreeIcon: $colorKey; // Used | ||||
| $colorItemTreeIconHover: $colorItemTreeIcon; // Used | ||||
| $colorItemTreeFg: $colorBodyFg; | ||||
| $colorItemTreeSelectedBg: pushBack($colorKey, 15%); | ||||
| $colorItemTreeSelectedBg: lighten($colorKey, 15%); | ||||
| $colorItemTreeSelectedFg: $colorBodyBg; | ||||
| $colorItemTreeEditingBg: #caf1ff; | ||||
| $colorItemTreeEditingFg: $colorEditAreaFg; | ||||
| $colorItemTreeEditingBg: $editColor; | ||||
| $colorItemTreeEditingFg: $editColorFg; | ||||
| $colorItemTreeVC: $colorBodyFg; | ||||
| $colorItemTreeVCHover: $colorKey; | ||||
| $colorItemTreeSelectedVC: $colorBodyBg; | ||||
| $shdwItemTreeIcon: none; | ||||
|  | ||||
| // Images | ||||
| @@ -289,54 +247,37 @@ $scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px; | ||||
| $scrollbarTrackColorBg: rgba(#000, 0.2); | ||||
| $scrollbarThumbColor: darken($colorBodyBg, 50%); | ||||
| $scrollbarThumbColorHov: $colorKey; | ||||
| $scrollbarThumbColorOverlay: darken($colorOvrBg, 50%); | ||||
| $scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov; | ||||
| $scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%); | ||||
| $scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%); | ||||
| $scrollbarThumbColorMenu: darken($colorMenuBg, 10%); | ||||
| $scrollbarThumbColorMenuHov: darken($scrollbarThumbColorMenu, 2%); | ||||
|  | ||||
| // Splitter | ||||
| $splitterD: 7px; | ||||
| $splitterHandleD: 2px; | ||||
| $splitterHandleHitMargin: 4px; | ||||
| $splitterGrippyD: ($splitterHandleD - 4, 75px, 50px); // thickness, length, min-length | ||||
| $colorSplitterBaseBg: $colorBodyBg; | ||||
| $colorSplitterBg: pullForward($colorSplitterBaseBg, 20%); | ||||
| $colorSplitterBg: darken($colorSplitterBaseBg, 20%); | ||||
| $colorSplitterFg: $colorBodyBg; | ||||
| $colorSplitterHover: $colorKey; // pullForward($colorSplitterBg, $hoverRatioPercent * 2); | ||||
| $colorSplitterHover: $colorKey; | ||||
| $colorSplitterActive: $colorKey; | ||||
| $splitterBtnD: (16px, 35px); // height, width | ||||
| $splitterBtnColorBg: #eee; | ||||
| $splitterBtnColorFg: #999; | ||||
| $splitterBtnColorHoverBg: rgba($colorKey, 1); | ||||
| $splitterBtnColorHoverFg: $colorBodyBg; | ||||
| $colorSplitterGrippy: pullForward($colorSplitterBaseBg, 30%); | ||||
| $splitterShdw: none; | ||||
| $splitterEndCr: none; | ||||
|  | ||||
| // Minitabs | ||||
| $colorMiniTabBg: $colorSplitterBg; | ||||
| $colorMiniTabFg: pullForward($colorMiniTabBg, 30%); | ||||
| $colorMiniTabBgHov: $colorSplitterHover; | ||||
| $colorMiniTabFgHov: #fff; | ||||
| $splitterBtnColorBg: $colorBtnBg; | ||||
| $splitterBtnColorFg: #ddd; | ||||
| $splitterBtnLabelColorFg: #999; | ||||
| $splitterCollapsedBtnColorBg: #ccc; | ||||
| $splitterCollapsedBtnColorFg: #666; | ||||
| $splitterCollapsedBtnColorBgHov: $colorKey; | ||||
| $splitterCollapsedBtnColorFgHov: $colorKeyFg; | ||||
|  | ||||
| // Mobile | ||||
| $colorMobilePaneLeft: darken($colorBodyBg, 2%); | ||||
| $colorMobilePaneLeftTreeItemBg: rgba($colorBodyFg, 0.1); //pullForward($colorMobilePaneLeft, 3%); | ||||
| $colorMobilePaneLeftTreeItemBg: rgba($colorBodyFg, 0.1); | ||||
| $colorMobilePaneLeftTreeItemFg: $colorItemTreeFg; | ||||
| $colorMobileSelectListTreeItemBg: rgba(#000, 0.05); | ||||
|  | ||||
| // Datetime Picker, Calendar | ||||
| $colorCalCellHovBg: $colorKey; | ||||
| $colorCalCellHovFg: $colorKeyFg; | ||||
| $colorCalCellSelectedBg: $colorItemTreeSelectedBg; | ||||
| $colorCalCellSelectedFg: $colorItemTreeSelectedFg; | ||||
| $colorCalCellInMonthBg: pullForward($colorMenuBg, 5%); | ||||
|  | ||||
| // About Screen | ||||
| $colorAboutLink: #84b3ff; | ||||
| $colorAboutLink: $colorKeySubtle; | ||||
|  | ||||
| // Loading | ||||
| $colorLoadingFg: $colorAlt1; | ||||
| $colorLoadingFg: #776ba2; | ||||
| $colorLoadingBg: rgba($colorLoadingFg, 0.1); | ||||
|  | ||||
| // Transitions | ||||
| @@ -346,14 +287,50 @@ $transInBounce: all 200ms cubic-bezier(.47,.01,.25,1.5); | ||||
| $transInBounceBig: all 300ms cubic-bezier(.2,1.6,.6,3); | ||||
|  | ||||
| // Discrete items, like Notebook entries, Widget rules | ||||
| $createBtnTextTransform: uppercase; | ||||
|  | ||||
| @mixin discreteItem() { | ||||
|     background: rgba($colorBodyFg,0.1); | ||||
|     border: 1px solid $colorInteriorBorder; | ||||
|     border-radius: $controlCr; | ||||
|  | ||||
|     .c-input-inline:hover { | ||||
|         background: $colorBodyBg; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin discreteItemInnerElem() { | ||||
|     border: 1px solid $colorBodyBg; | ||||
|     border-radius: $controlCr; } | ||||
|     border-radius: $controlCr; | ||||
| } | ||||
|  | ||||
| @mixin themedButton($c: $colorBtnBg) { | ||||
|     background: $c; | ||||
| } | ||||
|  | ||||
|  | ||||
| /**************************************************** 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: lighten($sliderColorBase, 20%); | ||||
| $sliderColorKnobHov: rgba($sliderColorBase, 0.7); | ||||
| $sliderColorRangeValHovBg: $sliderColorRange; | ||||
| $sliderColorRangeValHovFg: $colorBodyFg; | ||||
| $sliderKnobW: 15px; | ||||
| $sliderKnobR: 2px; | ||||
| */ | ||||
|  | ||||
| // Content status | ||||
| /* | ||||
| $colorAlert: #ff3c00; | ||||
| $colorWarningHi: #990000; | ||||
| $colorWarningLo: #ff9900; | ||||
| $colorDiagnostic: #a4b442; | ||||
| $colorCommand: #3693bd; | ||||
| $colorInfo: #2294a2; | ||||
| $colorOk: #33cc33; | ||||
| */ | ||||
|   | ||||
| @@ -40,19 +40,21 @@ $inputTextP: $inputTextPTopBtm $inputTextPLeftRight; | ||||
| $menuLineH: 1.5rem; | ||||
| $treeItemIndent: 16px; | ||||
| $treeTypeIconW: 18px; | ||||
| $overlayOuterMargin: 5%; | ||||
| $overlayOuterMarginLg: 5%; | ||||
| $overlayOuterMarginDialog: 20%; | ||||
| $overlayInnerMargin: 25px; | ||||
|  | ||||
| /*************** Items */ | ||||
| $itemPadLR: 5px; | ||||
| $ueBrowseGridItemLg: 200px; | ||||
| $gridItemDesk: 175px; | ||||
| $gridItemMobile: 32px; | ||||
| /*************** Tabular */ | ||||
| $tabularHeaderH: 22px; | ||||
| $tabularTdPadLR: $itemPadLR; | ||||
| $tabularTdPadTB: 2px; | ||||
|  | ||||
| /************************** MOBILE */ | ||||
| $mobileMenuIconD: 34px; // Used | ||||
| $mobileMenuIconD: 24px; // Used | ||||
| $mobileTreeItemH: 35px; // Used | ||||
|  | ||||
| /************************** VISUAL */ | ||||
| @@ -176,34 +178,38 @@ $glyph-icon-notebook: '\e1131'; | ||||
|  | ||||
| /************************** GLYPHS AS DATA URI */ | ||||
| // Only objects have been converted, for use in Create menu and folder views | ||||
| $bg-icon-activity: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M288 32H160l160 160H174.872C152.74 153.742 111.377 128 64 128H0v256h64c47.377 0 88.74-25.742 110.872-64H320L160 480h128l224-224L288 32z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-activity-mode: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 0C148.6 0 56.6 66.2 18.6 160H64c28.4 0 54 12.4 71.5 32H256l-96-96h128l160 160-160 160H160l96-96H135.5C118 339.6 92.4 352 64 352H18.6c38 93.8 129.9 160 237.4 160 141.4 0 256-114.6 256-256S397.4 0 256 0z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-autoflow-tabular: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M96 0C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h32V0H96zM192 0h128v512H192zM416 0h-32v352h128V96c0-52.8-43.2-96-96-96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-clock: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256 256-114.6 256-256S397.4 0 256 0zm135 345c-6.4 11.1-18.3 18-31.2 18-6.3 0-12.5-1.7-18-4.8l-110.9-64-.1-.1c-.4-.2-.8-.5-1.2-.7l-.4-.3-.9-.6-.6-.5-.6-.5-.9-.7-.3-.3c-.4-.3-.7-.6-1.1-.9-2.5-2.3-4.7-5-6.5-7.9-.1-.2-.3-.5-.4-.7s-.3-.5-.4-.7c-1.6-3-2.9-6.2-3.6-9.6v-.1c-.1-.5-.2-.9-.3-1.4 0-.1 0-.3-.1-.4-.1-.3-.1-.7-.1-1.1s-.1-.5-.1-.8 0-.5-.1-.8-.1-.8-.1-1.1v-.5-1.4V81c0-19.9 16.1-36 36-36s36 16.1 36 36v161.2l92.9 53.6c17.1 10 22.9 32 13 49.2z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-database: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 256C114.615 256 0 213.019 0 160v256c0 53.019 114.615 96 256 96s256-42.981 256-96V160c0 53.019-114.615 96-256 96z'/%3e%3cellipse fill='%23666666' cx='256' cy='96' rx='256' ry='96'/%3e%3c/svg%3e"); | ||||
| $bg-icon-database-query: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M341.76 409.643C316.369 423.871 287.118 432 256 432c-97.047 0-176-78.953-176-176S158.953 80 256 80s176 78.953 176 176c0 31.118-8.129 60.369-22.357 85.76l95.846 95.846C509.747 430.661 512 423.429 512 416V96c0-53.019-114.615-96-256-96S0 42.981 0 96v320c0 53.019 114.615 96 256 96 63.055 0 120.774-8.554 165.388-22.73l-79.628-79.627z'/%3e%3cpath fill='%23666666' d='M176 256c0 44.112 35.888 80 80 80s80-35.888 80-80-35.888-80-80-80-80 35.888-80 80z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-dataset: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 96H288l-54.6-54.6-18.7-18.7C202.2 10.2 177.6 0 160 0H32C14.4 0 0 14.4 0 32v192c0-35.2 28.8-64 64-64h384c35.2 0 64 28.8 64 64v-64c0-35.2-28.8-64-64-64zM448 224H64c-35.2 0-64 28.8-64 64v160c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64zM160 448H96V288h64v160zm128 0h-64V288h64v160zm128 0h-64V288h64v160z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-datatable: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 256C114.6 256 0 213 0 160v256c0 53 114.6 96 256 96s256-43 256-96V160c0 53-114.6 96-256 96zm192 31.5v128c-18.3 7.8-39.9 14.4-64 19.7v-128c24.1-5.3 45.7-11.9 64-19.7zm-320 19.7v128c-24.1-5.2-45.7-11.9-64-19.7v-128c18.3 7.8 39.9 14.4 64 19.7zM192 445V317c20.5 2 41.9 3 64 3s43.5-1.1 64-3v128c-20.5 2-41.9 3-64 3s-43.5-1.1-64-3z'/%3e%3cellipse fill='%23666666' cx='256' cy='96' rx='256' ry='96'/%3e%3c/svg%3e"); | ||||
| $bg-icon-dictionary: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M416 320c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96v160l-64-32-64 32V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96v-96c0 52.8-43.2 96-96 96H96v-96h320z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-folder: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 96H288l-54.6-54.6-18.7-18.7C202.2 10.2 177.6 0 160 0H32C14.4 0 0 14.4 0 32v192c0-35.2 28.8-64 64-64h384c35.2 0 64 28.8 64 64v-64c0-35.2-28.8-64-64-64zM448 224H64c-35.2 0-64 28.8-64 64v160c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zm0 448H64V64h384v384z'/%3e%3cpath fill='%23666666' d='M160 128l-64 64v224h320V256l-64-64-64 64z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-layout: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M224 0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h128V0zM416 0H288v288.832h224V96c0-52.8-43.2-96-96-96zM288 512h128c52.8 0 96-43.2 96-96v-64.832H288V512z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-object: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='none' d='M256 96L76.8 208 256 320l179.2-112z'/%3e%3cpath fill='%23666666' d='M256 512l256-160V160L255.99 0 0 160v192l256 160zm0-416l179.2 112L256 320 76.8 208 256 96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-object-unknown: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M255-1L-1 159v192l256 160 256-160V159L255-1zm37.7 430.6c-10.6 10.4-23 15.4-38 15.4-15.6 0-28.1-4.9-38.1-14.8-10-10-14.8-22.4-14.8-38.1 0-15.2 5.1-27.6 15.5-38.1s22.6-15.6 37.4-15.6c14.8 0 27.1 5.2 37.8 16 10.7 10.8 15.9 23.2 15.9 38-.1 14.5-5.4 27-15.7 37.2zm26.4-156.3c-11.8 5.9-18.7 11-21.7 16.2-1.8 3.1-3 7.4-3.7 13.4v20.5H213v-22.1c0-20.1 2.2-34.9 6.5-44 4-8.6 11.3-15.1 22.4-20l17.4-7.7c16-7.1 24.1-17.6 24.1-31.4 0-8-3-15.2-8.6-20.9-5.6-5.6-12.8-8.6-20.8-8.6-12 0-27.2 5-31.4 28.7l-1.1 6.1H148l.7-8.1c2-22.3 8.5-41.2 19.4-56.1 9.8-13.5 22.8-24.3 38.5-32.3 15.7-8 32.3-12 49.1-12 30.3 0 55.1 9.7 75.7 29.8 20.6 20 30.6 44 30.6 73.6 0 35.4-14.4 60.7-42.9 74.9z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-packet: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='none' d='M256 96L76.8 208 256 320l179.2-112z'/%3e%3cpath fill='%23666666' d='M256 0L0 160v256c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96V160L256 0zm0 96l179.2 112L256 320 76.8 208 256 96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-page: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M352 256c-52.8 0-96-43.2-96-96V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96V256H352z'/%3e%3cpath fill='%23666666' d='M384 192h128L320 0v128c0 35.2 28.8 64 64 64z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-plot-overlay: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M415 0H97C43.65 0 0 43.65 0 97v203.41c7.09 9.32 12.83 14.17 16 15.42 7.14-2.81 27.22-23.77 46.48-73C83.71 188.64 120.64 124 176 124c26.2 0 50.71 14.58 72.85 43.34 18.67 24.25 32.42 54.46 40.67 75.54 19.26 49.19 39.34 70.15 46.48 73 7.14-2.81 27.22-23.77 46.48-73C403.71 188.64 440.64 124 496 124a69.55 69.55 0 0 1 16 1.87V97c0-53.35-43.65-97-97-97z'/%3e%3cpath fill='%23666666' d='M496 196.17c-7.14 2.81-27.22 23.76-46.48 73C428.29 323.36 391.36 388 336 388c-26.2 0-50.71-14.58-72.85-43.34-18.67-24.25-32.42-54.46-40.67-75.54-19.26-49.19-39.34-70.15-46.48-73-7.14 2.81-27.22 23.76-46.48 73C108.29 323.36 71.36 388 16 388a69.56 69.56 0 0 1-16-1.87V415c0 53.35 43.65 97 97 97h318c53.35 0 97-43.65 97-97V211.59c-7.09-9.32-12.83-14.17-16-15.42z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-plot-stacked: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M44.8 156c12.49 0 24.48-13.26 42.76-35.09 22.71-27.14 51-60.91 98-60.91 22.32 0 43.31 7.73 62.4 23 14.34 11.45 25.58 25.21 36.46 38.53C303.63 145 314 156 326.4 156H512V97c0-53.35-43.65-97-97-97H97C43.65 0 0 43.65 0 97v59h44.8z'/%3e%3cpath fill='%23666666' d='M264.75 205.2c-14.12-11.32-25.26-25-36-38.14C211 145.32 199.37 132 185.6 132c-12.53 0-24.54 13.27-42.83 35.12-22.7 27.12-51 60.88-98 60.88H0v56h185.6c22 0 42.77 7.67 61.65 22.8 14.12 11.32 25.26 25 36 38.14C301 366.68 312.63 380 326.4 380c12.53 0 24.54-13.27 42.83-35.12 22.7-27.12 51-60.88 98-60.88H512v-56H326.4c-22.03 0-42.77-7.67-61.65-22.8z'/%3e%3cpath fill='%23666666' d='M467.2 356c-12.49 0-24.48 13.26-42.76 35.09-22.71 27.14-51 60.91-98 60.91-22.32 0-43.31-7.73-62.4-23-14.34-11.45-25.58-25.21-36.46-38.53C208.37 367 198 356 185.6 356H0v59c0 53.35 43.65 97 97 97h318c53.35 0 97-43.65 97-97v-59h-44.8z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-session: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M317.8 262.2c3.3 2.1 6.6 4.3 9.6 6.8l60.2 48.2c14.8 11.9 41.9 11.9 56.7 0l67.6-54c.1-2.4.1-4.7.1-7.1 0-26.1-3.9-51.2-11.1-74.9L423.5 243c-29.1 23.3-70.1 29.6-105.7 19.2zM124.3 317.1l60.2-48.2c29-23.2 70-29.6 105.6-19.2-3.3-2.1-6.6-4.3-9.6-6.8l-60.2-48.2c-14.8-11.9-41.9-11.9-56.7 0L103.5 243c-20 16-45.7 24-71.5 24-10.8 0-21.5-1.4-31.9-4.2v.8c2.5 1.7 5 3.4 7.3 5.3l60.2 48.2c14.9 11.9 41.9 11.9 56.7 0z'/%3e%3cpath fill='%23666666' d='M60.3 189.1l60.2-48.2c40.1-32.1 102.8-32.1 142.9 0l60.2 48.2c14.8 11.9 41.9 11.9 56.7 0l90.5-72.4C425.2 46.5 346 0 256 0 136.7 0 36.4 81.6 8 192.1c15.4 8.8 38.9 7.8 52.3-3zM344.5 371l-60.2-48.2c-14.8-11.9-41.9-11.9-56.7 0L167.5 371c-20 16-45.7 24-71.5 24-23.9 0-47.7-6.9-67.1-20.7C71.7 456.1 157.3 512 256 512s184.3-55.9 227.1-137.7c-40.2 28.7-99.9 27.6-138.6-3.3z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zM320 224H192v-96h128v96zm-128 32h128v96H192v-96zm-32 96H32v-96h128v96zm0-224v96H32v-96h128zM64 480c-8.5 0-16.5-3.3-22.6-9.4S32 456.5 32 448v-64h128v96H64zm128 0v-96h128v96H192zm288-32c0 8.5-3.3 16.5-9.4 22.6S456.5 480 448 480h-96v-96h128v64zm0-96H352v-96h128v96zm0-128H352v-96h128v96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-lad: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.7.1.1 28.7 0 64v384c.1 35.3 28.7 63.9 64 64h384c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM32 128h128v96H32v-96zm0 128h128v96H32v-96zm32 224c-17.6-.1-31.9-14.4-32-32v-64h128v96H64zm128 0v-96h128v96H192zm288-32c-.1 17.6-14.4 31.9-32 32h-96v-96h128v64zm0-192v96H192v-96h32v-32h-32v-96h288v96h-32v32h32z'/%3e%3cpath fill='%23666666' d='M391.2 273.7L336 246.1V160c0-8.8-7.2-16-16-16s-16 7.2-16 16v105.9l72.8 36.4c7.9 4 17.5.8 21.5-7.2 4-7.8.8-17.5-7.1-21.4z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-lad-set: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M64 384V96c-35.3.1-63.9 28.7-64 64v288c.1 35.3 28.7 63.9 64 64h288c35.3-.1 63.9-28.7 64-64H128c-35.3-.1-63.9-28.7-64-64z'/%3e%3cpath fill='%23666666' d='M448 0H160c-35.3.1-63.9 28.7-64 64v288c.1 35.3 28.7 63.9 64 64h288c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM128 96h96v64h-96V96zm0 96h96v96h-96v-96zm32 192c-17.6-.1-31.9-14.4-32-32v-32h96v64h-64zm96 0v-64h96v64h-96zm224-32c-.1 17.6-14.4 31.9-32 32h-64v-64h96v32zm0-64H256V96h224v192z'/%3e%3cpath fill='%23666666' d='M416 240c8.8 0 16-7.2 16-16 0-6.9-4.4-13-10.9-15.2L384 196.5V144c0-8.8-7.2-16-16-16s-16 7.2-16 16v75.5l58.9 19.6c1.7.6 3.4.9 5.1.9z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-realtime: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M0 64v384c0 35.2 28.8 64 64 64h288c35.2 0 64-28.8 64-64V340c-19.8 7.8-41.4 12-64 12-35.4 0-68.4-10.5-96-28.6V352h-96v-96h35.3c-5.2-10.1-9.4-20.8-12.6-32H160v-96h22.7C203.6 54.2 271.6 0 352 0H64C28.8 0 0 28.8 0 64zm288 320h96v64c0 8.5-3.3 16.5-9.4 22.6S360.5 480 352 480h-64v-96zm-160 96H64c-8.5 0-16.5-3.3-22.6-9.4S32 456.5 32 448v-64h96v96zm0-128H32v-96h96v96zm32 32h96v96h-96v-96zm-32-160H32v-96h96v96z'/%3e%3cpath fill='%23666666' d='M192 160c0 88.4 71.6 160 160 160s160-71.6 160-160S440.4 0 352 0 192 71.6 192 160zm49.7 39.8L227 187.5c-1.4-6.4-2.3-12.9-2.7-19.6 15.1-.1 30.1-5 41.9-14.8l39.6-33c7.5-6.2 21.1-6.2 28.6 0l39.6 33c2.8 2.3 5.7 4.3 8.8 6.1-23-11.7-52.7-9.2-72.8 7.5l-39.6 33c-7.6 6.3-21.2 6.3-28.7.1zM352 288c-36.7 0-69.7-15.4-93-40.1 14.2-.6 28.1-5.5 39.2-14.7l39.6-33c7.5-6.2 21.1-6.2 28.6 0l39.6 33c11 9.2 25 14.1 39.2 14.7-23.5 24.7-56.5 40.1-93.2 40.1zm125.9-151.3c1.4 7.5 2.1 15.3 2.1 23.3 0 9.4-1 18.6-3 27.5l-14.7 12.3c-7.5 6.2-21.1 6.2-28.6 0l-39.6-33c-2.8-2.3-5.7-4.3-8.8-6.1 23 11.7 52.7 9.2 72.8-7.5l19.8-16.5zM352 32c46.4 0 87.1 24.7 109.5 61.7l-31.2 26c-7.5 6.2-21.1 6.2-28.6 0l-39.6-33c-23.6-19.7-60.6-19.7-84.3 0l-39.6 33c-2.5 2.1-5.7 3.5-9.1 4.2C244.7 70.8 293.8 32 352 32z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-scrolling: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M32 0C14.4 0 0 14.4 0 32v96h224V0H32zM512 128V32c0-17.6-14.4-32-32-32H288v128h224zM0 192v96c0 17.6 14.4 32 32 32h192V192H0zM480 320c17.6 0 32-14.4 32-32v-96H288v128h192zM256 512L128 384h256z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-telemetry: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M16 315.83c7.14-2.81 27.22-23.77 46.48-73C83.71 188.64 120.64 124 176 124c26.2 0 50.71 14.58 72.85 43.34 18.67 24.25 32.42 54.46 40.67 75.54 19.26 49.19 39.34 70.15 46.48 73 7.14-2.81 27.22-23.77 46.48-73 18.7-47.75 49.57-103.57 94.47-116.23A255.87 255.87 0 0 0 256 0C114.62 0 0 114.62 0 256a257.18 257.18 0 0 0 5 50.52c4.77 5.39 8.61 8.37 11 9.31z'/%3e%3cpath fill='%23666666' d='M496 196.17c-7.14 2.81-27.22 23.76-46.48 73C428.29 323.36 391.36 388 336 388c-26.2 0-50.71-14.58-72.85-43.34-18.67-24.25-32.42-54.46-40.67-75.54-19.26-49.19-39.34-70.15-46.48-73-7.14 2.81-27.22 23.76-46.48 73-18.7 47.75-49.57 103.57-94.47 116.23A255.87 255.87 0 0 0 256 512c141.38 0 256-114.62 256-256a257.18 257.18 0 0 0-5-50.52c-4.77-5.39-8.61-8.37-11-9.31z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-timeline: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M128 128h192v64H128zM192 224h192v64H192zM160 320h192v64H160z'/%3e%3cpath fill='%23666666' d='M416 0h-64v96h63.8c.1 0 .1.1.2.2v319.7c0 .1-.1.1-.2.2H352v96h64c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96zM96 415.8V96.2c0-.1.1-.1.2-.2H160V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h64v-96H96.2c-.1 0-.2-.1-.2-.2z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-timer: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M288 73.3V32.01a32 32 0 0 0-32-32h-64a32 32 0 0 0-32 32V73.3C67.48 100.84 0 186.54 0 288.01c0 123.71 100.29 224 224 224s224-100.29 224-224c0-101.48-67.5-187.2-160-214.71zm-54 224.71l-131.88 105.5A167.4 167.4 0 0 1 56 288.01c0-92.64 75.36-168 168-168 3.36 0 6.69.11 10 .31v177.69z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-topic: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M227.18 238.32l43.15-43.15a25.18 25.18 0 0 1 35.36 0l43.15 43.15a94.42 94.42 0 0 0 35.18 22.25V174.5l-28.82-28.82a95.11 95.11 0 0 0-134.35 0l-43.15 43.15a25.18 25.18 0 0 1-35.36 0L128 174.5v86.07a95.11 95.11 0 0 0 99.18-22.25z'/%3e%3cpath fill='%23666666' d='M252.82 273.68l-43.15 43.15a25.18 25.18 0 0 1-35.36 0l-43.15-43.15c-1-1-2.1-2-3.18-3v98.68a95.11 95.11 0 0 0 131.18-3l43.15-43.15a25.18 25.18 0 0 1 35.36 0l43.15 43.15c1 1 2.1 2 3.18 3v-98.68a95.11 95.11 0 0 0-131.18 3z'/%3e%3cpath fill='%23666666' d='M416 0h-64v96h63.83l.17.17v319.66l-.17.17H352v96h64c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96zM160 416H96.17l-.17-.17V96.17l.17-.17H160V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h64v-96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-box-with-dashed-lines: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M0 192h64v128H0zM64 64.11l.11-.11H160V0H64A64.19 64.19 0 0 0 0 64v96h64V64.11zM64 447.89V352H0v96a64.19 64.19 0 0 0 64 64h96v-64H64.11zM192 0h128v64H192zM448 447.89l-.11.11H352v64h96a64.19 64.19 0 0 0 64-64v-96h-64v95.89zM448 0h-96v64h95.89l.11.11V160h64V64a64.19 64.19 0 0 0-64-64zM448 192h64v128h-64zM192 448h128v64H192zM128 128h256v256H128z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-summary-widget: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zm-24.1 305.2l-41.3 71.6-94.8-65.8 9.6 115h-82.7l9.6-115-94.8 65.8-41.3-71.6L192.5 256 88.1 206.8l41.3-71.6 94.8 65.8-9.6-115h82.7l-9.6 115 94.8-65.8 41.3 71.6L319.5 256l104.4 49.2z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-notebook: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 55.4c0-39.9-27.7-63.7-61.5-52.7L0 128h448V55.4zM448 160H0v288c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64zm-32 256H224V256h192v160z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-alert-rect: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath d='M448 0H64C28.7.1.1 28.7 0 64v384c.1 35.3 28.7 63.9 64 64h384c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM288 448h-64v-64h64v64zm10.9-192L280 352h-48l-18.9-96V64H299v192z' fill='%23000000'/%3e%3c/svg%3e"); | ||||
| $bg-icon-alert-triangle: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath d='M499.1 424.4L287.8 54.6c-17.5-30.6-46-30.6-63.5 0L12.9 424.4C-4.6 455 9.9 480 45.1 480h421.7c35.3 0 49.8-25 32.3-55.6zM288 448h-64v-64h64v64zm10.9-192L280 352h-48l-18.9-96V128H299v128z' fill='%23000000'/%3e%3c/svg%3e"); | ||||
| $bg-icon-bell: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cg fill='%23000000'%3e%3cpath d='M256 512c53 0 96-43 96-96H160c0 53 43 96 96 96zM448 224v-32C448 86 362 0 256 0S64 86 64 192v32c0 35.3-28.7 64-64 64v64h512v-64c-35.3 0-64-28.7-64-64z'/%3e%3c/g%3e%3c/svg%3e"); | ||||
| $bg-icon-info: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath d='M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256 256-114.6 256-256S397.4 0 256 0zm0 64c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm96 352H160v-64h32V224h128v128h32v64z' fill='%23000000'/%3e%3c/svg%3e"); | ||||
| $bg-icon-activity: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M288 32H160l160 160H174.872C152.74 153.742 111.377 128 64 128H0v256h64c47.377 0 88.74-25.742 110.872-64H320L160 480h128l224-224L288 32z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-activity-mode: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M256 0C148.6 0 56.6 66.2 18.6 160H64c28.4 0 54 12.4 71.5 32H256l-96-96h128l160 160-160 160H160l96-96H135.5C118 339.6 92.4 352 64 352H18.6c38 93.8 129.9 160 237.4 160 141.4 0 256-114.6 256-256S397.4 0 256 0z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-autoflow-tabular: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M96 0C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h32V0H96zM192 0h128v512H192zM416 0h-32v352h128V96c0-52.8-43.2-96-96-96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-clock: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256 256-114.6 256-256S397.4 0 256 0zm135 345c-6.4 11.1-18.3 18-31.2 18-6.3 0-12.5-1.7-18-4.8l-110.9-64-.1-.1c-.4-.2-.8-.5-1.2-.7l-.4-.3-.9-.6-.6-.5-.6-.5-.9-.7-.3-.3c-.4-.3-.7-.6-1.1-.9-2.5-2.3-4.7-5-6.5-7.9-.1-.2-.3-.5-.4-.7s-.3-.5-.4-.7c-1.6-3-2.9-6.2-3.6-9.6v-.1c-.1-.5-.2-.9-.3-1.4 0-.1 0-.3-.1-.4-.1-.3-.1-.7-.1-1.1s-.1-.5-.1-.8 0-.5-.1-.8-.1-.8-.1-1.1v-.5-1.4V81c0-19.9 16.1-36 36-36s36 16.1 36 36v161.2l92.9 53.6c17.1 10 22.9 32 13 49.2z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-database: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M256 256C114.615 256 0 213.019 0 160v256c0 53.019 114.615 96 256 96s256-42.981 256-96V160c0 53.019-114.615 96-256 96z'/%3e%3cellipse fill='%23000000' cx='256' cy='96' rx='256' ry='96'/%3e%3c/svg%3e"); | ||||
| $bg-icon-database-query: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M341.76 409.643C316.369 423.871 287.118 432 256 432c-97.047 0-176-78.953-176-176S158.953 80 256 80s176 78.953 176 176c0 31.118-8.129 60.369-22.357 85.76l95.846 95.846C509.747 430.661 512 423.429 512 416V96c0-53.019-114.615-96-256-96S0 42.981 0 96v320c0 53.019 114.615 96 256 96 63.055 0 120.774-8.554 165.388-22.73l-79.628-79.627z'/%3e%3cpath fill='%23000000' d='M176 256c0 44.112 35.888 80 80 80s80-35.888 80-80-35.888-80-80-80-80 35.888-80 80z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-dataset: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 96H288l-54.6-54.6-18.7-18.7C202.2 10.2 177.6 0 160 0H32C14.4 0 0 14.4 0 32v192c0-35.2 28.8-64 64-64h384c35.2 0 64 28.8 64 64v-64c0-35.2-28.8-64-64-64zM448 224H64c-35.2 0-64 28.8-64 64v160c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64zM160 448H96V288h64v160zm128 0h-64V288h64v160zm128 0h-64V288h64v160z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-datatable: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M256 256C114.6 256 0 213 0 160v256c0 53 114.6 96 256 96s256-43 256-96V160c0 53-114.6 96-256 96zm192 31.5v128c-18.3 7.8-39.9 14.4-64 19.7v-128c24.1-5.3 45.7-11.9 64-19.7zm-320 19.7v128c-24.1-5.2-45.7-11.9-64-19.7v-128c18.3 7.8 39.9 14.4 64 19.7zM192 445V317c20.5 2 41.9 3 64 3s43.5-1.1 64-3v128c-20.5 2-41.9 3-64 3s-43.5-1.1-64-3z'/%3e%3cellipse fill='%23000000' cx='256' cy='96' rx='256' ry='96'/%3e%3c/svg%3e"); | ||||
| $bg-icon-dictionary: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M416 320c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96v160l-64-32-64 32V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96v-96c0 52.8-43.2 96-96 96H96v-96h320z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-folder: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 96H288l-54.6-54.6-18.7-18.7C202.2 10.2 177.6 0 160 0H32C14.4 0 0 14.4 0 32v192c0-35.2 28.8-64 64-64h384c35.2 0 64 28.8 64 64v-64c0-35.2-28.8-64-64-64zM448 224H64c-35.2 0-64 28.8-64 64v160c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zm0 448H64V64h384v384z'/%3e%3cpath fill='%23000000' d='M160 128l-64 64v224h320V256l-64-64-64 64z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-layout: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M224 0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h128V0zM416 0H288v288.832h224V96c0-52.8-43.2-96-96-96zM288 512h128c52.8 0 96-43.2 96-96v-64.832H288V512z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-object: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='none' d='M256 96L76.8 208 256 320l179.2-112z'/%3e%3cpath fill='%23000000' d='M256 512l256-160V160L255.99 0 0 160v192l256 160zm0-416l179.2 112L256 320 76.8 208 256 96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-object-unknown: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M255-1L-1 159v192l256 160 256-160V159L255-1zm37.7 430.6c-10.6 10.4-23 15.4-38 15.4-15.6 0-28.1-4.9-38.1-14.8-10-10-14.8-22.4-14.8-38.1 0-15.2 5.1-27.6 15.5-38.1s22.6-15.6 37.4-15.6c14.8 0 27.1 5.2 37.8 16 10.7 10.8 15.9 23.2 15.9 38-.1 14.5-5.4 27-15.7 37.2zm26.4-156.3c-11.8 5.9-18.7 11-21.7 16.2-1.8 3.1-3 7.4-3.7 13.4v20.5H213v-22.1c0-20.1 2.2-34.9 6.5-44 4-8.6 11.3-15.1 22.4-20l17.4-7.7c16-7.1 24.1-17.6 24.1-31.4 0-8-3-15.2-8.6-20.9-5.6-5.6-12.8-8.6-20.8-8.6-12 0-27.2 5-31.4 28.7l-1.1 6.1H148l.7-8.1c2-22.3 8.5-41.2 19.4-56.1 9.8-13.5 22.8-24.3 38.5-32.3 15.7-8 32.3-12 49.1-12 30.3 0 55.1 9.7 75.7 29.8 20.6 20 30.6 44 30.6 73.6 0 35.4-14.4 60.7-42.9 74.9z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-packet: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='none' d='M256 96L76.8 208 256 320l179.2-112z'/%3e%3cpath fill='%23000000' d='M256 0L0 160v256c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96V160L256 0zm0 96l179.2 112L256 320 76.8 208 256 96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-page: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M352 256c-52.8 0-96-43.2-96-96V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96V256H352z'/%3e%3cpath fill='%23000000' d='M384 192h128L320 0v128c0 35.2 28.8 64 64 64z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-plot-overlay: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M415 0H97C43.65 0 0 43.65 0 97v203.41c7.09 9.32 12.83 14.17 16 15.42 7.14-2.81 27.22-23.77 46.48-73C83.71 188.64 120.64 124 176 124c26.2 0 50.71 14.58 72.85 43.34 18.67 24.25 32.42 54.46 40.67 75.54 19.26 49.19 39.34 70.15 46.48 73 7.14-2.81 27.22-23.77 46.48-73C403.71 188.64 440.64 124 496 124a69.55 69.55 0 0 1 16 1.87V97c0-53.35-43.65-97-97-97z'/%3e%3cpath fill='%23000000' d='M496 196.17c-7.14 2.81-27.22 23.76-46.48 73C428.29 323.36 391.36 388 336 388c-26.2 0-50.71-14.58-72.85-43.34-18.67-24.25-32.42-54.46-40.67-75.54-19.26-49.19-39.34-70.15-46.48-73-7.14 2.81-27.22 23.76-46.48 73C108.29 323.36 71.36 388 16 388a69.56 69.56 0 0 1-16-1.87V415c0 53.35 43.65 97 97 97h318c53.35 0 97-43.65 97-97V211.59c-7.09-9.32-12.83-14.17-16-15.42z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-plot-stacked: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M44.8 156c12.49 0 24.48-13.26 42.76-35.09 22.71-27.14 51-60.91 98-60.91 22.32 0 43.31 7.73 62.4 23 14.34 11.45 25.58 25.21 36.46 38.53C303.63 145 314 156 326.4 156H512V97c0-53.35-43.65-97-97-97H97C43.65 0 0 43.65 0 97v59h44.8z'/%3e%3cpath fill='%23000000' d='M264.75 205.2c-14.12-11.32-25.26-25-36-38.14C211 145.32 199.37 132 185.6 132c-12.53 0-24.54 13.27-42.83 35.12-22.7 27.12-51 60.88-98 60.88H0v56h185.6c22 0 42.77 7.67 61.65 22.8 14.12 11.32 25.26 25 36 38.14C301 366.68 312.63 380 326.4 380c12.53 0 24.54-13.27 42.83-35.12 22.7-27.12 51-60.88 98-60.88H512v-56H326.4c-22.03 0-42.77-7.67-61.65-22.8z'/%3e%3cpath fill='%23000000' d='M467.2 356c-12.49 0-24.48 13.26-42.76 35.09-22.71 27.14-51 60.91-98 60.91-22.32 0-43.31-7.73-62.4-23-14.34-11.45-25.58-25.21-36.46-38.53C208.37 367 198 356 185.6 356H0v59c0 53.35 43.65 97 97 97h318c53.35 0 97-43.65 97-97v-59h-44.8z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-session: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M317.8 262.2c3.3 2.1 6.6 4.3 9.6 6.8l60.2 48.2c14.8 11.9 41.9 11.9 56.7 0l67.6-54c.1-2.4.1-4.7.1-7.1 0-26.1-3.9-51.2-11.1-74.9L423.5 243c-29.1 23.3-70.1 29.6-105.7 19.2zM124.3 317.1l60.2-48.2c29-23.2 70-29.6 105.6-19.2-3.3-2.1-6.6-4.3-9.6-6.8l-60.2-48.2c-14.8-11.9-41.9-11.9-56.7 0L103.5 243c-20 16-45.7 24-71.5 24-10.8 0-21.5-1.4-31.9-4.2v.8c2.5 1.7 5 3.4 7.3 5.3l60.2 48.2c14.9 11.9 41.9 11.9 56.7 0z'/%3e%3cpath fill='%23000000' d='M60.3 189.1l60.2-48.2c40.1-32.1 102.8-32.1 142.9 0l60.2 48.2c14.8 11.9 41.9 11.9 56.7 0l90.5-72.4C425.2 46.5 346 0 256 0 136.7 0 36.4 81.6 8 192.1c15.4 8.8 38.9 7.8 52.3-3zM344.5 371l-60.2-48.2c-14.8-11.9-41.9-11.9-56.7 0L167.5 371c-20 16-45.7 24-71.5 24-23.9 0-47.7-6.9-67.1-20.7C71.7 456.1 157.3 512 256 512s184.3-55.9 227.1-137.7c-40.2 28.7-99.9 27.6-138.6-3.3z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zM320 224H192v-96h128v96zm-128 32h128v96H192v-96zm-32 96H32v-96h128v96zm0-224v96H32v-96h128zM64 480c-8.5 0-16.5-3.3-22.6-9.4S32 456.5 32 448v-64h128v96H64zm128 0v-96h128v96H192zm288-32c0 8.5-3.3 16.5-9.4 22.6S456.5 480 448 480h-96v-96h128v64zm0-96H352v-96h128v96zm0-128H352v-96h128v96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-lad: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 0H64C28.7.1.1 28.7 0 64v384c.1 35.3 28.7 63.9 64 64h384c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM32 128h128v96H32v-96zm0 128h128v96H32v-96zm32 224c-17.6-.1-31.9-14.4-32-32v-64h128v96H64zm128 0v-96h128v96H192zm288-32c-.1 17.6-14.4 31.9-32 32h-96v-96h128v64zm0-192v96H192v-96h32v-32h-32v-96h288v96h-32v32h32z'/%3e%3cpath fill='%23000000' d='M391.2 273.7L336 246.1V160c0-8.8-7.2-16-16-16s-16 7.2-16 16v105.9l72.8 36.4c7.9 4 17.5.8 21.5-7.2 4-7.8.8-17.5-7.1-21.4z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-lad-set: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M64 384V96c-35.3.1-63.9 28.7-64 64v288c.1 35.3 28.7 63.9 64 64h288c35.3-.1 63.9-28.7 64-64H128c-35.3-.1-63.9-28.7-64-64z'/%3e%3cpath fill='%23000000' d='M448 0H160c-35.3.1-63.9 28.7-64 64v288c.1 35.3 28.7 63.9 64 64h288c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM128 96h96v64h-96V96zm0 96h96v96h-96v-96zm32 192c-17.6-.1-31.9-14.4-32-32v-32h96v64h-64zm96 0v-64h96v64h-96zm224-32c-.1 17.6-14.4 31.9-32 32h-64v-64h96v32zm0-64H256V96h224v192z'/%3e%3cpath fill='%23000000' d='M416 240c8.8 0 16-7.2 16-16 0-6.9-4.4-13-10.9-15.2L384 196.5V144c0-8.8-7.2-16-16-16s-16 7.2-16 16v75.5l58.9 19.6c1.7.6 3.4.9 5.1.9z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-realtime: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M0 64v384c0 35.2 28.8 64 64 64h288c35.2 0 64-28.8 64-64V340c-19.8 7.8-41.4 12-64 12-35.4 0-68.4-10.5-96-28.6V352h-96v-96h35.3c-5.2-10.1-9.4-20.8-12.6-32H160v-96h22.7C203.6 54.2 271.6 0 352 0H64C28.8 0 0 28.8 0 64zm288 320h96v64c0 8.5-3.3 16.5-9.4 22.6S360.5 480 352 480h-64v-96zm-160 96H64c-8.5 0-16.5-3.3-22.6-9.4S32 456.5 32 448v-64h96v96zm0-128H32v-96h96v96zm32 32h96v96h-96v-96zm-32-160H32v-96h96v96z'/%3e%3cpath fill='%23000000' d='M192 160c0 88.4 71.6 160 160 160s160-71.6 160-160S440.4 0 352 0 192 71.6 192 160zm49.7 39.8L227 187.5c-1.4-6.4-2.3-12.9-2.7-19.6 15.1-.1 30.1-5 41.9-14.8l39.6-33c7.5-6.2 21.1-6.2 28.6 0l39.6 33c2.8 2.3 5.7 4.3 8.8 6.1-23-11.7-52.7-9.2-72.8 7.5l-39.6 33c-7.6 6.3-21.2 6.3-28.7.1zM352 288c-36.7 0-69.7-15.4-93-40.1 14.2-.6 28.1-5.5 39.2-14.7l39.6-33c7.5-6.2 21.1-6.2 28.6 0l39.6 33c11 9.2 25 14.1 39.2 14.7-23.5 24.7-56.5 40.1-93.2 40.1zm125.9-151.3c1.4 7.5 2.1 15.3 2.1 23.3 0 9.4-1 18.6-3 27.5l-14.7 12.3c-7.5 6.2-21.1 6.2-28.6 0l-39.6-33c-2.8-2.3-5.7-4.3-8.8-6.1 23 11.7 52.7 9.2 72.8-7.5l19.8-16.5zM352 32c46.4 0 87.1 24.7 109.5 61.7l-31.2 26c-7.5 6.2-21.1 6.2-28.6 0l-39.6-33c-23.6-19.7-60.6-19.7-84.3 0l-39.6 33c-2.5 2.1-5.7 3.5-9.1 4.2C244.7 70.8 293.8 32 352 32z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-tabular-scrolling: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M32 0C14.4 0 0 14.4 0 32v96h224V0H32zM512 128V32c0-17.6-14.4-32-32-32H288v128h224zM0 192v96c0 17.6 14.4 32 32 32h192V192H0zM480 320c17.6 0 32-14.4 32-32v-96H288v128h192zM256 512L128 384h256z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-telemetry: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M16 315.83c7.14-2.81 27.22-23.77 46.48-73C83.71 188.64 120.64 124 176 124c26.2 0 50.71 14.58 72.85 43.34 18.67 24.25 32.42 54.46 40.67 75.54 19.26 49.19 39.34 70.15 46.48 73 7.14-2.81 27.22-23.77 46.48-73 18.7-47.75 49.57-103.57 94.47-116.23A255.87 255.87 0 0 0 256 0C114.62 0 0 114.62 0 256a257.18 257.18 0 0 0 5 50.52c4.77 5.39 8.61 8.37 11 9.31z'/%3e%3cpath fill='%23000000' d='M496 196.17c-7.14 2.81-27.22 23.76-46.48 73C428.29 323.36 391.36 388 336 388c-26.2 0-50.71-14.58-72.85-43.34-18.67-24.25-32.42-54.46-40.67-75.54-19.26-49.19-39.34-70.15-46.48-73-7.14 2.81-27.22 23.76-46.48 73-18.7 47.75-49.57 103.57-94.47 116.23A255.87 255.87 0 0 0 256 512c141.38 0 256-114.62 256-256a257.18 257.18 0 0 0-5-50.52c-4.77-5.39-8.61-8.37-11-9.31z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-timeline: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M128 128h192v64H128zM192 224h192v64H192zM160 320h192v64H160z'/%3e%3cpath fill='%23000000' d='M416 0h-64v96h63.8c.1 0 .1.1.2.2v319.7c0 .1-.1.1-.2.2H352v96h64c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96zM96 415.8V96.2c0-.1.1-.1.2-.2H160V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h64v-96H96.2c-.1 0-.2-.1-.2-.2z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-timer: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M288 73.3V32.01a32 32 0 0 0-32-32h-64a32 32 0 0 0-32 32V73.3C67.48 100.84 0 186.54 0 288.01c0 123.71 100.29 224 224 224s224-100.29 224-224c0-101.48-67.5-187.2-160-214.71zm-54 224.71l-131.88 105.5A167.4 167.4 0 0 1 56 288.01c0-92.64 75.36-168 168-168 3.36 0 6.69.11 10 .31v177.69z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-topic: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M227.18 238.32l43.15-43.15a25.18 25.18 0 0 1 35.36 0l43.15 43.15a94.42 94.42 0 0 0 35.18 22.25V174.5l-28.82-28.82a95.11 95.11 0 0 0-134.35 0l-43.15 43.15a25.18 25.18 0 0 1-35.36 0L128 174.5v86.07a95.11 95.11 0 0 0 99.18-22.25z'/%3e%3cpath fill='%23000000' d='M252.82 273.68l-43.15 43.15a25.18 25.18 0 0 1-35.36 0l-43.15-43.15c-1-1-2.1-2-3.18-3v98.68a95.11 95.11 0 0 0 131.18-3l43.15-43.15a25.18 25.18 0 0 1 35.36 0l43.15 43.15c1 1 2.1 2 3.18 3v-98.68a95.11 95.11 0 0 0-131.18 3z'/%3e%3cpath fill='%23000000' d='M416 0h-64v96h63.83l.17.17v319.66l-.17.17H352v96h64c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96zM160 416H96.17l-.17-.17V96.17l.17-.17H160V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h64v-96z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-box-with-dashed-lines: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M0 192h64v128H0zM64 64.11l.11-.11H160V0H64A64.19 64.19 0 0 0 0 64v96h64V64.11zM64 447.89V352H0v96a64.19 64.19 0 0 0 64 64h96v-64H64.11zM192 0h128v64H192zM448 447.89l-.11.11H352v64h96a64.19 64.19 0 0 0 64-64v-96h-64v95.89zM448 0h-96v64h95.89l.11.11V160h64V64a64.19 64.19 0 0 0-64-64zM448 192h64v128h-64zM192 448h128v64H192zM128 128h256v256H128z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-summary-widget: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zm-24.1 305.2l-41.3 71.6-94.8-65.8 9.6 115h-82.7l9.6-115-94.8 65.8-41.3-71.6L192.5 256 88.1 206.8l41.3-71.6 94.8 65.8-9.6-115h82.7l-9.6 115 94.8-65.8 41.3 71.6L319.5 256l104.4 49.2z'/%3e%3c/svg%3e"); | ||||
| $bg-icon-notebook: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M448 55.4c0-39.9-27.7-63.7-61.5-52.7L0 128h448V55.4zM448 160H0v288c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64zm-32 256H224V256h192v160z'/%3e%3c/svg%3e"); | ||||
| @@ -20,115 +20,6 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /******************************************************** PLACEHOLDERS */ | ||||
| @mixin cControl() { | ||||
|     $fs: 1em; | ||||
|     @include userSelectNone(); | ||||
|     display: inline-flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     overflow: hidden; | ||||
|  | ||||
|     &:before, | ||||
|     &:after { | ||||
|         font-family: symbolsfont; | ||||
|         display: block; | ||||
|         flex: 0 0 auto; | ||||
|     } | ||||
|  | ||||
|     &:after { | ||||
|         font-size: 0.8em; | ||||
|     } | ||||
|  | ||||
|     [class*="__label"] { | ||||
|         @include ellipsize(); | ||||
|         display: block; | ||||
|         line-height: $fs; // Remove effect on top and bottom padding | ||||
|         font-size: $fs; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin cButton() { | ||||
|     @include cControl(); | ||||
|     background: $colorBtnBg; | ||||
|     border-radius: $controlCr; | ||||
|     color: $colorBtnFg; | ||||
|     cursor: pointer; | ||||
|     padding: nth($btnPad, 1) nth($btnPad, 2); | ||||
|  | ||||
|     &:hover { | ||||
|         background: $colorBtnBgHov; | ||||
|         color: $colorBtnFgHov; | ||||
|     } | ||||
|  | ||||
|     &[class*="--major"] { | ||||
|         background: $colorBtnMajorBg; | ||||
|         color: $colorBtnMajorFg; | ||||
|  | ||||
|         &:hover { | ||||
|             background: $colorBtnMajorBgHov; | ||||
|             color: $colorBtnMajorFgHov; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &[class*='--caution'] { | ||||
|         background: $colorBtnCautionBg; | ||||
|         color: $colorBtnCautionFg; | ||||
|  | ||||
|         &:hover { | ||||
|             background: $colorBtnCautionBgHov; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin cClickIcon() { | ||||
|     // A clickable element that just includes the icon, no background | ||||
|     // Padding is included to facilitate a bigger hit area | ||||
|     // Make the icon bigger relative to its container | ||||
|     @include cControl(); | ||||
|     $pLR: 3px; | ||||
|     $pTB: 3px; | ||||
|     border-radius: $controlCr; | ||||
|     color: $colorKey; | ||||
|     cursor: pointer; | ||||
|     padding: $pTB $pLR ; | ||||
|  | ||||
|     &:hover { | ||||
|         background: rgba($colorKey, 0.2); | ||||
|     } | ||||
|  | ||||
|     &:before, | ||||
|     *:before { | ||||
|         // *:before handles any nested containers that may contain glyph elements | ||||
|         // Needed for c-togglebutton. | ||||
|         font-size: 1.3em; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin cCtrlWrapper { | ||||
|     // Provides a wrapper around  buttons and other controls | ||||
|     // Contains control and provides positioning context for contained menu/palette. | ||||
|     // Wraps --menu elements, contains button and menu | ||||
|     overflow: visible; | ||||
|  | ||||
|     .c-menu { | ||||
|         // Default position of contained menu | ||||
|         top: 100%; left: 0; | ||||
|     } | ||||
|  | ||||
|     &[class*='--menus-up'] { | ||||
|         .c-menu { | ||||
|             top: auto; bottom: 100%; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &[class*='--menus-left'] { | ||||
|         .c-menu { | ||||
|             left: auto; right: 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /********* Buttons */ | ||||
| // Optionally can include icon in :before via markup | ||||
| button { | ||||
| @@ -159,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; | ||||
| @@ -206,7 +102,7 @@ button { | ||||
|         font-size: 0.7em; | ||||
|     } | ||||
| } | ||||
|     /********* Disclosure Triangle */ | ||||
| /********* Disclosure Triangle */ | ||||
| // Provides an arrow icon that when clicked expands an element to reveal its contents. | ||||
| // Used in tree items. Always placed BEFORE an element. | ||||
| .c-disclosure-triangle { | ||||
| @@ -237,55 +133,73 @@ button { | ||||
| } | ||||
|  | ||||
| /******************************************************** FORM ELEMENTS */ | ||||
| /********* Inline inputs */ | ||||
| .c-input-inline { | ||||
|     // A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus | ||||
|     @include input-base(); | ||||
|     border: 1px solid transparent; | ||||
|     display: block !important; | ||||
|     min-width: 0; | ||||
|     padding-left: 0; | ||||
|     padding-right: 0; | ||||
|     overflow: hidden; | ||||
|     transition: all 250ms ease; | ||||
|     white-space: nowrap; | ||||
| input, textarea { | ||||
|     font-family: inherit; | ||||
|     font-weight: inherit; | ||||
|     letter-spacing: inherit; | ||||
| } | ||||
|  | ||||
|     &:not(:focus) { | ||||
|         text-overflow: ellipsis; | ||||
|     } | ||||
|  | ||||
|     &:hover, | ||||
|     &:focus { | ||||
|         padding-left: $inputTextPLeftRight; | ||||
|         padding-right: $inputTextPLeftRight; | ||||
|     } | ||||
|     &:hover { | ||||
|         border-color: rgba($colorBodyFg, 0.2); | ||||
|     } | ||||
|     &:focus { | ||||
|         @include nice-input($shdw: rgba(0, 0, 0, 0.6) 0 1px 3px); | ||||
|         border-color: transparent; | ||||
| input[type=text], | ||||
| input[type=search], | ||||
| input[type=number] { | ||||
|     @include reactive-input(); | ||||
|     padding: $inputTextP; | ||||
|     &.numeric { | ||||
|         text-align: right; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .c-labeled-input { | ||||
|     // An input used in the Toolbar | ||||
|     // Assumes label is before the input | ||||
|     @include cControl(); | ||||
|  | ||||
|     input { | ||||
|         margin-left: $interiorMarginSm; | ||||
|     } | ||||
| input[type=number]::-webkit-inner-spin-button, | ||||
| input[type=number]::-webkit-outer-spin-button { | ||||
|     margin-right: -5px !important; | ||||
|     margin-top: -1px !important; | ||||
| } | ||||
|  | ||||
| /******************************************************** HYPERLINKS AND HYPERLINK BUTTONS */ | ||||
| .c-hyperlink { | ||||
|     &--link { | ||||
|         color: $colorKey; | ||||
| .c-input { | ||||
|     &--datetime { | ||||
|         // Sized for values such as 2018-09-28 22:32:33.468Z | ||||
|         width: 160px; | ||||
|     } | ||||
|  | ||||
|     &--button { | ||||
|         @include cButton(); | ||||
|     &--hrs-min-sec { | ||||
|         // Sized for values such as 00:25:00 | ||||
|         width: 60px; | ||||
|     } | ||||
|  | ||||
|     &-inline, | ||||
|     &--inline { | ||||
|         // A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus | ||||
|         @include reactive-input($bg: transparent); | ||||
|         box-shadow: none; | ||||
|         display: block !important; | ||||
|         min-width: 0; | ||||
|         padding-left: 0; | ||||
|         padding-right: 0; | ||||
|         overflow: hidden; | ||||
|         transition: all 250ms ease; | ||||
|         white-space: nowrap; | ||||
|  | ||||
|         &:not(:focus) { | ||||
|             text-overflow: ellipsis; | ||||
|         } | ||||
|  | ||||
|         &:hover, | ||||
|         &:focus { | ||||
|             background: $colorInputBg; | ||||
|             padding-left: $inputTextPLeftRight; | ||||
|             padding-right: $inputTextPLeftRight; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &--labeled { | ||||
|         // TODO: replace .c-labeled-input with this | ||||
|         // An input used in the Toolbar | ||||
|         // Assumes label is before the input | ||||
|         @include cControl(); | ||||
|  | ||||
|         input { | ||||
|             margin-left: $interiorMarginSm; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -323,7 +237,6 @@ button { | ||||
| } | ||||
|  | ||||
| @mixin menuInner() { | ||||
|     color: $colorMenuFg; | ||||
|     li { | ||||
|         @include cControl(); | ||||
|         justify-content: start; | ||||
| @@ -349,10 +262,6 @@ button { | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin modalMenu() { | ||||
|     // Optional modifier that makes a c-menu more mobile-friendly | ||||
| } | ||||
|  | ||||
| .c-menu { | ||||
|     @include menuOuter(); | ||||
|     @include menuInner(); | ||||
| @@ -397,11 +306,6 @@ button { | ||||
|         justify-content: stretch; | ||||
|  | ||||
|         .l-item-description { | ||||
|             &__icon, | ||||
|             &__description { | ||||
|                 //flex: 1 1 50%; | ||||
|             } | ||||
|  | ||||
|             &__name, | ||||
|             &__description { | ||||
|                 margin-top: $interiorMarginLg; | ||||
| @@ -413,6 +317,7 @@ button { | ||||
|             } | ||||
|  | ||||
|             &__name { | ||||
|                 color: $colorMenuFg; | ||||
|                 flex: 0 0 auto; | ||||
|                 font-size: 1.25em; | ||||
|             } | ||||
| @@ -576,3 +481,9 @@ button { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /***************************************************** SLIDERS */ | ||||
| .c-slider { | ||||
|     @include cControl(); | ||||
|     > * + * { margin-left: $interiorMargin; } | ||||
| } | ||||
|   | ||||
| @@ -49,7 +49,7 @@ | ||||
|     font-style: normal; | ||||
| } | ||||
|  | ||||
| /******************************************************** RESETS */ | ||||
| /******************************* RESETS */ | ||||
| *, | ||||
| :before, | ||||
| :after { | ||||
| @@ -60,7 +60,7 @@ div { | ||||
|     position: relative; | ||||
| } | ||||
|  | ||||
| /******************************************************** UTILITIES */ | ||||
| /******************************* UTILITIES */ | ||||
| .u-contents { | ||||
|     display: contents; | ||||
| } | ||||
| @@ -74,7 +74,7 @@ div { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /******************************************************** BROWSER ELEMENTS */ | ||||
| /******************************* BROWSER ELEMENTS */ | ||||
| body.desktop { | ||||
|     ::-webkit-scrollbar { | ||||
|         box-sizing: border-box; | ||||
| @@ -92,30 +92,16 @@ body.desktop { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .overlay ::-webkit-scrollbar-thumb { | ||||
|         background: $scrollbarThumbColorOverlay; | ||||
|         &:hover { | ||||
|             background: $scrollbarThumbColorOverlayHov; | ||||
|         } | ||||
|     ::-webkit-scrollbar-corner { | ||||
|         background: transparent; | ||||
|     } | ||||
|  | ||||
|     .menu ::-webkit-scrollbar-thumb { | ||||
|     .c-menu ::-webkit-scrollbar-thumb { | ||||
|         background: $scrollbarThumbColorMenu; | ||||
|         &:hover { | ||||
|             background: $scrollbarThumbColorMenuHov; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     ::-webkit-scrollbar-corner { | ||||
|         background: transparent; | ||||
|     } | ||||
| } | ||||
|  | ||||
| input[type=number]::-webkit-inner-spin-button, | ||||
| input[type=number]::-webkit-outer-spin-button { | ||||
|     //margin: -1px -5px inherit -5px !important; | ||||
|     margin-right: -5px !important; | ||||
|     margin-top: -1px !important; | ||||
| } | ||||
|  | ||||
| /************************** HTML ENTITIES */ | ||||
| @@ -223,21 +209,7 @@ body.desktop .has-local-controls { | ||||
|     //} | ||||
| //} | ||||
|  | ||||
| /******************************************************** IS */ | ||||
|  | ||||
| .is-selectable { | ||||
|     &:hover { | ||||
|          | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| .is-editing { | ||||
|     .is-selectable { | ||||
|  | ||||
|     } | ||||
| } | ||||
| /******************************************************** LEGACY */ | ||||
| /************************** LEGACY */ | ||||
|  | ||||
| mct-container { | ||||
|     display: block; | ||||
| @@ -309,6 +281,21 @@ a.disabled { | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| .no-selection { | ||||
|     // aka selection = "None". Used in palettes and their menu buttons. | ||||
|     $c: red; | ||||
|     $s: 48%; | ||||
|     $e: 52%; | ||||
|     background-image: linear-gradient(-45deg, | ||||
|             transparent $s - 5%, | ||||
|             $c $s, | ||||
|             $c $e, | ||||
|             transparent $e + 5% | ||||
|     ); | ||||
|     background-repeat: no-repeat; | ||||
|     background-size: contain; | ||||
| } | ||||
|  | ||||
| .scrolling, | ||||
| .scroll { | ||||
|     overflow: auto; | ||||
|   | ||||
| @@ -20,34 +20,6 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| @mixin glyphBefore($unicode, $family: 'symbolsfont') { | ||||
|     &:before { | ||||
|         content: $unicode; | ||||
|         font-family: $family; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin glyphAfter($unicode, $family: 'symbolsfont') { | ||||
|     &:after { | ||||
|         content: $unicode; | ||||
|         font-family: $family; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin glyphBg($glyphUrl) { | ||||
|     background-image: $glyphUrl; | ||||
|     background-position: center; | ||||
|     background-size: contain; | ||||
|     background-repeat: no-repeat; | ||||
| } | ||||
|  | ||||
| [class*="icon-"] { | ||||
|     &:before, &:after | ||||
|     { | ||||
|         -webkit-font-smoothing: antialiased; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /************************** 16 PX CLASSES */ | ||||
| .icon-alert-rect {  @include glyphBefore($glyph-icon-alert-rect); } | ||||
| .icon-alert-triangle {  @include glyphBefore($glyph-icon-alert-triangle); } | ||||
| @@ -171,6 +143,10 @@ | ||||
| .icon-grippy-12px {  @include glyphBefore($glyph-icon-grippy,'symbolsfont-12px'); } | ||||
|  | ||||
| /************************** GLYPH BG CLASSES */ | ||||
| .bg-icon-alert-rect { @include glyphBg($bg-icon-alert-rect); } | ||||
| .bg-icon-alert-triangle { @include glyphBg($bg-icon-alert-triangle); } | ||||
| .bg-icon-bell { @include glyphBg($bg-icon-bell); } | ||||
| .bg-icon-info { @include glyphBg($bg-icon-info); } | ||||
| .bg-icon-activity { @include glyphBg($bg-icon-activity); } | ||||
| .bg-icon-activity-mode { @include glyphBg($bg-icon-activity-mode); } | ||||
| .bg-icon-autoflow-tabular { @include glyphBg($bg-icon-autoflow-tabular); } | ||||
|   | ||||
| @@ -20,7 +20,34 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| // VERSION MANUALLY MIGRATED FROM VUE-TOOLBAR | ||||
| /************************** GLYPHS */ | ||||
| @mixin glyphBefore($unicode, $family: 'symbolsfont') { | ||||
|     &:before { | ||||
|         content: $unicode; | ||||
|         font-family: $family; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin glyphAfter($unicode, $family: 'symbolsfont') { | ||||
|     &:after { | ||||
|         content: $unicode; | ||||
|         font-family: $family; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin glyphBg($glyphUrl) { | ||||
|     background-image: $glyphUrl; | ||||
|     background-position: center; | ||||
|     background-size: contain; | ||||
|     background-repeat: no-repeat; | ||||
| } | ||||
|  | ||||
| [class*="icon-"] { | ||||
|     &:before, &:after | ||||
|     { | ||||
|         -webkit-font-smoothing: antialiased; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /************************** VISUALS */ | ||||
| @mixin ancillaryIcon($d, $c) { | ||||
| @@ -115,33 +142,14 @@ | ||||
|     top: $m; right: $m; bottom: $m; left: $m; | ||||
| } | ||||
|  | ||||
| @mixin gridTwoColumn() { | ||||
|     display: grid; | ||||
|     grid-row-gap: 0; | ||||
|     grid-template-columns: 1fr 2fr; | ||||
|     align-items: start; | ||||
|  | ||||
|     [class*="header"] { | ||||
|         border-radius: $smallCr; | ||||
|         background-color: $colorInspectorSectionHeaderBg; | ||||
|         color: $colorInspectorSectionHeaderFg; | ||||
|         margin: 0 0 $interiorMarginSm 0; | ||||
|         padding: $interiorMarginSm $interiorMargin; | ||||
|  | ||||
|         &:not(:first-child) { | ||||
|             // Allow multiple headers within a component | ||||
|             margin-top: $interiorMarginLg; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     [class*="span-all"], | ||||
|     [class*="header"] { | ||||
|         @include gridTwoColumnSpanCols(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin gridTwoColumnSpanCols() { | ||||
|     grid-column: 1 / 3; | ||||
| @mixin propertiesHeader() { | ||||
|     border-radius: $smallCr; | ||||
|     background-color: $colorInspectorSectionHeaderBg; | ||||
|     color: $colorInspectorSectionHeaderFg; | ||||
|     font-weight: normal; | ||||
|     margin: 0 0 $interiorMarginSm 0; | ||||
|     padding: $interiorMarginSm $interiorMargin; | ||||
|     text-transform: uppercase; | ||||
| } | ||||
|  | ||||
| @mixin modalFullScreen() { | ||||
| @@ -165,10 +173,17 @@ | ||||
| } | ||||
|  | ||||
| /************************** CONTROLS, BUTTONS */ | ||||
| @mixin hover { | ||||
|     body.desktop & { | ||||
|         &:hover { | ||||
|             @content | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin htmlInputReset() { | ||||
|     appearance: none; | ||||
|     background: none; | ||||
|     background-color: transparent; | ||||
|     background: transparent; | ||||
|     border: none; | ||||
|     border-radius: 0; | ||||
|     outline: none; | ||||
| @@ -184,7 +199,7 @@ | ||||
|     border-radius: $controlCr; | ||||
|  | ||||
|     &.error { | ||||
|         background-color: $colorFormFieldErrorBg; | ||||
|         background: $colorFormFieldErrorBg; | ||||
|         color: $colorFormFieldErrorFg; | ||||
|     } | ||||
| } | ||||
| @@ -202,22 +217,136 @@ | ||||
|     box-shadow: $shdwInput; | ||||
|     color: $fg; | ||||
|  | ||||
|     &:hover { | ||||
|         box-shadow: $shdwInputHov; | ||||
|     } | ||||
|  | ||||
|     &:focus { | ||||
|         box-shadow: $shdwInputFoc; | ||||
|     } | ||||
|  | ||||
|     @include hover() { | ||||
|         &:not(:focus) { | ||||
|             box-shadow: $shdwInputHov; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin button($bg: $colorBtnBg, $fg: $colorBtnFg, $radius: $controlCr, $shdw: none) { | ||||
|     // Is this being used? Remove if not. | ||||
|     background: $bg; | ||||
|     color: $fg; | ||||
|     border-radius: $radius; | ||||
|     box-shadow: $shdw; | ||||
| } | ||||
|  | ||||
| @mixin cControl() { | ||||
|     $fs: 1em; | ||||
|     @include userSelectNone(); | ||||
|     display: inline-flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     overflow: hidden; | ||||
|  | ||||
|     &:before, | ||||
|     &:after { | ||||
|         font-family: symbolsfont; | ||||
|         display: block; | ||||
|         flex: 0 0 auto; | ||||
|     } | ||||
|  | ||||
|     &:after { | ||||
|         font-size: 0.8em; | ||||
|     } | ||||
|  | ||||
|     [class*="__label"] { | ||||
|         @include ellipsize(); | ||||
|         display: block; | ||||
|         line-height: $fs; // Remove effect on top and bottom padding | ||||
|         font-size: $fs; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin cButton() { | ||||
|     @include cControl(); | ||||
|     @include themedButton(); | ||||
|     border-radius: $controlCr; | ||||
|     color: $colorBtnFg; | ||||
|     cursor: pointer; | ||||
|     padding: $interiorMargin floor($interiorMargin * 1.25); | ||||
|  | ||||
|     @include hover() { | ||||
|         background: $colorBtnBgHov; | ||||
|         color: $colorBtnFgHov; | ||||
|     } | ||||
|  | ||||
|     &[class*="--major"] { | ||||
|         background: $colorBtnMajorBg; | ||||
|         color: $colorBtnMajorFg; | ||||
|  | ||||
|         @include hover() { | ||||
|             background: $colorBtnMajorBgHov; | ||||
|             color: $colorBtnMajorFgHov; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &[class*='--caution'] { | ||||
|         background: $colorBtnCautionBg; | ||||
|         color: $colorBtnCautionFg; | ||||
|  | ||||
|         &:hover { | ||||
|             background: $colorBtnCautionBgHov; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin cClickIcon() { | ||||
|     // A clickable element that just includes the icon, no background | ||||
|     // Padding is included to facilitate a bigger hit area | ||||
|     // Make the icon bigger relative to its container | ||||
|     @include cControl(); | ||||
|     $pLR: 4px; | ||||
|     $pTB: 3px; | ||||
|     background: none; | ||||
|     box-shadow: none; | ||||
|     border-radius: $controlCr; | ||||
|     color: $colorKey; | ||||
|     cursor: pointer; | ||||
|     padding: $pTB $pLR ; | ||||
|  | ||||
|     @include hover() { | ||||
|         background: $colorClickIconBgHov; | ||||
|         color: $colorClickIconFgHov; | ||||
|     } | ||||
|  | ||||
|     &:before, | ||||
|     *:before { | ||||
|         // *:before handles any nested containers that may contain glyph elements | ||||
|         // Needed for c-togglebutton. | ||||
|         font-size: 1.2em; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin cCtrlWrapper { | ||||
|     // Provides a wrapper around  buttons and other controls | ||||
|     // Contains control and provides positioning context for contained menu/palette. | ||||
|     // Wraps --menu elements, contains button and menu | ||||
|     overflow: visible; | ||||
|  | ||||
|     .c-menu { | ||||
|         // Default position of contained menu | ||||
|         top: 100%; left: 0; | ||||
|     } | ||||
|  | ||||
|     &[class*='--menus-up'] { | ||||
|         .c-menu { | ||||
|             top: auto; bottom: 100%; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &[class*='--menus-left'] { | ||||
|         .c-menu { | ||||
|             left: auto; right: 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @mixin wrappedInput() { | ||||
|     // An input that is wrapped. Optionally includes a __label or icon element. | ||||
|     // Based on .c-search. | ||||
|   | ||||
| @@ -24,8 +24,8 @@ | ||||
| //!********************************* CONTROLS *! | ||||
| //@import "../styles/controls/breadcrumb"; | ||||
| @import "../styles/controls/buttons"; | ||||
| @import "../styles/controls/palette"; | ||||
| @import "../styles/controls/controls"; | ||||
| //@import "../styles/controls/palette"; | ||||
| //@import "../styles/controls/controls"; | ||||
| @import "../styles/controls/lists"; | ||||
| @import "../styles/controls/menus"; | ||||
| @import "../styles/controls/messages"; | ||||
| @@ -46,7 +46,7 @@ | ||||
| //@import "../styles/search/search"; | ||||
| //@import "../styles/mobile/search/search"; | ||||
| @import "../styles/overlay/overlay"; | ||||
| //@import "../styles/tree/tree"; | ||||
| @import "../styles/tree/tree"; // TEMP - NEED FOR TREE IN INSPECTOR | ||||
| @import "../styles/object-label"; | ||||
| //@import "../styles/mobile/tree"; | ||||
| @import "../styles/user-environ/frame"; | ||||
|   | ||||
| @@ -116,7 +116,6 @@ | ||||
|     $p: $interiorMarginSm; | ||||
|     @include discreteItem(); | ||||
|     display: flex; | ||||
|     //flex-wrap: wrap; | ||||
|     padding: $interiorMarginSm $interiorMarginSm $interiorMarginSm $interiorMargin; | ||||
|  | ||||
|     &__time, | ||||
| @@ -156,7 +155,7 @@ | ||||
|     } | ||||
|  | ||||
|     &__text { | ||||
|         min-height: 24px; // Needed in Firefox when field is blank | ||||
|         min-height: 22px; // Needed in Firefox when field is blank | ||||
|         white-space: pre-wrap; | ||||
|  | ||||
|         &.is-blank-notebook-entry { | ||||
|   | ||||
| @@ -24,5 +24,6 @@ | ||||
| // Meant for use as a single line import in Vue SFC's. | ||||
| // Do not include anything that renders to CSS! | ||||
| @import "constants"; | ||||
| @import "constants-snow"; // TEMP | ||||
| @import "constants-espresso"; // TEMP | ||||
| //@import "constants-snow"; // TEMP | ||||
| @import "mixins"; | ||||
| @@ -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> | ||||
| @@ -5,7 +5,6 @@ | ||||
|             'l-pane--horizontal-handle-after': type === 'horizontal' && handle === 'after', | ||||
|             'l-pane--vertical-handle-before': type === 'vertical' && handle === 'before', | ||||
|             'l-pane--vertical-handle-after': type === 'vertical' && handle === 'after', | ||||
|             'l-pane--collapsable' : collapsable, | ||||
|             'l-pane--collapsed': collapsed, | ||||
|             'l-pane--reacts': !handle, | ||||
|             'l-pane--resizing': resizing === true | ||||
| @@ -14,11 +13,13 @@ | ||||
|              class="l-pane__handle" | ||||
|              @mousedown="start"> | ||||
|         </div> | ||||
|         <button v-if="label" | ||||
|            class="l-pane__collapse-button" | ||||
|            @click="toggleCollapse"> | ||||
|         <div class="l-pane__header" | ||||
|              v-if="label"> | ||||
|             <span class="l-pane__label">{{ label }}</span> | ||||
|         </button> | ||||
|             <button class="l-pane__collapse-button c-button" | ||||
|                     v-if="collapsable" | ||||
|                     @click="toggleCollapse"></button> | ||||
|         </div> | ||||
|         <div class="l-pane__contents"> | ||||
|             <slot></slot> | ||||
|         </div> | ||||
| @@ -61,14 +62,11 @@ | ||||
|             // __handle and __label don't appear in mobile | ||||
|             display: none; | ||||
|         } | ||||
|  | ||||
|         &__collapse-button { | ||||
|             position: absolute; | ||||
|          | ||||
|         &__header { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             top: 0; right: 0; // Default | ||||
|             z-index: 1; | ||||
|             margin-bottom: $interiorMargin; | ||||
|         } | ||||
|  | ||||
|         &--reacts { | ||||
| @@ -85,6 +83,7 @@ | ||||
|                 transition: opacity 150ms ease; | ||||
|                 opacity: 0; | ||||
|                 pointer-events: none; | ||||
|                 overflow: hidden; | ||||
|  | ||||
|                 > * { | ||||
|                     min-width: 0 !important; | ||||
| @@ -111,7 +110,6 @@ | ||||
|         &__contents { | ||||
|             flex: 1 1 100%; | ||||
|             opacity: 1; | ||||
|             padding: $interiorMargin; | ||||
|             pointer-events: inherit; | ||||
|             transition: opacity 250ms ease 250ms; | ||||
|  | ||||
| @@ -121,13 +119,10 @@ | ||||
|             } | ||||
|  | ||||
|             > [class*="__"] + [class*="__"] { | ||||
|                 // Create margin between elements in a pane | ||||
|                 // Doesn't match first elem, but will match all subsequent | ||||
|                 margin-top: $interiorMargin; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /************************ DESKTOP STYLES */ | ||||
|         /************************************************ DESKTOP STYLES */ | ||||
|         body.desktop & { | ||||
|             &__handle { | ||||
|                 background: $colorSplitterBg; | ||||
| @@ -150,52 +145,35 @@ | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &__header { | ||||
|                 font-size: floor(12px * .9); | ||||
|             } | ||||
|  | ||||
|             &__collapse-button { | ||||
|                 $m: 2px; | ||||
|                 $h: 12px; | ||||
|                 box-shadow: none; | ||||
|                 background: $splitterBtnColorBg; | ||||
|                 color: $splitterBtnColorFg; | ||||
|                 flex: 0 0 nth($splitterBtnD, 1); | ||||
|                 font-size: $h * .9; | ||||
|                 position: relative; | ||||
|                 justify-content: start; | ||||
|                 transition: $transOut; | ||||
|                 border-radius: $smallCr; | ||||
|                 font-size: 6px; | ||||
|                 line-height: 90%; | ||||
|                 padding: 3px 15px; | ||||
|  | ||||
|                 &:after { | ||||
|                     // Close icon | ||||
|                     background: $colorBtnBg; | ||||
|                     border-radius: $smallCr; | ||||
|                     color: $colorBtnFg; | ||||
|                     content: $glyph-icon-arrow-right-equilateral; | ||||
|                     display: block; | ||||
|                     font-family: symbolsfont; | ||||
|                     font-size: 6px; | ||||
|                     line-height: 90%; | ||||
|                     padding: 3px 15px; | ||||
|                     position: absolute; | ||||
|                     right: $m; | ||||
|                     top: $m; | ||||
|                     transition: $transOut; | ||||
|                     z-index: -1; | ||||
|                 } | ||||
|  | ||||
|                 &:hover { | ||||
|                     background: rgba(black, 0.1); | ||||
|                     &:after { | ||||
|                         background: $splitterBtnColorHoverBg; | ||||
|                         color: $splitterBtnColorHoverFg; | ||||
|                         transition: $transIn; | ||||
|                     } | ||||
|                 @include hover() { | ||||
|                     background: $colorBtnBgHov; | ||||
|                     color: $colorBtnFgHov; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &__label { | ||||
|                 // Name of the pane | ||||
|                 @include ellipsize(); | ||||
|                 @include userSelectNone(); | ||||
|                 color: $splitterBtnLabelColorFg; | ||||
|                 display: block; | ||||
|                 padding-right: nth($splitterBtnD, 2) + $interiorMargin; // Force label to ellipsis | ||||
|                 pointer-events: none; | ||||
|                 text-transform: uppercase; | ||||
|                 transform-origin: top left; | ||||
|                 flex: 1 0 90%; | ||||
|                 flex: 1 1 auto; | ||||
|             } | ||||
|  | ||||
|             &--resizing { | ||||
| @@ -208,6 +186,7 @@ | ||||
|             } | ||||
|  | ||||
|             &[class*="--collapsed"] { | ||||
|                 /********************************* STYLES FOR DESKTOP COLLAPSED PANES, ALL ORIENTATIONS */ | ||||
|                 $d: nth($splitterBtnD, 1); | ||||
|                 flex-basis: $d; | ||||
|                 min-width: $d !important; | ||||
| @@ -217,19 +196,24 @@ | ||||
|                     display: none; | ||||
|                 } | ||||
|  | ||||
|                 > .l-pane__collapse-button { | ||||
|                     background: $splitterBtnColorFg; | ||||
|                     color: $splitterBtnColorBg; | ||||
|  | ||||
|                 .l-pane__header { | ||||
|                     &:hover { | ||||
|                         background: $splitterBtnColorHoverBg !important; | ||||
|                         color: $splitterCollapsedBtnColorFgHov; | ||||
|                         .l-pane__label { | ||||
|                             color: inherit; | ||||
|                         } | ||||
|                         .l-pane__collapse-button { | ||||
|                             background: $splitterCollapsedBtnColorBgHov; | ||||
|                             color: inherit; | ||||
|                             transition: $transIn; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             > .l-pane__collapse-button { | ||||
|                 height: nth($splitterBtnD, 1); | ||||
|                 padding: $interiorMarginSm $interiorMarginSm; | ||||
|                 .l-pane__collapse-button { | ||||
|                     background: $splitterCollapsedBtnColorBg; | ||||
|                     color: $splitterCollapsedBtnColorFg; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &[class*="--horizontal"] { | ||||
| @@ -248,31 +232,44 @@ | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 .l-pane__collapse-button { | ||||
|                     &:before { | ||||
|                         content: $glyph-icon-arrow-right-equilateral; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 &[class*="--collapsed"] { | ||||
|                     > .l-pane__collapse-button { | ||||
|                     /************************ COLLAPSED HORIZONTAL SPLITTER, EITHER DIRECTION */ | ||||
|                     [class*="__header"] { | ||||
|                         @include abs(); | ||||
|                         margin: 0; | ||||
|                     } | ||||
|  | ||||
|                     [class*="label"] { | ||||
|                         position: absolute; | ||||
|                         transform: translate($interiorMarginLg + 1, 18px) rotate(90deg); | ||||
|                         left: 3px; | ||||
|                         top: 0; | ||||
|                         z-index: 1; | ||||
|                     } | ||||
|  | ||||
|                     .l-pane__collapse-button { | ||||
|                         border-top-left-radius: 0; | ||||
|                         border-bottom-left-radius: 0; // Only have to do this once, because of scaleX(-1) below. | ||||
|                         position: absolute; | ||||
|                         top: 0; right: 0; bottom: 0; left: 0; | ||||
|                         height: auto; width: 100%; | ||||
|                         padding: 0; | ||||
|  | ||||
|                         [class*="label"] { | ||||
|                         &:before { | ||||
|                             position: absolute; | ||||
|                             transform: translate($interiorMarginLg + 1, 18px) rotate(90deg); | ||||
|                             top: 0; | ||||
|                         } | ||||
|  | ||||
|                         &:after { | ||||
|                             background: none; | ||||
|                             padding: 0; | ||||
|                             top: $interiorMargin; | ||||
|                             left: 50%; | ||||
|                             right: auto; | ||||
|                             transform: translateX(-50%); | ||||
|                             width: auto; | ||||
|                             top: 5px; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 /************************** Horizontal Splitter Before */ | ||||
|                 // Inspector pane | ||||
|                 &[class*="-before"] { | ||||
|                     > .l-pane__handle { | ||||
|                         left: 0; | ||||
| @@ -280,15 +277,14 @@ | ||||
|                     } | ||||
|  | ||||
|                     &[class*="--collapsed"] { | ||||
|                         > .l-pane__collapse-button { | ||||
|                             &:after { | ||||
|                                 transform: translateX(-50%) scaleX(-1); | ||||
|                             } | ||||
|                         .l-pane__collapse-button { | ||||
|                             transform: scaleX(-1); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 /************************** Horizontal Splitter After */ | ||||
|                 // Tree pane | ||||
|                 &[class*="-after"] { | ||||
|                     > .l-pane__handle { | ||||
|                         right: 0; | ||||
| @@ -296,7 +292,7 @@ | ||||
|                     } | ||||
|  | ||||
|                     &:not([class*="--collapsed"]) { | ||||
|                         > .l-pane__collapse-button:after { | ||||
|                         .l-pane__collapse-button { | ||||
|                             transform: scaleX(-1); | ||||
|                         } | ||||
|                     } | ||||
| @@ -320,19 +316,19 @@ | ||||
|                 } | ||||
|  | ||||
|                 /************************** Vertical Splitter Before */ | ||||
|                 // Pane collapses downward | ||||
|                 // Pane collapses downward. Used by Elements pool in Inspector | ||||
|                 &[class*="-before"] { | ||||
|                     > .l-pane__handle { | ||||
|                         top: 0; | ||||
|                         transform: translateY(floor($splitterHandleD / -1)); | ||||
|                     } | ||||
|  | ||||
|                     > .l-pane__collapse-button:after { | ||||
|                     .l-pane__collapse-button:before { | ||||
|                         content: $glyph-icon-arrow-down; | ||||
|                     } | ||||
|  | ||||
|                     &.l-pane--collapsed { | ||||
|                         > .l-pane__collapse-button:after { | ||||
|                         > .l-pane__collapse-button { | ||||
|                             transform: scaleY(-1); | ||||
|                         } | ||||
|                     } | ||||
|   | ||||
| @@ -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> | ||||
| @@ -18,8 +18,6 @@ | ||||
|     @import "~styles/sass-base"; | ||||
|  | ||||
|     .c-inspector { | ||||
|         min-width: 150px; | ||||
|  | ||||
|         > [class*="__"] { | ||||
|             min-height: 50px; | ||||
|  | ||||
| @@ -52,7 +50,7 @@ | ||||
|         } | ||||
|  | ||||
|         /************************************************************** LEGACY */ | ||||
|         // TODO: refactor when markup can be converted | ||||
|         // TODO: refactor when legacy properties markup can be converted | ||||
|         .inspector-location { | ||||
|             display: inline-block; | ||||
|  | ||||
| @@ -93,10 +91,45 @@ | ||||
|                 width: 4px; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         .l-inspector-part { | ||||
|             display: contents; | ||||
|         } | ||||
|  | ||||
|         h2 { | ||||
|             @include propertiesHeader(); | ||||
|             font-size: 0.65rem; | ||||
|             grid-column: 1 / 3; | ||||
|         } | ||||
|  | ||||
|         .tree .grid-properties { | ||||
|             margin-left: $treeItemIndent + $interiorMarginLg; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .c-properties { | ||||
|         @include gridTwoColumn(); | ||||
|         display: grid; | ||||
|         grid-row-gap: 0; | ||||
|         grid-template-columns: 1fr 2fr; | ||||
|         align-items: start; | ||||
|         min-width: 150px; | ||||
|  | ||||
|         [class*="header"] { | ||||
|             @include propertiesHeader(); | ||||
|  | ||||
|             &:not(:first-child) { | ||||
|                 // Allow multiple headers within a component | ||||
|                 margin-top: $interiorMarginLg; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [class*="span-all"], | ||||
|         [class*="header"] { | ||||
|             grid-column: 1 / 3; | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|         + .c-properties { | ||||
|             // Margin between components | ||||
| @@ -139,7 +172,7 @@ | ||||
|             word-break: break-all; | ||||
|             &:first-child { | ||||
|                 // If there is no preceding .label element, make value span columns | ||||
|                 @include gridTwoColumnSpanCols(); | ||||
|                 grid-column: 1 / 3; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -75,7 +75,12 @@ | ||||
|                 this.openmct.editor.cancel(); | ||||
|             }, | ||||
|             saveAndFinishEditing() { | ||||
|                 this.openmct.editor.save(); | ||||
|                 this.openmct.editor.save().then(()=> { | ||||
|                     this.openmct.notifications.info('Save successful'); | ||||
|                 }).catch((error) => { | ||||
|                     this.openmct.notifications.error('Error saving objects'); | ||||
|                     console.error(error); | ||||
|                 }); | ||||
|             } | ||||
|         }, | ||||
|         data: function () { | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| <template> | ||||
|     <div class="l-shell" :class="{'is-editing': isEditing}"> | ||||
|     <div class="l-shell" :class="{ | ||||
|             'is-editing': isEditing | ||||
|         }"> | ||||
|         <div class="l-shell__head"> | ||||
|             <CreateButton class="l-shell__create-button"></CreateButton> | ||||
|             <div class="l-shell__controls"> | ||||
| @@ -23,12 +25,9 @@ | ||||
|                 <div class="l-shell__search"> | ||||
|                     <search class="c-search--major" ref="shell-search"></search> | ||||
|                 </div> | ||||
|                 <div class="l-shell__tree"> | ||||
|                     <mct-tree></mct-tree> | ||||
|                 </div> | ||||
|                 <mct-tree class="l-shell__tree"></mct-tree> | ||||
|             </pane> | ||||
|             <pane class="l-shell__pane-main" | ||||
|                 :class="{ 'is-editing' : true }"> | ||||
|             <pane class="l-shell__pane-main"> | ||||
|                 <browse-bar class="l-shell__main-view-browse-bar" | ||||
|                             ref="browseBar"> | ||||
|                 </browse-bar> | ||||
| @@ -48,7 +47,7 @@ | ||||
|             </pane> | ||||
|         </multipane> | ||||
|         <div class="l-shell__status"> | ||||
|             <MctStatus></MctStatus> | ||||
|             <StatusBar></StatusBar> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
| @@ -62,47 +61,67 @@ | ||||
|         top: 0; right: 0; bottom: 0; left: 0; | ||||
|         display: flex; | ||||
|         flex-flow: column nowrap; | ||||
|         overflow: hidden; | ||||
|  | ||||
|         &__status { | ||||
|             background: $colorBodyFg; | ||||
|             color: $colorBodyBg; | ||||
|             border-top: 1px solid $colorInteriorBorder; | ||||
|             background: $colorStatusBarBg; | ||||
|             color: $colorStatusBarFg; | ||||
|             height: 24px; | ||||
|             padding: $interiorMarginSm; | ||||
|         } | ||||
|  | ||||
|         &__pane-tree { | ||||
|             background: $colorTreeBg; | ||||
|             width: 40%; | ||||
|  | ||||
|             [class*="collapse-button"] { | ||||
|                 // For mobile, collapse button becomes menu icon | ||||
|                 body.mobile & { | ||||
|                     height: $mobileMenuIconD; | ||||
|                     width: $mobileMenuIconD; | ||||
|                     @include cClickIcon(); | ||||
|                     position: absolute; | ||||
|                     right: -2 * nth($shellPanePad, 2); // Needs to be -1 * when pane is collapsed | ||||
|                     top: 0; | ||||
|                     transform: translateX(100%); | ||||
|                     width: $mobileMenuIconD; | ||||
|                     z-index: 2; | ||||
|  | ||||
|                     &:before { | ||||
|                         color: $colorKey; | ||||
|                         content: $glyph-icon-menu-hamburger; | ||||
|                         font-family: symbolsfont; | ||||
|                         font-size: 1.4em; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         &__pane-main, | ||||
|         &__pane-tree { | ||||
|             > .l-pane__contents { | ||||
|         &__pane-tree, | ||||
|         &__pane-inspector, | ||||
|         &__pane-main { | ||||
|             .l-pane__contents { | ||||
|                 display: flex; | ||||
|                 flex-flow: column nowrap; | ||||
|  | ||||
|                 > * { | ||||
|                     flex: 0 0 auto; | ||||
|                     + * { | ||||
|                         margin-top: $interiorMarginLg; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         body.mobile & { | ||||
|             &__pane-tree { | ||||
|                 background: linear-gradient(90deg, transparent 70%, rgba(black, 0.2) 99%, rgba(black, 0.3)); | ||||
|  | ||||
|                 &[class*="--collapsed"] { | ||||
|                     [class*="collapse-button"] { | ||||
|                         right: -1 * nth($shellPanePad, 2); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         body.phone.portrait & { | ||||
|             &__pane-tree { | ||||
|                 width: calc(100% - #{$mobileMenuIconD}); | ||||
|                 width: calc(100% - #{$mobileMenuIconD + (2 * nth($shellPanePad, 2))}); | ||||
|  | ||||
|                 + .l-pane { | ||||
|                     // Hide pane-main when this pane is expanded | ||||
| @@ -138,13 +157,13 @@ | ||||
|         } | ||||
|  | ||||
|         body.mobile & .l-shell__main-view-browse-bar { | ||||
|             margin-left: $mobileMenuIconD - $interiorMarginLg; // Make room for the hamburger! | ||||
|             margin-left: $mobileMenuIconD; // Make room for the hamburger! | ||||
|         } | ||||
|  | ||||
|         &__head { | ||||
|             align-items: center; | ||||
|             background: $colorHeadBg; | ||||
|             justify-content: space-between; | ||||
|             border-bottom: 1px solid $colorInteriorBorder; | ||||
|             padding: $interiorMargin; | ||||
|  | ||||
|             > [class*="__"] + [class*="__"] { | ||||
| @@ -165,27 +184,40 @@ | ||||
|         } | ||||
|  | ||||
|         /******************************* MAIN AREA */ | ||||
|  | ||||
|         &__main-container { | ||||
|             // Wrapper for main views | ||||
|             flex: 1 1 auto; | ||||
|             flex: 1 1 auto !important; | ||||
|             overflow: auto; | ||||
|             //font-size: 16px; // TEMP FOR LEGACY STYLING | ||||
|         } | ||||
|  | ||||
|         &__tree { | ||||
|             // Tree component within __pane-tree | ||||
|             flex: 1 1 100%; | ||||
|             overflow-y: auto; | ||||
|             flex: 1 1 auto !important; | ||||
|         } | ||||
|  | ||||
|         &__time-conductor { | ||||
|             border-top: 1px solid $colorInteriorBorder; | ||||
|             flex: 0 0 auto; | ||||
|             padding-top: $interiorMargin; | ||||
|         } | ||||
|  | ||||
|         &__main { | ||||
|             > .l-pane { | ||||
|                 padding: nth($shellPanePad, 1) nth($shellPanePad, 2); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         body.desktop & { | ||||
|             /********** HEAD AND STATUS */ | ||||
|             &__main { | ||||
|                 // Top and bottom padding in container that holds tree, __pane-main and Inspector | ||||
|                 padding: $shellMainPad; | ||||
|                 > .l-pane { | ||||
|                     padding-top: 0; | ||||
|                     padding-bottom: 0; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &__pane-tree, | ||||
|             &__pane-inspector { | ||||
|                 max-width: 30%; | ||||
| @@ -198,18 +230,12 @@ | ||||
|             &__pane-inspector { | ||||
|                 width: 200px; | ||||
|             } | ||||
|  | ||||
|             &__toolbar { | ||||
|                 flex: 0 0 auto; | ||||
|                 margin-bottom: $interiorMargin; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
|     import Inspector from '../inspector/Inspector.vue'; | ||||
|     import MctStatus from './MctStatus.vue'; | ||||
|     import MctTree from './mct-tree.vue'; | ||||
|     import ObjectView from './ObjectView.vue'; | ||||
|     import MctTemplate from '../legacy/mct-template.vue'; | ||||
| @@ -219,7 +245,8 @@ | ||||
|     import multipane from '../controls/multipane.vue'; | ||||
|     import pane from '../controls/pane.vue'; | ||||
|     import BrowseBar from './BrowseBar.vue'; | ||||
|     import Toolbar from './Toolbar.vue'; | ||||
|     import StatusBar from './status-bar/StatusBar.vue'; | ||||
|     import Toolbar from '../toolbar/Toolbar.vue'; | ||||
|  | ||||
|     var enterFullScreen = () => { | ||||
|         var docElm = document.documentElement; | ||||
| @@ -251,12 +278,8 @@ | ||||
|  | ||||
|     export default { | ||||
|         inject: ['openmct'], | ||||
|         data() { | ||||
|             return {isEditing: false}; | ||||
|         }, | ||||
|         components: { | ||||
|             Inspector, | ||||
|             MctStatus, | ||||
|             MctTree, | ||||
|             ObjectView, | ||||
|             'mct-template': MctTemplate, | ||||
| @@ -266,6 +289,7 @@ | ||||
|             multipane, | ||||
|             pane, | ||||
|             BrowseBar, | ||||
|             StatusBar, | ||||
|             Toolbar | ||||
|         }, | ||||
|         mounted() { | ||||
| @@ -276,7 +300,8 @@ | ||||
|         data: function () { | ||||
|             return { | ||||
|                 fullScreen: false, | ||||
|                 conductorComponent: {} | ||||
|                 conductorComponent: {}, | ||||
|                 isEditing: false | ||||
|             } | ||||
|         }, | ||||
|         methods: { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user