* 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.
362 lines
11 KiB
Vue
362 lines
11 KiB
Vue
<template>
|
|
<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">
|
|
<button class="c-icon-button c-icon-button--major icon-new-window" title="Open in a new browser tab"
|
|
@click="openInNewTab"
|
|
target="_blank">
|
|
</button>
|
|
<button v-bind:class="['c-icon-button c-icon-button--major', fullScreen ? 'icon-fullscreen-collapse' : 'icon-fullscreen-expand']"
|
|
v-bind:title="`${fullScreen ? 'Exit' : 'Enable'} full screen mode`"
|
|
@click="fullScreenToggle">
|
|
</button>
|
|
</div>
|
|
<app-logo></app-logo>
|
|
</div>
|
|
<multipane class="l-shell__main"
|
|
type="horizontal">
|
|
<pane class="l-shell__pane-tree"
|
|
handle="after"
|
|
label="Browse"
|
|
collapsable>
|
|
<mct-tree class="l-shell__tree"></mct-tree>
|
|
</pane>
|
|
<pane class="l-shell__pane-main">
|
|
<browse-bar class="l-shell__main-view-browse-bar"
|
|
ref="browseBar">
|
|
</browse-bar>
|
|
<toolbar v-if="toolbar" class="l-shell__toolbar"></toolbar>
|
|
<object-view class="l-shell__main-container"
|
|
ref="browseObject"
|
|
:showEditView="true">
|
|
</object-view>
|
|
<component class="l-shell__time-conductor"
|
|
:is="conductorComponent">
|
|
</component>
|
|
</pane>
|
|
<pane class="l-shell__pane-inspector l-pane--holds-multipane"
|
|
handle="before"
|
|
label="Inspect"
|
|
collapsable>
|
|
<Inspector :isEditing="isEditing" ref="inspector"></Inspector>
|
|
</pane>
|
|
</multipane>
|
|
<div class="l-shell__status">
|
|
<StatusBar></StatusBar>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
@import "~styles/sass-base";
|
|
|
|
/******************************* SHELL */
|
|
.l-shell {
|
|
position: absolute;
|
|
top: 0; right: 0; bottom: 0; left: 0;
|
|
display: flex;
|
|
flex-flow: column nowrap;
|
|
overflow: hidden;
|
|
|
|
&__status {
|
|
background: $colorStatusBarBg;
|
|
color: $colorStatusBarFg;
|
|
height: 24px;
|
|
padding: $interiorMarginSm;
|
|
}
|
|
|
|
&__pane-tree {
|
|
width: 40%;
|
|
|
|
[class*="collapse-button"] {
|
|
// For mobile, collapse button becomes menu icon
|
|
body.mobile & {
|
|
@include cClickIconButton();
|
|
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 {
|
|
content: $glyph-icon-menu-hamburger;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
&__pane-tree,
|
|
&__pane-inspector,
|
|
&__pane-main {
|
|
.l-pane__contents {
|
|
display: flex;
|
|
flex-flow: column nowrap;
|
|
overflow-x: hidden;
|
|
|
|
> * {
|
|
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 + (2 * nth($shellPanePad, 2))});
|
|
|
|
+ .l-pane {
|
|
// Hide pane-main when this pane is expanded
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
&[class*="--collapsed"] + .l-pane {
|
|
// Show pane-main when tree is collapsed
|
|
opacity: 1;
|
|
pointer-events: inherit;
|
|
transition: opacity 250ms ease 250ms;
|
|
}
|
|
}
|
|
}
|
|
|
|
&__head,
|
|
&__pane-inspector {
|
|
body.mobile & {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
&__head,
|
|
&__status {
|
|
flex: 0 0 auto;
|
|
display: flex;
|
|
}
|
|
|
|
/******************************* HEAD */
|
|
&__main-view-browse-bar {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
body.mobile & .l-shell__main-view-browse-bar {
|
|
margin-left: $mobileMenuIconD; // Make room for the hamburger!
|
|
}
|
|
|
|
&__head {
|
|
align-items: center;
|
|
background: $colorHeadBg;
|
|
justify-content: space-between;
|
|
padding: $interiorMargin;
|
|
|
|
> [class*="__"] + [class*="__"] {
|
|
margin-left: $interiorMargin;
|
|
}
|
|
}
|
|
|
|
&__create-button,
|
|
&__app-logo {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
&__controls {
|
|
flex: 1 1 100%;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
margin-right: 2.5%;
|
|
}
|
|
|
|
/******************************* MAIN AREA */
|
|
&__main-container {
|
|
// Wrapper for main views
|
|
flex: 1 1 auto !important;
|
|
overflow: auto;
|
|
}
|
|
|
|
&__tree {
|
|
// Tree component within __pane-tree
|
|
flex: 1 1 auto !important;
|
|
}
|
|
|
|
&__time-conductor {
|
|
border-top: 1px solid $colorInteriorBorder;
|
|
padding-top: $interiorMargin;
|
|
}
|
|
|
|
&__main {
|
|
> .l-pane {
|
|
padding: nth($shellPanePad, 1) nth($shellPanePad, 2);
|
|
}
|
|
}
|
|
|
|
body.desktop & {
|
|
&__main {
|
|
// Top and bottom padding in container that holds tree, __pane-main and Inspector
|
|
padding: $shellMainPad;
|
|
min-height: 0;
|
|
|
|
> .l-pane {
|
|
padding-top: 0;
|
|
padding-bottom: 0;
|
|
}
|
|
}
|
|
|
|
&__pane-tree,
|
|
&__pane-inspector {
|
|
max-width: 30%;
|
|
}
|
|
|
|
&__pane-tree {
|
|
width: 300px;
|
|
}
|
|
|
|
&__pane-inspector {
|
|
width: 200px;
|
|
}
|
|
}
|
|
|
|
&__toolbar {
|
|
$p: $interiorMargin;
|
|
background: $editUIBaseColor;
|
|
border-radius: $basicCr;
|
|
height: $p + 24px; // Need to standardize the height
|
|
padding: $p;
|
|
}
|
|
}
|
|
|
|
.is-editing {
|
|
.l-shell__main-container {
|
|
$m: 3px;
|
|
box-shadow: $colorBodyBg 0 0 0 1px, $editUIAreaShdw;
|
|
margin-left: $m;
|
|
margin-right: $m;
|
|
|
|
&[s-selected] {
|
|
// Provide a clearer selection context articulation for the main edit area
|
|
box-shadow: $colorBodyBg 0 0 0 1px, $editUIAreaShdwSelected;
|
|
}
|
|
}
|
|
}
|
|
|
|
</style>
|
|
|
|
<script>
|
|
import Inspector from '../inspector/Inspector.vue';
|
|
import MctTree from './mct-tree.vue';
|
|
import ObjectView from '../components/ObjectView.vue';
|
|
import MctTemplate from '../legacy/mct-template.vue';
|
|
import CreateButton from './CreateButton.vue';
|
|
import multipane from './multipane.vue';
|
|
import pane from './pane.vue';
|
|
import BrowseBar from './BrowseBar.vue';
|
|
import StatusBar from './status-bar/StatusBar.vue';
|
|
import Toolbar from '../toolbar/Toolbar.vue';
|
|
import AppLogo from './AppLogo.vue';
|
|
|
|
var enterFullScreen = () => {
|
|
var docElm = document.documentElement;
|
|
|
|
if (docElm.requestFullscreen) {
|
|
docElm.requestFullscreen();
|
|
} else if (docElm.mozRequestFullScreen) { /* Firefox */
|
|
docElm.mozRequestFullScreen();
|
|
} else if (docElm.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
|
|
docElm.webkitRequestFullscreen();
|
|
} else if (docElm.msRequestFullscreen) { /* IE/Edge */
|
|
docElm.msRequestFullscreen();
|
|
}
|
|
};
|
|
var exitFullScreen = () => {
|
|
if (document.exitFullscreen) {
|
|
document.exitFullscreen();
|
|
}
|
|
else if (document.mozCancelFullScreen) {
|
|
document.mozCancelFullScreen();
|
|
}
|
|
else if (document.webkitCancelFullScreen) {
|
|
document.webkitCancelFullScreen();
|
|
}
|
|
else if (document.msExitFullscreen) {
|
|
document.msExitFullscreen();
|
|
}
|
|
}
|
|
|
|
export default {
|
|
inject: ['openmct'],
|
|
components: {
|
|
Inspector,
|
|
MctTree,
|
|
ObjectView,
|
|
'mct-template': MctTemplate,
|
|
CreateButton,
|
|
multipane,
|
|
pane,
|
|
BrowseBar,
|
|
StatusBar,
|
|
Toolbar,
|
|
AppLogo
|
|
},
|
|
mounted() {
|
|
this.openmct.editor.on('isEditing', (isEditing)=>{
|
|
this.isEditing = isEditing;
|
|
});
|
|
|
|
this.openmct.selection.on('change', this.toggleHasToolbar);
|
|
},
|
|
data: function () {
|
|
return {
|
|
fullScreen: false,
|
|
conductorComponent: undefined,
|
|
isEditing: false,
|
|
hasToolbar: false
|
|
}
|
|
},
|
|
computed: {
|
|
toolbar() {
|
|
return this.hasToolbar && this.isEditing;
|
|
}
|
|
},
|
|
methods: {
|
|
fullScreenToggle() {
|
|
if (this.fullScreen) {
|
|
this.fullScreen = false;
|
|
exitFullScreen();
|
|
} else {
|
|
this.fullScreen = true;
|
|
enterFullScreen();
|
|
}
|
|
},
|
|
openInNewTab(event) {
|
|
window.open(window.location.href);
|
|
},
|
|
toggleHasToolbar(selection) {
|
|
let structure = undefined;
|
|
|
|
if (!selection || !selection[0]) {
|
|
structure = [];
|
|
} else {
|
|
structure = this.openmct.toolbars.get(selection);
|
|
}
|
|
|
|
this.hasToolbar = structure.length > 0;
|
|
}
|
|
}
|
|
}
|
|
</script>
|