浏览代码

Make detached cdb window more generic and resizable (#197)

Leonardo Jeanteur 4 年之前
父节点
当前提交
53b175224e
共有 10 个文件被更改,包括 247 次插入30 次删除
  1. 1 1
      bin/cdb.css
  2. 3 1
      bin/cdb.less
  3. 0 0
      bin/common.css
  4. 1 0
      bin/common.less
  5. 1 0
      bin/libs/font-awesome-imports.less
  6. 41 7
      bin/style.css
  7. 57 16
      bin/style.less
  8. 135 0
      hide/comp/DetachablePanel.hx
  9. 2 4
      hide/comp/ResizablePanel.hx
  10. 6 1
      hide/comp/SceneEditor.hx

+ 1 - 1
bin/cdb.css

@@ -373,7 +373,7 @@
   min-width: 500px;
   min-width: 500px;
   min-height: 500px;
   min-height: 500px;
 }
 }
-.cdb.cdb-obj-editor {
+.cdb.cdb-obj-editor:not(.cdb-large .cdb.cdb-obj-editor) {
   margin-top: 10px;
   margin-top: 10px;
 }
 }
 .cdb.cdb-obj-editor > .cdb-sheet {
 .cdb.cdb-obj-editor > .cdb-sheet {

+ 3 - 1
bin/cdb.less

@@ -423,7 +423,9 @@
 	}
 	}
 
 
 	&.cdb-obj-editor {
 	&.cdb-obj-editor {
-		margin-top : 10px;
+		&:not(.cdb-large &) {
+			margin-top : 10px;
+		}
 		>.cdb-sheet {
 		>.cdb-sheet {
 			border : 2px solid #333;
 			border : 2px solid #333;
 			>tr>th {
 			>tr>th {

+ 0 - 0
bin/common.css


+ 1 - 0
bin/common.less

@@ -1,3 +1,4 @@
+// out: false
 // z-index layers
 // z-index layers
 
 
 @default-layer: 200;
 @default-layer: 200;

+ 1 - 0
bin/libs/font-awesome-imports.less

@@ -1,3 +1,4 @@
+// out: false
 /**
 /**
     Imports all fontawesome icons into the custom icon system for hide
     Imports all fontawesome icons into the custom icon system for hide
     Icons available as fa-iconname are now available as ico-iconname
     Icons available as fa-iconname are now available as ico-iconname

+ 41 - 7
bin/style.css

@@ -256,20 +256,59 @@ input[type=checkbox]:checked:after {
   background: #444444;
   background: #444444;
   opacity: 1;
   opacity: 1;
 }
 }
-.splitter.vertical .drag_handle {
+.splitter.vertical {
+  width: 100%;
+  height: 5px;
+}
+.splitter.vertical .drag-handle {
   width: 100%;
   width: 100%;
   height: 15px;
   height: 15px;
   position: absolute;
   position: absolute;
   top: -5px;
   top: -5px;
   cursor: ns-resize;
   cursor: ns-resize;
 }
 }
-.splitter.horizontal .drag_handle {
+.splitter.horizontal {
+  width: 5px;
+  height: 100%;
+}
+.splitter.horizontal .drag-handle {
   width: 15px;
   width: 15px;
   height: 100%;
   height: 100%;
   position: absolute;
   position: absolute;
   left: -5px;
   left: -5px;
   cursor: ew-resize;
   cursor: ew-resize;
 }
 }
+.layout-controls:not(.detached .layout-controls) {
+  display: none;
+}
+.detached.detachable-panel {
+  position: fixed;
+  bottom: 20px;
+  left: 20%;
+  right: 620px;
+  z-index: 800;
+}
+.detached.detachable-panel .splitter {
+  z-index: 810;
+  position: absolute;
+}
+.detached.detachable-panel .splitter.handle-right {
+  right: -5px;
+}
+.detached.detachable-panel .splitter.handle-left {
+  left: -5px;
+}
+.detached.detachable-panel .splitter.handle-top {
+  height: 15px;
+  top: -15px;
+}
+.detached.detachable-panel .splitter.handle-top .drag-handle {
+  cursor: move;
+  top: 0px;
+}
+.detached.detachable-panel .splitter.handle-bottom {
+  bottom: -5px;
+}
 .hide-scenetree {
 .hide-scenetree {
   flex: 1;
   flex: 1;
   background-color: #111;
   background-color: #111;
@@ -766,12 +805,7 @@ input[type=checkbox]:checked:after {
   opacity: 0.5;
   opacity: 0.5;
 }
 }
 .hide-properties .cdb-large .cdb-obj-editor {
 .hide-properties .cdb-large .cdb-obj-editor {
-  position: fixed;
-  bottom: 20px;
   max-height: 800px;
   max-height: 800px;
-  left: 20%;
-  right: 620px;
-  z-index: 800;
   overflow: auto;
   overflow: auto;
   padding: 2px;
   padding: 2px;
   background: #111;
   background: #111;

+ 57 - 16
bin/style.less

@@ -281,20 +281,67 @@ input[type=checkbox] {
 		opacity : 1;
 		opacity : 1;
 	}
 	}
 
 
-	&.vertical .drag_handle {
+	&.vertical {
 		width : 100%;
 		width : 100%;
-		height : 15px;
-		position : absolute;
-		top : -5px;
-		cursor : ns-resize;
+		height : 5px;
+		.drag-handle {
+			width : 100%;
+			height : 15px;
+			position : absolute;
+			top : -5px;
+			cursor : ns-resize;
+		}
 	}
 	}
 
 
-	&.horizontal .drag_handle {
-		width : 15px;
+	&.horizontal {
+		width : 5px;
 		height : 100%;
 		height : 100%;
-		position : absolute;
-		left  : -5px;
-		cursor : ew-resize;
+		.drag-handle {
+			width : 15px;
+			height : 100%;
+			position : absolute;
+			left  : -5px;
+			cursor : ew-resize;
+		}
+	}
+}
+
+.detached {
+
+	.layout-controls:not(& .layout-controls) {
+		display : none;
+	}
+
+	&.detachable-panel {
+		position: fixed;
+		bottom : 20px;
+		left: 20%;
+		right: 620px;
+		z-index: @popup-layer;
+
+		.splitter {
+			z-index : @popup-layer + 10;
+			position : absolute;
+
+			&.handle-right {
+				right : -5px;
+			}
+			&.handle-left {
+				left : -5px;
+			}
+			&.handle-top {
+				height : 15px;
+				top : -15px;
+
+				.drag-handle {
+					cursor : move;
+					top : 0px;
+				}
+			}
+			&.handle-bottom {
+				bottom : -5px;
+			}
+		}
 	}
 	}
 }
 }
 
 
@@ -861,12 +908,7 @@ input[type=checkbox] {
 
 
 	.cdb-large {
 	.cdb-large {
 		.cdb-obj-editor {
 		.cdb-obj-editor {
-			position: fixed;
-			bottom : 20px;
 			max-height: 800px;
 			max-height: 800px;
-			left: 20%;
-			right: 620px;
-			z-index: @popup-layer;
 			overflow: auto;
 			overflow: auto;
 			padding: 2px;
 			padding: 2px;
 			background: #111;
 			background: #111;
@@ -876,7 +918,6 @@ input[type=checkbox] {
 			opacity: 1;
 			opacity: 1;
 		}
 		}
 	}
 	}
-
 }
 }
 
 
 /* Curve editor */
 /* Curve editor */

+ 135 - 0
hide/comp/DetachablePanel.hx

@@ -0,0 +1,135 @@
+package hide.comp;
+
+enum Side {
+	None;
+	Left;
+	Right;
+	Top;
+	Bottom;
+}
+
+class DetachablePanel extends hide.comp.Component {
+	// don't touch the width ? on resize check the new height to not go beyond min bottom
+
+	var currentSide = Side.None;
+	public var defaultState = {
+		left : "20%",
+		right : "620px",
+		bottom : "20px",
+		top : "unset",
+		width : "unset",
+	};
+	public var minWidth = 300;
+	public var minBottom = 20;
+
+	public function new(?parent : Element, ?el : Element) {
+		super(parent, el);
+		element.addClass("detachable-panel");
+		var layoutControls = new Element('<div class="layout-controls">
+			<div class="splitter horizontal handle-right"><div class="drag-handle"></div></div>
+			<div class="splitter horizontal handle-left"><div class="drag-handle"></div></div>
+			<div class="splitter vertical handle-top"><div class="drag-handle"></div></div>
+		</div>');
+			// <div class="splitter vertical handle-bottom"><div class="drag-handle"></div></div>
+
+		var document = new Element(js.Browser.document);
+
+		var startState = { x : 0, y : 0, left : 0, right : 0, top : 0, bottom : 0, width : 0, height : 0 };
+		function initDrag(e : js.jquery.Event) {
+			startState = {
+				x : e.clientX,
+				y : e.clientY,
+				left : Std.parseInt(element.css("left")),
+				right : Std.parseInt(element.css("right")),
+				top : Std.parseInt(element.css("top")),
+				bottom : Std.parseInt(element.css("bottom")),
+				width : Std.parseInt(element.css("width")),
+				height : Std.parseInt(element.css("height")),
+			}
+			element.css("width", startState.width + "px");
+			element.css("right", "unset");
+		}
+
+		layoutControls.find(".handle-right .drag-handle").first().mousedown((e : js.jquery.Event) -> {
+			currentSide = Right;
+			initDrag(e);
+		});
+		layoutControls.find(".handle-left .drag-handle").first().mousedown((e : js.jquery.Event) -> {
+			currentSide = Left;
+			initDrag(e);
+		});
+		layoutControls.find(".handle-top .drag-handle").first()
+			.mousedown((e : js.jquery.Event) -> {
+				currentSide = Top;
+				initDrag(e);
+			})
+			.dblclick((e) -> {
+				e.preventDefault();
+				resetLayout();
+			});
+
+		document.mousemove((e : js.jquery.Event) -> {
+			switch (currentSide) {
+			case Left:
+				e.stopPropagation();
+				var newLeft = e.clientX;
+				if( newLeft < 0 )
+					return;
+				var diff = newLeft - startState.left;
+				var newWidth = startState.width - diff;
+				if( newWidth < minWidth ) {
+					newLeft = startState.left + startState.width - minWidth;
+					newWidth = minWidth;
+				}
+				element.css("left", newLeft + "px");
+				element.css("width", newWidth + "px");
+			case Right:
+				e.stopPropagation();
+				var newWidth = startState.width + e.clientX - startState.x;
+				if( startState.left + newWidth > js.Browser.window.innerWidth )
+					newWidth = Std.int(js.Browser.window.innerWidth) - e.clientX;
+				if( newWidth < minWidth )
+					newWidth = minWidth;
+				element.css("width", newWidth + "px");
+			case Top:
+				e.stopPropagation();
+				var diffx = startState.x - e.clientX;
+				var newLeft = startState.left - diffx;
+				if( newLeft < 0 )
+					newLeft = 0;
+				if( newLeft + startState.width > js.Browser.window.innerWidth )
+					newLeft = Std.int(js.Browser.window.innerWidth) - startState.width;
+				element.css("left", newLeft + "px");
+			case Bottom:
+			case None:
+			}
+		});
+		document.mouseleave((_) -> {
+			currentSide = None;
+		});
+		document.mouseup((_) -> {
+			currentSide = None;
+			saveLayout();
+		});
+
+		layoutControls.appendTo(element);
+	}
+
+	function saveLayout() {
+		var toSave = element.css(["left", "right"]);
+		if( toSave != null )
+			saveDisplayState("detachedOffsets", toSave);
+	}
+
+	public function resetLayout() {
+		element.css(defaultState);
+		saveDisplayState("detachedOffsets", {});
+	}
+
+	public function setDetached(val) {
+		element.toggleClass("detached", val);
+		var existingState = getDisplayState("detachedOffsets");
+		if( existingState != null )
+			element.css(existingState);
+	}
+}

+ 2 - 4
hide/comp/ResizablePanel.hx

@@ -11,17 +11,15 @@ class ResizablePanel extends hide.comp.Component {
 	public function new(layoutDirection : LayoutDirection, element : Element) {
 	public function new(layoutDirection : LayoutDirection, element : Element) {
 		super(null, element);
 		super(null, element);
 		this.layoutDirection = layoutDirection;
 		this.layoutDirection = layoutDirection;
-		var splitter = new Element('<div class="splitter"><div class="drag_handle"></div></div>');
+		var splitter = new Element('<div class="splitter"><div class="drag-handle"></div></div>');
 		switch (layoutDirection) {
 		switch (layoutDirection) {
 			case Horizontal:
 			case Horizontal:
 				splitter.addClass("horizontal");
 				splitter.addClass("horizontal");
-				splitter.width("5px");
 			case Vertical:
 			case Vertical:
 				splitter.addClass("vertical");
 				splitter.addClass("vertical");
-				splitter.height("5px");
 		}
 		}
 		splitter.insertBefore(element);
 		splitter.insertBefore(element);
-		var handle = splitter.find(".drag_handle").first();
+		var handle = splitter.find(".drag-handle").first();
 		var drag = false;
 		var drag = false;
 		var startSize = 0;
 		var startSize = 0;
 		var startPos = 0;
 		var startPos = 0;

+ 6 - 1
hide/comp/SceneEditor.hx

@@ -1422,12 +1422,16 @@ class SceneEditor {
 		');
 		');
 
 
 		var cdbLarge = @:privateAccess view.getDisplayState("cdbLarge");
 		var cdbLarge = @:privateAccess view.getDisplayState("cdbLarge");
+		var detachable = new DetachablePanel();
+		detachable.saveDisplayKey = "detachedCdb";
 		group.find(".btn-cdb-large").click((_) -> {
 		group.find(".btn-cdb-large").click((_) -> {
 			cdbLarge = !cdbLarge;
 			cdbLarge = !cdbLarge;
 			@:privateAccess view.saveDisplayState("cdbLarge", cdbLarge);
 			@:privateAccess view.saveDisplayState("cdbLarge", cdbLarge);
 			group.toggleClass("cdb-large", cdbLarge);
 			group.toggleClass("cdb-large", cdbLarge);
+			detachable.setDetached(cdbLarge);
 		});
 		});
 		group.toggleClass("cdb-large", cdbLarge == true);
 		group.toggleClass("cdb-large", cdbLarge == true);
+		detachable.setDetached(cdbLarge == true);
 
 
 		var select = group.find("select");
 		var select = group.find("select");
 		for(t in types) {
 		for(t in types) {
@@ -1463,7 +1467,8 @@ class SceneEditor {
 			var ctx = context.shared.getContexts(e)[0];
 			var ctx = context.shared.getContexts(e)[0];
 			if( ctx != null )
 			if( ctx != null )
 				fileRef = ctx.shared.currentPath;
 				fileRef = ctx.shared.currentPath;
-			var editor = new hide.comp.cdb.ObjEditor(curType, view.config, e.props, fileRef, props);
+			detachable.element.appendTo(props);
+			var editor = new hide.comp.cdb.ObjEditor(curType, view.config, e.props, fileRef, detachable.element);
 			editor.undo = properties.undo;
 			editor.undo = properties.undo;
 			editor.fileView = view;
 			editor.fileView = view;
 			editor.onChange = function(pname) {
 			editor.onChange = function(pname) {