panel_ex.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. 面板扩展
  3. 功能: 自动布局窗口
  4. */
  5. 'use strict';
  6. const path = require('path');
  7. const fs = require('fs');
  8. module.exports = {
  9. /** @type import('../../panel/vs-panel/vs-panel-base') */
  10. parent : null,
  11. // 面板初始化
  12. ready(parent){
  13. // index.js 对象
  14. // 读取自动布局信息
  15. this.parent = parent;
  16. this.parent_dom = Editor.Panel.find('simple-code');
  17. this.layout_dom_flex = this.getLayoutDomFlex()
  18. this.self_flex_per = this.parent.cfg.self_flex_per || this.getSelfFlexPercent();
  19. },
  20. onLoad(){
  21. // 监听焦点
  22. let focusPanels = [this.parent.$editorB,this.parent.$tabList];
  23. for (let i = 0; i < focusPanels.length; i++) {
  24. const dom = focusPanels[i];
  25. dom.addEventListener('focus',(e)=>{
  26. this.setAutoLayout(true)
  27. },true);
  28. }
  29. this.parent_dom.addEventListener('blur',(e)=>{
  30. setTimeout(()=>{
  31. let panel = Editor.Panel.getFocusedPanel()
  32. let is_need_close = this.isSameGroupPanel(panel);
  33. if(is_need_close){
  34. this.setAutoLayout(panel == this)
  35. }
  36. },10)
  37. },false);
  38. // 伸缩快捷键
  39. this.parent.addKeybodyEventByName('switchEditorWindow',(e)=>
  40. {
  41. let isOpen = !this.old_focused_state;
  42. this.setAutoLayout(isOpen,true)
  43. isOpen ? Editor.Panel.focus('simple-code') : Editor.Panel.focus('scene')
  44. e.preventDefault();
  45. },0)
  46. this.setAutoLayout(Editor.Panel.getFocusedPanel() == this.parent_dom);
  47. },
  48. // 设置选项
  49. setOptions(cfg,isInit)
  50. {
  51. if(!isInit)
  52. {
  53. if(this.parent.cfg.is_lock_window) {
  54. return;
  55. }
  56. if (cfg.autoLayoutMin != null) {
  57. this.setAutoLayout(true);
  58. this.setAutoLayout(false);
  59. }
  60. if (cfg.autoLayoutMax != null) {
  61. this.setAutoLayout(false);
  62. this.setAutoLayout(true);
  63. }
  64. }
  65. },
  66. // 监听焦点: 每0.5s检测是否调整布局了
  67. onCheckLayout(isUpLayout)
  68. {
  69. // 正在播放中过渡特效中
  70. if(this.layout_dom_flex && this.layout_dom_flex.style['-webkit-transition']){
  71. return;
  72. }
  73. if(isUpLayout)
  74. {
  75. let rate = this.getSelfFlexPercent();
  76. if(Math.abs(rate*100-this.parent.cfg.autoLayoutMin) > 3){
  77. this.self_flex_per = this.parent.cfg.self_flex_per = rate;
  78. }
  79. }
  80. // 伸缩窗口
  81. let panel = Editor.Panel.getFocusedPanel()
  82. let is_self = panel == this && !this.comparisonParentDom(this.parent.$toolsPanel,this.parent_dom._focusedElement);
  83. let is_need_close = this.isSameGroupPanel(panel);
  84. if(is_self || is_need_close){
  85. this.setAutoLayout(is_self)
  86. }
  87. },
  88. // 设置展开面板或收起来
  89. setAutoLayout(is_focused,isUse)
  90. {
  91. if(this.parent.cfg.is_lock_window && !isUse)
  92. return;
  93. this.layout_dom_flex = this.getLayoutDomFlex();
  94. let now_flex = this.layout_dom_flex && this.layout_dom_flex.style.flex;
  95. if(!this.parent.cfg.autoLayoutMin || now_flex == null || (this.old_focused_state != null && this.old_focused_state == is_focused)){
  96. return;
  97. }
  98. this.old_focused_state = is_focused;
  99. // 焦点改变时修改布局
  100. // 统计其它同级窗口总宽或总高
  101. let flexs = this.getFlexs();
  102. // 是否水平布局
  103. let is_horizontal = this.layout_dom_flex.isHorizontal;//this.isHorizontalLayout();
  104. if(is_horizontal){
  105. for (const i in flexs) {
  106. const flexInfo = flexs[i];
  107. if(this.parent.cfg.autoLayoutDt){
  108. flexInfo.dom.style['-webkit-transition'] = 'flex '+this.parent.cfg.autoLayoutDt+"s ease "+(this.parent.cfg.autoLayoutDelay || '0')+'s'
  109. }
  110. let flex = flexInfo.dom.style.flex;
  111. if(is_focused){
  112. flexInfo.dom.old_flex_grow = flexInfo.flex[0]
  113. flex = flexInfo.dom != this.layout_dom_flex ? '0.1 1 0%' : '1 1 0%';
  114. }else if(flexInfo.dom.old_flex_grow != null){
  115. flex = flexInfo.dom.old_flex_grow + ' 1 0%'// + ls;
  116. }
  117. flexInfo.dom.style.flex = flex;
  118. }
  119. }else{ // 垂直布局
  120. let my_per = is_focused ? (this.parent.cfg.autoLayoutMax ? this.parent.cfg.autoLayoutMax * 0.01 : this.self_flex_per) : this.parent.cfg.autoLayoutMin*0.01; // 调整窗口缩放比例
  121. let max_per = 1
  122. let sub_per = max_per-my_per;
  123. let ohter_size = 0
  124. for (const i in flexs) {
  125. const flexInfo = flexs[i];
  126. if(flexInfo.dom != this.layout_dom_flex){
  127. ohter_size += Number(flexInfo.flex[0])
  128. }
  129. }
  130. for (const i in flexs)
  131. {
  132. const flexInfo = flexs[i];
  133. if(this.parent.cfg.autoLayoutDt){
  134. flexInfo.dom.style['-webkit-transition']='flex '+this.parent.cfg.autoLayoutDt+"s ease "+(this.parent.cfg.autoLayoutDelay || '0')+'s'
  135. }
  136. if(flexInfo.dom != this.layout_dom_flex)
  137. {
  138. let per = Number(flexInfo.flex[0])/ohter_size;//占用空间百分比
  139. let oth_per = isNaN(per) ? sub_per : per*sub_per; // 临时修复布局异常bug;
  140. flexInfo.dom.style.flex = oth_per+' 1 0%'
  141. }else{
  142. flexInfo.dom.style.flex = my_per+' 1 0%'
  143. }
  144. }
  145. }
  146. let actEnd = ()=>
  147. {
  148. this.layout_dom_flex.removeEventListener("transitionend", actEnd);
  149. for (const i in flexs)
  150. {
  151. const flexInfo = flexs[i];
  152. flexInfo.dom.style['-webkit-transition'] = '';//清除过渡动画
  153. }
  154. this.parent.$overlay.style.display = "none";
  155. this.parent.upLayout();
  156. // 场景刷新下,有时会出黑边
  157. for (let i = 0; i < Editor.Panel.panels.length; i++) {
  158. const panel = Editor.Panel.panels[i];
  159. if(panel && panel._onPanelResize) panel._onPanelResize()
  160. }
  161. }
  162. if(this.parent.cfg.autoLayoutDt)
  163. {
  164. this.parent.$overlay.style.display = this.layout_dom_flex.parentElement.children[0] == this.layout_dom_flex ? "" : "inline"; // 自己在最顶层就不必显示蒙版
  165. this.layout_dom_flex.addEventListener('transitionend',actEnd,false);
  166. }else{
  167. actEnd();
  168. }
  169. },
  170. // 是否父节点的子子级
  171. comparisonParentDom(parentDom,domNode){
  172. if (domNode == null) return false;
  173. if(parentDom == domNode)
  174. return true
  175. else if(domNode.parentElement)
  176. return this.comparisonParentDom(parentDom,domNode.parentElement)
  177. else
  178. return false;
  179. },
  180. // 和本面板是同一组垂直的面板
  181. isSameGroupPanel(panel)
  182. {
  183. if(panel == null) return false;
  184. let flexs = this.getFlexs();
  185. for (const i in flexs) {
  186. const flexInfo = flexs[i];
  187. if(flexInfo.dom != this.layout_dom_flex){
  188. let isHas = this.comparisonParentDom(flexInfo.dom,panel);
  189. if(isHas){
  190. return true;
  191. }
  192. }
  193. }
  194. return false;
  195. },
  196. // 其它窗口总高度
  197. getFlexs()
  198. {
  199. let list = {}
  200. if(this.layout_dom_flex && this.layout_dom_flex.parentElement){
  201. for (let i = 0; i < this.layout_dom_flex.parentElement.children.length; i++) {
  202. let dom = this.layout_dom_flex.parentElement.children[i];
  203. if(dom.style.flex){
  204. list[i] = {flex:dom.style.flex.split(' '),dom};
  205. }
  206. }
  207. }
  208. return list;
  209. },
  210. // 本窗口当前占用空间百分比
  211. getSelfFlexPercent()
  212. {
  213. this.layout_dom_flex = this.getLayoutDomFlex();
  214. let flexs = this.getFlexs();
  215. let max_height = 0
  216. let self_flex
  217. for (const i in flexs) {
  218. const flexInfo = flexs[i];
  219. max_height += Number(flexInfo.flex[0])
  220. if(flexInfo.dom == this.layout_dom_flex){
  221. self_flex = flexInfo.flex;
  222. }
  223. }
  224. if(self_flex){
  225. return self_flex[0]/max_height;
  226. }
  227. return 0
  228. },
  229. // 获得竖板布局层
  230. getLayoutDomFlex(){
  231. return this.getLayoutDomFlexByPanel(this.parent_dom);
  232. },
  233. // 获得编辑器所在的布局块对象
  234. getLayoutDomFlexByPanel(panel){
  235. let layout_dom_flex;
  236. if(panel && panel.parentElement)
  237. {
  238. layout_dom_flex = panel.parentElement;
  239. if(!layout_dom_flex.parentElement) return;
  240. let isHorizontal = true;
  241. for (let i = 0; i < layout_dom_flex.parentElement.children.length; i++) {
  242. const dom = layout_dom_flex.parentElement.children[i];
  243. if(Math.abs(dom.scrollHeight - layout_dom_flex.scrollHeight)>50){
  244. isHorizontal = false;
  245. }
  246. }
  247. // 这里水平布局了两排以上
  248. if(isHorizontal){
  249. let n = layout_dom_flex.parentElement.tagName
  250. if(n == "UI-MAIN-DOCK"){
  251. layout_dom_flex.isHorizontal = true;// 面板,标记使用水平布局
  252. }else{
  253. layout_dom_flex = layout_dom_flex.parentElement
  254. delete layout_dom_flex.isHorizontal;
  255. }
  256. }
  257. }else{
  258. layout_dom_flex = undefined;
  259. }
  260. return layout_dom_flex;
  261. },
  262. // 面板销毁
  263. onDestroy(){
  264. this.setAutoLayout(false);
  265. },
  266. messages:{
  267. 'switchEditorWindow'()
  268. {
  269. if(!this.parent.is_init_finish){
  270. return;
  271. }
  272. let isOpen = !this.old_focused_state;
  273. this.setAutoLayout(isOpen)
  274. isOpen ? this.parent_dom.focus() : this.parent_dom.blur()
  275. },
  276. },
  277. };