 c6053e234a
			
		
	
	c6053e234a
	
	
	
		
			
			* Modify Selection API to support multi-select via shift click. * Add support for shift + click to add and remove the selection. * Display message in Location and Properties for multi-select. * Define applicableSelectedItems for toolbar items. Move toolbar control definitions to functions. * Hide positioning inputs if multi-select. Show a 'non-specific' icon when a discrete setting can't be shown in a mixed setting." * Add toolbar controls in groups per layout item type. Add nonSpecific property to toolbar items to be used by toolbar controls to show non-specific icon. * Modify toolbar button to react to nonSpecific flag. Get form value by checking value of applicable selected items. * Support deleting multiple selected objects. * Do not disable controls when selected items have mixed setting. * Revert default color to original value. * Changes to snap-to-grid * Remove timeout for updating toolbar after mutation. Do not copy toolbar item when iterating the structure. * Implement move to top and move to bottom for multi-select * Implement move up and move down for multi-select. * Markup and CSS changes for mixed settings in toolbar - Toggle, color-picker buttons; - TODO: check other themes and sync; * Mixed settings styling complete - Refined and synced theme constants; - Styling for all toolbar components; - Text size menu handling; - Inspector messaging; * Fix selection path * Mixed settings styling refinements - Normalized button styling for mixed style context; - Better theme constant naming; - Refined swatch styling, better theme constants; * First cut at getting the bounding rectangle working for multi-select. * Set pointer-events to none on c-edit-frame to prevent marquee reacting to click events. * Delete capturing before calling select. * Remove EditMarquee from ITEM_TYPE_VIEW_MAP * Pass selected layout items as a prop to edit marquee instead of selection so that x, y, w, h are updated. * Multi-select c-frame-edit visual fixes - WIP * Add complexContent class for a single selected item whose type is subobject-view. * Move 'c-frame-edit-move' div to layout frame. * Saving work - multi-move WIP * Fixes issue with selection happening at end of drag * Styles fixed for new markup organization - Marquee, frame styles; - $editMarqueeBorder style added to theme constants; * Significant functionality for .c-frame-edit__move element - Added .is-multi-selected class to .l-layout when > 1 items selected; - __move element now handles multi-select and complex content (CC) objects: -- 0 to 1 items selected, displays as hover bar with grippy on all CC objects, -- > 1 items selected, __move covers all of the frame of all selected CC items and doesn't allow sub-object selection, and only displays as hover bar on non-selected CC objects; - Added better styling for selected objects while editing; - Code cleanup and consolidation; - Left translucent green style applied to __move element to temporarily aid development; - TODO: fix line drawing object; * - Fix an issue where shift click did not remove the selected item from the selection after move. - Modify telemetry and subobject views to emit move and endMove events. - Clone selectedLayoutItems to get initial positions instead of selection so subsequent moves start from the current position. * Fix cursor for __move, code comment refinements * Code cleanup, line view markup changes - line view markup brought into line with structure in LayoutFrame.vue; * Implement multi-resize * Simplify edit marquee code. Revert image and text views' default position to the original values. * Fix resize for single selection when snap to grid is disabled * Hide edit marquee if single line is selected, and show c-frame-edit in line-view instead. * Fix for LineView handles * Remove snap to grid toggle button and modify the migration script to convert elements with pixel coordinates to grid. * Fix resizing single line * Calculate width and height differently for line to position marquee correctly. * Fix moving single selected line * Calculate the height and width for line before comparing them with max height and width to correct the marquee position. * Change the logic for showing frame edit for lines to check for item id. * Allow multi-move with line in the mix. * Implement multi-resize when grabbing SW corner. * Removed temp green tint from __move element * Fix object undefined error. * Implement multi-resize for all items except line (take 2). * Misc UI 7 - CSS selectors to properly display edit marquee, don't show in browse mode; * Fix multi-resize for lines. Make sure line's height and width is minimum 1. * Disable inspector views when multiple objects are selected. * Restored layout grid display on sub-layout selection * Clean up code * Fixes - Edit marquee display fixes; * More code clean up * SIGNIFICANT fixes and rewriting in LayoutFrame.vue - Styles for .c-frame-edit__move element for selection and hovering; - local controls; - view large button; - Theme constants updated; * Get selected item's index from layoutItems. * Address review feedback. * Merge topic-core-refactor * Reset keyString to empty string after setting original path when domainObject is undefined. Add proper check for selection.
		
			
				
	
	
		
			265 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| /*****************************************************************************
 | |
|  * 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.
 | |
|  *****************************************************************************/
 | |
| 
 | |
| <template>
 | |
|     <div class="l-layout__frame c-frame no-frame"
 | |
|          :style="style">
 | |
|         <svg width="100%" height="100%">
 | |
|             <line v-bind="linePosition"
 | |
|                   :stroke="item.stroke"
 | |
|                   stroke-width="2">
 | |
|             </line>
 | |
|         </svg>
 | |
| 
 | |
|         <div class="c-frame-edit__move"
 | |
|              @mousedown="startDrag($event)"></div>
 | |
|         <div class="c-frame-edit" v-if="showFrameEdit">
 | |
|             <div class="c-frame-edit__handle"
 | |
|                  :class="startHandleClass"
 | |
|                  @mousedown="startDrag($event, 'start')"></div>
 | |
|             <div class="c-frame-edit__handle"
 | |
|                  :class="endHandleClass"
 | |
|                  @mousedown="startDrag($event, 'end')"></div>
 | |
|         </div>
 | |
|     </div>
 | |
| </template>
 | |
| 
 | |
|  <script>
 | |
| 
 | |
|     const START_HANDLE_QUADRANTS = {
 | |
|         1: 'c-frame-edit__handle--sw',
 | |
|         2: 'c-frame-edit__handle--se',
 | |
|         3: 'c-frame-edit__handle--ne',
 | |
|         4: 'c-frame-edit__handle--nw'
 | |
|     };
 | |
| 
 | |
|     const END_HANDLE_QUADRANTS = {
 | |
|         1: 'c-frame-edit__handle--ne',
 | |
|         2: 'c-frame-edit__handle--nw',
 | |
|         3: 'c-frame-edit__handle--sw',
 | |
|         4: 'c-frame-edit__handle--se'
 | |
|     };
 | |
| 
 | |
|     export default {
 | |
|         makeDefinition() {
 | |
|             return {
 | |
|                 x: 5,
 | |
|                 y: 10,
 | |
|                 x2: 10,
 | |
|                 y2: 5,
 | |
|                 stroke: '#717171'
 | |
|             };
 | |
|         },
 | |
|         inject: ['openmct'],
 | |
|         props: {
 | |
|             item: Object,
 | |
|             gridSize: Array,
 | |
|             initSelect: Boolean,
 | |
|             index: Number,
 | |
|             multiSelect: Boolean
 | |
|         },
 | |
|         data() {
 | |
|             return {
 | |
|                 dragPosition: undefined,
 | |
|                 dragging: undefined,
 | |
|                 selection: []
 | |
|             };
 | |
|         },
 | |
|         computed: {
 | |
|             showFrameEdit() {
 | |
|                 let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
 | |
|                 return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
 | |
|             },
 | |
|             position() {
 | |
|                 let {x, y, x2, y2} = this.item;
 | |
|                 if (this.dragging && this.dragPosition) {
 | |
|                     ({x, y, x2, y2} = this.dragPosition);
 | |
|                 }
 | |
|                 return {x, y, x2, y2};
 | |
|             },
 | |
|             style() {
 | |
|                 let {x, y, x2, y2} = this.position;
 | |
|                 let width = Math.max(this.gridSize[0] * Math.abs(x - x2), 1);
 | |
|                 let height = Math.max(this.gridSize[1] * Math.abs(y - y2), 1);
 | |
|                 let left = this.gridSize[0] * Math.min(x, x2);
 | |
|                 let top = this.gridSize[1] * Math.min(y, y2);
 | |
|                 return {
 | |
|                     left: `${left}px`,
 | |
|                     top: `${top}px`,
 | |
|                     width: `${width}px`,
 | |
|                     height: `${height}px`,
 | |
|                 };
 | |
|             },
 | |
|             startHandleClass() {
 | |
|                 return START_HANDLE_QUADRANTS[this.vectorQuadrant];
 | |
|             },
 | |
|             endHandleClass() {
 | |
|                 return END_HANDLE_QUADRANTS[this.vectorQuadrant];
 | |
|             },
 | |
|             vectorQuadrant() {
 | |
|                 let {x, y, x2, y2} = this.position;
 | |
|                 if (x2 > x) {
 | |
|                     if (y2 < y) {
 | |
|                         return 1;
 | |
|                     }
 | |
|                     return 4;
 | |
|                 }
 | |
|                 if (y2 < y) {
 | |
|                     return 2;
 | |
|                 }
 | |
|                 return 3;
 | |
|             },
 | |
|             linePosition() {
 | |
|                 if (this.vectorQuadrant === 1) {
 | |
|                     return {
 | |
|                         x1: '0%',
 | |
|                         y1: '100%',
 | |
|                         x2: '100%',
 | |
|                         y2: '0%'
 | |
|                     };
 | |
|                 }
 | |
|                 if (this.vectorQuadrant === 4) {
 | |
|                     return {
 | |
|                         x1: '0%',
 | |
|                         y1: '0%',
 | |
|                         x2: '100%',
 | |
|                         y2: '100%'
 | |
|                     };
 | |
|                 }
 | |
|                 if (this.vectorQuadrant === 2) {
 | |
|                     return {
 | |
|                         x1: '0%',
 | |
|                         y1: '0%',
 | |
|                         x2: '100%',
 | |
|                         y2: '100%'
 | |
|                     };
 | |
|                 }
 | |
|                 if (this.vectorQuadrant === 3) {
 | |
|                     return {
 | |
|                         x1: '100%',
 | |
|                         y1: '0%',
 | |
|                         x2: '0%',
 | |
|                         y2: '100%'
 | |
|                     };
 | |
|                 }
 | |
|             }
 | |
|         },
 | |
|         methods: {
 | |
|             startDrag(event, position) {
 | |
|                 this.dragging = position;
 | |
|                 document.body.addEventListener('mousemove', this.continueDrag);
 | |
|                 document.body.addEventListener('mouseup', this.endDrag);
 | |
|                 this.startPosition = [event.pageX, event.pageY];
 | |
|                 this.dragPosition = {
 | |
|                     x: this.item.x,
 | |
|                     y: this.item.y,
 | |
|                     x2: this.item.x2,
 | |
|                     y2: this.item.y2
 | |
|                 };
 | |
|                 event.preventDefault();
 | |
|             },
 | |
|             continueDrag(event) {
 | |
|                 event.preventDefault();
 | |
|                 let pxDeltaX = this.startPosition[0] - event.pageX;
 | |
|                 let pxDeltaY = this.startPosition[1] - event.pageY;
 | |
|                 let newPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
 | |
| 
 | |
|                 if (!this.dragging) {
 | |
|                     if (!_.isEqual(newPosition, this.dragPosition)) {
 | |
|                         let gridDelta = [event.pageX - this.startPosition[0], event.pageY - this.startPosition[1]];
 | |
|                         this.dragPosition = newPosition;
 | |
|                         this.$emit('move', this.toGridDelta(gridDelta));
 | |
|                     }
 | |
|                 } else {
 | |
|                     this.dragPosition = newPosition;
 | |
|                 }
 | |
|             },
 | |
|             endDrag(event) {
 | |
|                 document.body.removeEventListener('mousemove', this.continueDrag);
 | |
|                 document.body.removeEventListener('mouseup', this.endDrag);
 | |
|                 let {x, y, x2, y2} = this.dragPosition;
 | |
|                 if (!this.dragging) {
 | |
|                     this.$emit('endMove');
 | |
|                 } else {
 | |
|                     this.$emit('endLineResize', this.item, {x, y, x2, y2});
 | |
|                 }
 | |
|                 this.dragPosition = undefined;
 | |
|                 this.dragging = undefined;
 | |
|                 event.preventDefault();
 | |
|             },
 | |
|             calculateDragPosition(pxDeltaX, pxDeltaY) {
 | |
|                 let gridDeltaX = Math.round(pxDeltaX / this.gridSize[0]);
 | |
|                 let gridDeltaY = Math.round(pxDeltaY / this.gridSize[0]); // TODO: should this be gridSize[1]?
 | |
|                 let {x, y, x2, y2} = this.item;
 | |
|                 let dragPosition = {x, y, x2, y2};
 | |
| 
 | |
|                 if (this.dragging === 'start') {
 | |
|                     dragPosition.x -= gridDeltaX;
 | |
|                     dragPosition.y -= gridDeltaY;
 | |
|                 } else if (this.dragging === 'end') {
 | |
|                     dragPosition.x2 -= gridDeltaX;
 | |
|                     dragPosition.y2 -= gridDeltaY;
 | |
|                 } else {
 | |
|                     // dragging entire line.
 | |
|                     dragPosition.x -= gridDeltaX;
 | |
|                     dragPosition.y -= gridDeltaY;
 | |
|                     dragPosition.x2 -= gridDeltaX;
 | |
|                     dragPosition.y2 -= gridDeltaY;
 | |
|                 }
 | |
|                 return dragPosition;
 | |
|             },
 | |
|             setSelection(selection) {
 | |
|                 this.selection = selection;
 | |
|             },
 | |
|             toGridDelta(pixelDelta) {
 | |
|                 return pixelDelta.map((v, i) => {
 | |
|                     return Math.round(v / this.gridSize[i]);
 | |
|                 });
 | |
|             }
 | |
|         },
 | |
|         watch: {
 | |
|             index(newIndex) {
 | |
|                 if (!this.context) {
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 this.context.index = newIndex;
 | |
|             }
 | |
|         },
 | |
|         mounted() {
 | |
|             this.openmct.selection.on('change', this.setSelection);
 | |
|             this.context = {
 | |
|                 layoutItem: this.item,
 | |
|                 index: this.index
 | |
|             };
 | |
|             this.removeSelectable = this.openmct.selection.selectable(
 | |
|                 this.$el, this.context, this.initSelect);
 | |
|         },
 | |
|         destroyed() {
 | |
|             if (this.removeSelectable) {
 | |
|                 this.removeSelectable();
 | |
|             }
 | |
|             this.openmct.selection.off('change', this.setSelection);
 | |
|         }
 | |
|     }
 | |
|  </script>
 |