verticalResizablePanes.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import App from '../../base'
  2. export default App.directive('verticalResizablePanes', [
  3. 'localStorage',
  4. 'ide',
  5. function (localStorage, ide) {
  6. return {
  7. restrict: 'A',
  8. link(scope, element, attrs) {
  9. const name = attrs.verticalResizablePanes
  10. const minSize = scope.$eval(attrs.verticalResizablePanesMinSize)
  11. const maxSize = scope.$eval(attrs.verticalResizablePanesMaxSize)
  12. const defaultSize = scope.$eval(attrs.verticalResizablePanesDefaultSize)
  13. let storedSize = null
  14. let manualResizeIncoming = false
  15. if (name) {
  16. const storageKey = `vertical-resizable:${name}:south-size`
  17. storedSize = localStorage(storageKey)
  18. $(window).unload(() => {
  19. if (storedSize) {
  20. localStorage(storageKey, storedSize)
  21. }
  22. })
  23. }
  24. const layoutOptions = {
  25. center: {
  26. paneSelector: '[vertical-resizable-top]',
  27. paneClass: 'vertical-resizable-top',
  28. size: 'auto',
  29. },
  30. south: {
  31. paneSelector: '[vertical-resizable-bottom]',
  32. paneClass: 'vertical-resizable-bottom',
  33. resizerClass: 'vertical-resizable-resizer',
  34. resizerCursor: 'ns-resize',
  35. size: 'auto',
  36. resizable: true,
  37. closable: false,
  38. slidable: false,
  39. spacing_open: 6,
  40. spacing_closed: 6,
  41. maxSize: '75%',
  42. },
  43. }
  44. const toggledExternally =
  45. attrs.verticalResizablePanesToggledExternallyOn
  46. const hiddenExternally = attrs.verticalResizablePanesHiddenExternallyOn
  47. const hiddenInitially = attrs.verticalResizablePanesHiddenInitially
  48. const resizeOn = attrs.verticalResizablePanesResizeOn
  49. const resizerDisabledClass = `${layoutOptions.south.resizerClass}-disabled`
  50. function enableResizer() {
  51. if (layoutHandle.resizers && layoutHandle.resizers.south) {
  52. layoutHandle.resizers.south.removeClass(resizerDisabledClass)
  53. }
  54. }
  55. function disableResizer() {
  56. if (layoutHandle.resizers && layoutHandle.resizers.south) {
  57. layoutHandle.resizers.south.addClass(resizerDisabledClass)
  58. }
  59. }
  60. function handleDragEnd() {
  61. manualResizeIncoming = true
  62. }
  63. function handleResize(paneName, paneEl, paneState) {
  64. if (manualResizeIncoming) {
  65. storedSize = paneState.size
  66. }
  67. manualResizeIncoming = false
  68. }
  69. if (toggledExternally) {
  70. scope.$on(toggledExternally, (e, open) => {
  71. if (open) {
  72. enableResizer()
  73. layoutHandle.sizePane(
  74. 'south',
  75. storedSize ?? defaultSize ?? 'auto'
  76. )
  77. } else {
  78. disableResizer()
  79. layoutHandle.sizePane('south', 'auto')
  80. }
  81. })
  82. }
  83. if (hiddenExternally) {
  84. ide.$scope.$on(hiddenExternally, (e, open) => {
  85. if (open) {
  86. layoutHandle.show('south')
  87. } else {
  88. layoutHandle.hide('south')
  89. }
  90. })
  91. }
  92. if (resizeOn) {
  93. ide.$scope.$on(resizeOn, () => {
  94. ide.$timeout(() => {
  95. layoutHandle.resizeAll()
  96. })
  97. })
  98. }
  99. if (maxSize) {
  100. layoutOptions.south.maxSize = maxSize
  101. }
  102. if (minSize) {
  103. layoutOptions.south.minSize = minSize
  104. }
  105. if (defaultSize) {
  106. layoutOptions.south.size = defaultSize
  107. }
  108. // The `drag` event fires only when the user manually resizes the panes; the `resize` event fires even when
  109. // the layout library internally resizes itself. In order to get explicit user-initiated resizes, we need to
  110. // listen to `drag` events. However, when the `drag` event fires, the panes aren't yet finished sizing so we
  111. // get the pane size *before* the resize happens. We do get the correct size in the next `resize` event.
  112. // The solution to work around this is to set up a flag in `drag` events which tells the next `resize` event
  113. // that it was user-initiated (therefore, storing the value).
  114. layoutOptions.south.ondrag_end = handleDragEnd
  115. layoutOptions.south.onresize = handleResize
  116. const layoutHandle = element.layout(layoutOptions)
  117. if (hiddenInitially === 'true') {
  118. layoutHandle.hide('south')
  119. }
  120. },
  121. }
  122. },
  123. ])