Compare commits
46 Commits
plot-mobil
...
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'"
|
key="'menu-arrow'"
|
||||||
mct-object='domainObject'
|
mct-object='domainObject'
|
||||||
class="flex-elem context-available-w"></mct-representation>
|
class="flex-elem context-available-w"></mct-representation>
|
||||||
</span>
|
</span>
|
||||||
<a class="s-button icon-expand t-btn-view-large"
|
|
||||||
title="View large"
|
|
||||||
mct-trigger-modal>
|
|
||||||
</a>
|
|
||||||
@@ -21,32 +21,11 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
.t-fixed-position {
|
.t-fixed-position {
|
||||||
&.l-fixed-position {
|
&.l-fixed-position {
|
||||||
position: absolute;
|
@extend .abs;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-fixed-position-item {
|
.l-fixed-position-item {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border: 1px solid transparent;
|
|
||||||
|
|
||||||
&.s-not-selected {
|
&.s-not-selected {
|
||||||
opacity: 0.8;
|
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 {
|
.s-status-editing {
|
||||||
&.l-fixed-position {
|
.l-fixed-position-item-handle.edit-corner { display: block; }
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -704,11 +704,6 @@ textarea {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.view-switcher,
|
|
||||||
.t-btn-view-large {
|
|
||||||
@include trans-prop-nice-fade($controlFadeMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************** BROWSER ELEMENTS */
|
/******************************************************** BROWSER ELEMENTS */
|
||||||
body.desktop {
|
body.desktop {
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|||||||
@@ -19,12 +19,24 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
.s-status-editing .l-object-wrapper,
|
.t-edit-handle-holder { display: none; }
|
||||||
.edit-main {
|
|
||||||
// .s-status-editing .l-object-wrapper is relevant to New Edit Mode;
|
.l-grid-holder {
|
||||||
// .edit-main is legacy for old edit mode.
|
display: none;
|
||||||
$handleD: 15px;
|
position: relative;
|
||||||
$cr: 5px;
|
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-corner,
|
||||||
.edit-handle {
|
.edit-handle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -32,81 +44,59 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.edit-corner {
|
.edit-corner {
|
||||||
|
background: rgba($colorSelectableSelectedPrimary, 0.5);
|
||||||
|
cursor: crosshair;
|
||||||
|
display: none; // Hide by default
|
||||||
|
border: 1px solid $colorSelectableSelectedPrimary;
|
||||||
width: $handleD;
|
width: $handleD;
|
||||||
height: $handleD;
|
height: $handleD;
|
||||||
|
$o: (-1 * $handleD) + 1px;
|
||||||
&:hover {
|
&:hover {
|
||||||
z-index: 11;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
&.edit-resize-nw {
|
&.edit-resize-nw { top: $o; left: $o; }
|
||||||
border-bottom-right-radius: $cr;
|
&.edit-resize-ne { top: $o; right: $o; }
|
||||||
cursor: nw-resize;
|
&.edit-resize-se { bottom: $o; right: $o; }
|
||||||
top: 0; left: 0;
|
&.edit-resize-sw { bottom: $o; left: $o; }
|
||||||
}
|
|
||||||
&.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-handle {
|
.edit-handle.edit-move {
|
||||||
top: $handleD; right: $handleD; bottom: $handleD; left: $handleD;
|
// main move box for the whole frame element
|
||||||
&.edit-move {
|
$m: 0;
|
||||||
$m: 0; //$handleD;
|
left: $m;
|
||||||
cursor: move;
|
right: $m;
|
||||||
left: $m;
|
top: $m;
|
||||||
right: $m;
|
bottom: $m;
|
||||||
top: $m;
|
z-index: 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame.child-frame.panel {
|
.frame.child-frame.panel {
|
||||||
&:hover {
|
&:hover {
|
||||||
@include boxShdwLarge();
|
|
||||||
border-color: $colorSelectableSelectedPrimary;
|
|
||||||
.view-switcher {
|
.view-switcher {
|
||||||
opacity: 1;
|
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);
|
@include animToParams(overlayIn, $dur: $durLargeViewExpand, $delay: 0);
|
||||||
background: $colorBodyBg;
|
background: $colorBodyBg;
|
||||||
|
z-index: 101;
|
||||||
|
|
||||||
.abs.inner-holder {
|
.abs.inner-holder {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -203,10 +204,19 @@
|
|||||||
@include animToParams(contentsIn, $dur: 50ms, $delay: $durLargeViewExpand * 1.25);
|
@include animToParams(contentsIn, $dur: 50ms, $delay: $durLargeViewExpand * 1.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide View Large button
|
||||||
.t-btn-view-large {
|
.t-btn-view-large {
|
||||||
display: none;
|
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;
|
$ohH: $btnFrameH;
|
||||||
$bc: $colorInteriorBorder;
|
$bc: $colorInteriorBorder;
|
||||||
&.child-frame.panel {
|
&.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
|
z-index: 0; // Needed to prevent child-frame controls from showing through when another child-frame is above
|
||||||
&:hover {
|
&:not(.no-frame) {
|
||||||
border-color: lighten($bc, 10%);
|
background: $colorBodyBg;
|
||||||
|
border: 1px solid $bc;
|
||||||
|
&:hover {
|
||||||
|
border-color: lighten($bc, 10%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.object-browse-bar {
|
.object-browse-bar {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
height: $ohH;
|
height: $ohH;
|
||||||
line-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 {
|
> .object-holder.abs {
|
||||||
top: $ohH + $interiorMargin;
|
top: $ohH + $interiorMargin;
|
||||||
}
|
}
|
||||||
.contents {
|
.contents {
|
||||||
$myM: $interiorMargin;
|
$m: $interiorMargin;
|
||||||
top: $myM;
|
top: $m;
|
||||||
right: $myM;
|
right: $m;
|
||||||
bottom: $myM;
|
bottom: $m;
|
||||||
left: $myM;
|
left: $m;
|
||||||
}
|
}
|
||||||
&.frame-template {
|
&.frame-template {
|
||||||
.s-button,
|
.s-button,
|
||||||
@@ -67,15 +82,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.view-switcher {
|
.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
|
// Hide the name when the view switcher is in a frame context
|
||||||
.title-label {
|
.title-label {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.no-frame {
|
&.no-frame {
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
border: none !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 {
|
&.t-frame-outer > .t-rep-frame {
|
||||||
&.contents {
|
&.contents {
|
||||||
$m: 2px;
|
$m: 2px;
|
||||||
@@ -85,7 +110,7 @@
|
|||||||
left: $m;
|
left: $m;
|
||||||
}
|
}
|
||||||
> .t-frame-inner {
|
> .t-frame-inner {
|
||||||
> .object-browse-bar {
|
> .object-browse-bar .left {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
> .object-holder.abs {
|
> .object-holder.abs {
|
||||||
@@ -117,8 +142,7 @@
|
|||||||
body.desktop .frame {
|
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
|
// 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
|
// Frame template is used because we need to target the lowest nested frame
|
||||||
.view-switcher,
|
.right {
|
||||||
.t-btn-view-large {
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
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.
|
// Target the first descendant so that we only show the elements in the outermost container.
|
||||||
// Handles the case where we have layouts in layouts.
|
// Handles the case where we have layouts in layouts.
|
||||||
&:hover > .object-browse-bar {
|
&:hover > .object-browse-bar {
|
||||||
.view-switcher,
|
.right {
|
||||||
.t-btn-view-large {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
pointer-events: inherit;
|
pointer-events: inherit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,21 +19,36 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
.s-selectable {
|
.s-hover-border {
|
||||||
border: 1px solid transparent;
|
border: 1px dotted transparent;
|
||||||
|
}
|
||||||
|
|
||||||
&.s-hover {
|
.s-status-editing {
|
||||||
// Styles when hovering over a selectable object
|
// Limit to editing mode until we have sub-object selection
|
||||||
border-color: $colorSelectableHov !important;
|
.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.
|
// Styles for a selected object. Also used by legacy Fixed Position/Panel objects.
|
||||||
border-color: $colorSelectableSelectedPrimary !important;
|
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 {
|
.s-selected > .s-moveable,
|
||||||
@include boxShdwLarge();
|
.s-selected.s-moveable {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,29 @@ define([
|
|||||||
"type": "layout",
|
"type": "layout",
|
||||||
"template": layoutTemplate,
|
"template": layoutTemplate,
|
||||||
"editable": true,
|
"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",
|
"key": "fixed",
|
||||||
|
|||||||
@@ -25,15 +25,20 @@
|
|||||||
<!-- Background grid -->
|
<!-- Background grid -->
|
||||||
<div class="l-grid-holder" ng-click="controller.clearSelection()">
|
<div class="l-grid-holder" ng-click="controller.clearSelection()">
|
||||||
<div class="l-grid l-grid-x"
|
<div class="l-grid l-grid-x"
|
||||||
|
ng-if="!controller.getGridSize()[0] < 3"
|
||||||
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
||||||
<div class="l-grid l-grid-y"
|
<div class="l-grid l-grid-y"
|
||||||
|
ng-if="!controller.getGridSize()[1] < 3"
|
||||||
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
|
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Fixed position elements -->
|
<!-- Fixed position elements -->
|
||||||
<div ng-repeat="element in controller.getElements()"
|
<div ng-repeat="element in controller.getElements()"
|
||||||
class="l-fixed-position-item"
|
class="l-fixed-position-item s-selectable s-moveable s-hover-border"
|
||||||
ng-class="{ 's-not-selected': controller.selected() && !controller.selected(element) }"
|
ng-class="{
|
||||||
|
's-not-selected': controller.selected() && !controller.selected(element),
|
||||||
|
's-selected': controller.selected(element)
|
||||||
|
}"
|
||||||
ng-style="element.style"
|
ng-style="element.style"
|
||||||
ng-click="controller.select(element)">
|
ng-click="controller.select(element)">
|
||||||
<mct-include key="element.template"
|
<mct-include key="element.template"
|
||||||
@@ -43,15 +48,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Selection highlight, handles -->
|
<!-- Selection highlight, handles -->
|
||||||
<span ng-if="controller.selected()">
|
<span class="s-selected s-moveable" ng-if="controller.selected()">
|
||||||
<div class="l-fixed-position-item s-selectable s-selected s-moveable"
|
<div class="l-fixed-position-item t-edit-handle-holder"
|
||||||
mct-drag-down="controller.moveHandle().startDrag(controller.selected())"
|
mct-drag-down="controller.moveHandle().startDrag(controller.selected())"
|
||||||
mct-drag="controller.moveHandle().continueDrag(delta)"
|
mct-drag="controller.moveHandle().continueDrag(delta)"
|
||||||
mct-drag-up="controller.moveHandle().endDrag()"
|
mct-drag-up="controller.moveHandle().endDrag()"
|
||||||
ng-style="controller.selected().style">
|
ng-style="controller.selected().style">
|
||||||
</div>
|
</div>
|
||||||
<div ng-repeat="handle in controller.handles()"
|
<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()"
|
ng-style="handle.style()"
|
||||||
mct-drag-down="handle.startDrag()"
|
mct-drag-down="handle.startDrag()"
|
||||||
mct-drag="handle.continueDrag(delta)"
|
mct-drag="handle.continueDrag(delta)"
|
||||||
|
|||||||
@@ -29,15 +29,21 @@
|
|||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||||
<mct-representation key="'switcher'"
|
<mct-representation
|
||||||
ng-model="representation"
|
key="'switcher'"
|
||||||
mct-object="domainObject">
|
ng-model="representation"
|
||||||
|
mct-object="domainObject">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
|
<a class="s-button icon-expand t-btn-view-large"
|
||||||
|
title="View large"
|
||||||
|
mct-trigger-modal>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="abs object-holder">
|
<div class="abs object-holder">
|
||||||
<mct-representation key="representation.selected.key"
|
<mct-representation
|
||||||
mct-object="representation.selected.key && domainObject">
|
key="representation.selected.key"
|
||||||
|
mct-object="representation.selected.key && domainObject">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,19 +19,33 @@
|
|||||||
this source code distribution or the Licensing information page available
|
this source code distribution or the Licensing information page available
|
||||||
at runtime from the About dialog for additional information.
|
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-repeat="childObject in composition"
|
||||||
|
ng-click="controller.select($event, childObject.getId())"
|
||||||
ng-style="controller.getFrameStyle(childObject.getId())">
|
ng-style="controller.getFrameStyle(childObject.getId())">
|
||||||
|
|
||||||
<mct-representation key="'frame'"
|
<mct-representation key="'frame'"
|
||||||
class="frame child-frame holder contents abs"
|
class="t-rep-frame holder contents abs"
|
||||||
mct-object="childObject">
|
mct-object="childObject">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
<!-- Drag handles -->
|
<!-- 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"
|
<span class="edit-handle edit-move"
|
||||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
|
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
|
||||||
mct-drag="controller.continueDrag(delta)"
|
mct-drag="controller.continueDrag(delta)"
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ define(
|
|||||||
DEFAULT_GRID_SIZE = [32, 32],
|
DEFAULT_GRID_SIZE = [32, 32],
|
||||||
MINIMUM_FRAME_SIZE = [320, 180];
|
MINIMUM_FRAME_SIZE = [320, 180];
|
||||||
|
|
||||||
|
// Method names to expose from this controller
|
||||||
|
var HIDE = 'hideFrame', SHOW = 'showFrame';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The LayoutController is responsible for supporting the
|
* The LayoutController is responsible for supporting the
|
||||||
* Layout view. It arranges frames according to saved configuration
|
* Layout view. It arranges frames according to saved configuration
|
||||||
@@ -79,6 +82,11 @@ define(
|
|||||||
],
|
],
|
||||||
dimensions: self.defaultDimensions()
|
dimensions: self.defaultDimensions()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Store the id so that the newly-dropped object
|
||||||
|
// gets selected during refresh composition
|
||||||
|
self.droppedFrameId = id;
|
||||||
|
|
||||||
// Mark change as persistable
|
// Mark change as persistable
|
||||||
if ($scope.commit) {
|
if ($scope.commit) {
|
||||||
$scope.commit("Dropped a frame.");
|
$scope.commit("Dropped a frame.");
|
||||||
@@ -111,6 +119,13 @@ define(
|
|||||||
|
|
||||||
$scope.composition = composition;
|
$scope.composition = composition;
|
||||||
self.layoutPanels(ids);
|
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.
|
// saved by the EditRepresenter.
|
||||||
$scope.configuration =
|
$scope.configuration =
|
||||||
$scope.configuration || {};
|
$scope.configuration || {};
|
||||||
|
|
||||||
// Make sure there is a "panels" field in the
|
// Make sure there is a "panels" field in the
|
||||||
// view configuration.
|
// view configuration.
|
||||||
$scope.configuration.panels =
|
$scope.configuration.panels =
|
||||||
$scope.configuration.panels || {};
|
$scope.configuration.panels || {};
|
||||||
// Store the position of this panel.
|
|
||||||
$scope.configuration.panels[self.activeDragId] =
|
$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
|
// Mark this object as dirty to encourage persistence
|
||||||
if ($scope.commit) {
|
if ($scope.commit) {
|
||||||
$scope.commit("Moved frame.");
|
$scope.commit("Moved frame.");
|
||||||
@@ -144,6 +167,10 @@ define(
|
|||||||
// Watch for changes to the grid size in the model
|
// Watch for changes to the grid size in the model
|
||||||
$scope.$watch("model.layoutGrid", updateGridSize);
|
$scope.$watch("model.layoutGrid", updateGridSize);
|
||||||
|
|
||||||
|
$scope.$watch("selection", function (selection) {
|
||||||
|
this.selection = selection;
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
// Update composed objects on screen, and position panes
|
// Update composed objects on screen, and position panes
|
||||||
$scope.$watchCollection("model.composition", refreshComposition);
|
$scope.$watchCollection("model.composition", refreshComposition);
|
||||||
|
|
||||||
@@ -151,6 +178,20 @@ define(
|
|||||||
$scope.$on("mctDrop", handleDrop);
|
$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
|
// Convert from { positions: ..., dimensions: ... } to an
|
||||||
// appropriate ng-style argument, to position frames.
|
// appropriate ng-style argument, to position frames.
|
||||||
LayoutController.prototype.convertPosition = function (raw) {
|
LayoutController.prototype.convertPosition = function (raw) {
|
||||||
@@ -293,9 +334,100 @@ define(
|
|||||||
* view configuration.
|
* view configuration.
|
||||||
*/
|
*/
|
||||||
LayoutController.prototype.endDrag = function () {
|
LayoutController.prototype.endDrag = function () {
|
||||||
|
this.frameMoved = true;
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
this.frameMoved = false;
|
||||||
|
}.bind(this), 0);
|
||||||
|
|
||||||
this.endDragInScope();
|
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;
|
return LayoutController;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ define([
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
var OVERLAY_TEMPLATE = '' +
|
var OVERLAY_TEMPLATE = '' +
|
||||||
'<div class="abs overlay l-large-view">' +
|
|
||||||
' <div class="abs blocker"></div>' +
|
' <div class="abs blocker"></div>' +
|
||||||
' <div class="abs outer-holder">' +
|
' <div class="abs outer-holder">' +
|
||||||
' <a class="close icon-x-in-circle"></a>' +
|
' <a class="close icon-x-in-circle"></a>' +
|
||||||
@@ -37,8 +36,7 @@ define([
|
|||||||
' <a class="t-done s-button major">Done</a>' +
|
' <a class="t-done s-button major">Done</a>' +
|
||||||
' </div>' +
|
' </div>' +
|
||||||
' </div>' +
|
' </div>' +
|
||||||
' </div>' +
|
' </div>';
|
||||||
'</div>';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MCT Trigger Modal is intended for use in only one location: inside the
|
* MCT Trigger Modal is intended for use in only one location: inside the
|
||||||
@@ -81,7 +79,8 @@ define([
|
|||||||
function openOverlay() {
|
function openOverlay() {
|
||||||
// Remove frame classes from being applied in a non-frame context
|
// Remove frame classes from being applied in a non-frame context
|
||||||
$(frame).removeClass('frame frame-template');
|
$(frame).removeClass('frame frame-template');
|
||||||
overlay = document.createElement('span');
|
overlay = document.createElement('div');
|
||||||
|
$(overlay).addClass('abs overlay l-large-view');
|
||||||
overlay.innerHTML = OVERLAY_TEMPLATE;
|
overlay.innerHTML = OVERLAY_TEMPLATE;
|
||||||
overlayContainer = overlay.querySelector('.t-contents');
|
overlayContainer = overlay.querySelector('.t-contents');
|
||||||
closeButton = overlay.querySelector('a.close');
|
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 () {
|
beforeEach(function () {
|
||||||
mockScope = jasmine.createSpyObj(
|
mockScope = jasmine.createSpyObj(
|
||||||
"$scope",
|
"$scope",
|
||||||
@@ -60,7 +71,7 @@ define(
|
|||||||
);
|
);
|
||||||
mockEvent = jasmine.createSpyObj(
|
mockEvent = jasmine.createSpyObj(
|
||||||
'event',
|
'event',
|
||||||
['preventDefault']
|
['preventDefault', 'stopPropagation']
|
||||||
);
|
);
|
||||||
|
|
||||||
testModel = {};
|
testModel = {};
|
||||||
@@ -72,7 +83,8 @@ define(
|
|||||||
panels: {
|
panels: {
|
||||||
a: {
|
a: {
|
||||||
position: [20, 10],
|
position: [20, 10],
|
||||||
dimensions: [5, 5]
|
dimensions: [5, 5],
|
||||||
|
hasFrame: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -82,10 +94,17 @@ define(
|
|||||||
mockScope.domainObject = mockDomainObject("mockDomainObject");
|
mockScope.domainObject = mockDomainObject("mockDomainObject");
|
||||||
mockScope.model = testModel;
|
mockScope.model = testModel;
|
||||||
mockScope.configuration = testConfiguration;
|
mockScope.configuration = testConfiguration;
|
||||||
|
mockScope.selection = jasmine.createSpyObj(
|
||||||
|
'selection',
|
||||||
|
['select', 'get', 'selected', 'deselect']
|
||||||
|
);
|
||||||
|
|
||||||
spyOn(mockScope.domainObject, "useCapability").andCallThrough();
|
spyOn(mockScope.domainObject, "useCapability").andCallThrough();
|
||||||
|
|
||||||
controller = new LayoutController(mockScope);
|
controller = new LayoutController(mockScope);
|
||||||
spyOn(controller, "layoutPanels").andCallThrough();
|
spyOn(controller, "layoutPanels").andCallThrough();
|
||||||
|
|
||||||
|
findWatch("selection")(mockScope.selection);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Model changes will indicate that panel positions
|
// Model changes will indicate that panel positions
|
||||||
@@ -289,6 +308,43 @@ define(
|
|||||||
expect(controller.getFrameStyle("b"))
|
expect(controller.getFrameStyle("b"))
|
||||||
.not.toEqual(oldStyle);
|
.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