mirror of
https://github.com/nasa/openmct.git
synced 2025-04-21 01:21:19 +00:00
Implemented context menu action registry
This commit is contained in:
parent
74faf1bd48
commit
a7948ce83e
src
@ -222,6 +222,8 @@ define([
|
||||
|
||||
this.overlays = new OverlayAPI.default();
|
||||
|
||||
this.contextMenu = new api.ContextMenuRegistry();
|
||||
|
||||
this.legacyRegistry = defaultRegistry;
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
|
@ -28,6 +28,7 @@ define([
|
||||
'./telemetry/TelemetryAPI',
|
||||
'./indicators/IndicatorAPI',
|
||||
'./notifications/NotificationAPI',
|
||||
'./contextMenu/ContextMenuRegistry',
|
||||
'./Editor'
|
||||
|
||||
], function (
|
||||
@ -38,6 +39,7 @@ define([
|
||||
TelemetryAPI,
|
||||
IndicatorAPI,
|
||||
NotificationAPI,
|
||||
ContextMenuRegistry,
|
||||
EditorAPI
|
||||
) {
|
||||
return {
|
||||
@ -48,6 +50,7 @@ define([
|
||||
TelemetryAPI: TelemetryAPI,
|
||||
IndicatorAPI: IndicatorAPI,
|
||||
NotificationAPI: NotificationAPI.default,
|
||||
EditorAPI: EditorAPI
|
||||
EditorAPI: EditorAPI,
|
||||
ContextMenuRegistry: ContextMenuRegistry.default
|
||||
};
|
||||
});
|
||||
|
75
src/api/contextMenu/ContextMenuRegistry.js
Normal file
75
src/api/contextMenu/ContextMenuRegistry.js
Normal file
@ -0,0 +1,75 @@
|
||||
import ContextMenuComponent from '../../ui/components/controls/ContextMenu.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
class ContextMenuRegistry {
|
||||
constructor() {
|
||||
this._allActions = [];
|
||||
this._activeContextMenu = undefined;
|
||||
|
||||
this._hideActiveContextMenu = this._hideActiveContextMenu.bind(this);
|
||||
}
|
||||
|
||||
registerAction(actionDefinition) {
|
||||
this._allActions.push(actionDefinition);
|
||||
}
|
||||
|
||||
attachTo(targetElement, objectPath) {
|
||||
let showContextMenu = (event) => {
|
||||
this._showContextMenuForObjectPath(event, objectPath);
|
||||
};
|
||||
|
||||
targetElement.addEventListener('contextmenu', showContextMenu);
|
||||
|
||||
return function detach() {
|
||||
targetElement.removeEventListener('contextMenu', showContextMenu);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_showContextMenuForObjectPath(event, objectPath) {
|
||||
let applicableActions = this._allActions.filter(
|
||||
(action) => action.appliesTo(objectPath));
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (this._activeContextMenu) {
|
||||
this._hideActiveContextMenu();
|
||||
}
|
||||
|
||||
this._activeContextMenu = this._createContextMenuFromActions(applicableActions);
|
||||
this._activeContextMenu.$mount();
|
||||
this._activeContextMenu.$el.style.left = `${event.clientX}px`;
|
||||
this._activeContextMenu.$el.style.top = `${event.clientY}px`;
|
||||
|
||||
document.body.appendChild(this._activeContextMenu.$el);
|
||||
document.addEventListener('click', this._hideActiveContextMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_hideActiveContextMenu() {
|
||||
document.removeEventListener('click', this._hideActiveContextMenu);
|
||||
document.body.removeChild(this._activeContextMenu.$el);
|
||||
this._activeContextMenu.$destroy();
|
||||
this._activeContextMenu = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_createContextMenuFromActions(actions) {
|
||||
return new Vue({
|
||||
components: {
|
||||
ContextMenu: ContextMenuComponent
|
||||
},
|
||||
provide: {
|
||||
actions: actions
|
||||
},
|
||||
template: '<ContextMenu></ContextMenu>'
|
||||
});
|
||||
}
|
||||
}
|
||||
export default ContextMenuRegistry;
|
@ -148,4 +148,4 @@ define([], function () {
|
||||
}
|
||||
|
||||
return DisplayLayoutToolbar;
|
||||
});
|
||||
});
|
||||
|
@ -1,78 +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(['zepto'], function ($) {
|
||||
/**
|
||||
* @typedef Context
|
||||
* @property {*} item
|
||||
* @property {HTMLElement} element
|
||||
* @property {Context} parent the containing context (may be undefined)
|
||||
* @memberof module:openmct
|
||||
*/
|
||||
|
||||
|
||||
function ContextManager() {
|
||||
this.counter = 0;
|
||||
this.contexts = {};
|
||||
}
|
||||
|
||||
ContextManager.prototype.nextId = function () {
|
||||
this.counter += 1;
|
||||
return "context-" + this.counter;
|
||||
};
|
||||
|
||||
ContextManager.prototype.context = function (item, htmlElement) {
|
||||
var $element = $(htmlElement);
|
||||
var id = $element.attr('data-context') || this.nextId();
|
||||
|
||||
$element.attr('data-context', id);
|
||||
|
||||
if (this.contexts[id] && this.contexts[id].item !== item) {
|
||||
this.release(htmlElement);
|
||||
}
|
||||
|
||||
if (!this.contexts[id]) {
|
||||
var $parent = $element.closest('[data-context]');
|
||||
var parentId = $parent.attr('data-context');
|
||||
var parentContext = parentId ? this.contexts[parentId] : undefined;
|
||||
this.contexts[id] = {
|
||||
item: item,
|
||||
element: htmlElement,
|
||||
parent: parentContext
|
||||
};
|
||||
}
|
||||
|
||||
return this.contexts[id];
|
||||
};
|
||||
|
||||
ContextManager.prototype.release = function (htmlElement) {
|
||||
var $element = $(htmlElement);
|
||||
var id = $element.attr('data-context');
|
||||
|
||||
if (id) {
|
||||
delete this.contexts[id];
|
||||
$element.removeAttr('data-context');
|
||||
}
|
||||
};
|
||||
|
||||
return ContextManager;
|
||||
});
|
@ -1,58 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(['zepto'], function ($) {
|
||||
function HoverGesture(hoverManager) {
|
||||
this.hoverManager = hoverManager;
|
||||
}
|
||||
|
||||
HoverGesture.prototype.apply = function (htmlElement) {
|
||||
var $element = $(htmlElement);
|
||||
var hoverManager = this.hoverManager;
|
||||
|
||||
function update() {
|
||||
$(hoverManager.all()).removeClass('hovering');
|
||||
$(hoverManager.top()).addClass('hovering');
|
||||
}
|
||||
|
||||
function enter() {
|
||||
hoverManager.add(htmlElement);
|
||||
update();
|
||||
}
|
||||
|
||||
function leave() {
|
||||
hoverManager.remove(htmlElement);
|
||||
update();
|
||||
}
|
||||
|
||||
$element.on('mouseenter', enter);
|
||||
$element.on('mouseleave', leave);
|
||||
|
||||
return function () {
|
||||
leave();
|
||||
$element.off('mouseenter', enter);
|
||||
$element.off('mouseleave', leave);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
return HoverGesture;
|
||||
});
|
@ -1,60 +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(['zepto'], function ($) {
|
||||
function SelectGesture(selection, contextManager) {
|
||||
this.selection = selection;
|
||||
this.contextManager = contextManager;
|
||||
}
|
||||
|
||||
SelectGesture.prototype.apply = function (htmlElement, item) {
|
||||
var $element = $(htmlElement);
|
||||
var contextManager = this.contextManager;
|
||||
var selection = this.selection;
|
||||
var path = contextManager.path(item, htmlElement);
|
||||
|
||||
function select() {
|
||||
selection.add(path);
|
||||
}
|
||||
|
||||
function change() {
|
||||
var selected = selection.primary();
|
||||
$element.toggleClass(
|
||||
'selected',
|
||||
selected && path.matches(selected)
|
||||
);
|
||||
}
|
||||
|
||||
$element.addClass('selectable');
|
||||
$element.on('click', select);
|
||||
selection.on('change', change);
|
||||
change(); // Initialize
|
||||
|
||||
return function () {
|
||||
contextManager.release(htmlElement);
|
||||
$element.off('click', select);
|
||||
selection.off('change', change);
|
||||
};
|
||||
};
|
||||
|
||||
return SelectGesture;
|
||||
});
|
@ -1,29 +1,20 @@
|
||||
<template>
|
||||
<div class="c-menu">
|
||||
<ul>
|
||||
<li v-for="item in contextMenuItems"
|
||||
:class="item.class"
|
||||
:title="item.title">
|
||||
{{ item.name }}
|
||||
<li v-for="action in actions"
|
||||
:key="action.name"
|
||||
:class="action.cssClass"
|
||||
:title="action.description"
|
||||
@click="action.invoke">
|
||||
{{ action.name }}
|
||||
</li>
|
||||
<li v-if="actions.length === 0">No actions defined.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
contextMenuItems: [
|
||||
{name: 'Open In New Tab', class: 'icon-new-window', title: 'Open in a new browser tab'},
|
||||
{name: 'Preview', class: 'hide-in-t-main-view icon-eye-open', title: 'Preview in large dialog'},
|
||||
{name: 'Edit Properties...', class: 'major icon-pencil', title: 'Edit properties of this object.'},
|
||||
{name: 'Duplicate', class: 'icon-duplicate', title: 'Duplicate object to another location.'},
|
||||
{name: 'Create Link', class: 'icon-link', title: 'Create Link to object in another location.'},
|
||||
{name: 'Export as JSON', class: 'icon-export', title: 'Export as JSON'},
|
||||
{name: 'Import from JSON', class: 'icon-import', title: 'Import from JSON'}
|
||||
]
|
||||
}
|
||||
}
|
||||
inject: ['actions']
|
||||
}
|
||||
</script>
|
@ -11,11 +11,10 @@
|
||||
|
||||
<script>
|
||||
|
||||
import ContextMenu from '../mixins/context-menu';
|
||||
import ObjectLink from '../mixins/object-link';
|
||||
|
||||
export default {
|
||||
mixins: [ContextMenu, ObjectLink],
|
||||
mixins: [ObjectLink],
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
domainObject: Object
|
||||
@ -32,6 +31,8 @@ export default {
|
||||
});
|
||||
this.$once('hook:destroyed', removeListener);
|
||||
}
|
||||
let detachContextMenu = this.openmct.contextMenu.attachTo(this.$el);
|
||||
this.$once('hook:destroyed', detachContextMenu);
|
||||
},
|
||||
computed: {
|
||||
typeClass() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user