[Layout] Support sub-object selection in layout (#1811)
Updates to sub object selection, first cut of selection APIs. * [API] Add inspector view registry to register inspector view providers and show a view in the inspector. [API] Modify the selection API to register the click event and handle the event. The API will add a class to the selected object and the immediate parent of the selected object. [Directive] Implemenet mct-selectable directive for making an element selectable. [Layout] Update the layout controller to use the Selection API. Also, add double click gesture to allow drilling into a selected object. Populate the Elements pool with contained elements of the selected object. Update toolbar and inspector to listen for the changes in selection. * [Frontend] Mods to markup and CSS for sub-object selection * MCTSelectable allows selection in initialization, use to select on navigation [Frontend] Show grid in first nested layout, hide from deeper nesting. Only show grids when applicable to relative selection. * Fix checkstyle and lint errors * Bring back the change that made mct-init-select work * [Inspector] Make sure the right content is displayed based on whether a view provider exists or not. * Only show table options when editing * Make reviewers' requested changes * Fix broken tests * [Frontend] Cleanups and tweaks Fixes #1811 - Cleanups between frame, editor and selecting.scss; - Hover and selected borders visually pumped up a bit; - Solid borders on hover and selecting when browsing; - Dashed borders for layouts when editing; - Fixed cursor to only show move capability when element is selected; * [Frontend] Tweaks to frame.no-frame layout Fixes #1811 - Margin set to 0; - Overflow set to hidden; * [Frontend] Fixed position items border width fixed Fixes #1811 - Set to 1px; * Add tests for inspector controller and fix broken tests. Clean up code. * [Fixed Position] Stop event propagation on click handlers in fixed position to avoid the event reaching the selection click handlers which caused issues with toolbar and selection." * Fix tests * Add tests * Add test * Remove element from document
This commit is contained in:
committed by
Pete Richards
parent
50b4d5cb28
commit
425655bae0
@@ -260,7 +260,9 @@ define([
|
||||
"key": "LayoutController",
|
||||
"implementation": LayoutController,
|
||||
"depends": [
|
||||
"$scope"
|
||||
"$scope",
|
||||
"$element",
|
||||
"openmct"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
's-selected': controller.selected(element)
|
||||
}"
|
||||
ng-style="element.style"
|
||||
ng-click="controller.select(element)">
|
||||
ng-click="controller.select(element, $event)">
|
||||
<mct-include key="element.template"
|
||||
parameters="{ gridSize: controller.getGridSize() }"
|
||||
ng-model="element">
|
||||
@@ -53,14 +53,16 @@
|
||||
mct-drag-down="controller.moveHandle().startDrag(controller.selected())"
|
||||
mct-drag="controller.moveHandle().continueDrag(delta)"
|
||||
mct-drag-up="controller.moveHandle().endDrag()"
|
||||
ng-style="controller.selected().style">
|
||||
ng-style="controller.selected().style"
|
||||
ng-click="$event.stopPropagation()">
|
||||
</div>
|
||||
<div ng-repeat="handle in controller.handles()"
|
||||
class="l-fixed-position-item-handle edit-corner"
|
||||
ng-style="handle.style()"
|
||||
mct-drag-down="handle.startDrag()"
|
||||
mct-drag="handle.continueDrag(delta)"
|
||||
mct-drag-up="handle.endDrag()">
|
||||
mct-drag-up="handle.endDrag()"
|
||||
ng-click="$event.stopPropagation()">
|
||||
</div>
|
||||
</span>
|
||||
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
|
||||
<div class="abs l-layout"
|
||||
ng-controller="LayoutController as controller"
|
||||
ng-click="controller.clearSelection()">
|
||||
ng-click="controller.bypassSelection($event)">
|
||||
|
||||
<!-- Background grid -->
|
||||
<div class="l-grid-holder" ng-click="controller.clearSelection()">
|
||||
<div class="l-grid-holder"
|
||||
ng-show="!controller.drilledIn"
|
||||
ng-click="controller.bypassSelection($event)">
|
||||
<div class="l-grid l-grid-x"
|
||||
ng-if="!controller.getGridSize()[0] < 3"
|
||||
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
||||
@@ -34,10 +36,12 @@
|
||||
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
|
||||
</div>
|
||||
|
||||
<div class='abs frame t-frame-outer child-frame panel s-selectable s-moveable s-hover-border'
|
||||
ng-class="{ 'no-frame': !controller.hasFrame(childObject), 's-selected':controller.selected(childObject) }"
|
||||
<div class="abs frame t-frame-outer child-frame panel s-selectable s-moveable s-hover-border {{childObject.getId() + '-' + $id}} t-object-type-{{ childObject.getModel().type }}"
|
||||
ng-class="{ 'no-frame': !controller.hasFrame(childObject), 's-drilled-in': controller.isDrilledIn(childObject) }"
|
||||
ng-repeat="childObject in composition"
|
||||
ng-click="controller.select($event, childObject.getId())"
|
||||
ng-init="controller.selectIfNew(childObject.getId() + '-' + $id, childObject)"
|
||||
mct-selectable="controller.getContext(childObject, true)"
|
||||
ng-dblclick="controller.drill($event, childObject)"
|
||||
ng-style="controller.getFrameStyle(childObject.getId())">
|
||||
|
||||
<mct-representation key="'frame'"
|
||||
@@ -45,7 +49,7 @@
|
||||
mct-object="childObject">
|
||||
</mct-representation>
|
||||
<!-- Drag handles -->
|
||||
<span class="abs t-edit-handle-holder s-hover-border" ng-if="controller.selected(childObject)">
|
||||
<span class="abs t-edit-handle-holder" ng-if="controller.selected(childObject) && !controller.isDrilledIn(childObject)">
|
||||
<span class="edit-handle edit-move"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
@@ -73,7 +77,6 @@
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -506,7 +506,11 @@ define(
|
||||
* Set the active user selection in this view.
|
||||
* @param element the element to select
|
||||
*/
|
||||
FixedController.prototype.select = function select(element) {
|
||||
FixedController.prototype.select = function select(element, event) {
|
||||
if (event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (this.selection) {
|
||||
// Update selection...
|
||||
this.selection.select(element);
|
||||
|
||||
@@ -27,9 +27,11 @@
|
||||
*/
|
||||
define(
|
||||
[
|
||||
'zepto',
|
||||
'./LayoutDrag'
|
||||
],
|
||||
function (
|
||||
$,
|
||||
LayoutDrag
|
||||
) {
|
||||
|
||||
@@ -50,10 +52,12 @@ define(
|
||||
* @constructor
|
||||
* @param {Scope} $scope the controller's Angular scope
|
||||
*/
|
||||
function LayoutController($scope) {
|
||||
function LayoutController($scope, $element, openmct) {
|
||||
var self = this,
|
||||
callbackCount = 0;
|
||||
|
||||
this.$element = $element;
|
||||
|
||||
// Update grid size when it changed
|
||||
function updateGridSize(layoutGrid) {
|
||||
var oldSize = self.gridSize;
|
||||
@@ -123,12 +127,11 @@ define(
|
||||
self.layoutPanels(ids);
|
||||
self.setFrames(ids);
|
||||
|
||||
// If there is a newly-dropped object, select it.
|
||||
if (self.droppedIdToSelectAfterRefresh) {
|
||||
self.select(null, self.droppedIdToSelectAfterRefresh);
|
||||
delete self.droppedIdToSelectAfterRefresh;
|
||||
} else if (composition.indexOf(self.selectedId) === -1) {
|
||||
self.clearSelection();
|
||||
if (self.selectedId &&
|
||||
self.selectedId !== $scope.domainObject.getId() &&
|
||||
composition.indexOf(self.selectedId) === -1) {
|
||||
// Click triggers selection of layout parent.
|
||||
self.$element[0].click();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -160,22 +163,39 @@ define(
|
||||
}
|
||||
};
|
||||
|
||||
// Sets the selectable object in response to the selection change event.
|
||||
function setSelection(selectable) {
|
||||
var selection = selectable[0];
|
||||
|
||||
if (!selection) {
|
||||
delete self.selectedId;
|
||||
return;
|
||||
}
|
||||
|
||||
self.selectedId = selection.context.oldItem.getId();
|
||||
self.drilledIn = undefined;
|
||||
self.selectable = selectable;
|
||||
}
|
||||
|
||||
this.positions = {};
|
||||
this.rawPositions = {};
|
||||
this.gridSize = DEFAULT_GRID_SIZE;
|
||||
this.$scope = $scope;
|
||||
this.drilledIn = undefined;
|
||||
this.openmct = openmct;
|
||||
|
||||
// Watch for changes to the grid size in the model
|
||||
$scope.$watch("model.layoutGrid", updateGridSize);
|
||||
|
||||
$scope.$watch("selection", function (selection) {
|
||||
this.selection = selection;
|
||||
}.bind(this));
|
||||
|
||||
// Update composed objects on screen, and position panes
|
||||
$scope.$watchCollection("model.composition", refreshComposition);
|
||||
|
||||
// Position panes where they are dropped
|
||||
openmct.selection.on('change', setSelection);
|
||||
|
||||
$scope.$on("$destroy", function () {
|
||||
openmct.selection.off("change", setSelection);
|
||||
});
|
||||
|
||||
$scope.$on("mctDrop", handleDrop);
|
||||
}
|
||||
|
||||
@@ -357,37 +377,14 @@ define(
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the object is currently selected.
|
||||
* Checks if the object is currently selected.
|
||||
*
|
||||
* @param {string} obj the object to check for selection
|
||||
* @returns {boolean} true if selected, otherwise false
|
||||
*/
|
||||
LayoutController.prototype.selected = function (obj) {
|
||||
return !!this.selectedId && this.selectedId === obj.getId();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the active user selection in this view.
|
||||
*
|
||||
* @param event the mouse event
|
||||
* @param {string} id the object id
|
||||
*/
|
||||
LayoutController.prototype.select = function (event, id) {
|
||||
if (event) {
|
||||
event.stopPropagation();
|
||||
if (this.selection) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
this.selectedId = id;
|
||||
|
||||
var selectedObj = {};
|
||||
selectedObj[this.frames[id] ? 'hideFrame' : 'showFrame'] = this.toggleFrame.bind(this, id);
|
||||
|
||||
if (this.selection) {
|
||||
this.selection.select(selectedObj);
|
||||
}
|
||||
var sobj = this.openmct.selection.get()[0];
|
||||
return (sobj && sobj.context.oldItem.getId() === obj.getId()) ? true : false;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -396,7 +393,7 @@ define(
|
||||
* @param {string} id the object id
|
||||
* @private
|
||||
*/
|
||||
LayoutController.prototype.toggleFrame = function (id) {
|
||||
LayoutController.prototype.toggleFrame = function (id, domainObject) {
|
||||
var configuration = this.$scope.configuration;
|
||||
|
||||
if (!configuration.panels[id]) {
|
||||
@@ -404,21 +401,75 @@ define(
|
||||
}
|
||||
|
||||
this.frames[id] = configuration.panels[id].hasFrame = !this.frames[id];
|
||||
this.select(undefined, id); // reselect so toolbar updates
|
||||
|
||||
var selection = this.openmct.selection.get();
|
||||
selection[0].context.toolbar = this.getToolbar(id, domainObject);
|
||||
this.openmct.selection.select(selection); // reselect so toolbar updates
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the current user selection.
|
||||
* Gets the toolbar object for the given domain object.
|
||||
*
|
||||
* @param id the domain object id
|
||||
* @param domainObject the domain object
|
||||
* @returns {object}
|
||||
* @private
|
||||
*/
|
||||
LayoutController.prototype.clearSelection = function () {
|
||||
LayoutController.prototype.getToolbar = function (id, domainObject) {
|
||||
var toolbarObj = {};
|
||||
toolbarObj[this.frames[id] ? 'hideFrame' : 'showFrame'] = this.toggleFrame.bind(this, id, domainObject);
|
||||
return toolbarObj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bypasses selection if drag is in progress.
|
||||
*
|
||||
* @param event the angular event object
|
||||
*/
|
||||
LayoutController.prototype.bypassSelection = function (event) {
|
||||
if (this.dragInProgress) {
|
||||
if (event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the domain object is drilled in.
|
||||
*
|
||||
* @param domainObject the domain object
|
||||
* @return true if the object is drilled in, false otherwise
|
||||
*/
|
||||
LayoutController.prototype.isDrilledIn = function (domainObject) {
|
||||
return this.drilledIn === domainObject.getId();
|
||||
};
|
||||
|
||||
/**
|
||||
* Puts the given object in the drilled-in mode.
|
||||
*
|
||||
* @param event the angular event object
|
||||
* @param domainObject the domain object
|
||||
*/
|
||||
LayoutController.prototype.drill = function (event, domainObject) {
|
||||
if (event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (!domainObject.getCapability('editor').inEditContext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selection) {
|
||||
this.selection.deselect();
|
||||
delete this.selectedId;
|
||||
if (!domainObject.hasCapability('composition')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable since fixed position doesn't use the selection API yet
|
||||
if (domainObject.getModel().type === 'telemetry.fixed') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.drilledIn = domainObject.getId();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -440,6 +491,36 @@ define(
|
||||
return this.gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the selection context.
|
||||
*
|
||||
* @param domainObject the domain object
|
||||
* @returns {object} the context object which includes
|
||||
* item, oldItem and toolbar
|
||||
*/
|
||||
LayoutController.prototype.getContext = function (domainObject, toolbar) {
|
||||
return {
|
||||
item: domainObject.useCapability('adapter'),
|
||||
oldItem: domainObject,
|
||||
toolbar: toolbar ? this.getToolbar(domainObject.getId(), domainObject) : undefined
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects a newly-dropped object.
|
||||
*
|
||||
* @param classSelector the css class selector
|
||||
* @param domainObject the domain object
|
||||
*/
|
||||
LayoutController.prototype.selectIfNew = function (selector, domainObject) {
|
||||
if (domainObject.getId() === this.droppedIdToSelectAfterRefresh) {
|
||||
setTimeout(function () {
|
||||
$('.' + selector)[0].click();
|
||||
delete this.droppedIdToSelectAfterRefresh;
|
||||
}.bind(this), 0);
|
||||
}
|
||||
};
|
||||
|
||||
return LayoutController;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -21,8 +21,14 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["../src/LayoutController"],
|
||||
function (LayoutController) {
|
||||
[
|
||||
"../src/LayoutController",
|
||||
"zepto"
|
||||
],
|
||||
function (
|
||||
LayoutController,
|
||||
$
|
||||
) {
|
||||
|
||||
describe("The Layout controller", function () {
|
||||
var mockScope,
|
||||
@@ -32,7 +38,12 @@ define(
|
||||
controller,
|
||||
mockCompositionCapability,
|
||||
mockComposition,
|
||||
mockCompositionObjects;
|
||||
mockCompositionObjects,
|
||||
mockOpenMCT,
|
||||
mockSelection,
|
||||
mockDomainObjectCapability,
|
||||
$element = [],
|
||||
selectable = [];
|
||||
|
||||
function mockPromise(value) {
|
||||
return {
|
||||
@@ -58,21 +69,18 @@ define(
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
getCapability: function () {
|
||||
return mockDomainObjectCapability;
|
||||
},
|
||||
hasCapability: function (param) {
|
||||
if (param === 'composition') {
|
||||
return id !== 'b';
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Utility function to find a watch for a given expression
|
||||
function findWatch(expr) {
|
||||
var watch;
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
watch = call.args[1];
|
||||
}
|
||||
});
|
||||
return watch;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
@@ -88,7 +96,6 @@ define(
|
||||
mockComposition = ["a", "b", "c"];
|
||||
mockCompositionObjects = mockComposition.map(mockDomainObject);
|
||||
|
||||
|
||||
testConfiguration = {
|
||||
panels: {
|
||||
a: {
|
||||
@@ -97,27 +104,70 @@ define(
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mockDomainObjectCapability = jasmine.createSpyObj('capability',
|
||||
['inEditContext']
|
||||
);
|
||||
mockCompositionCapability = mockPromise(mockCompositionObjects);
|
||||
|
||||
mockScope.domainObject = mockDomainObject("mockDomainObject");
|
||||
mockScope.model = testModel;
|
||||
mockScope.configuration = testConfiguration;
|
||||
mockScope.selection = jasmine.createSpyObj(
|
||||
'selection',
|
||||
['select', 'get', 'selected', 'deselect']
|
||||
);
|
||||
|
||||
selectable[0] = {
|
||||
context: {
|
||||
oldItem: mockScope.domainObject
|
||||
}
|
||||
};
|
||||
|
||||
mockSelection = jasmine.createSpyObj("selection", [
|
||||
'select',
|
||||
'on',
|
||||
'off',
|
||||
'get'
|
||||
]);
|
||||
mockSelection.get.andReturn(selectable);
|
||||
mockOpenMCT = {
|
||||
selection: mockSelection
|
||||
};
|
||||
|
||||
$element = $('<div></div>');
|
||||
$(document).find('body').append($element);
|
||||
spyOn($element[0], 'click');
|
||||
|
||||
spyOn(mockScope.domainObject, "useCapability").andCallThrough();
|
||||
|
||||
controller = new LayoutController(mockScope);
|
||||
controller = new LayoutController(mockScope, $element, mockOpenMCT);
|
||||
spyOn(controller, "layoutPanels").andCallThrough();
|
||||
|
||||
findWatch("selection")(mockScope.selection);
|
||||
|
||||
jasmine.Clock.useMock();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$element.remove();
|
||||
});
|
||||
|
||||
|
||||
it("listens for selection change events", function () {
|
||||
expect(mockOpenMCT.selection.on).toHaveBeenCalledWith(
|
||||
'change',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it("cleans up on scope destroy", function () {
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
'$destroy',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
mockScope.$on.calls[0].args[1]();
|
||||
|
||||
expect(mockOpenMCT.selection.off).toHaveBeenCalledWith(
|
||||
'change',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
// Model changes will indicate that panel positions
|
||||
// may have changed, for instance.
|
||||
it("watches for changes to composition", function () {
|
||||
@@ -320,67 +370,35 @@ define(
|
||||
.not.toEqual(oldStyle);
|
||||
});
|
||||
|
||||
it("allows panels to be selected", function () {
|
||||
it("allows objects to be selected", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
selectable[0].context.oldItem = childObj;
|
||||
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
|
||||
|
||||
expect(controller.selected(childObj)).toBe(true);
|
||||
});
|
||||
|
||||
it("prevents event bubbling while drag is in progress", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
|
||||
controller.select(mockEvent, childObj.getId());
|
||||
// Do a drag
|
||||
controller.startDrag(childObj.getId(), [1, 1], [0, 0]);
|
||||
controller.continueDrag([100, 100]);
|
||||
controller.endDrag();
|
||||
|
||||
// Because mouse position could cause the parent object to be selected, this should be ignored.
|
||||
controller.bypassSelection(mockEvent);
|
||||
|
||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
||||
|
||||
expect(controller.selected(childObj)).toBe(true);
|
||||
});
|
||||
|
||||
it("allows selection to be cleared", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
|
||||
controller.select(null, childObj.getId());
|
||||
controller.clearSelection();
|
||||
|
||||
expect(controller.selected(childObj)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("prevents clearing selection while drag is in progress", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
var id = childObj.getId();
|
||||
|
||||
controller.select(mockEvent, id);
|
||||
|
||||
// Do a drag
|
||||
controller.startDrag(id, [1, 1], [0, 0]);
|
||||
controller.continueDrag([100, 100]);
|
||||
controller.endDrag();
|
||||
|
||||
// Because mouse position could cause clearSelection to be called, this should be ignored.
|
||||
controller.clearSelection();
|
||||
|
||||
expect(controller.selected(childObj)).toBe(true);
|
||||
|
||||
// Shoud be able to clear the selection after dragging is done.
|
||||
// Shoud be able to select another object when dragging is done.
|
||||
jasmine.Clock.tick(0);
|
||||
controller.clearSelection();
|
||||
mockEvent.stopPropagation.reset();
|
||||
controller.bypassSelection(mockEvent);
|
||||
|
||||
expect(controller.selected(childObj)).toBe(false);
|
||||
});
|
||||
|
||||
it("clears selection after moving/resizing", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
var id = childObj.getId();
|
||||
|
||||
controller.select(mockEvent, id);
|
||||
|
||||
// Do a drag
|
||||
controller.startDrag(id, [1, 1], [0, 0]);
|
||||
controller.continueDrag([100, 100]);
|
||||
controller.endDrag();
|
||||
|
||||
jasmine.Clock.tick(0);
|
||||
controller.clearSelection();
|
||||
|
||||
expect(controller.selected(childObj)).toBe(false);
|
||||
expect(mockEvent.stopPropagation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows frames by default", function () {
|
||||
@@ -398,43 +416,74 @@ define(
|
||||
it("hides frame when selected object has frame ", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
controller.select(mockEvent, childObj.getId());
|
||||
|
||||
expect(mockScope.selection.select).toHaveBeenCalled();
|
||||
|
||||
var selectedObj = mockScope.selection.select.mostRecentCall.args[0];
|
||||
selectable[0].context.oldItem = childObj;
|
||||
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
|
||||
var toolbarObj = controller.getToolbar(childObj.getId(), childObj);
|
||||
|
||||
expect(controller.hasFrame(childObj)).toBe(true);
|
||||
expect(selectedObj.hideFrame).toBeDefined();
|
||||
expect(selectedObj.hideFrame).toEqual(jasmine.any(Function));
|
||||
expect(toolbarObj.hideFrame).toBeDefined();
|
||||
expect(toolbarObj.hideFrame).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("shows frame when selected object has no frame", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
|
||||
var childObj = mockCompositionObjects[1];
|
||||
controller.select(mockEvent, childObj.getId());
|
||||
|
||||
expect(mockScope.selection.select).toHaveBeenCalled();
|
||||
|
||||
var selectedObj = mockScope.selection.select.mostRecentCall.args[0];
|
||||
selectable[0].context.oldItem = childObj;
|
||||
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
|
||||
var toolbarObj = controller.getToolbar(childObj.getId(), childObj);
|
||||
|
||||
expect(controller.hasFrame(childObj)).toBe(false);
|
||||
expect(selectedObj.showFrame).toBeDefined();
|
||||
expect(selectedObj.showFrame).toEqual(jasmine.any(Function));
|
||||
expect(toolbarObj.showFrame).toBeDefined();
|
||||
expect(toolbarObj.showFrame).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("deselects the object that is no longer in the composition", function () {
|
||||
it("selects the parent object when selected object is removed", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
controller.select(mockEvent, childObj.getId());
|
||||
selectable[0].context.oldItem = childObj;
|
||||
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
|
||||
|
||||
var composition = ["b", "c"];
|
||||
mockScope.$watchCollection.mostRecentCall.args[1](composition);
|
||||
|
||||
expect(controller.selected(childObj)).toBe(false);
|
||||
expect($element[0].click).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows objects to be drilled-in only when editing", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
childObj.getCapability().inEditContext.andReturn(false);
|
||||
controller.drill(mockEvent, childObj);
|
||||
|
||||
expect(controller.isDrilledIn(childObj)).toBe(false);
|
||||
});
|
||||
|
||||
it("allows objects to be drilled-in only if it has sub objects", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[1];
|
||||
childObj.getCapability().inEditContext.andReturn(true);
|
||||
controller.drill(mockEvent, childObj);
|
||||
|
||||
expect(controller.isDrilledIn(childObj)).toBe(false);
|
||||
});
|
||||
|
||||
it("selects a newly-dropped object", function () {
|
||||
mockScope.$on.mostRecentCall.args[1](
|
||||
mockEvent,
|
||||
'd',
|
||||
{ x: 300, y: 100 }
|
||||
);
|
||||
|
||||
var childObj = mockDomainObject("d");
|
||||
var testElement = $("<div class='some-class'></div>");
|
||||
$element.append(testElement);
|
||||
spyOn(testElement[0], 'click');
|
||||
|
||||
controller.selectIfNew('some-class', childObj);
|
||||
jasmine.Clock.tick(0);
|
||||
|
||||
expect(testElement[0].click).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user