[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