Compare commits

...

46 Commits

Author SHA1 Message Date
728faea4ce [Frontend] Hover border sanding and polishing
Fixes #1658
Prevent hover border from showing when nested;
Show hover border for all elements when Layout editing;
2017-08-17 14:49:49 -07:00
59db676fd8 [Frontend] Disallow selection of nested frames
Fixes #1658
2017-08-17 12:04:21 -07:00
f89c74dfa3 Added a test for the case where selection should not be cleared when moving/resizing. 2017-08-17 10:52:23 -07:00
60ece16c33 Fixed lint and checkstyle errors. 2017-08-17 10:12:28 -07:00
7dd7421890 Removed unnecessary comments and clarified code by using toBe(true). 2017-08-16 17:23:15 -07:00
6d6124820d Set a default value on hasFrame and made sure 'hyperlink' objects have no frame by default. 2017-08-16 16:59:33 -07:00
1b334086b6 Merge remote-tracking branch 'origin' into layout-issue-1658 2017-08-16 16:03:29 -07:00
d725e30481 Merge remote-tracking branch 'origin/layout-issue-1658-styling' into layout-issue-1658 2017-08-15 16:35:30 -07:00
5b26264409 Added tests for selecting an object and clearing selection. 2017-08-15 16:34:52 -07:00
8466ba51a0 [Front-end] Tweaks to View Large button and overlay
Fixes #1658
Tweaks to Large View overlay template;
Now displays Large View button in nested Layout within Large View;
CSS tweaks;
2017-08-15 10:41:03 -07:00
c2ed84d7ca [Front-end] Enable View Large when frame is hidden
Fixes #1658
View Large button and view Switcher now
displayed on hover when frame is hidden for a Layout child object;
Moved location of View Large button in markup;
Tweaked location of view Switcher in markup;
CSS mods accordingly;
2017-08-14 17:08:14 -07:00
425fbc91e2 Merge remote-tracking branch 'origin/layout-issue-1658-styling' into layout-issue-1658 2017-08-14 16:09:45 -07:00
3dd36e7ce8 Merge remote-tracking branch 'origin' into layout-issue-1658 2017-08-14 16:08:31 -07:00
9925c2dd38 Fixed the brokend tests. 2017-08-14 16:07:52 -07:00
0239faa9a8 [Front-end] CSS organization
Fixes #1658
Moved grid CSS into editor.scss
2017-08-14 15:37:38 -07:00
e802b5344c [Front-end] Added visual layout grid to Layouts
Fixes #1658
Hides grid when grid size is less than 3 px;
2017-08-14 15:03:35 -07:00
b5f196ede8 [Front-end] Bring over Hyperlink styling
Fixes #1658
Change icon for Hyperlink (cherry picked from commit f5a92f6)
2017-08-14 12:49:02 -07:00
dbc7c910cc [Front-end] Bring over Hyperlink styling
Fixes #1658
(cherry picked from commit 0417b7e)
2017-08-14 12:48:33 -07:00
0acf8d9edc [Front-end] Prevernt Hyperlink click when editing
Fixes #1685
Prevent Hyperlink object from being clickable
when in Edit mode;
2017-08-14 12:06:57 -07:00
af5d42da1e Merge branch 'layout-issue-1658' of https://github.com/nasa/openmct into layout-issue-1658-styling 2017-08-14 11:57:58 -07:00
4dff369807 [Front-end] Integrate Hyperlink
Fixes #1685
Fixed problematic markup in hyperlink.html;
Styling for Hyperlink in Layout context;
Tweaks to no-frame style;
2017-08-14 11:57:49 -07:00
eb999ad37b Removed the resize parameter and defined a flag and set a timeout instead to clear it. 2017-08-14 11:35:58 -07:00
36a0976e98 Merge branch 'layout-issue-1658' of https://github.com/nasa/openmct into layout-issue-1658-styling 2017-08-14 10:53:54 -07:00
cbc2555687 Set a flag when frame is resized so clearSelection() can handle and keep the selection. 2017-08-14 10:41:00 -07:00
e040abc329 Merge branch 'master' into layout-issue-1658-styling 2017-08-14 10:35:00 -07:00
d5ca720eff Merge remote-tracking branch 'origin/layout-issue-1658-styling' into layout-issue-1658 2017-08-11 15:23:53 -07:00
d605b2ce43 [Frontend] Fixed view-large btn
Fixes #1658
Messing up hover on frame element,
t-edit-handle was displaying in browse mode -
now hide by default and only show in edit-mode
2017-08-11 14:58:37 -07:00
d895b47bc6 [Frontend] Cherry pick over new glyphs
Fixes #1658
Updated art for glyphs for
icon-frame-show and -hide;
(cherry picked from commit 43b9264)
2017-08-11 14:37:47 -07:00
33efe77172 Merge remote-tracking branches 'origin' and 'origin/layout-issue-1658-styling' into layout-issue-1658 2017-08-11 14:28:44 -07:00
bbd5dfe335 [Frontend] Added no-frame styling
Fixes #1658
Markup and CSS for no-frame;
Removed no-frame parameters passed
to frame.html;
2017-08-11 14:02:48 -07:00
71a1b46d69 Disallow moving/resizing before selecting the frame. 2017-08-11 13:55:05 -07:00
d86ce9794e [Frontend] Tweaked FP bg grid
Fixes #1658
2017-08-11 13:15:31 -07:00
c2d2cbfa1e [Frontend] Selecting in Layouts and Fixed Position
Fixes #1658
WIP; CSS cleanup; sanding and polishing;
2017-08-11 12:01:25 -07:00
f384ca3f53 [Frontend] Selecting in Layouts and Fixed Position
Fixes #1658
WIP!
Finessed styles and markup; only show move cursor when
object is selected;
2017-08-11 11:31:54 -07:00
ce858ca598 [Frontend] Major changes re. selecting in Layouts and Fixed Position
Fixes #1658
WIP!
Significant changes to markup and CSS for .s-selected,
.s-selectable, etc.
Applied to Layouts and Fixed Position objects;
Restored bg grid to FP objects;
Possibly breaks Panels at this point;
TO-DO: checkout Panels and fix if needed, remove
commented CSS code;
2017-08-10 18:28:37 -07:00
6df5de9cce Merge branch 'layout-issue-1658' of https://github.com/nasa/openmct into layout-issue-1658-styling 2017-08-10 14:54:57 -07:00
9f59b1920b Merge branch 'master' into layout-issue-1658 2017-08-10 14:53:35 -07:00
f778f73bfc Merge branch 'master' into layout-issue-1658-styling 2017-08-10 14:52:38 -07:00
63579668bd Added code to hide the object header when the frame is hidden. Also, replace the inline style with the 'abs' css class. 2017-08-10 14:37:04 -07:00
9087147dda Added code to select the newly-added object. 2017-08-09 16:20:19 -07:00
0d61d70b8c Swapped the css class for showing/hiding frame. 2017-08-09 15:33:11 -07:00
e1e2fc5bcd Merge remote-tracking branch 'refs/remotes/origin/layout-issue-1658' into layout-issue-1658 2017-08-09 13:28:51 -07:00
5a3b98c731 Removed unused reselect(). 2017-08-09 13:14:07 -07:00
df01646954 make new selection object on toggle
Make and select a new object every time the frame is toggled.  This
ensures that the EditToolbarRepresenter detects the change of selection
and updates it's display state.
2017-08-09 10:28:42 -07:00
a986ddddcc Added a mutation listener. 2017-08-08 16:05:22 -07:00
c8eba1fbad Added selection capability for the panels in layout. Also, added a toggle button in the toolbar to allow showing/hiding frame around the panels. 2017-08-08 10:53:17 -07:00
14 changed files with 392 additions and 179 deletions

View File

@ -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>

View File

@ -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; }
}

View File

@ -704,11 +704,6 @@ textarea {
}
}
.view-switcher,
.t-btn-view-large {
@include trans-prop-nice-fade($controlFadeMs);
}
/******************************************************** BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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",

View File

@ -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)"

View File

@ -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>

View File

@ -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)"

View File

@ -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;
}
);

View File

@ -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');

View File

@ -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);
});
});
}
);