Merge branch 'open-master' into open1035

Merge in latest changes into topic branch for WTD-1035,
dialog warning before navigating out of Edit mode.
This commit is contained in:
Victor Woeltjen 2015-03-31 14:32:55 -07:00
commit 8a8c84eacf
45 changed files with 791 additions and 418 deletions

View File

@ -92,6 +92,7 @@ define(
key: 'create',
glyph: type.getGlyph(),
name: type.getName(),
type: type.getKey(),
description: type.getDescription(),
context: context
};

View File

@ -2,12 +2,13 @@
mct-object="domainObject"
ng-model="representation">
</mct-representation>
<div class="holder edit-area outline abs">
<div class="holder edit-area outline abs"
ng-controller="SplitPaneController as vSplitter">
<mct-toolbar name="mctToolbar"
structure="toolbar.structure"
ng-model="toolbar.state">
</mct-toolbar>
<div class='split-layout vertical contents abs work-area' ng-controller="SplitPaneController as vSplitter">
<div class='split-layout vertical contents abs work-area'>
<div
class='abs pane left edit-main'
ng-style="{ right: (vSplitter.state()+5) + 'px'}"

View File

@ -23,13 +23,32 @@ define(
) {
// This is a "lookup" style capability (it looks up other
// domain objects), and it should be idempotent
return new EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
true // Idempotent
);
var capability = new EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
true // Idempotent
),
// Track the real root object for the Elements pane
trueRoot = capability.getRoot();
// Provide access to the real root, for the Elements pane.
capability.getTrueRoot = function () {
return trueRoot;
};
// Hide ancestry after the root of this subgraph
if (cache.isRoot(domainObject)) {
capability.getRoot = function () {
return editableObject;
};
capability.getPath = function () {
return [editableObject];
};
}
return capability;
};
}
);

View File

@ -16,7 +16,7 @@ define(
function updateRoot(domainObject) {
var context = domainObject &&
domainObject.getCapability('context'),
newRoot = context && context.getRoot(),
newRoot = context && context.getTrueRoot(),
oldId = root && root.getId(),
newId = newRoot && newRoot.getId();

View File

@ -34,7 +34,8 @@ define(
*/
function EditableDomainObjectCache(EditableDomainObject) {
var cache = new EditableModelCache(),
dirty = {};
dirty = {},
root;
return {
/**
@ -45,11 +46,24 @@ define(
* @returns {DomainObject} the domain object in an editable form
*/
getEditableObject: function (domainObject) {
// Track the top-level domain object; this will have
// some special behavior for its context capability.
root = root || domainObject;
// Provide an editable form of the object
return new EditableDomainObject(
domainObject,
cache.getCachedModel(domainObject)
);
},
/**
* Check if a domain object is (effectively) the top-level
* object in this editable subgraph.
* @returns {boolean} true if it is the root
*/
isRoot: function (domainObject) {
return domainObject === root;
},
/**
* Mark an editable domain object (presumably already cached)
* as having received modifications during editing; it should be

View File

@ -19,18 +19,22 @@ define(
// methods for domain objects, so give it an
// arbitrary interface to wrap.
mockContext =
jasmine.createSpyObj("context", [ "getDomainObject" ]);
jasmine.createSpyObj("context", [ "getDomainObject", "getRoot" ]);
mockTestObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel", "getCapability" ]
);
mockFactory =
jasmine.createSpyObj("factory", ["getEditableObject"]);
mockFactory = jasmine.createSpyObj(
"factory",
["getEditableObject", "isRoot"]
);
someValue = { x: 42 };
mockContext.getRoot.andReturn(mockTestObject);
mockContext.getDomainObject.andReturn(mockTestObject);
mockFactory.getEditableObject.andReturn(someValue);
mockFactory.isRoot.andReturn(true);
capability = new EditableContextCapability(
mockContext,
@ -47,6 +51,18 @@ define(
expect(mockContext.getDomainObject.calls.length).toEqual(1);
});
it("hides the root object", function () {
expect(capability.getRoot()).toEqual(mockEditableObject);
expect(capability.getPath()).toEqual([mockEditableObject]);
});
it("exposes the root object through a different method", function () {
// Should still go through the factory...
expect(capability.getTrueRoot()).toEqual(someValue);
// ...with value of the unwrapped capability's getRoot
expect(mockFactory.getEditableObject)
.toHaveBeenCalledWith(mockTestObject);
});
});
}
);

View File

@ -19,14 +19,14 @@ define(
);
mockContext = jasmine.createSpyObj(
'context',
[ 'getRoot' ]
[ 'getTrueRoot' ]
);
mockDomainObject.getId.andReturn('test-id');
mockDomainObject.getCapability.andReturn(mockContext);
// Return a new instance of the root object each time
mockContext.getRoot.andCallFake(function () {
mockContext.getTrueRoot.andCallFake(function () {
var mockRoot = jasmine.createSpyObj('root', ['getId']);
mockRoot.getId.andReturn('root-id');
return mockRoot;
@ -75,7 +75,7 @@ define(
firstRoot = controller.getRoot();
// Change the exposed root
mockContext.getRoot.andCallFake(function () {
mockContext.getTrueRoot.andCallFake(function () {
var mockRoot = jasmine.createSpyObj('root', ['getId']);
mockRoot.getId.andReturn('other-root-id');
return mockRoot;

View File

@ -99,6 +99,17 @@ define(
expect(captured.saved).toEqual(1);
});
it("tracks the root object of the Edit mode subgraph", function () {
// Root object is the first object exposed to the cache
var domainObjects = ['a', 'b', 'c'].map(TestObject);
domainObjects.forEach(function (obj) {
cache.getEditableObject(obj);
});
expect(cache.isRoot(domainObjects[0])).toBeTruthy();
expect(cache.isRoot(domainObjects[1])).toBeFalsy();
expect(cache.isRoot(domainObjects[2])).toBeFalsy();
});
});
}

View File

@ -150,7 +150,18 @@
"representations": [
{
"key": "tree",
"templateUrl": "templates/tree.html",
"templateUrl": "templates/subtree.html",
"uses": [ "composition" ],
"type": "root",
"priority": "preferred"
},
{
"key": "tree",
"templateUrl": "templates/tree.html"
},
{
"key": "subtree",
"templateUrl": "templates/subtree.html",
"uses": [ "composition" ]
},
{

View File

@ -1,5 +1,5 @@
/* CONSTANTS */
/* line 17, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 17, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
@ -20,38 +20,38 @@ time, mark, audio, video {
font-size: 100%;
vertical-align: baseline; }
/* line 22, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 22, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
html {
line-height: 1; }
/* line 24, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 24, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
ol, ul {
list-style: none; }
/* line 26, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 26, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
table {
border-collapse: collapse;
border-spacing: 0; }
/* line 28, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 28, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle; }
/* line 30, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 30, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
q, blockquote {
quotes: none; }
/* line 103, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 103, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none; }
/* line 32, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 32, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
a img {
border: none; }
/* line 116, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
/* line 116, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
display: block; }
@ -218,7 +218,7 @@ span {
.user-environ .edit-area .tool-bar {
bottom: auto;
height: 35px;
line-height: 33px; }
line-height: 28px; }
/* line 38, ../sass/user-environ/_layout.scss */
.user-environ .edit-area .work-area {
top: 45px; }
@ -388,35 +388,21 @@ span {
width: 100%;
pointer-events: none;
z-index: 0; }
/* line 17, ../sass/_fixed-position.scss */
.t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-x {
background-image: -webkit-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -moz-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -o-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-repeat: repeat-x; }
/* line 21, ../sass/_fixed-position.scss */
.t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-y {
background-image: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -moz-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -o-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-repeat: repeat-y; }
/* line 28, ../sass/_fixed-position.scss */
/* line 21, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item {
position: absolute;
border: 1px solid transparent; }
/* line 32, ../sass/_fixed-position.scss */
/* line 25, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item.s-selected {
-webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
-moz-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
border-color: #0099cc;
cursor: move; }
/* line 37, ../sass/_fixed-position.scss */
/* line 30, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item.s-not-selected {
opacity: 0.8; }
/* line 43, ../sass/_fixed-position.scss */
/* line 36, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-box,
.t-fixed-position .l-fixed-position-item .l-fixed-position-image,
.t-fixed-position .l-fixed-position-item .l-fixed-position-text {
@ -425,20 +411,20 @@ span {
box-sizing: border-box;
height: 100%;
width: 100%; }
/* line 51, ../sass/_fixed-position.scss */
/* line 44, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-image {
background-size: cover;
background-repeat: no-repeat;
background-position: left top; }
/* line 57, ../sass/_fixed-position.scss */
background-position: center; }
/* line 50, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text {
text-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px;
border: 1px solid transparent;
font-size: 0.8rem; }
/* line 62, ../sass/_fixed-position.scss */
/* line 55, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-static-text {
padding: 3px; }
/* line 67, ../sass/_fixed-position.scss */
/* line 60, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem {
overflow: hidden;
position: absolute;
@ -452,27 +438,41 @@ span {
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 50%; }
/* line 71, ../sass/_fixed-position.scss */
/* line 64, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-title {
right: auto;
left: 3px; }
/* line 75, ../sass/_fixed-position.scss */
/* line 68, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value {
right: 3px;
left: auto;
text-align: right; }
/* line 80, ../sass/_fixed-position.scss */
/* line 73, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value.telem-only {
left: 3px;
width: auto; }
/* line 91, ../sass/_fixed-position.scss */
/* line 84, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item-handle {
background: rgba(0, 153, 204, 0.5);
cursor: crosshair;
border: 1px solid #0099cc;
position: absolute; }
/* line 103, ../sass/_fixed-position.scss */
/* line 98, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-x {
background-image: -webkit-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -moz-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -o-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-repeat: repeat-x; }
/* line 102, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-y {
background-image: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -moz-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: -o-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-image: linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
background-repeat: repeat-y; }
/* line 110, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected):hover {
border: 1px dotted rgba(0, 153, 204, 0.5); }
@ -1126,8 +1126,7 @@ a.l-btn span {
.btn-bar .btn,
.btn-bar .btn-set,
.btn-bar .t-btn {
display: inline-block;
margin-left: 5px; }
display: inline-block; }
/* line 157, ../sass/controls/_controls.scss */
.l-composite-control {
@ -1137,23 +1136,24 @@ a.l-btn span {
line-height: 18px; }
/* line 166, ../sass/controls/_controls.scss */
.control-group {
.l-control-group {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
border-left: 1px solid #4d4d4d;
display: inline-block;
padding: 0 5px;
position: relative; }
/* line 173, ../sass/controls/_controls.scss */
.control-group:first-child {
/* line 174, ../sass/controls/_controls.scss */
.l-control-group:first-child {
border-left: none;
padding-left: 0; }
/* line 179, ../sass/controls/_controls.scss */
/* line 180, ../sass/controls/_controls.scss */
.btn-set {
display: inline-block;
position: relative; }
/* line 184, ../sass/controls/_controls.scss */
/* line 185, ../sass/controls/_controls.scss */
.btn-set .btn,
.btn-set .t-btn {
-webkit-border-radius: 0;
@ -1163,7 +1163,7 @@ a.l-btn span {
border-radius: 0;
border-left: 1px solid #666666;
margin-left: 0; }
/* line 188, ../sass/controls/_controls.scss */
/* line 189, ../sass/controls/_controls.scss */
.btn-set .btn:first-child,
.btn-set .t-btn:first-child {
border-left: none;
@ -1173,7 +1173,7 @@ a.l-btn span {
-moz-border-radius-bottomleft: 3px;
-webkit-border-bottom-left-radius: 3px;
border-bottom-left-radius: 3px; }
/* line 192, ../sass/controls/_controls.scss */
/* line 193, ../sass/controls/_controls.scss */
.btn-set .btn:last-child,
.btn-set .t-btn:last-child {
-moz-border-radius-topright: 3px;
@ -1183,7 +1183,7 @@ a.l-btn span {
-webkit-border-bottom-right-radius: 3px;
border-bottom-right-radius: 3px; }
/* line 203, ../sass/controls/_controls.scss */
/* line 204, ../sass/controls/_controls.scss */
.object-browse-bar .btn,
.object-browse-bar .t-btn,
.top-bar .buttons-main .btn,
@ -1194,7 +1194,7 @@ a.l-btn span {
font-size: 12.6px;
height: 28px;
line-height: 28px; }
/* line 209, ../sass/controls/_controls.scss */
/* line 210, ../sass/controls/_controls.scss */
.object-browse-bar .btn .icon:not(.invoke-menu),
.object-browse-bar .t-btn .icon:not(.invoke-menu),
.top-bar .buttons-main .btn .icon:not(.invoke-menu),
@ -1204,7 +1204,7 @@ a.l-btn span {
font-size: 150%;
vertical-align: middle; }
/* line 217, ../sass/controls/_controls.scss */
/* line 218, ../sass/controls/_controls.scss */
label.checkbox.custom {
cursor: pointer;
display: inline-block;
@ -1213,13 +1213,13 @@ label.checkbox.custom {
padding-left: 19px;
position: relative;
vertical-align: top; }
/* line 228, ../sass/controls/_controls.scss */
/* line 229, ../sass/controls/_controls.scss */
label.checkbox.custom em {
color: #999999;
display: inline-block;
height: 14px;
min-width: 14px; }
/* line 233, ../sass/controls/_controls.scss */
/* line 234, ../sass/controls/_controls.scss */
label.checkbox.custom em:before {
-webkit-border-radius: 2.25px;
-moz-border-radius: 2.25px;
@ -1240,51 +1240,51 @@ label.checkbox.custom {
top: 0;
position: absolute;
text-align: center; }
/* line 251, ../sass/controls/_controls.scss */
/* line 252, ../sass/controls/_controls.scss */
label.checkbox.custom.no-text {
overflow: hidden;
margin-right: 0;
padding-left: 0;
height: 14px;
width: 14px; }
/* line 257, ../sass/controls/_controls.scss */
/* line 258, ../sass/controls/_controls.scss */
label.checkbox.custom.no-text em {
overflow: hidden; }
/* line 261, ../sass/controls/_controls.scss */
/* line 262, ../sass/controls/_controls.scss */
label.checkbox.custom input {
display: none; }
/* line 263, ../sass/controls/_controls.scss */
/* line 264, ../sass/controls/_controls.scss */
label.checkbox.custom input:checked ~ em:before {
background: #0099cc;
color: #ccf2ff;
content: "2"; }
/* line 271, ../sass/controls/_controls.scss */
/* line 272, ../sass/controls/_controls.scss */
.input-labeled {
margin-left: 5px; }
/* line 273, ../sass/controls/_controls.scss */
/* line 274, ../sass/controls/_controls.scss */
.input-labeled label {
display: inline-block;
margin-right: 3px; }
/* line 277, ../sass/controls/_controls.scss */
/* line 278, ../sass/controls/_controls.scss */
.input-labeled.inline {
display: inline-block; }
/* line 280, ../sass/controls/_controls.scss */
/* line 281, ../sass/controls/_controls.scss */
.input-labeled:first-child {
margin-left: 0; }
/* line 285, ../sass/controls/_controls.scss */
/* line 286, ../sass/controls/_controls.scss */
.btn-menu label.checkbox.custom {
margin-left: 5px; }
/* line 290, ../sass/controls/_controls.scss */
/* line 291, ../sass/controls/_controls.scss */
.item .checkbox.checked label {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
border-bottom: none; }
/* line 296, ../sass/controls/_controls.scss */
/* line 297, ../sass/controls/_controls.scss */
.btn-menu {
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(100%, #404040));
background-image: -webkit-linear-gradient(#4d4d4d, #404040);
@ -1315,42 +1315,42 @@ label.checkbox.custom {
background-image: -moz-linear-gradient(#666666, #4d4d4d);
background-image: -o-linear-gradient(#666666, #4d4d4d);
background-image: linear-gradient(#666666, #4d4d4d); }
/* line 303, ../sass/controls/_controls.scss */
/* line 304, ../sass/controls/_controls.scss */
.btn-menu.dropdown {
padding-left: 5px;
padding-right: 5px; }
/* line 309, ../sass/controls/_controls.scss */
padding-left: 10px;
padding-right: 10px; }
/* line 310, ../sass/controls/_controls.scss */
.btn-menu:not(.disabled):hover {
color: #cccccc; }
/* line 313, ../sass/controls/_controls.scss */
/* line 314, ../sass/controls/_controls.scss */
.btn-menu.btn-invoke-menu {
color: #0099cc;
padding: 0 5px; }
/* line 317, ../sass/controls/_controls.scss */
/* line 318, ../sass/controls/_controls.scss */
.btn-menu.btn-invoke-menu:hover {
color: deepskyblue; }
/* line 327, ../sass/controls/_controls.scss */
/* line 328, ../sass/controls/_controls.scss */
.btn-menu .type-icon {
margin-right: 5px; }
/* line 330, ../sass/controls/_controls.scss */
/* line 331, ../sass/controls/_controls.scss */
.btn-menu .menu {
position: absolute;
left: 0;
text-align: left; }
/* line 335, ../sass/controls/_controls.scss */
/* line 336, ../sass/controls/_controls.scss */
.btn-menu .menu .ui-symbol.icon {
width: 12px; }
/* line 341, ../sass/controls/_controls.scss */
/* line 342, ../sass/controls/_controls.scss */
.top-bar .btn-menu {
height: 35px;
line-height: 35px;
padding-right: 10px; }
/* line 349, ../sass/controls/_controls.scss */
/* line 350, ../sass/controls/_controls.scss */
.top-bar .btn-menu.browse-btn {
margin-right: 5px;
padding-left: 35px; }
/* line 352, ../sass/controls/_controls.scss */
/* line 353, ../sass/controls/_controls.scss */
.top-bar .btn-menu.browse-btn .badge {
-webkit-border-radius: 4.5px;
-moz-border-radius: 4.5px;
@ -1369,30 +1369,30 @@ label.checkbox.custom {
height: auto; }
/******************************************************** OBJECT-HEADER */
/* line 369, ../sass/controls/_controls.scss */
/* line 370, ../sass/controls/_controls.scss */
.object-header {
display: inline-block;
font-size: 1em; }
/* line 372, ../sass/controls/_controls.scss */
/* line 373, ../sass/controls/_controls.scss */
.object-header .title {
color: white; }
/* line 375, ../sass/controls/_controls.scss */
/* line 376, ../sass/controls/_controls.scss */
.object-header .type-icon {
font-size: 1.5em;
margin-right: 5px;
vertical-align: middle; }
/* line 384, ../sass/controls/_controls.scss */
/* line 385, ../sass/controls/_controls.scss */
.top-bar .object-header,
.object-browse-bar .object-header {
font-size: 1.1em; }
/* line 386, ../sass/controls/_controls.scss */
/* line 387, ../sass/controls/_controls.scss */
.top-bar .object-header span,
.object-browse-bar .object-header span {
display: inline-block; }
/******************************************************** VIEW-CONTROLS */
/* line 395, ../sass/controls/_controls.scss */
/* line 396, ../sass/controls/_controls.scss */
.view-controls .view-type {
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
@ -1406,16 +1406,16 @@ label.checkbox.custom {
line-height: 20px;
padding-left: 5px;
padding-right: 5px; }
/* line 406, ../sass/controls/_controls.scss */
/* line 407, ../sass/controls/_controls.scss */
.view-controls .view-type.cur {
background: #666666; }
/* line 411, ../sass/controls/_controls.scss */
/* line 412, ../sass/controls/_controls.scss */
.edit-mode .top-bar .control-set.edit-view-controls {
margin-right: 50px; }
/******************************************************** SLIDERS */
/* line 422, ../sass/controls/_controls.scss */
/* line 423, ../sass/controls/_controls.scss */
.slider .slot {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
@ -1438,7 +1438,7 @@ label.checkbox.custom {
right: 0;
bottom: auto;
left: 0; }
/* line 433, ../sass/controls/_controls.scss */
/* line 434, ../sass/controls/_controls.scss */
.slider .knob {
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(100%, #404040));
background-image: -webkit-linear-gradient(#4d4d4d, #404040);
@ -1489,12 +1489,12 @@ label.checkbox.custom {
/* line 120, ../sass/_mixins.scss */
.slider .knob:not(.disabled):hover:before {
border-color: rgba(0, 153, 204, 0.9); }
/* line 444, ../sass/controls/_controls.scss */
/* line 445, ../sass/controls/_controls.scss */
.slider .knob:before {
top: 1px;
bottom: 3px;
left: 5px; }
/* line 451, ../sass/controls/_controls.scss */
/* line 452, ../sass/controls/_controls.scss */
.slider .range {
background: rgba(0, 153, 204, 0.6);
cursor: ew-resize;
@ -1505,12 +1505,12 @@ label.checkbox.custom {
left: auto;
height: auto;
width: auto; }
/* line 461, ../sass/controls/_controls.scss */
/* line 462, ../sass/controls/_controls.scss */
.slider .range:hover {
background: rgba(0, 153, 204, 0.7); }
/******************************************************** BROWSER ELEMENTS */
/* line 469, ../sass/controls/_controls.scss */
/* line 470, ../sass/controls/_controls.scss */
::-webkit-scrollbar {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
@ -1529,7 +1529,7 @@ label.checkbox.custom {
height: 10px;
width: 10px; }
/* line 475, ../sass/controls/_controls.scss */
/* line 476, ../sass/controls/_controls.scss */
::-webkit-scrollbar-thumb {
background-image: -webkit-gradient(linear, 50% 0%, 50% 20, color-stop(0%, #666666), color-stop(100%, #595959));
background-image: -webkit-linear-gradient(#666666, #595959 20px);
@ -1548,7 +1548,7 @@ label.checkbox.custom {
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
border-top: 1px solid gray; }
/* line 482, ../sass/controls/_controls.scss */
/* line 483, ../sass/controls/_controls.scss */
::-webkit-scrollbar-thumb:hover {
background-image: -webkit-gradient(linear, 50% 0%, 50% 20, color-stop(0%, #808080), color-stop(100%, #737373));
background-image: -webkit-linear-gradient(#808080, #737373 20px);
@ -1556,7 +1556,7 @@ label.checkbox.custom {
background-image: -o-linear-gradient(#808080, #737373 20px);
background-image: linear-gradient(#808080, #737373 20px); }
/* line 487, ../sass/controls/_controls.scss */
/* line 488, ../sass/controls/_controls.scss */
::-webkit-scrollbar-corner {
background: rgba(0, 0, 0, 0.4); }
@ -1568,6 +1568,10 @@ label.checkbox.custom {
.checkbox-list li {
margin-bottom: 5px; }
/* line 14, ../sass/controls/_lists.scss */
.l-tree-item-flat-list .tree-item .label {
left: 5px !important; }
/******************************************************** MENUS */
/* line 2, ../sass/controls/_menus.scss */
.menu-element {
@ -1621,7 +1625,7 @@ label.checkbox.custom {
box-sizing: border-box;
border-top: 1px solid #737373;
line-height: 1.5rem;
padding: 3px 10px 3px 32px;
padding: 3px 10px 3px 35px;
white-space: nowrap; }
/* line 25, ../sass/controls/_menus.scss */
.menu-element .menu ul li:first-child {
@ -2199,13 +2203,13 @@ input[type="text"] {
/* line 68, ../sass/forms/_filter.scss */
.top-bar input.filter {
font-size: .8em;
font-size: .9em;
height: 35px;
line-height: 35px;
margin-right: 5px;
margin-top: -5px;
padding-left: 10px;
padding-right: 10px; }
padding-right: 10px;
vertical-align: top; }
/* line 79, ../sass/forms/_filter.scss */
.top-bar .icon-filter {
font-size: 1.4em; }
@ -2633,8 +2637,8 @@ input[type="text"] {
.tool-bar {
border-bottom: 1px solid #4d4d4d; }
/* line 3, ../sass/user-environ/_tool-bar.scss */
.tool-bar .control-group {
height: 35px; }
.tool-bar .l-control-group {
height: 28px; }
/* line 6, ../sass/user-environ/_tool-bar.scss */
.tool-bar input[type="text"] {
-webkit-box-sizing: border-box;
@ -2817,10 +2821,10 @@ input[type="text"] {
.wait-spinner {
display: block;
position: absolute;
-webkit-animation: rotation .6s infinite linear;
-moz-animation: rotation .6s infinite linear;
-o-animation: rotation .6s infinite linear;
animation: rotation .6s infinite linear;
-webkit-animation: rotation 0.6s infinite linear;
-moz-animation: rotation 0.6s infinite linear;
-o-animation: rotation 0.6s infinite linear;
animation: rotation 0.6s infinite linear;
border-color: rgba(0, 153, 204, 0.25);
border-top-color: #0099cc;
border-style: solid;
@ -2859,10 +2863,10 @@ input[type="text"] {
.treeview .wait-spinner {
display: block;
position: absolute;
-webkit-animation: rotation .6s infinite linear;
-moz-animation: rotation .6s infinite linear;
-o-animation: rotation .6s infinite linear;
animation: rotation .6s infinite linear;
-webkit-animation: rotation 0.6s infinite linear;
-moz-animation: rotation 0.6s infinite linear;
-o-animation: rotation 0.6s infinite linear;
animation: rotation 0.6s infinite linear;
border-color: rgba(0, 153, 204, 0.25);
border-top-color: #0099cc;
border-style: solid;

View File

@ -7,96 +7,135 @@ ul.tree {
list-style-type: none;
margin: 0;
padding: 0; }
/* line 4, ../sass/tree/_tree.scss */
ul.tree li .tree-item {
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
-webkit-transition: background-color 0.25s;
-moz-transition: background-color 0.25s;
-o-transition: background-color 0.25s;
transition: background-color 0.25s;
/* line 3, ../sass/tree/_tree.scss */
ul.tree li {
display: block;
font-size: 0.80rem;
height: 1.5rem;
line-height: 1.5rem;
margin-bottom: 3px;
position: relative; }
/* line 17, ../sass/tree/_tree.scss */
ul.tree li .tree-item.loading {
color: #666666;
font-style: italic; }
/* line 20, ../sass/tree/_tree.scss */
ul.tree li .tree-item.loading .wait-spinner {
margin-left: 14px; }
/* line 24, ../sass/tree/_tree.scss */
ul.tree li .tree-item:not(.loading) {
cursor: pointer; }
/* line 26, ../sass/tree/_tree.scss */
ul.tree li .tree-item:not(.loading):hover {
/* line 6, ../sass/tree/_tree.scss */
ul.tree li span.tree-item {
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
-webkit-transition: background-color 0.25s;
-moz-transition: background-color 0.25s;
-o-transition: background-color 0.25s;
transition: background-color 0.25s;
display: block;
font-size: 0.80rem;
height: 1.5rem;
line-height: 1.5rem;
margin-bottom: 3px;
position: relative; }
/* line 17, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .view-control {
display: inline-block;
margin-left: 5px;
width: 10px; }
/* line 23, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .view-control:hover {
color: #ffc700; }
/* line 28, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label {
display: block;
overflow: hidden;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
width: auto;
height: auto;
left: 20px; }
/* line 34, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .type-icon {
overflow: hidden;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
width: auto;
height: auto;
text-shadow: rgba(0, 0, 0, 0.6) 0 1px 2px;
color: #0099cc; }
/* line 38, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .type-icon .alert {
text-shadow: rgba(0, 0, 0, 0.3) 0 1px 2px;
background: #333333;
color: #ff3c00;
font-size: 0.7em;
margin-top: -3px;
top: 0;
right: auto;
bottom: auto;
left: 9px;
height: auto;
width: auto;
position: absolute;
z-index: 2; }
/* line 54, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .title-label {
overflow: hidden;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
width: auto;
height: auto;
display: block;
left: 25px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; }
/* line 66, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading {
pointer-events: none; }
/* line 68, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading .label {
opacity: 0.5; }
/* line 70, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading .label .title-label {
font-style: italic; }
/* line 74, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading .wait-spinner {
margin-left: 14px; }
/* line 79, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.selected {
background: #005177;
color: white; }
/* line 83, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.selected .view-control {
color: #0099cc; }
/* line 86, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.selected .label .type-icon {
color: #fff; }
/* line 92, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.selected):hover {
background: #404040;
color: #cccccc; }
/* line 29, ../sass/tree/_tree.scss */
ul.tree li .tree-item:not(.loading):hover .context-trigger {
/* line 95, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.selected):hover .context-trigger {
display: block; }
/* line 32, ../sass/tree/_tree.scss */
ul.tree li .tree-item:not(.loading):hover .icon {
/* line 98, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.selected):hover .icon {
color: #33ccff; }
/* line 37, ../sass/tree/_tree.scss */
ul.tree li .tree-item .selected {
color: #fff; }
/* line 40, ../sass/tree/_tree.scss */
ul.tree li .tree-item .view-control {
display: inline-block;
width: 10px; }
/* line 46, ../sass/tree/_tree.scss */
ul.tree li .tree-item .view-control:hover {
color: #ffc700; }
/* line 50, ../sass/tree/_tree.scss */
ul.tree li .tree-item .context-trigger {
display: none;
top: -1px;
position: absolute;
right: 3px; }
/* line 56, ../sass/tree/_tree.scss */
ul.tree li .tree-item .context-trigger .btn-invoke-menu {
font-size: 0.75em;
height: 0.9rem;
line-height: 0.9rem; }
/* line 62, ../sass/tree/_tree.scss */
ul.tree li .tree-item .icon {
text-shadow: rgba(0, 0, 0, 0.6) 0 1px 2px;
color: #0099cc;
left: 15px; }
/* line 67, ../sass/tree/_tree.scss */
ul.tree li .tree-item .icon .alert {
text-shadow: rgba(0, 0, 0, 0.3) 0 1px 2px;
background: #333333;
color: #ff3c00;
font-size: 0.7em;
margin-top: -3px;
top: 0;
right: auto;
bottom: auto;
left: 9px;
height: auto;
width: auto;
/* line 104, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.loading) {
cursor: pointer; }
/* line 109, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .context-trigger {
display: none;
top: -1px;
position: absolute;
z-index: 2; }
/* line 83, ../sass/tree/_tree.scss */
ul.tree li .tree-item .title-label {
display: block;
position: absolute;
top: 0;
left: 37px;
right: 0;
overflow: hidden;
text-overflow: ellipsis;
height: 1.5rem;
bottom: auto;
white-space: nowrap; }
/* line 99, ../sass/tree/_tree.scss */
right: 3px; }
/* line 115, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .context-trigger .btn-invoke-menu {
font-size: 0.75em;
height: 0.9rem;
line-height: 0.9rem; }
/* line 124, ../sass/tree/_tree.scss */
ul.tree ul.tree {
margin-left: 15px; }

View File

@ -2,7 +2,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg>
<metadata>
Created by FontForge 20110222 at Thu Feb 26 00:33:43 2015
Created by FontForge 20110222 at Thu Mar 19 18:28:43 2015
By deploy user
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
</metadata>
@ -72,8 +72,8 @@ d="M0 774l396 -397l-396 -396v793zM451 0v734h173v-734h-173z" />
d="M352 0l-352 367l352 368v-735z" />
<glyph glyph-name="greater" unicode="&#x3e;" horiz-adv-x="353"
d="M352 366l-352 -366v735z" />
<glyph glyph-name="A" unicode="A" horiz-adv-x="812"
d="M446 735l366 -368l-366 -367l-130 130l147 147h-156q-51 -76 -140 -76q-69 0 -118 48.5t-49 117.5t49 117.5t118 48.5q90 0 140 -75h156l-147 146zM167 295q30 0 51 21.5t21 50.5q0 30 -21 51.5t-51 21.5t-52 -21.5t-22 -51.5q0 -29 22.5 -50.5t51.5 -21.5z" />
<glyph glyph-name="A" unicode="A" horiz-adv-x="723"
d="M348 750q156 0 265.5 -109.5t109.5 -265.5q0 -155 -109.5 -265t-265.5 -110q-116 0 -210.5 65t-137.5 169h66q62 0 106 47h176l-141 -141h188l234 235l-234 234h-188l141 -140h-176q-43 48 -106 48h-66q43 104 137.5 168.5t210.5 64.5z" />
<glyph glyph-name="C" unicode="C"
d="M374 750q157 0 266.5 -109t109.5 -267q0 -155 -110 -264.5t-266 -109.5q-154 0 -264 110t-110 264q0 158 109.5 267t264.5 109zM558 281q7 14 3 29.5t-18 22.5l-131 68v260q0 36 -38 36q-16 0 -26 -9.5t-10 -26.5v-309l167 -85q9 -4 20 -4q22 0 33 18z" />
<glyph glyph-name="D" unicode="D" horiz-adv-x="811"
@ -83,9 +83,9 @@ d="M488 727q162 0 294.5 -100.5t194.5 -263.5q-63 -162 -195 -262.5t-294 -100.5q-16
<glyph glyph-name="F" unicode="F" horiz-adv-x="849"
d="M227 601q-41 0 -79 -26t-49 -61l-99 -317v255v95v164q0 20 14 34.5t34 14.5h234q22 0 37 -14.5t15 -34.5v-62h251q29 0 53 -13t35 -35h-446zM771 525q43 0 66 -25.5t12 -61.5l-111 -351q-11 -34 -49.5 -60.5t-80.5 -26.5h-486q-42 0 -65 26.5t-11 60.5l109 351
q12 36 51.5 61.5t82.5 25.5h482z" />
<glyph glyph-name="G" unicode="G" horiz-adv-x="724"
d="M658 381q0 -31 -3 -47l68 -72l-39 -68l-41 -69l-96 22q-44 -36 -79 -47l-26 -100h-161l-26 100q-25 8 -79 52l-100 -27l-38 69l-38 68l68 72q-4 16 -4 47q0 34 4 50l-68 69l76 136l100 -24q35 30 79 46l26 95h161l26 -95q43 -15 79 -46l96 24l41 -69l39 -67l-68 -69
q3 -16 3 -50zM361 224q66 0 113 45.5t47 111.5q0 65 -47 112.5t-113 47.5q-65 0 -112 -47.5t-47 -112.5q0 -66 46.5 -111.5t112.5 -45.5z" />
<glyph glyph-name="G" unicode="G" horiz-adv-x="749"
d="M749 328l-102 -25q-8 -32 -28 -69l54 -91l-66 -65l-91 54q-38 -21 -68 -28l-27 -104h-93l-25 104q-32 8 -69 28l-91 -54l-65 65l54 91q-20 37 -28 69l-104 25v93l104 27q7 30 28 68l-54 91l65 66l91 -54q37 20 69 28l25 102h93l27 -102q30 -7 68 -28l91 54l66 -66
l-54 -91q21 -38 28 -68l102 -27v-93zM515 374q0 58 -41.5 99.5t-99.5 41.5t-99 -41.5t-41 -99.5t41 -99t99 -41t99.5 41t41.5 99z" />
<glyph glyph-name="H" unicode="H" horiz-adv-x="774"
d="M0 0v700h180v-700h-180zM297 0v700h180v-700h-180zM594 192v508h180v-508h-180z" />
<glyph glyph-name="I" unicode="I" horiz-adv-x="853"
@ -115,8 +115,8 @@ d="M466 86q53 0 85 75.5t34 177.5h158q-12 -143 -118.5 -241t-251.5 -98q-147 0 -253
q2 58 13 103.5t24 66t24 20.5zM282 666q-54 0 -85 -73.5t-39 -179.5h-158q14 142 120.5 240t252.5 98q145 0 251.5 -98t118.5 -240h-341q-6 105 -37 179t-83 74z" />
<glyph glyph-name="U" unicode="U" horiz-adv-x="800"
d="M800 733l-396 -397l-397 397h793zM69 0q-29 0 -49 20t-20 49v123q0 29 20 49t49 20h671q28 0 48.5 -20.5t20.5 -48.5v-123q0 -28 -20.5 -48.5t-48.5 -20.5h-671z" />
<glyph glyph-name="V" unicode="V" horiz-adv-x="679"
d="M339 727l340 -236v-491h-340h-339v491zM339 255l252 176l-252 174l-252 -174z" />
<glyph glyph-name="V" unicode="V" horiz-adv-x="752"
d="M376 752l376 -235v-376q0 -57 -41.5 -99t-99.5 -42h-470q-57 0 -99 42t-42 99v376zM376 611l-263 -165l263 -164l264 164z" />
<glyph glyph-name="X" unicode="X" horiz-adv-x="753"
d="M471 471v-95h-95v-94h-94v94h-94v95h94v94h94v-94h95zM753 94l-94 -94l-149 149q-81 -55 -181 -55q-137 0 -232 97q-97 95 -97 233q0 137 97 232q95 97 232 97q138 0 233 -97q97 -95 97 -232q0 -100 -55 -181zM329 235q79 0 134 55t55 134q0 78 -55 133t-134 55
q-78 0 -133 -55t-55 -133q0 -79 55 -134t133 -55z" />
@ -137,8 +137,8 @@ d="M128 237l-61 61q-27 27 -27 67t27 67l271 271q28 28 69 28q39 0 67 -28l61 -60l-8
d="M394 492l393 -377h-787z" />
<glyph glyph-name="underscore" unicode="_" horiz-adv-x="807"
d="M807 603v-122h-143q-48 0 -82 33.5t-34 81.5v136h122v-129h137zM138 732h121v-136q0 -48 -34 -81.5t-81 -33.5h-144v122h138v129zM0 129v122h144q47 0 81 -34.5t34 -81.5v-135h-121v129h-138zM670 0h-122v135q0 47 34.5 81.5t81.5 34.5h143v-122h-137v-129z" />
<glyph glyph-name="a" unicode="a" horiz-adv-x="661"
d="M661 234h-278v-182l-52 -52l-54 52v182h-277q0 57 53 103t140 69v232q-81 36 -81 97h437q0 -61 -81 -97v-232q87 -23 140 -69t53 -103z" />
<glyph glyph-name="a" unicode="a" horiz-adv-x="723"
d="M407 691l316 -316l-316 -316h-180l224 226h-203q-24 -41 -66 -65.5t-92 -24.5h-90v361h90q51 0 93 -24t65 -66h203l-224 225h180z" />
<glyph glyph-name="c" unicode="c" horiz-adv-x="800"
d="M558 556q0 -9 -6.5 -15t-14.5 -6h-516q-9 0 -15 6t-6 15v149q0 9 6 15t15 6h516q8 0 14.5 -6t6.5 -15v-149zM779 458q9 0 15 -6t6 -15v-148q0 -9 -6 -15t-15 -6h-582q-8 0 -14 6t-6 15v148q0 9 6 15t14 6h582zM656 191q9 0 15 -6t6 -15v-149q0 -9 -6 -15t-15 -6h-549
q-8 0 -14.5 6t-6.5 15v149q0 9 6.5 15t14.5 6h549z" />
@ -199,6 +199,8 @@ d="M0 0l131 262l-131 262h91l132 -262l-132 -262h-91z" />
<glyph glyph-name="asciitilde" unicode="~" horiz-adv-x="799"
d="M658 363h141q-36 -150 -70 -227q-28 -58 -58 -88q-45 -46 -102 -48h-7q-55 0 -98 40q-34 31 -60 86q-35 72 -71 222q-35 137 -61 194q-9 18 -17.5 30t-12.5 15t-6 3q-3 0 -8 -4t-14.5 -18t-19.5 -35q-28 -62 -53 -170h-141q36 152 70 227q25 57 58 88q41 42 102 49
q57 2 105 -40q33 -31 60 -86q34 -73 70 -222q36 -140 62 -194q9 -18 17.5 -30t12.5 -15.5t5 -3.5q15 0 42 57q30 66 54 170z" />
<glyph glyph-name="Aring" unicode="&#xc5;" horiz-adv-x="500"
/>
<glyph glyph-name="agrave" unicode="&#xe0;" horiz-adv-x="753"
d="M752 141q0 -59 -41 -100t-100 -41h-470q-59 0 -100 41t-41 100v470q0 59 41 100t100 41h470q59 0 100 -41t41 -100v-470z" />
<glyph glyph-name="aacute" unicode="&#xe1;"
@ -213,6 +215,13 @@ d="M0 750h750v-94v-47v-47h-94v47h-187v-515h140v-94h-468v94h140v515h-187v-47h-94v
d="M656 750q39 0 66.5 -27.5t27.5 -66.5v-562q0 -39 -27.5 -66.5t-66.5 -27.5h-562q-39 0 -66.5 27.5t-27.5 66.5v562q0 39 27.5 66.5t66.5 27.5h562zM94 656v-562h234v562h-234zM656 94v562h-234v-562h234z" />
<glyph glyph-name="ccedilla" unicode="&#xe7;"
d="M656 750q39 0 66.5 -27.5t27.5 -66.5v-562q0 -39 -27.5 -66.5t-66.5 -27.5h-562q-39 0 -66.5 27.5t-27.5 66.5v562q0 39 27.5 66.5t66.5 27.5h562zM656 94v562h-234v-562h234z" />
<glyph glyph-name="egrave" unicode="&#xe8;" horiz-adv-x="754"
d="M703 703q47 -48 47 -116t-47 -117l-94 -94q-48 -48 -117 -48q-41 0 -84 24l-8 -9q28 -47 21.5 -104t-46.5 -97l-94 -94q-48 -48 -117 -48q-68 0 -116 48q-47 49 -47 117t47 116l94 94q47 47 115 47q47 0 85 -22l9 9q-28 47 -21.5 103.5t46.5 96.5l94 94q47 47 116 47
q70 0 117 -47zM307 209q26 25 21 62l-41 -41q-14 -12 -30 -12q-15 0 -27 12q-12 10 -12 28t12 29l41 41h-14q-28 0 -48 -20l-94 -94q-20 -20 -20 -49t20 -49q21 -22 49 -22q29 0 50 22zM635 538q21 20 21 49t-21 49q-20 20 -49 20t-49 -20l-94 -94q-25 -24 -20 -62l41 41
q10 12 28 12t29 -12q12 -12 12 -29q0 -14 -12 -28l-41 -41q3 0 7 -0.5t5 -0.5q29 0 50 22z" />
<glyph glyph-name="eacute" unicode="&#xe9;"
d="M188 235h-160q-28 67 -28 140q0 156 110 265.5t265 109.5q88 0 164 -37t129 -103h-105q-39 0 -66.5 -27.5t-27.5 -66.5v-92v-2h-188q-39 0 -66 -27t-27 -67v-92v-1zM564 516h160q26 -62 26 -141q0 -155 -109.5 -265t-265.5 -110q-86 0 -162.5 38t-128.5 103h104
q39 0 66 27.5t27 66.5v93h2h186q39 0 66.5 27.5t27.5 66.5v94h1z" />
<glyph glyph-name="fraction" unicode="&#x2044;" horiz-adv-x="761"
d="M380 751q158 0 269.5 -111.5t111.5 -268.5q0 -133 -82.5 -236.5t-209.5 -134.5l-4 491l-176 -490q-126 31 -207.5 134.5t-81.5 235.5q0 157 111.5 268.5t268.5 111.5zM168 488l55 20l-34 94l-56 -20zM410 530v100h-59v-100h59zM593 488l34 94l-55 20l-34 -94z" />
<glyph glyph-name="H.002" horiz-adv-x="803"

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -58,7 +58,7 @@ $colorItemSelected: $colorKey;
// Tree
$treeVCW: 10px;
$treeTypeIconW: 17px;
$treeTypeIconW: 20px;
$treeContextTriggerW: 20px;
$colorItemTreeIcon: $colorKey;
$colorItemTreeIconHover: lighten($colorItemTreeIcon, 20%);

View File

@ -14,13 +14,6 @@
height: 100%; width: 100%;
pointer-events: none;
z-index: 0;
&.l-grid-x {
@include bgTicks($colorGridLines, 'x');
}
&.l-grid-y {
@include bgTicks($colorGridLines, 'y');
}
}
}
}
@ -51,7 +44,7 @@
.l-fixed-position-image {
background-size: cover;
background-repeat: no-repeat;
background-position: left top;
background-position: center;
}
.l-fixed-position-text {
@ -99,6 +92,20 @@
}
.edit-mode .t-fixed-position {
&.l-fixed-position {
.l-grid-holder {
.l-grid {
&.l-grid-x {
@include bgTicks($colorGridLines, 'x');
}
&.l-grid-y {
@include bgTicks($colorGridLines, 'y');
}
}
}
}
.l-fixed-position-item {
&:not(.s-selected):hover {
border: 1px dotted rgba($colorKey, 0.5);

View File

@ -144,7 +144,7 @@
.btn-set,
.t-btn {
display: inline-block;
margin-left: $interiorMargin;
// margin-left: $interiorMargin;
}
.btn,
.t-btn {
@ -163,11 +163,12 @@
}
}
.control-group {
.l-control-group {
// Buttons that have a conceptual grouping - internal space between, and a divider between groups.
// @include test();
@include box-sizing(border-box);
border-left: 1px solid $colorInteriorBorder;
display: inline-block;
padding: 0 $interiorMargin;
position: relative;
&:first-child {
@ -295,7 +296,7 @@ label.checkbox.custom {
.btn-menu {
$h: 20px;
$p: $interiorMargin;
$p: $interiorMargin * 2;
$c: $colorBodyFg;
@include btnSubtle($colorBodyBg);
height: $h;

View File

@ -6,4 +6,13 @@
li {
margin-bottom: $interiorMargin;
}
}
.l-tree-item-flat-list {
// For lists of tree-items that are flat. Remove margin, etc. normally needed for the expansion arrow.
.tree-item {
.label {
left: $interiorMargin !important;
}
}
}

View File

@ -68,13 +68,13 @@
input.filter {
$h: $ueTopBarH;
$ip: 10px;
font-size: .8em;
font-size: .9em;
height: $h;
line-height: $h;
margin-right: $interiorMargin;
margin-top: -5px;
padding-left: $ip;
padding-right: $ip;
vertical-align: top;
}
.icon-filter {
font-size: 1.4em;

View File

@ -1,102 +1,127 @@
ul.tree {
@include menuUlReset();
li {
.tree-item {
// @include test();
@include border-radius($basicCr);
@include single-transition(background-color, 0.25s);
display: block;
font-size: 0.80rem;
height: $menuLineH;
line-height: $menuLineH;
margin-bottom: $interiorMarginSm;
// overflow: hidden;
// padding: 2px 4px 2px 7px;
position: relative;
// white-space: nowrap;
&.loading {
color: darken($colorBodyFg, 20%);
font-style: italic;
.wait-spinner {
margin-left: 14px;
}
}
&:not(.loading) {
cursor: pointer;
&:hover {
background: lighten($colorBodyBg, 5%);
color: lighten($colorBodyFg, 20%);
.context-trigger {
display: block;
}
.icon {
color: $colorItemTreeIconHover;
}
}
}
.selected {
color: #fff;
}
.view-control {
// @include test();
display: inline-block;
// margin-right: $interiorMargin;
// vertical-align: middle;
width: $treeVCW;
&:hover {
color: $colorItemTreeVCHover;
}
}
.context-trigger {
$h: 0.9rem;
display: none;
top: -1px;
position: absolute;
right: $interiorMarginSm;
.btn-invoke-menu {
font-size: 0.75em;
height: $h;
line-height: $h;
}
}
.icon {
// @include test();
@include txtShdwSubtle(0.6);
color: $colorItemTreeIcon;
left: $treeVCW + $interiorMargin;
.alert {
@include txtShdwSubtle(0.3);
background: $colorBodyBg;
color: $colorAlert;
font-size: 0.7em;
margin-top: -3px;
top: 0;
right: auto;
bottom: auto;
left: 9px;
height: auto;
width: auto;
position: absolute;
z-index: 2;
}
}
.title-label {
// @include test();
display: block;
position: absolute;
top: 0;
left: $treeVCW + $treeTypeIconW + ($interiorMargin * 2); //38px;
// right: $treeContextTriggerW + $interiorMargin; //Disabling as context trigger not being used
right: 0;
overflow: hidden;
text-overflow: ellipsis;
height: $menuLineH;
bottom: auto;
white-space: nowrap;
}
}
}
ul.tree {
margin-left: $treeVCW + $interiorMargin;
}
@include menuUlReset();
li {
display: block;
position: relative;
span.tree-item {
$runningItemW: 0;
@include border-radius($basicCr);
@include single-transition(background-color, 0.25s);
display: block;
font-size: 0.80rem;
height: $menuLineH;
line-height: $menuLineH;
margin-bottom: $interiorMarginSm;
position: relative;
.view-control {
display: inline-block;
margin-left: $interiorMargin;
// vertical-align: middle;
width: $treeVCW;
$runningItemW: $interiorMargin + $treeVCW;
&:hover {
color: $colorItemTreeVCHover;
}
}
.label {
display: block;
// border: 1px solid rgba(blue, 0.5);
@include absPosDefault();
left: $runningItemW + $interiorMargin;
.type-icon {
@include absPosDefault();
@include txtShdwSubtle(0.6);
color: $colorItemTreeIcon;
.alert {
@include txtShdwSubtle(0.3);
background: $colorBodyBg;
color: $colorAlert;
font-size: 0.7em;
margin-top: -3px;
top: 0;
right: auto;
bottom: auto;
left: 9px;
height: auto;
width: auto;
position: absolute;
z-index: 2;
}
}
.title-label {
@include absPosDefault();
display: block;
left: $runningItemW + ($interiorMargin * 2);
// right: $treeContextTriggerW + $interiorMargin; //Disabling as context trigger not being used
overflow: hidden;
text-overflow: ellipsis;
// height: $menuLineH;
white-space: nowrap;
}
}
&.loading {
pointer-events: none;
.label {
opacity: 0.5;
.title-label {
font-style: italic;
}
}
.wait-spinner {
margin-left: 14px;
}
}
&.selected {
$c: #fff;
background: #005177;
color: $c;
.view-control {
color: $colorItemTreeIcon;
}
.label .type-icon {
color: #fff; //$colorItemTreeIconHover;
}
}
&:not(.selected) {
&:hover {
background: lighten($colorBodyBg, 5%);
color: lighten($colorBodyFg, 20%);
.context-trigger {
display: block;
}
.icon {
color: $colorItemTreeIconHover;
}
}
}
&:not(.loading) {
cursor: pointer;
// @include tree-item-hover();
}
.context-trigger {
$h: 0.9rem;
display: none;
top: -1px;
position: absolute;
right: $interiorMarginSm;
.btn-invoke-menu {
font-size: 0.75em;
height: $h;
line-height: $h;
}
}
}
}
ul.tree {
margin-left: $treeVCW + $interiorMargin;
}
}

View File

@ -33,7 +33,7 @@
.tool-bar {
bottom: auto;
height: $tbH;
line-height: $tbH - 2;
line-height: $ueEditToolBarButtonH;
}
.work-area {
top: $tbH + $interiorMargin * 2;

View File

@ -1,7 +1,7 @@
.tool-bar {
border-bottom: 1px solid $colorInteriorBorder;
.control-group {
height: $ueEditToolBarH;
.l-control-group {
height: $ueEditToolBarButtonH;
}
input[type="text"] {
@include box-sizing(border-box);

View File

@ -13,7 +13,7 @@
Showing {{shown}} of {{count}} available options.
</div -->
<div class='line treeview checkbox-list' name='available'>
<div class='line treeview' name='available'>
<mct-representation key="'tree'"
mct-object="selector.root()"
ng-model="selector.treeModel">
@ -46,15 +46,20 @@
Showing {{shown}} of {{count}} available options.
</div -->
<div class='line treeview checkbox-list' name='selected'>
<div class='line treeview l-tree-item-flat-list' name='selected'>
<ul class="tree">
<li ng-repeat="selectedObject in selector.selected()">
<mct-representation key="'label'"
mct-object="selectedObject"
ng-click="selector.listModel.selectedObject = selectedObject"
ng-class="{ test: selector.listModel.selectedObject === selectedObject }">
<span
class="tree-item"
ng-class="{selected: selector.listModel.selectedObject === selectedObject }"
>
<mct-representation
key="'label'"
mct-object="selectedObject"
ng-click="selector.listModel.selectedObject = selectedObject"
>
</mct-representation>
</span>
</li>
</ul>
</div>

View File

@ -1,4 +1,4 @@
<span class="label">
<span class="label s-label">
<span class='ui-symbol icon type-icon'>
{{type.getGlyph()}}
<span class='ui-symbol icon alert hidden'>!</span>

View File

@ -0,0 +1,14 @@
<ul class="tree">
<li ng-if="!composition">
<span class="tree-item">
<span class="icon wait-spinner"></span>
<span class="title-label">Loading...</span>
</span>
</li>
<li ng-repeat="child in composition">
<mct-representation key="'tree-node'"
mct-object="child"
ng-model="ngModel">
</mct-representation>
</li>
</ul>

View File

@ -1,23 +1,31 @@
<span ng-controller="ToggleController as toggle">
<span ng-controller="TreeNodeController as treeNode">
<span class="tree-item menus-to-left">
<span class='ui-symbol view-control'
ng-click="toggle.toggle(); treeNode.trackExpansion()"
ng-if="model.composition !== undefined">
<span
class="tree-item menus-to-left"
ng-class="{selected: treeNode.isSelected()}"
>
<span
class='ui-symbol view-control'
ng-click="toggle.toggle(); treeNode.trackExpansion()"
ng-if="model.composition !== undefined"
>
{{toggle.isActive() ? "v" : ">"}}
</span>
<mct-representation key="'label'"
mct-object="domainObject"
ng-model="ngModel"
ng-click="ngModel.selectedObject = domainObject"
ng-class="{selected: treeNode.isSelected()}">
<mct-representation
key="'label'"
mct-object="domainObject"
ng-model="ngModel"
ng-click="ngModel.selectedObject = domainObject"
>
</mct-representation>
</span>
<span class="tree-item-subtree"
ng-show="toggle.isActive()"
ng-if="model.composition !== undefined">
<span
class="tree-item-subtree"
ng-show="toggle.isActive()"
ng-if="model.composition !== undefined"
>
<mct-representation key="'tree'"
<mct-representation key="'subtree'"
ng-model="ngModel"
mct-object="treeNode.hasBeenExpanded() && domainObject">
</mct-representation>

View File

@ -1,13 +1,7 @@
<ul class="tree">
<li ng-if="!composition">
<span class="tree-item">
<span class="icon wait-spinner"></span>
<span class="title-label">Loading...</span>
</span>
</li>
<li ng-repeat="child in composition">
<li>
<mct-representation key="'tree-node'"
mct-object="child"
mct-object="domainObject"
ng-model="ngModel">
</mct-representation>
</li>

View File

@ -115,6 +115,11 @@
}
]
},
{
"key": "root",
"name": "Root",
"glyph": "F"
},
{
"key": "folder",
"name": "Folder",
@ -157,8 +162,7 @@
},
{
"key": "mutation",
"implementation": "capabilities/MutationCapability.js",
"depends": [ "$q" ]
"implementation": "capabilities/MutationCapability.js"
},
{
"key": "delegation",

View File

@ -76,7 +76,12 @@ define(
* object which exposed this capability.
*/
getRoot: function () {
return this.getPath()[0];
var parentContext = parentObject &&
parentObject.getCapability('context');
return parentContext ?
parentContext.getRoot() :
(parentObject || domainObject);
}
};
}

View File

@ -21,6 +21,16 @@ define(
});
}
// Utility function to cast to a promise, without waiting
// for nextTick if a value is non-promise-like.
function fastPromise(value) {
return (value || {}).then ? value : {
then: function (callback) {
return fastPromise(callback(value));
}
};
}
/**
* The `mutation` capability allows a domain object's model to be
* modified. Wrapping such modifications in calls made through
@ -36,12 +46,11 @@ define(
* });
* ```
*
* @param $q Angular's $q service, for promises
* @param {DomainObject} domainObject the domain object
* which will expose this capability
* @constructor
*/
function MutationCapability($q, domainObject) {
function MutationCapability(domainObject) {
function mutate(mutator) {
// Get the object's model and clone it, so the
@ -73,8 +82,7 @@ define(
// Invoke the provided mutator, then make changes to
// the underlying model (if applicable.)
return $q.when(mutator(clone))
.then(handleMutation);
return fastPromise(mutator(clone)).then(handleMutation);
}
return {

View File

@ -28,6 +28,7 @@ define(
function addRoot(models) {
models.ROOT = {
name: "The root object",
type: "root",
composition: ids
};
return models;

View File

@ -13,21 +13,9 @@ define(
domainObject = { getModel: function () { return testModel; } },
mutation;
function mockPromise(value) {
return {
then: function (callback) {
return (value && value.then) ?
value : mockPromise(callback(value));
}
};
}
beforeEach(function () {
testModel = { number: 6 };
mutation = new MutationCapability(
{ when: mockPromise }, // $q
domainObject
);
mutation = new MutationCapability(domainObject);
});
it("allows mutation of a model", function () {

View File

@ -112,7 +112,7 @@
},
{
"property": "text",
"glyph": "p",
"glyph": "G",
"control": "dialog-button",
"title": "Text Properties",
"dialog": {
@ -221,12 +221,6 @@
],
"key": "layoutGrid",
"conversion": "number[]"
},
{
"label": "Panel(s)",
"control": "selector",
"type": "telemetry.panel",
"key": "somethingElse"
}
]
},

View File

@ -1,4 +1,4 @@
<a class="t-btn l-btn s-btn s-icon-btn s-very-subtle xxx"
<a class="t-btn l-btn s-btn s-icon-btn s-very-subtle"
ng-class="{ labeled: structure.text }"
ng-click="structure.click()">
<span class="ui-symbol icon">

View File

@ -1,7 +1,7 @@
<form novalidate>
<div class="tool-bar btn-bar contents abs">
<span ng-repeat="section in structure.sections"
class="control-group"
class="l-control-group"
ng-if="!section.hidden"
title="{{section.description}}">
<ng-form ng-repeat="item in section.items"

View File

@ -16,7 +16,7 @@
{
"key": "drag",
"implementation": "gestures/DragGesture.js",
"depends": [ "$log" ]
"depends": [ "$log", "dndService" ]
},
{
"key": "drop",
@ -42,6 +42,13 @@
"implementation": "gestures/GestureRepresenter.js",
"depends": [ "gestureService" ]
}
],
"services": [
{
"key": "dndService",
"implementation": "services/DndService.js",
"depends": [ "$log" ]
}
]
}
}

View File

@ -32,25 +32,43 @@ define(
* @param {ViewDefinition[]} views an array of view extensions
*/
function MCTRepresentation(representations, views, representers, $q, $log) {
var pathMap = {},
representationMap = {},
var representationMap = {},
gestureMap = {};
// Assemble all representations and views
// The distinction between views and representations is
// not important her (view is-a representation)
// not important here (view is-a representation)
representations.concat(views).forEach(function (representation) {
var path = [
var key = representation.key;
// Store the representation
representationMap[key] = representationMap[key] || [];
representationMap[representation.key].push(representation);
});
// Get a path to a representation
function getPath(representation) {
return [
representation.bundle.path,
representation.bundle.resources,
representation.templateUrl
].join("/");
}
// Consider allowing multiple templates with the same key
pathMap[representation.key] = path;
representationMap[representation.key] = representation;
});
// Look up a matching representation for this domain object
function lookup(key, domainObject) {
var candidates = representationMap[key] || [],
type,
i;
// Filter candidates by object type
for (i = 0; i < candidates.length; i += 1) {
type = candidates[i].type;
if (!type || !domainObject ||
domainObject.getCapability('type').instanceOf(type)) {
return candidates[i];
}
}
}
function link($scope, element, attrs) {
var activeRepresenters = representers.map(function (Representer) {
@ -60,8 +78,8 @@ define(
// Populate scope with any capabilities indicated by the
// representation's extension definition
function refreshCapabilities() {
var representation = representationMap[$scope.key],
domainObject = $scope.domainObject,
var domainObject = $scope.domainObject,
representation = lookup($scope.key, domainObject),
uses = ((representation || {}).uses || []);
if (domainObject) {
@ -89,8 +107,8 @@ define(
// as appropriate for current representation key and
// domain object.
function refresh() {
var representation = representationMap[$scope.key],
domainObject = $scope.domainObject,
var domainObject = $scope.domainObject,
representation = lookup($scope.key, domainObject),
uses = ((representation || {}).uses || []),
gestureKeys = ((representation || {}).gestures || []);
@ -100,7 +118,7 @@ define(
// Look up the actual template path, pass it to ng-include
// via the "inclusion" field
$scope.inclusion = pathMap[$scope.key];
$scope.inclusion = representation && getPath(representation);
// Any existing gestures are no longer valid; release them.
activeRepresenters.forEach(function (activeRepresenter) {

View File

@ -19,7 +19,7 @@ define(
* @param {DomainObject} domainObject the domain object which
* is represented; this will be passed on drop.
*/
function DragGesture($log, element, domainObject) {
function DragGesture($log, dndService, element, domainObject) {
function startDrag(e) {
var event = (e || {}).originalEvent || e;
@ -45,6 +45,19 @@ define(
domainObject.getId()
);
// Finally, also pass the id object instance via the
// dndService, allowing inspection during drag as well
// as retrieval of the original domain object.
dndService.setData(
GestureConstants.MCT_EXTENDED_DRAG_TYPE,
domainObject
);
dndService.setData(
GestureConstants.MCT_DRAG_TYPE,
domainObject.getId()
);
} catch (err) {
// Exceptions at this point indicate that the browser
// do not fully support drag-and-drop (e.g. if
@ -57,10 +70,17 @@ define(
}
function endDrag() {
// Clear the drag data after the drag is complete
dndService.removeData(GestureConstants.MCT_DRAG_TYPE);
dndService.removeData(GestureConstants.MCT_EXTENDED_DRAG_TYPE);
}
// Mark the element as draggable, and handle the dragstart event
$log.debug("Attaching drag gesture");
element.attr('draggable', 'true');
element.on('dragstart', startDrag);
element.on('dragend', endDrag);
return {
/**

View File

@ -10,6 +10,12 @@ define({
* calls.)
*/
MCT_DRAG_TYPE: 'mct-domain-object-id',
/**
* The string identifier for the data type used for drag-and-drop
* composition of domain objects, by object instance (passed through
* the dndService)
*/
MCT_EXTENDED_DRAG_TYPE: 'mct-domain-object',
/**
* An estimate for the dimensions of a context menu, used for
* positioning.

View File

@ -0,0 +1,50 @@
/*global define*/
define(
[],
function () {
"use strict";
/**
* Drag-and-drop service.
* Supplements HTML5 drag-and-drop support by:
* * Storing arbitrary JavaScript objects (not just strings.)
* * Allowing inspection of dragged objects during `dragover` events,
* etc. (which cannot be done in Chrome for security reasons)
* @constructor
* @param $log Angular's $log service
*/
function DndService($log) {
var data = {};
return {
/**
* Set drag data associated with a given type.
* @param {string} key the type's identiifer
* @param {*} value the data being dragged
*/
setData: function (key, value) {
$log.debug("Setting drag data for " + key);
data[key] = value;
},
/**
* Get drag data associated with a given type.
* @returns {*} the data being dragged
*/
getData: function (key) {
return data[key];
},
/**
* Remove data associated with active drags.
* @param {string} key the type to remove
*/
removeData: function (key) {
$log.debug("Clearing drag data for " + key);
delete data[key];
}
};
}
return DndService;
}
);

View File

@ -10,6 +10,7 @@ define(
var JQLITE_FUNCTIONS = [ "on", "off", "attr", "removeAttr" ],
LOG_FUNCTIONS = [ "error", "warn", "info", "debug"],
DND_FUNCTIONS = [ "setData", "getData", "removeData" ],
DOMAIN_OBJECT_METHODS = [ "getId", "getModel", "getCapability", "hasCapability", "useCapability"],
TEST_ID = "test-id";
@ -17,14 +18,16 @@ define(
describe("The drag gesture", function () {
var mockLog,
mockDndService,
mockElement,
mockDomainObject,
mockDataTransfer,
gesture,
fireGesture;
handlers,
gesture;
beforeEach(function () {
mockLog = jasmine.createSpyObj("$log", LOG_FUNCTIONS);
mockDndService = jasmine.createSpyObj("dndService", DND_FUNCTIONS);
mockElement = jasmine.createSpyObj("element", JQLITE_FUNCTIONS);
mockDomainObject = jasmine.createSpyObj("domainObject", DOMAIN_OBJECT_METHODS);
mockDataTransfer = jasmine.createSpyObj("dataTransfer", ["setData"]);
@ -32,12 +35,18 @@ define(
mockDomainObject.getId.andReturn(TEST_ID);
mockDomainObject.getModel.andReturn({});
gesture = new DragGesture(mockLog, mockElement, mockDomainObject);
fireGesture = mockElement.on.mostRecentCall.args[1];
handlers = {};
gesture = new DragGesture(mockLog, mockDndService, mockElement, mockDomainObject);
// Look up all handlers registered by the gesture
mockElement.on.calls.forEach(function (call) {
handlers[call.args[0]] = call.args[1];
});
});
it("listens for dragstart on the element", function () {
expect(mockElement.on.mostRecentCall.args[0]).toEqual("dragstart");
expect(handlers.dragstart).toEqual(jasmine.any(Function));
});
it("marks an element as draggable", function () {
@ -45,19 +54,48 @@ define(
});
it("places data in a dataTransfer object", function () {
fireGesture({ dataTransfer: mockDataTransfer });
handlers.dragstart({ dataTransfer: mockDataTransfer });
expect(mockDataTransfer.setData).toHaveBeenCalledWith(
GestureConstants.MCT_DRAG_TYPE,
TEST_ID
);
});
it("places domain object in the dnd service", function () {
handlers.dragstart({ dataTransfer: mockDataTransfer });
expect(mockDndService.setData).toHaveBeenCalledWith(
GestureConstants.MCT_DRAG_TYPE,
TEST_ID
);
expect(mockDndService.setData).toHaveBeenCalledWith(
GestureConstants.MCT_EXTENDED_DRAG_TYPE,
mockDomainObject
);
});
it("clears domain object from the dnd service on drag end", function () {
// Start dragging
handlers.dragstart({ dataTransfer: mockDataTransfer });
// Verify precondition
expect(mockDndService.removeData).not.toHaveBeenCalled();
// End the drag
handlers.dragend({ dataTransfer: mockDataTransfer });
// Should have removed the data that was attached
expect(mockDndService.removeData)
.toHaveBeenCalledWith(GestureConstants.MCT_DRAG_TYPE);
expect(mockDndService.removeData)
.toHaveBeenCalledWith(GestureConstants.MCT_EXTENDED_DRAG_TYPE);
});
it("logs a warning if dataTransfer cannot be set", function () {
// Verify precondition
expect(mockLog.warn).not.toHaveBeenCalled();
// Fire the gesture without a dataTransfer field
fireGesture({});
handlers.dragstart({});
// Should have logged a warning
expect(mockLog.warn).toHaveBeenCalled();
@ -73,7 +111,7 @@ define(
// Verify that attribute/listener were removed
expect(mockElement.removeAttr).toHaveBeenCalledWith("draggable");
expect(mockElement.off).toHaveBeenCalledWith("dragstart", fireGesture);
expect(mockElement.off).toHaveBeenCalledWith("dragstart", handlers.dragstart);
});
});

View File

@ -0,0 +1,45 @@
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
define(
["../../src/services/DndService"],
function (DndService) {
"use strict";
describe("The drag-and-drop service", function () {
var service;
beforeEach(function () {
var mockLog = jasmine.createSpyObj("$log", ['debug']);
service = new DndService(mockLog);
});
it("allows setting of arbitrary objects", function () {
var foo = {
bar: function () { return 42; }
};
service.setData('xyz', foo);
// Test that we can get back callable data, since this is
// a key reason for having a service separate from HTML5 DnD.
expect(service.getData('xyz').bar()).toEqual(42);
});
it("stores data under specified keys", function () {
service.setData('abc', 42);
service.setData('def', "some data");
expect(service.getData('abc')).toEqual(42);
expect(service.getData('def')).toEqual("some data");
});
it("removes data", function () {
service.setData('abc', 42);
service.removeData('abc');
expect(service.getData('abc')).toBeUndefined();
});
});
}
);

View File

@ -4,6 +4,7 @@
"gestures/DropGesture",
"gestures/GestureProvider",
"gestures/GestureRepresenter",
"services/DndService",
"MCTInclude",
"MCTRepresentation"
]

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>gov.nasa.arc.wtd</groupId>
<artifactId>open-mct-web</artifactId>
<version>0.6.0-SNAPSHOT</version>
<version>0.6.1-SNAPSHOT</version>
<name>Open MCT Web</name>
<packaging>war</packaging>