You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by mt...@apache.org on 2007/05/16 21:19:22 UTC

svn commit: r538736 - /incubator/xap/trunk/codebase/src/xap/widgets/dojo/TreeTable.js

Author: mturyn
Date: Wed May 16 14:19:21 2007
New Revision: 538736

URL: http://svn.apache.org/viewvc?view=rev&rev=538736
Log:
Very improved:
      1.) Implements a spacer column on the far right for table widgets that
           aren't filled by their html table bodies.
      2.) Removed some extraneous sizer handles that were causing [just the?]
			first column widths to jump a little.
	  3.) Improved post-drag behaviour:  now we should only be resizing the
			two columns around the dragged handle.
Last column resizing still a little off.
All scrollbar bugs still around.
	

Modified:
    incubator/xap/trunk/codebase/src/xap/widgets/dojo/TreeTable.js

Modified: incubator/xap/trunk/codebase/src/xap/widgets/dojo/TreeTable.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/widgets/dojo/TreeTable.js?view=diff&rev=538736&r1=538735&r2=538736
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/widgets/dojo/TreeTable.js (original)
+++ incubator/xap/trunk/codebase/src/xap/widgets/dojo/TreeTable.js Wed May 16 14:19:21 2007
@@ -115,7 +115,8 @@
 		xap.widgets.dojo.TreeTable.superclass.postCreate.apply(this,arguments) ;
 		this._created = true ;	
 // debugging
-//		window.foo = this ;
+// debug window.foo = this ;
+
 
 //if(location.href.indexOf("nested")>-1 ){
 //Xap.logString=""+location.href.split("/").pop()+":^"
@@ -466,7 +467,7 @@
 			this._resizeTable();
 		}
 		this._recolorAlternateRows();
-		this._redoSplitterStyling(1000) ;		
+		this._redoSplitPanelStyling(1000) ;		
 	},
 	
 	getVerticalScrollbarWidthPx: function(){   //debug::this.loggit('getVerticalScrollbarWidthPx') ;
@@ -684,12 +685,12 @@
 			this._initialWidth = aWidth ;
 		}
 
-		var delta = fWidth - oWidth ;
+		var deltaPx = fWidth - oWidth ;
 
-		if( delta == 0  ){
+		if( deltaPx == 0  ){
 			return ;
 		}
-		if( delta <0){
+		if( deltaPx <0){
 			// any need to do anything?
 			
 		} else {
@@ -703,16 +704,11 @@
 					
 					
 			
-			if( delta > 0 ){
+			if( deltaPx > 0 ){
 				//widened:
 				var w = fWidth + "px" ;
 
-
-				var headerChildren = this.headerRow.childNodes ;
-				var len = headerChildren.length ;				
-				var wLast 
-					= dojo.html.getMarginBox(headerChildren[len-1]).width ;
-				
+	
 				this.table.style.width = "100%" ;
 				var tableWidth = this.table.clientWidth +"px" ;
 				this.table.style.width = tableWidth ;
@@ -720,20 +716,22 @@
 				this.headerDiv.style.width = "100%" ; 
 				this.headerDiv.style.width = this.headerDiv.clientWidth +"px";
 				this.headerTable.style.width = tableWidth ;
-				this.headerRow.style.width 
-					= (this.getVerticalScrollbarWidthPx()+this.scrollDiv.scrollWidth) +"px" ;									
+//				this.headerRow.style.width 
+//					= (this.getVerticalScrollbarWidthPx()+this.scrollDiv.scrollWidth) +"px" ;									
 				
 				this.columnsSizer.paneWidth = fWidth ;			
 				this.columnsSizer.domNode.style.width = w ;				
-				this.extendLastColumn(wLast+delta) ;
+				this.extendLastColumn(deltaPx) ;
 			}
 		}
 	},	
 	
-	extendLastColumn: function(newWidth){   //debug::this.loggit('extendLastColumn') ;
+	extendLastColumn: function(changeInPixels){   //debug::this.loggit('extendLastColumn') ;
 		var headerChildren = this.headerRow.childNodes ;
 		var len = headerChildren.length ;
 		if(len > 0){
+			var newWidth = dojo.html.getMarginBox(headerChildren[len-1]).width ;
+			newWidth += changeInPixels ;
 			headerChildren[len-1].style.width = newWidth+"px";				
 			var sizer = this.columnsSizer ;
 			// Put all the extra space in the last column:
@@ -966,7 +964,7 @@
 	 
 	onExpandRow : function(row, expanded){   //debug::this.loggit('onExpandRow ') ;
 		this._recolorAlternateRows();
-		this._redoSplitterStyling(1000) ;
+		this._redoSplitPanelStyling(1000) ;
 		//event hook
 	},
 	 
@@ -981,7 +979,7 @@
 					+ this.scrollDiv.scrollWidth
 					)+"px" ;		
 			this.headerDiv.style.left = -this.scrollDiv.scrollLeft + "px";
-			this.splitterContainer.style.left=this.headerDiv.offsetLeft+"px";	
+			this.splitterContainer.style.left =this.headerDiv.offsetLeft+"px";	
 		}
 	},
 
@@ -1077,14 +1075,27 @@
 	_sizeSplitterContainer: function(){   //debug::this.loggit('_sizeSplitterContainer') ;
 		var box = {} ;
 
-		box.width = this.headerTable.clientWidth
+		box.width = this.domNode.clientWidth
 		box.height =  this.scrollDiv.clientHeight
 						+ this.headerTable.clientHeight - 2 ;
 		
 		dojo.html.setMarginBox(this.splitterContainer,box) ;	
 	},
 	
-		// Add sizers for the columns that have just been built:
+	_addSplitPane: function(aBox, lastPaneP){
+		var widg = dojo.widget.createWidget("DivWrapper",aBox) ;
+		// This is the proportion of the entire split
+		// pane given over to this panel:
+		var dom = widg.domNode ;
+
+		widg.sizeShare = aBox.width ;
+		this.columnsSizer.addChild( widg ) ;
+		if( lastPaneP ){
+			widg.sizeMin = 0 ;
+		}					
+	},	
+	
+	// Add sizers for the columns that have just been built:
 	// TODO:  Re-write table so that the header is already
 	// a split container instead of a table row---should make
 	// things much simpler here:
@@ -1094,8 +1105,8 @@
 			return ;
 		}
 	
-		if( this.columnsSizer ){
-			var sizer = this.columnsSizer ;
+		var sizer = this.columnsSizer ;
+		if( sizer ){			
 			dojo.event.disconnect(	
 								sizer,
 								sizer.endSizing,
@@ -1138,7 +1149,7 @@
 										{
 											height:box.height,
 											width:box.width,
-											sizerWidth: 1,
+											sizerWidth:1,
 											persist:false,
 											activeSizing:false
 										},
@@ -1151,67 +1162,38 @@
 
 		var h = this.domNode.offsetHeight +"px" ;
 				
-		var columnsSizer = this.columnsSizer ;
-		var sizers = columnsSizer.sizers ;
 		var foundTrueSizerWidth = false ;		
-																							
+							
+															
 		for (var ii = 0; ii<this.headerRow.childNodes.length; ++ii){
 			var node = this.headerRow.childNodes[ii] ;
 			var box = dojo.html.getMarginBox(node) ;				
-			
-			if(this._borderFudge==null){
-				this._borderFudge 
-					= box.width - dojo.html.getContentBox(node).width;
-			}
-
-			var widg = dojo.widget.createWidget("DivWrapper",box) ;
-			// This is the proportion of the entire split
-			// pane given over to this panel:
-			
-
-			
-			var dom = widg.domNode ;
-	
-			widg.sizeShare = box.width ;//+ borderFudge ;
-
-			columnsSizer.addChild( widg ) ;					
-
-			//restyle here to avoid showing the restyling on-screen later:
-			var aSizer 
-				= sizers[sizers.length - 1] ;			
-			if(aSizer){
-				aSizer.style.visibility="hidden" ;		
-				aSizer.style.height = 
-					(this.headerTable.offsetHeight
-						+ this.scrollDiv.offsetHeight) +"px" ;			
-				dojo.html.removeClass(aSizer, "dojoSplitContainerSizerH") ;
-				dojo.html.addClass(aSizer, "xapTableStationarySizers") ;
-				// No need to see the sizers; they should
-				// line up with the header boundaries
-				// --if they're off by a lot (O(5px))
-				// we'll care, but if they're off
-				// by ~1px we're better off not seeing
-				// them.  Full accuracy is probably impossible
-				// until the headerTable itself is made a 
-				// splitter container desendent:
-					aSizer.style.visibility="visible" ;	
-				if( dojo.render.html.ie ){
-					aSizer.style.filter = "alpha(opacity=0)" ;				
-				} else {
-					aSizer.style.opacity = 0.0 ;				
-				}
-
-				aSizer._xapReformatted = true ;		
-			}
+			this._addSplitPane(box) ;
 		}		
-									
-		this.columnsSizer.postCreate() ;
+								
+		// Add an additional sizer for any space that might 
+		// exist between the last true column and the right
+		// edge of the table:
+		var box = {height: this.headerDiv.clientHeight,
+					width: this.domNode.scrollWidth - this.headerTable.scrollWidth
+					}
+		this._addSplitPane(box,true) ;	
+		
+		this._lastSizer			
+			= this.columnsSizer.sizers[this.columnsSizer.sizers.length - 1] ;
+// This was recreating the sizers,producing too
+// many of them, and appears to be unneeded:
+//		this.columnsSizer.postCreate() ;
 
+		this._applyBasicSizerStyling() ;
 
 		
 		//this.columnsSizer._layoutPanels();
 		this._hideSplitterPanelsAndShowSizers(0) ;
 		
+		
+		// Trigger out methods when the splitter 
+		// beings and ends dragging a sizer line:		
 		dojo.event.connect(	
 							this.columnsSizer,
 							this.columnsSizer.endSizing,
@@ -1225,21 +1207,57 @@
 							this.onBeginSizing
 							) ;
 							
-		this._redoSplitterStyling(0) ;
+		this._redoSplitPanelStyling(0) ;
 		// The results we get after dragging seem better:
 		
 		this.onEndSizing() ;
 	},	
+	
+	_applyBasicSizerStyling: function(){
+	
+		for( var idx = 0; idx < this.columnsSizer.sizers.length; ++idx){
+			var aSizer = this.columnsSizer.sizers[idx] ;
+/*debug*/			aSizer.id = this.domNode.id + "_sizer_"+idx ;
+/*debug*/			aSizer.setAttribute("id",aSizer.id) ;
+/*debug*/ 	dojo.html.addClass(aSizer, "sizer_"+idx) ;
+			aSizer.style.visibility="hidden" ;		
+			aSizer.style.height = 
+				(this.headerTable.offsetHeight
+					+ this.scrollDiv.offsetHeight) +"px" ;			
+			dojo.html.removeClass(aSizer, "dojoSplitContainerSizerH") ;
+			dojo.html.addClass(aSizer, "xapTableStationarySizers") ;
+			// No need to see the sizers; they should
+			// line up with the header boundaries
+			// --if they're off by a lot (O(5px))
+			// we'll care, but if they're off
+			// by ~1px we're better off not seeing
+			// them.  Full accuracy is probably impossible
+			// until the headerTable itself is made a 
+			// splitter container desendent:
+			aSizer.style.visibility="visible" ;
+	
+// /*debug:*/	aSizer.style.backgroundColor = "darkcyan" ;			
+				
+			if( dojo.render.html.ie ){
+				aSizer.style.filter = "alpha(opacity=0)" ;				
+			} else {
+				aSizer.style.opacity = 0.0 ;				
+			}
+			
+			aSizer._xapReformatted = true ;	
+		}	
+	},
+	
 
-	_redoSplitterStyling: function(delay){   //debug::this.loggit('_redoSplitterStyling') ;
+	_redoSplitPanelStyling: function(delay){   //debug::this.loggit('_redoSplitPanelStyling') ;
 		if( delay != undefined ){
-			this._redoSplitterStylingTask
-				= dojo.lang.setTimeout(this,this._redoSplitterStyling,delay) ;
+			this._redoSplitPanelStylingTask
+				= dojo.lang.setTimeout(this,this._redoSplitPanelStyling,delay) ;
 			return ;
 		}
-		if( this._redoSplitterStylingTask ){
-			window.clearTimeout(this._redoSplitterStylingTask) ;
-			this._redoSplitterStylingTask = null ;
+		if( this._redoSplitPanelStylingTask ){
+			window.clearTimeout(this._redoSplitPanelStylingTask) ;
+			this._redoSplitPanelStylingTask = null ;
 		}
 
 		var sizer = this.columnsSizer ;
@@ -1267,31 +1285,30 @@
 			return ;
 		}
 		
-		var nSizers = nColumns - 1 ;
+		// One for each real inter-column border, one for the
+		// border between the last column and the rightmost, 
+		// spacer, pseudo-column:
+		var nSizers = nColumns ;
 		
-		
-		
-// Take out for now; hurts Tree instances:
-//		while( sizerDivs.length>nSizers ){
-//			sizerDomNode.removeChild(sizerDivs[sizerDivs.length - 1]) ;
-//			// go g.c....g.c.?
-//			sizerDivs[sizerDivs.length - 1] = null ;
-//			--sizerDivs.length ;
-//		}
-// Bring back, modified to be less effective but harmless, 
-// without it we get artifacts (sizers at left==0)
-// under IE6:
-		for( var ii=nSizers; ii< sizerDivs.length; ++ii){
-			sizerDivs[ii].style.visibility="hidden" ;
-		}
-
-
+		var remainingWidthPx 
+				= this.columnsSizer.paneWidth ;
+				
 		for(var ii=0; ii<sizerPanes.length; ++ii){
 			var sizerPane = sizerPanes[ii] ;
-			var w = dojo.html.getMarginBox(this.headerRow.childNodes[ii]).width ;
-			sizerPane.sizeShare = w ;
-			sizerPane.sizeActual = w ;	
-			sizerPane.domNode.style.width = (w)+"px" ;					
+
+			if( this.headerRow.childNodes[ii] ){
+				// This is a pane corresponding to a header cell:
+				var w = dojo.html.getMarginBox(this.headerRow.childNodes[ii]).width ;
+				sizerPane.sizeShare = w ;
+				sizerPane.sizeActual = w ;	
+				sizerPane.domNode.style.width = (w)+"px" ;
+				remainingWidthPx -= w ;
+			} else {
+				// this is the extra pane on the right
+				sizerPane.sizeShare = remainingWidthPx ;
+				sizerPane.sizeActual = remainingWidthPx ;	
+				sizerPane.domNode.style.width = (remainingWidthPx)+"px" ;			
+			}					
 		}
 		sizer._layoutPanels() ;
 	},
@@ -1304,9 +1321,12 @@
 		}
 		// Don't bother if there are no columns or,
 		// if we haven't built the full header row yet:
+		//("this.columnsSizer.children.length-1" because
+		// we have an extra split pane for the rightmost, spacer,
+		// pseudo-column:
 		if( !this._columns
 			||(this._columns.length==0)
-			 || (this._columns.length != this.columnsSizer.children.length)
+			 || (this._columns.length != (this.columnsSizer.children.length-1) )
 			){
 			return ;
 		}
@@ -1335,20 +1355,14 @@
 		if(!isXpIe6){
 			parent.style.visibility = "hidden" ;
 		}
-		
-		// TODO: get rid of bogus sizers; 'til then:
-		var nSizers = this._columns.length - 1 ;
-
-
 				
 
-		for(var ii=0; ii <= nSizers; ++ii){
+		for(var ii=0; ii < this._columns.length; ++ii){
 			var child = sizerHandles[ii] ;
 			var childStyle = child.style ;
 			childStyle.visibility = "visible" ;
-			childStyle.zIndex = 100 ;
+			childStyle.zIndex = 0 ;
 
-			
 			if(isXpIe6){
 				/* Can't set it to "transparent" in CSS because
 				   because that removes selectability under IE7;
@@ -1360,14 +1374,9 @@
 				childStyle.backgroundColor="transparent" ;			
 			}			
 		}	
-		for(var kk=nSizers; kk < sizerHandles.length ; ++kk){
-			var child = sizerHandles[kk] ;
-			child.style.visibility = "hidden" ;
-//debug			child.style.backgroundColor="violet";
-			child.style.zIndex = 500 ;
-		}	
+
 		var headers = this.headerRow.childNodes ;		
-		for(var jj=0; jj < splitterPanes.length; ++jj){
+		for(var jj=0; jj < headers.length; ++jj){
 			var paneWidget = splitterPanes[jj] ;		
 			var paneStyle = paneWidget.domNode.style ;
 			paneStyle.visibility="hidden" ;
@@ -1379,30 +1388,115 @@
 		// Readjust sizer handles to match				
 		// headers:
 		var headers = this.headerRow.childNodes ;
-		for(var kk=0; kk < nSizers ; ++kk){
+		for(var kk=0; kk < sizerHandles.length ; ++kk){
 			var child = sizerHandles[kk] ;			
 			var w = this._sizerWidth ;
-	
 			// Widen the sizers so they're more selectable:
 			//---sizers behave more accurately when they're
 			// slimmer, but are harder to select....		
 			child.style.width = this._sizerWidth+"px" ;
 			child.style.left 
 				= (child.offsetLeft 
-					- Math.floor(this._sizerWidth/2)							
-					) + "px" ;
+					- Math.floor(w/2)							
+					) + "px" ;			
 		}			
 		
 		sizer.virtualSizer.style.visibility = "visible" ;	
 	},
 
-	onEndSizing: function(){   //debug::this.loggit('onEndSizing') ;
+	onBeginSizing: function(e){   //debug::this.loggit('onBeginSizing') ;
+	
+		
+		// Find out which sizer handle was grabbed:	
+		this._grabbedSizer = e.target ;
+		
+		var sizers = this.columnsSizer.sizers ;
+		if( this._grabbedSizer == this._lastSizer ){	
+			this._lastTableRightPx 
+				= this._lastSizer.offsetLeft ;
+			this._grabbedSizerIndex 
+				= sizers.length - 1 ;
+			this._grabbedTheLastSizer = true ;
+		} else {
+			// Find which one we grabbed:
+			var idx = -1 ;
+			for( idx = -1 ; idx < sizers.length - 1; ++idx){
+				if( sizers[idx] == this._grabbedSizer ){
+					break ;
+				}
+			}
+			this._grabbedSizerIndex = idx ;
+		}
+			
+			
+		var dragger = this.columnsSizer.virtualSizer ;
+				
+		
+		
+		dojo.html.removeClass( dragger, "dojoSplitContainerVirtualSizerH" ) ;
+		dojo.html.addClass( dragger, "xapTableMovingSizer" ) ;
+		// Can't cache: table height might changed
+		dragger.style.height = this.domNode.offsetHeight+"px" ;
+		dragger.style.width = "1px" ;
+		// Bring splitter container to front so
+		// that we're not getting the column mouseover effects:
+		this.splitterContainer.style.visibility = "visible" ;	
+	},
+
+	onEndSizing: function(e){   //debug::this.loggit('onEndSizing') ;
 		dojo.html.removeClass( this.columnsSizer.virtualSizer, "xapTableMovingSizer" ) ;	
-		dojo.lang.setTimeout(this,this._reconcileHeaderAndBodyColumns,10) ;
+		
+		// user grabbed the last sizer:
+		if( this._grabbedTheLastSizer && this._lastTableRightPx ){
+			// The last sizer corresponds to a non-column;
+			// it defines the right boundary of the table:
+			var currentTableRightPx = this._lastSizer.offsetLeft ;
+			var deltaTableRightPx 
+				= currentTableRightPx 
+					- this._lastTableRightPx ;	
+					
+			// As soon as possible, avoid muddying the waters 
+			// for the next drag:
+			delete this._lastTableRightPx ;
+			delete this._grabbedSizerIndex ;
+			delete this._grabbedTheLastSizer ;				
+			this.headerTable.style.width = currentTableRightPx +"px" ;
+			this.table.style.width = this.headerTable.style.width ;
+			this.extendLastColumn(deltaTableRightPx) ;
+			return ;
+		}
+		// else---all other sizers:
+//debug:		alert("gsi: "+this._grabbedSizerIndex) ;
+		if( this._grabbedSizerIndex > -1 ){		
+			dojo.lang.setTimeout(
+								this,
+								this._reconcileHeaderAndBodyColumns,
+								10,
+								this._grabbedSizerIndex,
+								this._grabbedSizerIndex + 1
+								) ;
+		} else {
+			dojo.lang.setTimeout(
+								this,
+								this._reconcileHeaderAndBodyColumns,
+								10
+								) ;
+		}
 	},
 	
-	
-	_reconcileHeaderAndBodyColumns: function(){	   //debug::this.loggit('_reconcileHeaderAndBodyColumns') ;
+	// With arguments, should only adjust the columns in the
+	// range:
+	_reconcileHeaderAndBodyColumns: function(pStartCol,pEndCol){	   //debug::this.loggit('_reconcileHeaderAndBodyColumns') ;
+
+
+		var startCol = 0 ;
+		var endCol = this._columns.length - 1 ;
+		if( pStartCol ){
+			startCol = pStartCol ;
+			if( pEndCol ){
+				endCol = pEndCol ;
+			}
+		}
 	
 		if(!this.columnsSizer){
 			this._fixColumnWidths();
@@ -1411,15 +1505,17 @@
 			}
 			return ;
 		}
+		
+		
 
 		this.columnsSizer._layoutPanels() ;
 	
-		var children = this.columnsSizer.children ;
-	
 		// tell the columns how wide they ought to be:
 		var children = this.columnsSizer.children ;
 
-		for(var ii=0 ; ii < children.length; ++ii ){
+//debug: alert(pStartCol+":"+pEndCol+"----"+startCol+":"+endCol) ;
+		for(var ii=startCol ; ii < endCol+1; ++ii ){
+
 			var w = children[ii].sizeShare ;
 
 			var wPx = w +"px" ;
@@ -1450,19 +1546,8 @@
 		// they're over:
 		this._hideSplitterPanelsAndShowSizers(10) ;	
 
-	},
-	
-	onBeginSizing: function(){   //debug::this.loggit('onBeginSizing') ;
-		var dragger = this.columnsSizer.virtualSizer ;
-		dojo.html.removeClass( dragger, "dojoSplitContainerVirtualSizerH" ) ;
-		dojo.html.addClass( dragger, "xapTableMovingSizer" ) ;
-		// Can't cache: table height might changed
-		dragger.style.height = this.domNode.offsetHeight+"px" ;
-		dragger.style.width = "0px" ;
-		// Bring splitter container to front so
-		// that we're not getting the column mouseover effects:
-		this.splitterContainer.style.visibility = "visible" ;	
 	}
+	
 	
 }
 );