1 jls.loader.provide('jls.gui.BorderLayout'); 2 3 jls.loader.require('jls.gui.FlowLayout'); 4 5 /** 6 * @augments jls.gui.Layout 7 * @class This class represents a border layout. 8 * Child must define: region, splitter 9 */ 10 jls.gui.BorderLayout = jls.lang.Class.create(jls.gui.FlowLayout, 11 { 12 initialize : function($super, element) { 13 $super(element); 14 this._regions = {}; 15 this._splitSize = 0; 16 this._borderLeft = 0; 17 this._borderRight = 0; 18 this._borderTop = 0; 19 this._borderBottom = 0; 20 this._isResizing = false; 21 this._onMouseMove = this.onMouseMove.bind(this); 22 this._onMouseOut = this.stopResize.bind(this); 23 this._mouseOrigin = 0; 24 this._borderOrigin = 0; 25 this._resizingRegion = null; 26 }, 27 startResize : function(event) { 28 if ((this._isResizing) || (this._splitSize == 0)) { 29 return; 30 } 31 var cSize = this.getElement().getClientSize(); 32 var cWidth = cSize[0]; 33 var cHeight = cSize[1]; 34 //jls.logger.trace('BorderLayout startResize: ' + cWidth + 'x' + cHeight + ' ' + this._borderLeft + '-' + this._borderRight + ', ' + this._borderTop + '-' + this._borderBottom); 35 36 if (this.isRegionSplit('top') && (event.clientY >= this._borderTop) && (event.clientY <= this._borderTop + this._splitSize)) { 37 this._resizingRegion = 'top'; 38 this._borderOrigin = this._borderTop; 39 this._mouseOrigin = event.clientY; 40 } else if (this.isRegionSplit('bottom') && (event.clientY >= cHeight - this._borderBottom - this._splitSize) && (event.clientY <= cHeight - this._borderBottom)) { 41 this._resizingRegion = 'bottom'; 42 this._borderOrigin = this._borderBottom; 43 this._mouseOrigin = event.clientY; 44 } else if (this.isRegionSplit('left') && (event.clientX >= this._borderLeft) && (event.clientX <= this._borderLeft + this._splitSize)) { 45 this._resizingRegion = 'left'; 46 this._borderOrigin = this._borderLeft; 47 this._mouseOrigin = event.clientX; 48 } else if (this.isRegionSplit('right') && (event.clientX >= cWidth - this._borderRight - this._splitSize) && (event.clientX <= cWidth - this._borderRight)) { 49 this._resizingRegion = 'right'; 50 this._borderOrigin = this._borderRight; 51 this._mouseOrigin = event.clientX; 52 } else { 53 return; 54 } 55 this._isResizing = true; 56 this.getElement().observe('mousemove', this._onMouseMove); 57 this.getElement().observe('mouseout', this._onMouseOut); 58 }, 59 onMouseMove : function(event) { 60 jls.logger.trace('BorderLayout mousemove: ' + event.clientX + 'x' + event.clientY + ', region: ' + this._resizingRegion); 61 switch (this._resizingRegion) { 62 case 'top': 63 this._regions[this._resizingRegion].getStyle().setProperty('height', this._borderOrigin + event.clientY - this._mouseOrigin); 64 break; 65 case 'bottom': 66 this._regions[this._resizingRegion].getStyle().setProperty('height', this._borderOrigin + this._mouseOrigin - event.clientY); 67 break; 68 case 'left': 69 this._regions[this._resizingRegion].getStyle().setProperty('width', this._borderOrigin + event.clientX - this._mouseOrigin); 70 break; 71 case 'right': 72 this._regions[this._resizingRegion].getStyle().setProperty('width', this._borderOrigin + this._mouseOrigin - event.clientX); 73 break; 74 default: 75 return; 76 } 77 this.updateRegionStyle(); 78 this.getElement().update(); 79 }, 80 stopResize : function(event) { 81 //jls.logger.trace('BorderLayout stopResize()'); 82 if (this._isResizing) { 83 this.getElement().unobserve('mousemove', this._onMouseMove); 84 this.getElement().unobserve('mouseout', this._onMouseOut); 85 this._isResizing = false; 86 } 87 }, 88 onCreate : function() { 89 this.getElement().observe('mousedown', function(event) { 90 //jls.logger.trace('BorderLayout mousedown: ' + event.clientX + 'x' + event.clientY); 91 event.target.getLayout().startResize(event); 92 }); 93 this.getElement().observe('mouseup', function(event) { 94 //jls.logger.trace('BorderLayout mouseup: ' + event.clientX + 'x' + event.clientY); 95 event.target.getLayout().stopResize(event); 96 }); 97 }, 98 isRegionSplit : function(region) { 99 return (region in this._regions) && (this._regions[region].getStyle().getPropertyValue('splitter') == 'true'); 100 }, 101 getRegionStylePropertyValue : function(region, key, defaultValue) { 102 if (region in this._regions) { 103 var value = this._regions[region].getStyle().getPropertyValue(key); 104 if (value != null) { 105 return value; 106 } 107 } 108 return defaultValue || 0; 109 }, 110 updateRegionStyle : function() { 111 this._splitSize = this.getElement().getStyle().getPropertyValue('splitSize') || 0; 112 this._borderLeft = this.getRegionStylePropertyValue('left', 'width', 0); 113 this._borderRight = this.getRegionStylePropertyValue('right', 'width', 0); 114 this._borderTop = this.getRegionStylePropertyValue('top', 'height', 0); 115 this._borderBottom = this.getRegionStylePropertyValue('bottom', 'height', 0); 116 for (var r in this._regions) { 117 switch (r) { 118 case 'center': 119 this._regions[r].getStyle().setProperties({ 120 width: null, 121 height: null, 122 left: this._borderLeft + ('left' in this._regions ? this._splitSize : 0), 123 right: this._borderRight + ('right' in this._regions ? this._splitSize : 0), 124 top: this._borderTop + ('top' in this._regions ? this._splitSize : 0), 125 bottom: this._borderBottom + ('bottom' in this._regions ? this._splitSize : 0), 126 position: 'absolute' 127 }); 128 break; 129 case 'top': 130 this._regions[r].getStyle().setProperties({ 131 width: null, 132 height: this._borderTop, 133 left: 0, 134 right: 0, 135 top: 0, 136 bottom: null, 137 position: 'absolute' 138 }); 139 break; 140 case 'bottom': 141 this._regions[r].getStyle().setProperties({ 142 width: null, 143 height: this._borderBottom, 144 left: 0, 145 right: 0, 146 top: null, 147 bottom: 0, 148 position: 'absolute' 149 }); 150 break; 151 case 'left': 152 this._regions[r].getStyle().setProperties({ 153 width: this._borderLeft, 154 height: null, 155 left: 0, 156 right: null, 157 top: this._borderTop + ('top' in this._regions ? this._splitSize : 0), 158 bottom: this._borderBottom + ('bottom' in this._regions ? this._splitSize : 0), 159 position: 'absolute' 160 }); 161 break; 162 case 'right': 163 this._regions[r].getStyle().setProperties({ 164 width: this._borderRight, 165 height: null, 166 left: null, 167 right: 0, 168 top: this._borderTop + ('top' in this._regions ? this._splitSize : 0), 169 bottom: this._borderBottom + ('bottom' in this._regions ? this._splitSize : 0), 170 position: 'absolute' 171 }); 172 break; 173 } 174 } 175 }, 176 onAddChild : function($super, child) { 177 var region = child.getStyle().getPropertyValue('region'); 178 // check region 179 if (region == null) { 180 throw new jls.lang.Exception('The region is not defined'); 181 } 182 if (region in this._regions) { 183 throw new jls.lang.Exception('The region "' + region + '" is duplicated'); 184 } 185 this._regions[region] = child; 186 this.updateRegionStyle(); 187 $super(child); 188 }, 189 onRemoveChild : function(child) { 190 var region = child.getStyle().getPropertyValue('region'); 191 if (region != null) { 192 delete this._regions[region]; 193 this.updateRegionStyle(); 194 } 195 $super(child); 196 } 197 }); 198