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'" | ||||
|         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