189 lines
8.2 KiB
JavaScript
189 lines
8.2 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
|
* as represented by the Administrator of the National Aeronautics and Space
|
|
* Administration. All rights reserved.
|
|
*
|
|
* Open MCT Web 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 Web 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 define,Promise*/
|
|
|
|
/**
|
|
* Module defining DropGesture. Created by vwoeltje on 11/17/14.
|
|
*/
|
|
define(
|
|
['./GestureConstants',
|
|
'../../../commonUI/edit/src/objects/EditableDomainObject',
|
|
'uuid'],
|
|
function (GestureConstants, EditableDomainObject, uuid) {
|
|
"use strict";
|
|
|
|
/**
|
|
* A DropGesture adds and maintains event handlers upon an element
|
|
* such that it may act as a drop target for drag-drop composition.
|
|
*
|
|
* @memberof platform/representation
|
|
* @constructor
|
|
* @param $q Angular's $q, for promise handling
|
|
* @param element the jqLite-wrapped representation element
|
|
* @param {DomainObject} domainObject the domain object whose
|
|
* composition should be modified as a result of the drop.
|
|
*/
|
|
function DropGesture(dndService, $q, navigationService, objectService, instantiate, typeService, element, domainObject) {
|
|
var actionCapability = domainObject.getCapability('action'),
|
|
editableDomainObject,
|
|
action; // Action for the drop, when it occurs
|
|
|
|
function broadcastDrop(id, event) {
|
|
// Find the relevant scope...
|
|
var scope = element && element.scope && element.scope(),
|
|
rect;
|
|
if (scope && scope.$broadcast) {
|
|
// Get the representation's bounds, to convert
|
|
// drop position
|
|
rect = element[0].getBoundingClientRect();
|
|
|
|
// ...and broadcast the event. This allows specific
|
|
// views to have post-drop behavior which depends on
|
|
// drop position.
|
|
scope.$broadcast(
|
|
GestureConstants.MCT_DROP_EVENT,
|
|
id,
|
|
{
|
|
x: event.pageX - rect.left,
|
|
y: event.pageY - rect.top
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
function shouldCreateVirtualPanel(domainObject){
|
|
return domainObject.useCapability('view').filter(function (view){
|
|
return view.key==='plot' && domainObject.getModel().type!== 'telemetry.panel'
|
|
}).length > 0;
|
|
}
|
|
|
|
function dragOver(e) {
|
|
//Refresh domain object on each dragOver to catch external
|
|
// updates to the model
|
|
//Don't use EditableDomainObject for folders, allow immediate persistence
|
|
editableDomainObject = domainObject.hasCapability('editor') || domainObject.getModel().type==='folder' ? domainObject : new EditableDomainObject(domainObject, $q);
|
|
actionCapability = editableDomainObject.getCapability('action');
|
|
|
|
var event = (e || {}).originalEvent || e,
|
|
selectedObject = dndService.getData(
|
|
GestureConstants.MCT_EXTENDED_DRAG_TYPE
|
|
);
|
|
|
|
if (selectedObject) {
|
|
// TODO: Vary this based on modifier keys
|
|
action = actionCapability.getActions({
|
|
key: 'compose',
|
|
selectedObject: selectedObject
|
|
})[0];
|
|
//TODO: Fix this. Define an action for creating new
|
|
// virtual panel
|
|
if (action || shouldCreateVirtualPanel(domainObject)) {
|
|
event.dataTransfer.dropEffect = 'move';
|
|
|
|
// Indicate that we will accept the drag
|
|
event.preventDefault(); // Required in Chrome?
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
function createVirtualPanel(base, overlayId){
|
|
|
|
var typeKey = 'telemetry.panel',
|
|
type = typeService.getType(typeKey),
|
|
model = type.getInitialModel(),
|
|
id = uuid(),
|
|
newPanel = undefined;
|
|
|
|
model.type = typeKey;
|
|
newPanel = new EditableDomainObject(instantiate(model, id), $q);
|
|
|
|
[base.getId(), overlayId].forEach(function(id){
|
|
newPanel.getCapability('composition').add(id)
|
|
});
|
|
|
|
newPanel.getCapability('location').setPrimaryLocation(base.getCapability('location').getContextualLocation());
|
|
|
|
//var virtualPanel = new EditableDomainObject(newPanel, $q);
|
|
//virtualPanel.setOriginalObject(base);
|
|
newPanel.setOriginalObject(base);
|
|
//return virtualPanel;
|
|
return newPanel;
|
|
|
|
}
|
|
|
|
function drop(e) {
|
|
var event = (e || {}).originalEvent || e,
|
|
id = event.dataTransfer.getData(GestureConstants.MCT_DRAG_TYPE),
|
|
domainObjectType = editableDomainObject.getModel().type,
|
|
virtualObj;
|
|
|
|
// If currently in edit mode allow drag and drop gestures to the
|
|
// domain object. An exception to this is folders which have drop
|
|
// gestures in browse mode.
|
|
//if (domainObjectType === 'folder' || domainObject.hasCapability('editor')) {
|
|
|
|
// Handle the drop; add the dropped identifier to the
|
|
// destination domain object's composition, and persist
|
|
// the change.
|
|
if (id) {
|
|
if (shouldCreateVirtualPanel(domainObject)){
|
|
navigationService.setNavigation(createVirtualPanel(domainObject, id));
|
|
broadcastDrop(id, event);
|
|
} else {
|
|
$q.when(action && action.perform()).then(function (result) {
|
|
//Don't go into edit mode for folders
|
|
if (domainObjectType!=='folder') {
|
|
navigationService.setNavigation(editableDomainObject);
|
|
}
|
|
broadcastDrop(id, event);
|
|
});
|
|
}
|
|
}
|
|
//}
|
|
// TODO: Alert user if drag and drop is not allowed
|
|
}
|
|
|
|
// We can only handle drops if we have access to actions...
|
|
if (actionCapability) {
|
|
// Listen for dragover, to indicate we'll accept a drag
|
|
element.on('dragover', dragOver);
|
|
|
|
// Listen for the drop itself
|
|
element.on('drop', drop);
|
|
}
|
|
|
|
this.element = element;
|
|
this.dragOverCallback = dragOver;
|
|
this.dropCallback = drop;
|
|
}
|
|
|
|
DropGesture.prototype.destroy = function () {
|
|
this.element.off('dragover', this.dragOverCallback);
|
|
this.element.off('drop', this.dropCallback);
|
|
};
|
|
|
|
|
|
return DropGesture;
|
|
}
|
|
);
|