mirror of
https://github.com/nasa/openmct.git
synced 2025-06-24 18:25:19 +00:00
Compare commits
46 Commits
master
...
layout-iss
Author | SHA1 | Date | |
---|---|---|---|
728faea4ce | |||
59db676fd8 | |||
f89c74dfa3 | |||
60ece16c33 | |||
7dd7421890 | |||
6d6124820d | |||
1b334086b6 | |||
d725e30481 | |||
5b26264409 | |||
8466ba51a0 | |||
c2ed84d7ca | |||
425fbc91e2 | |||
3dd36e7ce8 | |||
9925c2dd38 | |||
0239faa9a8 | |||
e802b5344c | |||
b5f196ede8 | |||
dbc7c910cc | |||
0acf8d9edc | |||
af5d42da1e | |||
4dff369807 | |||
eb999ad37b | |||
36a0976e98 | |||
cbc2555687 | |||
e040abc329 | |||
d5ca720eff | |||
d605b2ce43 | |||
d895b47bc6 | |||
33efe77172 | |||
bbd5dfe335 | |||
71a1b46d69 | |||
d86ce9794e | |||
c2d2cbfa1e | |||
f384ca3f53 | |||
ce858ca598 | |||
6df5de9cce | |||
9f59b1920b | |||
f778f73bfc | |||
63579668bd | |||
9087147dda | |||
0d61d70b8c | |||
e1e2fc5bcd | |||
5a3b98c731 | |||
df01646954 | |||
a986ddddcc | |||
c8eba1fbad |
@ -28,8 +28,4 @@
|
||||
key="'menu-arrow'"
|
||||
mct-object='domainObject'
|
||||
class="flex-elem context-available-w"></mct-representation>
|
||||
</span>
|
||||
<a class="s-button icon-expand t-btn-view-large"
|
||||
title="View large"
|
||||
mct-trigger-modal>
|
||||
</a>
|
||||
</span>
|
@ -21,32 +21,11 @@
|
||||
*****************************************************************************/
|
||||
.t-fixed-position {
|
||||
&.l-fixed-position {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
||||
.l-grid-holder {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.l-grid {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
@extend .abs;
|
||||
}
|
||||
|
||||
.l-fixed-position-item {
|
||||
position: absolute;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&.s-not-selected {
|
||||
opacity: 0.8;
|
||||
}
|
||||
@ -105,37 +84,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-fixed-position-item-handle {
|
||||
$brd: 1px solid $colorKey;
|
||||
background: rgba($colorKey, 0.5);
|
||||
cursor: crosshair;
|
||||
border: $brd;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.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) {
|
||||
border: 1px dotted rgba($colorKey, 0.75);
|
||||
&:hover {
|
||||
border: 1px dotted rgba($colorKey, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
.s-status-editing {
|
||||
.l-fixed-position-item-handle.edit-corner { display: block; }
|
||||
}
|
||||
|
@ -704,11 +704,6 @@ textarea {
|
||||
}
|
||||
}
|
||||
|
||||
.view-switcher,
|
||||
.t-btn-view-large {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
}
|
||||
|
||||
/******************************************************** BROWSER ELEMENTS */
|
||||
body.desktop {
|
||||
::-webkit-scrollbar {
|
||||
|
@ -19,12 +19,24 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.s-status-editing .l-object-wrapper,
|
||||
.edit-main {
|
||||
// .s-status-editing .l-object-wrapper is relevant to New Edit Mode;
|
||||
// .edit-main is legacy for old edit mode.
|
||||
$handleD: 15px;
|
||||
$cr: 5px;
|
||||
.t-edit-handle-holder { display: none; }
|
||||
|
||||
.l-grid-holder {
|
||||
display: none;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.l-grid {
|
||||
@extend .abs;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
&.l-grid-y { background-position: 0 1px; }
|
||||
}
|
||||
}
|
||||
|
||||
.s-status-editing {
|
||||
$handleD: 5px;
|
||||
.t-edit-handle-holder { display: block; }
|
||||
.edit-corner,
|
||||
.edit-handle {
|
||||
position: absolute;
|
||||
@ -32,81 +44,59 @@
|
||||
}
|
||||
|
||||
.edit-corner {
|
||||
background: rgba($colorSelectableSelectedPrimary, 0.5);
|
||||
cursor: crosshair;
|
||||
display: none; // Hide by default
|
||||
border: 1px solid $colorSelectableSelectedPrimary;
|
||||
width: $handleD;
|
||||
height: $handleD;
|
||||
$o: (-1 * $handleD) + 1px;
|
||||
&:hover {
|
||||
z-index: 11;
|
||||
}
|
||||
&.edit-resize-nw {
|
||||
border-bottom-right-radius: $cr;
|
||||
cursor: nw-resize;
|
||||
top: 0; left: 0;
|
||||
}
|
||||
&.edit-resize-ne {
|
||||
border-bottom-left-radius: $cr;
|
||||
cursor: ne-resize;
|
||||
top: 0; right: 0;
|
||||
}
|
||||
&.edit-resize-se {
|
||||
border-top-left-radius: $cr;
|
||||
cursor: se-resize;
|
||||
bottom: 0; right: 0;
|
||||
}
|
||||
&.edit-resize-sw {
|
||||
border-top-right-radius: $cr;
|
||||
cursor: sw-resize;
|
||||
bottom: 0; left: 0;
|
||||
}
|
||||
|
||||
&.edit-resize-nw { top: $o; left: $o; }
|
||||
&.edit-resize-ne { top: $o; right: $o; }
|
||||
&.edit-resize-se { bottom: $o; right: $o; }
|
||||
&.edit-resize-sw { bottom: $o; left: $o; }
|
||||
}
|
||||
|
||||
.edit-handle {
|
||||
top: $handleD; right: $handleD; bottom: $handleD; left: $handleD;
|
||||
&.edit-move {
|
||||
$m: 0; //$handleD;
|
||||
cursor: move;
|
||||
left: $m;
|
||||
right: $m;
|
||||
top: $m;
|
||||
bottom: $m;
|
||||
z-index: 1;
|
||||
|
||||
}
|
||||
&.edit-resize-n {
|
||||
top: 0px; bottom: auto;
|
||||
height: $handleD;
|
||||
cursor: n-resize;
|
||||
}
|
||||
&.edit-resize-e {
|
||||
right: 0px; left: auto;
|
||||
width: $handleD;
|
||||
cursor: e-resize;
|
||||
}
|
||||
&.edit-resize-s {
|
||||
bottom: 0px; top: auto;
|
||||
height: $handleD;
|
||||
cursor: s-resize;
|
||||
}
|
||||
&.edit-resize-w {
|
||||
left: 0px; right: auto;
|
||||
width: $handleD;
|
||||
cursor: w-resize;
|
||||
}
|
||||
.edit-handle.edit-move {
|
||||
// main move box for the whole frame element
|
||||
$m: 0;
|
||||
left: $m;
|
||||
right: $m;
|
||||
top: $m;
|
||||
bottom: $m;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.frame.child-frame.panel {
|
||||
&:hover {
|
||||
@include boxShdwLarge();
|
||||
border-color: $colorSelectableSelectedPrimary;
|
||||
.view-switcher {
|
||||
opacity: 1;
|
||||
}
|
||||
.edit-corner {
|
||||
background-color: rgba($colorKey, 0.8);
|
||||
&:hover {
|
||||
background-color: rgba($colorKey, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Editing Grids
|
||||
.l-grid-holder {
|
||||
display: block;
|
||||
.l-grid {
|
||||
&.l-grid-x { @include bgTicks($colorGridLines, 'x'); }
|
||||
&.l-grid-y { @include bgTicks($colorGridLines, 'y'); }
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent nested frames from showing their grids
|
||||
.t-frame-outer .l-grid-holder { display: none !important; }
|
||||
|
||||
// Prevent nested elements from showing s-hover-border
|
||||
.t-frame-outer .s-hover-border {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
// Prevent nested frames from being selectable until we have proper sub-object editing
|
||||
.t-frame-outer .t-frame-outer {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +193,7 @@
|
||||
|
||||
@include animToParams(overlayIn, $dur: $durLargeViewExpand, $delay: 0);
|
||||
background: $colorBodyBg;
|
||||
z-index: 101;
|
||||
|
||||
.abs.inner-holder {
|
||||
opacity: 0;
|
||||
@ -203,10 +204,19 @@
|
||||
@include animToParams(contentsIn, $dur: 50ms, $delay: $durLargeViewExpand * 1.25);
|
||||
}
|
||||
|
||||
// Hide View Large button
|
||||
.t-btn-view-large {
|
||||
display: none;
|
||||
}
|
||||
z-index: 101;
|
||||
|
||||
// But show View Large button when it's nested inside a Layout
|
||||
.t-frame-inner .t-frame-inner .t-btn-view-large { display: block; }
|
||||
}
|
||||
}
|
||||
// When multiple Large Views are visible, hide the blocker for all but the first
|
||||
& + .l-large-view {
|
||||
.blocker {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,28 +23,43 @@
|
||||
$ohH: $btnFrameH;
|
||||
$bc: $colorInteriorBorder;
|
||||
&.child-frame.panel {
|
||||
background: $colorBodyBg;
|
||||
border: 1px solid $bc;
|
||||
z-index: 0; // Needed to prevent child-frame controls from showing through when another child-frame is above
|
||||
&:hover {
|
||||
border-color: lighten($bc, 10%);
|
||||
&:not(.no-frame) {
|
||||
background: $colorBodyBg;
|
||||
border: 1px solid $bc;
|
||||
&:hover {
|
||||
border-color: lighten($bc, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.object-browse-bar {
|
||||
font-size: 0.75em;
|
||||
height: $ohH;
|
||||
line-height: $ohH;
|
||||
.right {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
padding-left: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
&.t-object-type-timer,
|
||||
&.t-object-type-clock,
|
||||
&.t-object-type-hyperlink {
|
||||
// Hide the right side buttons for objects where they don't make sense
|
||||
// Note that this will hide the view Switcher button if applied
|
||||
// to an object that it.
|
||||
.object-browse-bar .right { display: none; }
|
||||
}
|
||||
|
||||
> .object-holder.abs {
|
||||
top: $ohH + $interiorMargin;
|
||||
}
|
||||
.contents {
|
||||
$myM: $interiorMargin;
|
||||
top: $myM;
|
||||
right: $myM;
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
$m: $interiorMargin;
|
||||
top: $m;
|
||||
right: $m;
|
||||
bottom: $m;
|
||||
left: $m;
|
||||
}
|
||||
&.frame-template {
|
||||
.s-button,
|
||||
@ -67,15 +82,25 @@
|
||||
}
|
||||
}
|
||||
.view-switcher {
|
||||
margin-left: $interiorMargin; // Kick other top bar elements away when I'm present.
|
||||
margin-right: $interiorMargin; // Kick other top bar elements away when I'm present.
|
||||
// Hide the name when the view switcher is in a frame context
|
||||
.title-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-frame {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
.object-browse-bar .right {
|
||||
$m: 0; // $interiorMarginSm;
|
||||
background: rgba(black, 0.3);
|
||||
border-radius: $basicCr;
|
||||
padding: $interiorMarginSm;
|
||||
position: absolute;
|
||||
top: $m; right: $m;
|
||||
z-index: 2;
|
||||
}
|
||||
&.t-frame-outer > .t-rep-frame {
|
||||
&.contents {
|
||||
$m: 2px;
|
||||
@ -85,7 +110,7 @@
|
||||
left: $m;
|
||||
}
|
||||
> .t-frame-inner {
|
||||
> .object-browse-bar {
|
||||
> .object-browse-bar .left {
|
||||
display: none;
|
||||
}
|
||||
> .object-holder.abs {
|
||||
@ -117,8 +142,7 @@
|
||||
body.desktop .frame {
|
||||
// Hide local controls initially and show it them on hover when they're in an element that's in a frame context
|
||||
// Frame template is used because we need to target the lowest nested frame
|
||||
.view-switcher,
|
||||
.t-btn-view-large {
|
||||
.right {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
@ -126,8 +150,7 @@ body.desktop .frame {
|
||||
// Target the first descendant so that we only show the elements in the outermost container.
|
||||
// Handles the case where we have layouts in layouts.
|
||||
&:hover > .object-browse-bar {
|
||||
.view-switcher,
|
||||
.t-btn-view-large {
|
||||
.right {
|
||||
opacity: 1;
|
||||
pointer-events: inherit;
|
||||
}
|
||||
|
@ -19,21 +19,36 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.s-selectable {
|
||||
border: 1px solid transparent;
|
||||
.s-hover-border {
|
||||
border: 1px dotted transparent;
|
||||
}
|
||||
|
||||
&.s-hover {
|
||||
// Styles when hovering over a selectable object
|
||||
border-color: $colorSelectableHov !important;
|
||||
.s-status-editing {
|
||||
// Limit to editing mode until we have sub-object selection
|
||||
.s-hover-border {
|
||||
// Show a border by default so user can see object bounds and empty objects
|
||||
border: 1px dotted rgba($colorSelectableSelectedPrimary, 0.3) !important;
|
||||
&:hover {
|
||||
border-color: rgba($colorSelectableSelectedPrimary, 0.7) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.s-selected {
|
||||
.s-selected > .s-hover-border,
|
||||
.s-selected.s-hover-border {
|
||||
// Styles for a selected object. Also used by legacy Fixed Position/Panel objects.
|
||||
border-color: $colorSelectableSelectedPrimary !important;
|
||||
@include boxShdwLarge();
|
||||
// Show edit-corners if you got 'em
|
||||
.edit-corner {
|
||||
display: block;
|
||||
&:hover {
|
||||
background-color: rgba($colorKey, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.s-moveable {
|
||||
@include boxShdwLarge();
|
||||
.s-selected > .s-moveable,
|
||||
.s-selected.s-moveable {
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
}
|
@ -62,7 +62,29 @@ define([
|
||||
"type": "layout",
|
||||
"template": layoutTemplate,
|
||||
"editable": true,
|
||||
"uses": []
|
||||
"uses": [],
|
||||
"toolbar": {
|
||||
"sections": [
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"method": "showFrame",
|
||||
"cssClass": "icon-frame-show",
|
||||
"control": "button",
|
||||
"title": "Show frame",
|
||||
"description": "Show frame"
|
||||
},
|
||||
{
|
||||
"method": "hideFrame",
|
||||
"cssClass": "icon-frame-hide",
|
||||
"control": "button",
|
||||
"title": "Hide frame",
|
||||
"description": "Hide frame"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "fixed",
|
||||
|
@ -25,15 +25,20 @@
|
||||
<!-- Background grid -->
|
||||
<div class="l-grid-holder" ng-click="controller.clearSelection()">
|
||||
<div class="l-grid l-grid-x"
|
||||
ng-if="!controller.getGridSize()[0] < 3"
|
||||
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
||||
<div class="l-grid l-grid-y"
|
||||
ng-if="!controller.getGridSize()[1] < 3"
|
||||
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
|
||||
</div>
|
||||
|
||||
<!-- Fixed position elements -->
|
||||
<div ng-repeat="element in controller.getElements()"
|
||||
class="l-fixed-position-item"
|
||||
ng-class="{ 's-not-selected': controller.selected() && !controller.selected(element) }"
|
||||
class="l-fixed-position-item s-selectable s-moveable s-hover-border"
|
||||
ng-class="{
|
||||
's-not-selected': controller.selected() && !controller.selected(element),
|
||||
's-selected': controller.selected(element)
|
||||
}"
|
||||
ng-style="element.style"
|
||||
ng-click="controller.select(element)">
|
||||
<mct-include key="element.template"
|
||||
@ -43,15 +48,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Selection highlight, handles -->
|
||||
<span ng-if="controller.selected()">
|
||||
<div class="l-fixed-position-item s-selectable s-selected s-moveable"
|
||||
<span class="s-selected s-moveable" ng-if="controller.selected()">
|
||||
<div class="l-fixed-position-item t-edit-handle-holder"
|
||||
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">
|
||||
</div>
|
||||
<div ng-repeat="handle in controller.handles()"
|
||||
class="l-fixed-position-item-handle"
|
||||
class="l-fixed-position-item-handle edit-corner"
|
||||
ng-style="handle.style()"
|
||||
mct-drag-down="handle.startDrag()"
|
||||
mct-drag="handle.continueDrag(delta)"
|
||||
|
@ -29,15 +29,21 @@
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||
<mct-representation key="'switcher'"
|
||||
ng-model="representation"
|
||||
mct-object="domainObject">
|
||||
<mct-representation
|
||||
key="'switcher'"
|
||||
ng-model="representation"
|
||||
mct-object="domainObject">
|
||||
</mct-representation>
|
||||
<a class="s-button icon-expand t-btn-view-large"
|
||||
title="View large"
|
||||
mct-trigger-modal>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs object-holder">
|
||||
<mct-representation key="representation.selected.key"
|
||||
mct-object="representation.selected.key && domainObject">
|
||||
<mct-representation
|
||||
key="representation.selected.key"
|
||||
mct-object="representation.selected.key && domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -19,19 +19,33 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="l-layout"
|
||||
ng-controller="LayoutController as controller">
|
||||
|
||||
<div class='frame child-frame panel abs'
|
||||
<div class="abs l-layout"
|
||||
ng-controller="LayoutController as controller"
|
||||
ng-click="controller.clearSelection()">
|
||||
|
||||
<!-- Background grid -->
|
||||
<div class="l-grid-holder" ng-click="controller.clearSelection()">
|
||||
<div class="l-grid l-grid-x"
|
||||
ng-if="!controller.getGridSize()[0] < 3"
|
||||
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
||||
<div class="l-grid l-grid-y"
|
||||
ng-if="!controller.getGridSize()[1] < 3"
|
||||
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) }"
|
||||
ng-repeat="childObject in composition"
|
||||
ng-click="controller.select($event, childObject.getId())"
|
||||
ng-style="controller.getFrameStyle(childObject.getId())">
|
||||
|
||||
<mct-representation key="'frame'"
|
||||
class="frame child-frame holder contents abs"
|
||||
class="t-rep-frame holder contents abs"
|
||||
mct-object="childObject">
|
||||
</mct-representation>
|
||||
<!-- Drag handles -->
|
||||
<span ng-show="domainObject.hasCapability('editor')">
|
||||
<span class="abs t-edit-handle-holder s-hover-border" ng-if="controller.selected(childObject)">
|
||||
<span class="edit-handle edit-move"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
|
@ -33,6 +33,9 @@ define(
|
||||
DEFAULT_GRID_SIZE = [32, 32],
|
||||
MINIMUM_FRAME_SIZE = [320, 180];
|
||||
|
||||
// Method names to expose from this controller
|
||||
var HIDE = 'hideFrame', SHOW = 'showFrame';
|
||||
|
||||
/**
|
||||
* The LayoutController is responsible for supporting the
|
||||
* Layout view. It arranges frames according to saved configuration
|
||||
@ -79,6 +82,11 @@ define(
|
||||
],
|
||||
dimensions: self.defaultDimensions()
|
||||
};
|
||||
|
||||
// Store the id so that the newly-dropped object
|
||||
// gets selected during refresh composition
|
||||
self.droppedFrameId = id;
|
||||
|
||||
// Mark change as persistable
|
||||
if ($scope.commit) {
|
||||
$scope.commit("Dropped a frame.");
|
||||
@ -111,6 +119,13 @@ define(
|
||||
|
||||
$scope.composition = composition;
|
||||
self.layoutPanels(ids);
|
||||
self.setDefaultFrame();
|
||||
|
||||
// If there is a newly-dropped object, select it.
|
||||
if (self.droppedFrameId) {
|
||||
self.select(null, self.droppedFrameId);
|
||||
delete self.droppedFrameId;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -123,13 +138,21 @@ define(
|
||||
// saved by the EditRepresenter.
|
||||
$scope.configuration =
|
||||
$scope.configuration || {};
|
||||
|
||||
// Make sure there is a "panels" field in the
|
||||
// view configuration.
|
||||
$scope.configuration.panels =
|
||||
$scope.configuration.panels || {};
|
||||
// Store the position of this panel.
|
||||
|
||||
$scope.configuration.panels[self.activeDragId] =
|
||||
self.rawPositions[self.activeDragId];
|
||||
$scope.configuration.panels[self.activeDragId] || {};
|
||||
|
||||
// Store the position and dimensions of this panel.
|
||||
$scope.configuration.panels[self.activeDragId].position =
|
||||
self.rawPositions[self.activeDragId].position;
|
||||
$scope.configuration.panels[self.activeDragId].dimensions =
|
||||
self.rawPositions[self.activeDragId].dimensions;
|
||||
|
||||
// Mark this object as dirty to encourage persistence
|
||||
if ($scope.commit) {
|
||||
$scope.commit("Moved frame.");
|
||||
@ -144,6 +167,10 @@ define(
|
||||
// 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);
|
||||
|
||||
@ -151,6 +178,20 @@ define(
|
||||
$scope.$on("mctDrop", handleDrop);
|
||||
}
|
||||
|
||||
// Set a default value for hasFrame property on a panel.
|
||||
// A 'hyperlink' object should have no frame by default.
|
||||
LayoutController.prototype.setDefaultFrame = function () {
|
||||
var panels = this.$scope.configuration.panels;
|
||||
|
||||
this.$scope.composition.forEach(function (object) {
|
||||
var id = object.getId();
|
||||
|
||||
if (panels[id] && panels[id].hasFrame === undefined) {
|
||||
panels[id].hasFrame = object.getModel().type === 'hyperlink' ? false : true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Convert from { positions: ..., dimensions: ... } to an
|
||||
// appropriate ng-style argument, to position frames.
|
||||
LayoutController.prototype.convertPosition = function (raw) {
|
||||
@ -293,9 +334,100 @@ define(
|
||||
* view configuration.
|
||||
*/
|
||||
LayoutController.prototype.endDrag = function () {
|
||||
this.frameMoved = true;
|
||||
|
||||
setTimeout(function () {
|
||||
this.frameMoved = false;
|
||||
}.bind(this), 0);
|
||||
|
||||
this.endDragInScope();
|
||||
};
|
||||
|
||||
/**
|
||||
* Check 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();
|
||||
}
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var selectedObj = {};
|
||||
var configuration = this.$scope.configuration;
|
||||
|
||||
this.selectedId = id;
|
||||
|
||||
// Toggle the visibility of the object frame
|
||||
function toggle() {
|
||||
// create new selection object so toolbar updates.
|
||||
selectedObj = {};
|
||||
|
||||
configuration.panels[id].hasFrame =
|
||||
!configuration.panels[id].hasFrame;
|
||||
|
||||
// Change which method is exposed, to influence
|
||||
// which button is shown in the toolbar
|
||||
selectedObj[configuration.panels[id].hasFrame ? HIDE : SHOW] = toggle;
|
||||
self.selection.deselect();
|
||||
self.selection.select(selectedObj);
|
||||
}
|
||||
|
||||
// Expose initial toggle
|
||||
selectedObj[configuration.panels[id].hasFrame ? HIDE : SHOW] = toggle;
|
||||
|
||||
if (this.selection) {
|
||||
this.selection.select(selectedObj);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the current user selection.
|
||||
*/
|
||||
LayoutController.prototype.clearSelection = function (event) {
|
||||
// Keep the selection if the frame is moved.
|
||||
if (this.frameMoved) {
|
||||
this.frameMoved = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selection) {
|
||||
this.selection.deselect();
|
||||
delete this.selectedId;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the object has frame.
|
||||
*/
|
||||
LayoutController.prototype.hasFrame = function (obj) {
|
||||
return this.$scope.configuration.panels[obj.getId()].hasFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of the grid, in pixels. The returned array
|
||||
* is in the form `[x, y]`.
|
||||
* @returns {number[]} the grid size
|
||||
*/
|
||||
LayoutController.prototype.getGridSize = function () {
|
||||
return this.gridSize;
|
||||
};
|
||||
|
||||
return LayoutController;
|
||||
}
|
||||
);
|
||||
|
@ -27,7 +27,6 @@ define([
|
||||
) {
|
||||
|
||||
var OVERLAY_TEMPLATE = '' +
|
||||
'<div class="abs overlay l-large-view">' +
|
||||
' <div class="abs blocker"></div>' +
|
||||
' <div class="abs outer-holder">' +
|
||||
' <a class="close icon-x-in-circle"></a>' +
|
||||
@ -37,8 +36,7 @@ define([
|
||||
' <a class="t-done s-button major">Done</a>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
'</div>';
|
||||
' </div>';
|
||||
|
||||
/**
|
||||
* MCT Trigger Modal is intended for use in only one location: inside the
|
||||
@ -81,7 +79,8 @@ define([
|
||||
function openOverlay() {
|
||||
// Remove frame classes from being applied in a non-frame context
|
||||
$(frame).removeClass('frame frame-template');
|
||||
overlay = document.createElement('span');
|
||||
overlay = document.createElement('div');
|
||||
$(overlay).addClass('abs overlay l-large-view');
|
||||
overlay.innerHTML = OVERLAY_TEMPLATE;
|
||||
overlayContainer = overlay.querySelector('.t-contents');
|
||||
closeButton = overlay.querySelector('a.close');
|
||||
|
@ -53,6 +53,17 @@ define(
|
||||
};
|
||||
}
|
||||
|
||||
// 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",
|
||||
@ -60,7 +71,7 @@ define(
|
||||
);
|
||||
mockEvent = jasmine.createSpyObj(
|
||||
'event',
|
||||
['preventDefault']
|
||||
['preventDefault', 'stopPropagation']
|
||||
);
|
||||
|
||||
testModel = {};
|
||||
@ -72,7 +83,8 @@ define(
|
||||
panels: {
|
||||
a: {
|
||||
position: [20, 10],
|
||||
dimensions: [5, 5]
|
||||
dimensions: [5, 5],
|
||||
hasFrame: true
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -82,10 +94,17 @@ define(
|
||||
mockScope.domainObject = mockDomainObject("mockDomainObject");
|
||||
mockScope.model = testModel;
|
||||
mockScope.configuration = testConfiguration;
|
||||
mockScope.selection = jasmine.createSpyObj(
|
||||
'selection',
|
||||
['select', 'get', 'selected', 'deselect']
|
||||
);
|
||||
|
||||
spyOn(mockScope.domainObject, "useCapability").andCallThrough();
|
||||
|
||||
controller = new LayoutController(mockScope);
|
||||
spyOn(controller, "layoutPanels").andCallThrough();
|
||||
|
||||
findWatch("selection")(mockScope.selection);
|
||||
});
|
||||
|
||||
// Model changes will indicate that panel positions
|
||||
@ -289,6 +308,43 @@ define(
|
||||
expect(controller.getFrameStyle("b"))
|
||||
.not.toEqual(oldStyle);
|
||||
});
|
||||
|
||||
it("allows panels to be selected", function () {
|
||||
var childObj = mockCompositionObjects[0];
|
||||
|
||||
controller.select(mockEvent, childObj.getId());
|
||||
|
||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
||||
|
||||
expect(controller.selected(childObj)).toBe(true);
|
||||
});
|
||||
|
||||
it("allows selection to be cleared", function () {
|
||||
var childObj = mockCompositionObjects[0];
|
||||
|
||||
controller.select(null, childObj.getId());
|
||||
controller.clearSelection();
|
||||
|
||||
expect(controller.selected(childObj)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("does not clear selection when 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();
|
||||
|
||||
controller.clearSelection();
|
||||
|
||||
expect(controller.selected(childObj)).toBe(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
Reference in New Issue
Block a user