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