[kaffe] CVS kaffe (jserv): Updated ScrollPane with boundary checking.

Kaffe CVS cvs-commits at kaffe.org
Mon Jul 12 01:59:16 PDT 2004


PatchSet 4953 
Date: 2004/07/12 06:42:49
Author: jserv
Branch: HEAD
Tag: (none) 
Log:
Updated ScrollPane with boundary checking.

	* libraries/javalib/java/awt/ScrollPane.java
	(ScrollPane): supports GraphicsEnvironment.isHeadless() checks.
	(addImpl): checks scrollbar type.
	(getScrollPosition), (getViewportSize), (layout), (layoutX):
	scrollbar boundary check.

Members: 
	libraries/javalib/java/awt/ScrollPane.java:1.13->1.14 

Index: kaffe/libraries/javalib/java/awt/ScrollPane.java
diff -u kaffe/libraries/javalib/java/awt/ScrollPane.java:1.13 kaffe/libraries/javalib/java/awt/ScrollPane.java:1.14
--- kaffe/libraries/javalib/java/awt/ScrollPane.java:1.13	Sat Nov 24 01:52:43 2001
+++ kaffe/libraries/javalib/java/awt/ScrollPane.java	Mon Jul 12 06:42:49 2004
@@ -1,19 +1,25 @@
-package java.awt;
-
-import java.awt.event.AdjustmentEvent;
-import java.awt.event.AdjustmentListener;
-
-/**
+/*
  * ScrollPane - widget for scrolling a child component
  *
  * Copyright (c) 1998
  *    Transvirtual Technologies, Inc.  All rights reserved.
  *
- * See the file "license.terms" for information on usage and redistribution 
- * of this file. 
+ * Copyright (c) 2004
+ *      Kaffe.org contributors, see ChangeLog for details.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
  *
  * @author P.C.Mehlitz
  */
+
+package java.awt;
+
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
 public class ScrollPane
   extends Container
   implements AdjustmentListener
@@ -28,6 +34,7 @@
 	Point pos;
 	Component child;
 	ChildWrapper wrapper;
+	static int named;
 
 class SPAdjustable
   extends Scrollbar
@@ -65,7 +72,7 @@
 }
 
 public void paint( Graphics g) {
-	g.paintChild( child, false);
+	g.paintChild(child, false);
 }
 }
 
@@ -74,7 +81,11 @@
 }
 
 public ScrollPane ( int policy ) {
+	if (GraphicsEnvironment.isHeadless ())
+		throw new HeadlessException ();
+
 	layoutm = null;
+	int bw = BORDER_WIDTH;
 	
 	if ( (policy >= 0) && (policy <= 2) )
 		this.policy = policy;
@@ -98,18 +109,20 @@
 }
 
 final protected void addImpl ( Component child, Object constraint, int idx ){
-	if ( (child != hScroll) && (child != vScroll) ){
-		if ( this.child != null )
-			remove( this.child);
-		
-		this.child = child;
-		wrapper = new ChildWrapper();
-		wrapper.add( child);
-		super.addImpl( wrapper, constraint, idx);
+	if (child == hScroll || child == vScroll) {
+		super.addImpl( child, constraint, -1);
 		
 	}
 	else {
-		super.addImpl( child, constraint, idx);
+		if (wrapper == null) {
+			wrapper = new ChildWrapper();
+			super.addImpl(wrapper, constraint, -1);
+		}
+		if (this.child != null) {
+			wrapper.remove(this.child);
+		}
+		this.child = child;
+		wrapper.add(child);
 	}
 }
 
@@ -121,9 +134,9 @@
 	int      val = e.getValue();
 	int      w = wrapper.width;
 	int      h = wrapper.height;
-	int      delta;
+	int      delta, w_delta, h_delta;
 	
-	if ( src == vScroll){
+	if ( src == vScroll) {
 		delta = val - pos.y;
 		pos.y = val;
 	}
@@ -134,45 +147,57 @@
 
 	// fake visibility while repositioning child
 	child.flags &= ~IS_VISIBLE;
-	child.setLocation( -pos.x, -pos.y);
+	if ( child.height < h ) {
+		child.setLocation(-pos.x, (h - child.height) / 2);
+	} else {
+		child.setLocation(-pos.x, -pos.y);
+	}
+	
 	child.flags |= IS_VISIBLE;
 
 	Graphics g = wrapper.getGraphics();
 
+	//just copy and clip ( background validation done by wrapper.paint() )
 	if ( g != null ) {
 		if ( src == vScroll ) {
 			if ( delta > 0 ) {  // scroll downwards
-				g.copyArea( 0, delta, w, h - delta, 0, -delta);
-				g.setClip( 0, h-delta, w, delta);
+				if ( delta < h ) {
+					h_delta = h - delta;
+					g.copyArea(0, delta, w, h_delta, 0, -delta);
+					g.clipRect(0, h_delta, w, delta + 1);
+				}
 			}
 			else {              // scroll upwards
-				g.copyArea( 0, 0, w, h+delta, 0, -delta);
-				g.setClip( 0, 0, w, -delta);
+				if ( -delta < h ) {
+					g.copyArea(0, 0, w, h + delta, 0, -delta);
+					g.clipRect(0, 0, w, -delta + 1);
+				}
 			}
 		}
 		else {
 			if ( delta > 0 ) {  // scroll right
-				g.copyArea( delta, 0, w-delta, h, -delta, 0);
-				g.setClip( w-delta, 0, delta, h);
+				if ( delta < w ) {
+					w_delta = w - delta;
+					g.copyArea(delta, 0, w_delta, h, -delta, 0);
+					g.clipRect(w_delta, 0, delta, h);
+				}
 			}
 			else {              // scroll left
-				g.copyArea( 0, 0, w+delta, h, -delta, 0);
-				g.setClip( 0, 0, -delta, h);
+				if ( -delta < w ) {
+					g.copyArea(0, 0, w + delta, h, -delta, 0);
+					g.clipRect( 0, 0, -delta, h);
+				}
 			}
 		}
 
-		wrapper.update( g);
-//		g.translate( child.x, child.y);
-//		child.paint( g);
-
+		wrapper.update(g);
 		g.dispose();
 	}
 }
 
 void checkScrollbarVisibility ( Dimension cd ) {
-	int      bw = BORDER_WIDTH;
-	int      w = width - 2*bw;
-	int      h = height -2*bw;
+	int w = width - insets.left - insets.right;
+	int h = height - insets.top - insets.bottom;
 
 	if ( (hScroll.flags & IS_VISIBLE) != 0 ) {
 		if ( cd.width <= w ) {
@@ -201,16 +226,48 @@
 	layout();
 }
 
+String getGenericName () {
+	/*
+	 * Apparently, the JDK increments the running number each time
+	 * after there was a genericName request. And yes, the stem is 
+	 * of course not the class name
+	 */
+	return "scrollpane" + (named++);
+}
+
 public Adjustable getHAdjustable () {
 	return hScroll;
 }
 
 public int getHScrollbarHeight () {
-	return (hScroll == null) ? 0 : Defaults.ScrollbarWidth;
+	return hScroll.preferredSize().height;
 }
 
+public Dimension getPreferredSize() {
+	// seems to be a fixed in Sun JDK
+	// return new Dimension(100, 100);
+	return super.getPreferredSize();
+}
+
+/**
+  * Returns the current scroll position of the viewport.
+  *
+  * @return The current scroll position of the viewport.
+  */
 public Point getScrollPosition () {
-	return pos;
+	int x = 0;
+	int y = 0;
+
+	Adjustable v = getVAdjustable();
+	Adjustable h = getHAdjustable();
+
+	if (v != null)
+		y = v.getValue();
+	if (h != null)
+		x = h.getValue();
+
+	return(new Point(x, y));
+	// return new Point(pos);
 }
 
 public int getScrollbarDisplayPolicy () {
@@ -221,13 +278,91 @@
 	return vScroll;
 }
 
-public int getVScrollbarWidth () {
-	return (vScroll == null) ? 0 : Defaults.ScrollbarWidth;
+/**
+  * Returns the current viewport size.  The viewport is the region of
+  * this object's window where the child is actually displayed.
+  *
+  * @return The viewport size.
+  */
+public Dimension getViewportSize ()
+{
+	Dimension viewsize = getSize();
+	//Insets insets = getInsets();
+
+	viewsize.width -= (insets.left + insets.right);
+	viewsize.height -= (insets.top + insets.bottom);
+
+	Component[] list = getComponents();
+	if ((list == null) || (list.length <= 0))
+		return viewsize;
+
+	Dimension dim = list[0].getPreferredSize();
+
+	if (dim.width <= 0 && dim.height <= 0)
+		return viewsize;
+
+	int vScrollbarWidth = getVScrollbarWidth ();
+	int hScrollbarHeight = getHScrollbarHeight ();
+
+	if (policy == SCROLLBARS_ALWAYS) {
+		viewsize.width -= vScrollbarWidth;
+		viewsize.height -= hScrollbarHeight;
+		return viewsize;
+	}
+
+	if (policy == SCROLLBARS_NEVER)
+		return viewsize;
+
+	// The scroll policy is SCROLLBARS_AS_NEEDED, so we need to see if
+	// either scrollbar is needed.
+
+	// Assume we don't need either scrollbar.
+	boolean mayNeedVertical = false;
+	boolean mayNeedHorizontal = false;
+
+	boolean needVertical = false;
+	boolean needHorizontal = false;
+
+	// Check if we need vertical scrollbars.  If we do, then we need to
+	// subtract the width of the vertical scrollbar from the viewport's
+	// width.
+	if (dim.height > viewsize.height)
+		needVertical = true;
+	else if (dim.height > (viewsize.height - hScrollbarHeight))
+		// This is tricky.  In this case the child is tall enough that its
+		// bottom edge would be covered by a horizontal scrollbar, if one
+		// were present.  This means that if there's a horizontal
+		// scrollbar then we need a vertical scrollbar.
+		mayNeedVertical = true;
+
+	if (dim.width > viewsize.width)
+		needHorizontal = true;
+	else if (dim.width > (viewsize.width - vScrollbarWidth))
+		mayNeedHorizontal = true;
+
+	if (needVertical && mayNeedHorizontal)
+		needHorizontal = true;
+
+	if (needHorizontal && mayNeedVertical)
+		needVertical = true;
+
+	if (needHorizontal)
+		viewsize.height -= hScrollbarHeight;
+
+	if (needVertical)
+		viewsize.width -= vScrollbarWidth;
+
+	return viewsize;
+	/* Kaffe's original implementation.
+	public Dimension getViewportSize () {
+        	return new Dimension( width - (insets.left + insets.right),
+                	              height - (insets.top + insets.bottom));
+	}
+	 */
 }
 
-public Dimension getViewportSize () {
-	return new Dimension( width - (insets.left + insets.right),
-	                      height - (insets.top + insets.bottom));
+public int getVScrollbarWidth () {
+	return vScroll.preferredSize().width;
 }
 
 public boolean isFocusTraversable () {
@@ -235,14 +370,17 @@
 }
 
 /**
- * @deprecated
- */
+  * Lays out this component.  This consists of resizing the sole child
+  * component to its perferred size.
+  *
+  * @deprecated This method is deprecated in favor of
+  * <code>doLayout()</code>.
+  */
 public void layout() {
 	if ( child == null ) {
 		return;
 	}
-	int bw = BORDER_WIDTH;
-	int sw = Defaults.ScrollbarWidth;
+
 	Dimension cd = child.getPreferredSize();
 	int w, h;
 
@@ -251,53 +389,132 @@
 	if ( policy == SCROLLBARS_AS_NEEDED )
 		checkScrollbarVisibility( cd);
 		
-	int vw = ((vScroll.flags & IS_VISIBLE) != 0) ? sw : 0;
-	int hh = ((hScroll.flags & IS_VISIBLE) != 0) ? sw : 0;
-	
+	int vw = ((vScroll.flags & IS_VISIBLE) != 0) ? vScroll.preferredSize().width : 0;
+	int hh = ((hScroll.flags & IS_VISIBLE) != 0) ? hScroll.preferredSize().height : 0;
+
+	w = width - (insets.left + insets.right + vw);
+	h = height - (insets.top + insets.bottom + hh);
+
+	hScroll.setBounds( insets.left, h, w, hh);
+	vScroll.setBounds( w, insets.top, vw,  h);
+
+	// check scroll position bounds
+	if ( w + pos.x > cd.width ) {
+		pos.x = Math.max( cd.width - w, 0);
+	}
+	if (  h + pos.y > cd.height ) {
+		pos.y = Math.max( cd.height - h, 0);
+	}
+
+	hScroll.setValues( pos.x, w, 0, cd.width, false);
+	vScroll.setValues( pos.y, h, 0, cd.height, false);
+
+	wrapper.setBounds( insets.left, insets.top, w , h);
+
+	if ( cd.width < wrapper.width ) {
+		cd.width = wrapper.width;
+	}
+
+	if ( cd.height < wrapper.height ) {
+		child.setBounds(
+			-pos.x, 
+			(wrapper.height - cd.height) / 2, 
+			cd.width, cd.height);
+	}
+	else {
+		child.setBounds( -pos.x, -pos.y, cd.width, cd.height);
+	}
+
+	flags &= ~IS_LAYOUTING;
+}
+
+public void layoutX() {
+	if ( child == null ) {
+		return;
+	}
 	
-	w = width - (2*bw + vw);
-	h = height - (2*bw + hh);
+	Dimension cd = child.getPreferredSize();
+	int w, h;
+	pos.x = pos.y = 0;
 	
-	hScroll.setBounds( 0, height - sw, width - vw, sw);
-	vScroll.setBounds( width - sw, 0, sw, height - hh);
+	flags |= IS_LAYOUTING;
 
-	hScroll.setValues( 0, w, 0, cd.width);
-	vScroll.setValues( 0, h, 0, cd.height);
+	if ( policy == SCROLLBARS_AS_NEEDED )
+		checkScrollbarVisibility( cd);
 
-	wrapper.setBounds( bw, bw, width - vw -2*bw , height - hh -2*bw);
-	child.setBounds( 0, 0, cd.width, cd.height);
+	int vw = ((vScroll.flags & IS_VISIBLE) != 0) ? 
+		vScroll.preferredSize().width : 0;
+	int hh = ((hScroll.flags & IS_VISIBLE) != 0) ? 
+		hScroll.preferredSize().height : 0;
+
+	w = width - (insets.left + insets.right + vw);
+	h = height - (insets.top + insets.bottom + hh);
+
+	hScroll.setBounds( insets.left, h, w, hh);
+	vScroll.setBounds( w, insets.top, vw,  h);
+
+	hScroll.setValues( 0, w, 0, cd.width, false);
+	vScroll.setValues( 0, h, 0, cd.height, false);
+
+	wrapper.setBounds( insets.left, insets.top, w , h);
+
+	if ( cd.width < wrapper.width ) {
+		cd.width = wrapper.width;
+	}
+
+	if ( cd.height < wrapper.height ) {
+		child.setBounds( 0, (wrapper.height-cd.height)/2, cd.width, cd.height);
+	}
+	else {
+		child.setBounds( 0, 0, cd.width, cd.height);
+	}
 
 	flags &= ~IS_LAYOUTING;
 }
 
 public void paint ( Graphics g ) {
-	int sw = Defaults.ScrollbarWidth;
-	int vw = ((vScroll.flags & IS_VISIBLE) != 0) ? sw : 0;
-	int hh = ((hScroll.flags & IS_VISIBLE) != 0) ? sw : 0;
-
 	if ( wrapper != null )
 		g.paintChild( wrapper, false);
-	if ( hh != 0 )
+	if ( ((hScroll.flags & IS_VISIBLE) != 0) )
 		g.paintChild( hScroll, false);
-	if ( vw != 0 )
+	if (((vScroll.flags & IS_VISIBLE) != 0) )
 		g.paintChild( vScroll, false);
-		
-	kaffePaintBorder( g, 0, 0, vw, hh);
 }
 
+public void remove ( int idx ) {
+	if (children[idx] == wrapper) {
+		wrapper.remove(child);
+	}
+ }
+
 final public void setLayout ( LayoutManager mgr ) {
 	throw new AWTError( "ScrollPane can't have LayoutManagers");
 }
 
+/**
+  * Sets the scroll position to the specified value.
+  *
+  * @param x The new X coordinate of the scroll position.
+  * @param y The new Y coordinate of the scroll position.
+  *
+  * @exception IllegalArgumentException If the specified value is outside
+  * the legal scrolling range.
+  */
 public void setScrollPosition ( Point p ) {
-	setScrollPosition( p.x, p.y);
+	Adjustable h = getHAdjustable();
+	Adjustable v = getVAdjustable();
+
+	if (h != null)
+		h.setValue(x);
+	if (v != null)
+		v.setValue(y);
+	setScrollPosition(x, y);
 }
 
 public void setScrollPosition ( int x, int y ) {
-	pos.x = x;
-	pos.y = y;
-	
+	// pos updated by adjustmentValueChanged ( incl.range check )
 	hScroll.setValue( x);
 	vScroll.setValue( y);
 }
 }
+




More information about the kaffe mailing list