Merge branch 'subobject-selection-1126' into api-1124b

Conflicts:
	bower.json
	index.html
	main.js
	src/openmct.js
This commit is contained in:
Victor Woeltjen 2016-09-29 10:54:08 -07:00
commit 53974bd69a
21 changed files with 765 additions and 16 deletions

View File

@ -28,16 +28,12 @@
<script src="bower_components/requirejs/require.js">
</script>
<script>
require(['main'], function (mct) {
require(['main'], function (openmct) {
require([
'./tutorials/todo/todo',
'./example/imagery/bundle',
'./example/eventGenerator/bundle',
'./example/generator/bundle'
], function (todoPlugin) {
mct.install(todoPlugin);
mct.run();
})
], openmct.start.bind(openmct));
});
</script>
<link rel="stylesheet" href="platform/commonUI/general/res/css/startup-base.css">

View File

@ -72,6 +72,7 @@ requirejs.config({
});
define([
'./src/openmct',
'./platform/framework/src/Main',
'./src/defaultRegistry',
'./src/MCT'
@ -94,4 +95,5 @@ define([
});
return mct;
});

View File

@ -72,7 +72,7 @@ define(
// Assemble all gestures into a map, for easy look up
gestures.forEach(function (gesture) {
gestureMap[gesture.key] = gesture;
gestureMap[gesture.key] = gestureMap[gesture.key] || gesture;
});
this.gestureMap = gestureMap;

21
src/Registry.js Normal file
View File

@ -0,0 +1,21 @@
define([], function () {
function Registry() {
this.providers = [];
}
Registry.prototype.get = function (context) {
return this.providers.filter(function (provider) {
return provider.appliesTo(context);
}).map(function (provider) {
return provider.get(context);
}).reduce(function (a, b) {
return Array.isArray(b) ? a.concat(b) : a.concat([b]);
}, []);
};
Registry.prototype.register = function (provider) {
this.providers.push(provider);
};
return Registry;
});

View File

@ -0,0 +1,68 @@
define([], function () {
function toLegacyIdentifier(identifier) {
return [identifier.namespace, identifier.key]
.map(function (part) {
return part.replace(':', '\\:');
}).join(":");
}
function fromLegacyIdentifier(id) {
var namespace = '',
identifier = key;
for (var i = 0, escaped = false, len=key.length; i < key.length; i++) {
if (escaped) {
escaped = false;
} else {
if (key[i] === "\\") {
escaped = true;
continue;
}
if (key[i] === ":") {
// namespace = key.slice(0, i);
identifier = key.slice(i + 1);
break;
}
}
namespace += key[i];
}
if (key === namespace) {
namespace = '';
}
return {
namespace: namespace,
identifier: identifier
};
}
function DomainObjectConverter(instantiate) {
this.instantiate = instantiate;
}
DomainObjectConverter.prototype.toLegacyDomainObject = function (domainObject) {
var model = JSON.parse(JSON.stringify(domainObject));
var id = toLegacyIdentifier(domainObject.identifier);
delete model.identifier;
if (model.composition) {
model.composition = model.composition.map(toLegacyIdentifier);
}
return this.instantiate(model, id);
};
DomainObjectConverter.prototype.fromLegacyDomainObject = function (domainObject) {
var newObject = JSON.parse(JSON.stringify(domainObject.getModel()));
newObject.identifier = fromLegacyIdentifier(domainObject.getId());
if (newObject.composition) {
newObject.composition =
newObject.composition.map(fromLegacyIdentifier);
}
return newObject;
};
return DomainObjectConverter;
});

View File

@ -0,0 +1,15 @@
define([], function () {
// Adapts old-timey actions to the new-fangled way.
function AdaptedActionProvider(legacyActionService) {
this.legacyActionService = legacyActionService;
}
AdaptedActionProvider.prototype.get = function (context) {
var legacyContext = {};
legacyContext.domainObject =
};
return AdaptedActionProvider;
});

View File

@ -0,0 +1,9 @@
define(
function () {
function AdaptedContextMenuGesture(openmct, $els, domainObject) {
this.destroy = openmct.gestures.contextual($els[0], domainObject);
}
return AdaptedContextMenuGesture;
}
);

View File

@ -0,0 +1,48 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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([
'legacyRegistry',
'./gestures/AdaptedContextMenuGesture',
'../openmct'
], function (legacyRegistry, AdaptedContextMenuGesture, openmct) {
legacyRegistry.register('adapter', {
extensions: {
services: [
{
key: "openmct",
implementation: function () {
return openmct;
}
}
],
gestures: [
{
key: "menu",
implementation: AdaptedContextMenuGesture,
priority: "preferred",
depends: ["openmct"]
}
]
}
});
});

View File

@ -0,0 +1,32 @@
define(['angular'], function (angular) {
function AngularView(template, scopeFn) {
this.template = template;
this.scopeFn = scopeFn;
}
AngularView.prototype.show = function (container) {
if (this.activeScope) {
this.destroy();
}
var $injector = angular.injector(['ng']);
var $compile = $injector.get('$compile');
var $rootScope = $injector.get('$rootScope');
var $scope = $rootScope.$new();
this.scopeFn($scope);
var elements = $compile(this.template)($scope);
angular.element(container).append(elements);
};
AngularView.prototype.destroy = function () {
if (this.activeScope) {
this.activeScope.$destroy();
this.activeScope = undefined;
}
};
return AngularView;
});

View File

@ -1,16 +1,73 @@
define(['./MCT', './api/Type'], function (MCT, Type) {
/**
* Open MCT is an extensible web application for building mission
* control user interfaces. This module is itself an instance of
* [MCT]{@link module:openmct.MCT}, which provides an interface for
* configuring and executing the application.
*
* @exports openmct
*/
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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([
'EventEmitter',
'./MCT',
'./api/Type',
'./Registry',
'./selection/Selection',
'./selection/ContextManager',
'./selection/SelectGesture',
'./ui/menu/ContextMenuGesture',
'./ui/OverlayManager',
'./ui/ViewRegistry'
], function (
EventEmitter,
MCT,
Type,
Registry,
Selection,
ContextManager,
SelectGesture,
ContextMenuGesture,
OverlayManager,
ViewRegistry
) {
var openmct = new MCT();
var overlayManager = new OverlayManager(window.document.body);
var actionRegistry = new Registry();
var selection = new Selection();
var manager = new ContextManager();
var select = new SelectGesture(manager, selection);
var contextMenu = new ContextMenuGesture(
selection,
overlayManager,
actionRegistry,
manager
);
EventEmitter.call(openmct);
openmct.MCT = MCT;
openmct.Type = Type;
openmct.selection = selection;
openmct.inspectors = new ViewRegistry();
openmct.gestures = {
selectable: select.apply.bind(select),
contextual: contextMenu.apply.bind(contextMenu)
};
return openmct;
});

View File

@ -0,0 +1,77 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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)
*/
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;
});

View File

@ -0,0 +1,58 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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;
});

View File

@ -0,0 +1,60 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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;
});

View File

@ -0,0 +1,64 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(['EventEmitter'], function (EventEmitter) {
function Selection() {
EventEmitter.call(this);
this.selected = [];
}
Selection.prototype = Object.create(EventEmitter.prototype);
Selection.prototype.add = function (path) {
this.clear(); // Only allow single select as initial simplification
this.selected.push(path);
this.emit('change');
};
Selection.prototype.remove = function (path) {
this.selected = this.selected.filter(function (otherPath) {
return !path.matches(otherPath);
});
this.emit('change');
};
Selection.prototype.contains = function (path) {
return this.selected.some(function (otherPath) {
return path.matches(otherPath);
});
};
Selection.prototype.clear = function () {
this.selected = [];
this.emit('change');
};
Selection.prototype.primary = function () {
return this.selected[this.selected.length - 1];
};
Selection.prototype.all = function () {
return this.selected;
};
return Selection;
});

View File

@ -0,0 +1,71 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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 ClickElsewhereGesture(body) {
this.$body = $(body);
this.pairs = [];
this.handleClick = this.handleClick.bind(this);
}
ClickElsewhereGesture.prototype.handleClick = function (event) {
this.pairs.forEach(function (pair) {
var x = event.clientX,
y = event.clientY,
rect = pair.element.getBoundingClientRect(),
xMin = rect.left,
xMax = xMin + rect.width,
yMin = rect.top,
yMax = yMin + rect.height;
if (x < xMin || x > xMax || y < yMin || y > yMax) {
pair.callback();
}
});
};
ClickElsewhereGesture.prototype.apply = function (htmlElement, callback) {
var pair = {
element: htmlElement,
callback: callback
};
if (this.pairs.length < 1) {
this.$body.on('mousedown', this.handleClick);
}
this.pairs.push(pair);
return function () {
this.pairs = this.pairs.filter(function (p) {
return p !== pair;
});
if (this.pairs.length < 1) {
this.$body.off('mousedown', this.handleClick);
}
}.bind(this);
};
return ClickElsewhereGesture;
});

43
src/ui/InspectorRegion.js Normal file
View File

@ -0,0 +1,43 @@
define(['zepto'], function ($) {
function InspectorRegion(element, selection, inspectors) {
this.element = element;
this.selection = selection;
this.inspectors = inspectors;
this.active = false;
this.onSelectionChange = this.onSelectionChange.bind(this);
}
InspectorRegion.prototype.onSelectionChange = function (item) {
var $element = $(this.element);
var providers = this.inspectors.get(item);
$element.empty();
if (factories.length > 0) {
providers[0].view(item).show(this.element);
}
};
InspectorRegion.prototype.activate = function () {
if (this.active) {
this.deactivate();
}
this.selection.on('change', this.onSelectionChange);
this.active = true;
};
InspectorRegion.prototype.deactivate = function () {
if (!this.active) {
return;
}
this.selection.off('change', this.onSelectionChange);
this.active = false;
};
return InspectorRegion;
});

40
src/ui/OverlayManager.js Normal file
View File

@ -0,0 +1,40 @@
define(['zepto'], function ($) {
function OverlayManager(bodyElement) {
this.$body = $(bodyElement);
}
OverlayManager.prototype.show = function (view, x, y) {
var $container = $('<div></div>');
var w = this.$body.width();
var h = this.$body.height();
x = x || 0;
y = y || 0;
$container.css('position', 'absolute');
if (x < w / 2) {
$container.css('left', x + 'px');
} else {
$container.css('right', (w - x) + 'px');
}
if (x < h / 2) {
$container.css('top', y + 'px');
} else {
$container.css('bottom', (h - y) + 'px');
}
view.show($container[0]);
this.$body.prepend($container);
return function () {
$container.remove();
view.destroy();
};
};
return OverlayManager;
});

18
src/ui/ViewRegistry.js Normal file
View File

@ -0,0 +1,18 @@
define([], function () {
function ViewRegistry() {
this.providers = [];
}
ViewRegistry.prototype.get = function (item) {
return this.providers.filter(function (provider) {
return provider.canView(item);
});
};
ViewRegistry.prototype.addProvider = function (provider) {
this.providers.push(provider);
};
return ViewRegistry;
});

View File

@ -0,0 +1,42 @@
define(['zepto', './ContextMenuView'], function ($, ContextMenuView) {
function ContextMenuGesture(
selection,
overlayManager,
actionRegistry,
contextManager
) {
this.selection = selection;
this.overlayManager = overlayManager;
this.actionRegistry = actionRegistry;
this.contextManager = contextManager;
}
ContextMenuGesture.prototype.apply = function (htmlElement, item) {
var overlayManager = this.overlayManager;
var selection = this.selection;
var actionRegistry = this.actionRegistry;
var contextManager = this.contextManager;
var $element = $(htmlElement);
var context = contextManager.context(item, htmlElement);
function showMenu(event) {
selection.add(context);
var x = event.clientX;
var y = event.clientY;
var actions = actionRegistry.get(context);
var view = new ContextMenuView(actions);
overlayManager.show(view, x, y);
event.preventDefault();
}
$element.on('contextmenu', showMenu);
return $element.off.bind($element, 'contextmenu', showMenu);
};
return ContextMenuGesture;
});

View File

@ -0,0 +1,16 @@
define([
'zepto',
'text!./context-menu.html',
'../../adapter/ui/AngularView'
], function ($, template, AngularView) {
function ContextMenuView(actions) {
AngularView.call(this, template, function ($scope) {
$scope.menuActions = actions;
});
}
ContextMenuView.prototype = Object.create(AngularView.prototype);
return ContextMenuView;
});

View File

@ -0,0 +1,12 @@
<div class="menu-element context-menu-wrapper mobile-disable-select">
<div class="menu context-menu">
<ul>
<li ng-repeat="menuAction in menuActions"
ng-click="menuAction.perform()"
title="{{menuAction.getMetadata().description}}"
class="{{menuAction.getMetadata().cssclass}}">
{{menuAction.getMetadata().name}}
</li>
</ul>
</div>
</div>